*** 0.96c/linux/Makefile	Sun Jul  5 03:09:23 1992
--- linux/Makefile	Sat Jul 11 20:11:52 1992
***************
*** 89,95 ****
  
  Version:
  	@./makever.sh
! 	@echo \#define UTS_RELEASE \"0.96c-`cat .version`\" > include/linux/config_rel.h
  	@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
  	touch include/linux/config.h
  
--- 89,95 ----
  
  Version:
  	@./makever.sh
! 	@echo \#define UTS_RELEASE \"0.96c.pl1-`cat .version`\" > include/linux/config_rel.h
  	@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
  	touch include/linux/config.h
  
*** 0.96c/linux/boot/setup.S	Tue May 19 03:36:58 1992
--- linux/boot/setup.S	Thu Jul  9 14:41:55 1992
***************
*** 189,197 ****
  	out	#0xA1,al
  	.word	0x00eb,0x00eb
  	mov	al,#0xFF		! mask off all interrupts for now
- 	out	#0x21,al
- 	.word	0x00eb,0x00eb
  	out	#0xA1,al
  
  ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
  ! need no steenking BIOS anyway (except for the initial loading :-).
--- 189,198 ----
  	out	#0xA1,al
  	.word	0x00eb,0x00eb
  	mov	al,#0xFF		! mask off all interrupts for now
  	out	#0xA1,al
+ 	.word	0x00eb,0x00eb
+ 	mov	al,#0xFB		! mask all irq's but irq2 which
+ 	out	#0x21,al		! is cascaded
  
  ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
  ! need no steenking BIOS anyway (except for the initial loading :-).
***************
*** 241,250 ****
  	push	ds
  	push	cs
  	pop	ds
! 	mov 	ax,#0xc000
  	mov	es,ax
  	lea	si,msg1
! 	call	prtstr
  flush:	in	al,#0x60		! Flush the keyboard buffer
  	cmp	al,#0x82
  	jb	nokey
--- 242,316 ----
  	push	ds
  	push	cs
  	pop	ds
! 
! ! First try and execute a VESA BIOS call
! 
! 	mov	ax,#0x4f00		! AX = VESA BIOS func RETURN SVGA Info
! 	push	cs
! 	pop	es
! 	lea	di,vib			! ES:[DI] -> VESA Information Block Ptr
! 	int	0x10
! 
! 	cmp	ax,#0x004f		! Check result status
! 	jne	novesa			! VESA BIOS not supported or failed
! 
! ! OK!  We got a VESA BIOS, let's figure out what we can do!
! 
! ! Print out the VESA information from the VIB
! 
! 	lea	si,vib			! This should print out VESA
! 	lodsb
! 	call	prnt1
! 	lodsb
! 	call	prnt1
! 	lodsb
! 	call	prnt1
! 	lodsb
! 	call	prnt1
! 	call	space
! 
! 	mov	al,vib+5		! This is the version of VESA supported
! 	call	dprnt
! 	mov	al,#0x2e
! 	call	prnt1
! 	mov	al,vib+4
! 	call	dprnt
! 	call	space
! 
! 	push	ds
! 	lds	si,vib+6		! This prints out the OEM string
! 	call	prtstr
! 	call	space
! 	pop	ds
! 
! 	mov	al,vib+10		! This prints out the Vesa Capabilities
! 	call	dprnt
! 	mov	al,vib+11
! 	call	dprnt
! 	mov	al,vib+12
! 	call	dprnt
! 	mov	al,vib+13
! 	call	dprnt
! 
! 	push	ds			! Finally, go through the list of modes
! 	lds	si,vib+14
! model:	lodsw				! Get mode number
! 	cmp	ax,#0xFFFF
! 	je	isvesa
! 	call	addmod			! Check to see if this is a TEXT mode
! 	jmp	model
! 
! isvesa:	call	docr
! 	pop	ds
! 	lea	si,dscvesa
! 	lea	di,movesa
! 	lea	cx,selmod
! 	jmp	cx
! 
! novesa:	mov 	ax,#0xc000
  	mov	es,ax
  	lea	si,msg1
! 	call	prtstr			! Press <RETURN> to see SVGA-modes ...
  flush:	in	al,#0x60		! Flush the keyboard buffer
  	cmp	al,#0x82
  	jb	nokey
***************
*** 463,485 ****
  	mov	al,#0x55
  	xor	al,#0xea
  	cmp	al,bh
! 	jne	novid7
  	lea	si,dscvideo7
  	lea	di,movideo7
  selmod:	push	si
! 	lea	si,msg2
  	call	prtstr
! 	xor	cx,cx
! 	mov	cl,(di)
  	pop	si
  	push	si
  	push	cx
  tbl:	pop	bx
  	push	bx
! 	mov	al,bl
! 	sub	al,cl
! 	call	dprnt
  	call	spcing
  	lodsw
  	xchg	al,ah
  	call	dprnt
--- 529,566 ----
  	mov	al,#0x55
  	xor	al,#0xea
  	cmp	al,bh
! 	je	isvideo7
! 	lea	cx,set8x8
! 	jmp	cx
! isvideo7:
  	lea	si,dscvideo7
  	lea	di,movideo7
+ 
+ ! Upon Entry to SELMOD, SI -> list of Modes, DI -> List of Mode Numbers
+ 
  selmod:	push	si
! 	lea	si,msg2			! Numb:   Mode:   COLSxROWS
  	call	prtstr
! 	mov	cx,(di)			! This gets Number of Modes in list
  	pop	si
  	push	si
  	push	cx
  tbl:	pop	bx
  	push	bx
! 	mov	ax,bx
! 	sub	ax,cx
! 	call	hprntl			! Print out selection number
! 	push	ax
  	call	spcing
+ 	pop	ax
+ 	push	di
+ 	add	ax,ax
+ 	add	ax,#2
+ 	add	di,ax
+ 	mov	ax,(di)
+ 	call	hprntl			! Print out MODE number
+ 	call	spcing
+ 	pop	di
  	lodsw
  	xchg	al,ah
  	call	dprnt
***************
*** 493,499 ****
  	loop	tbl
  	pop	cx
  	call	docr
! 	lea	si,msg3
  	call	prtstr
  	pop	si
  	add	cl,#0x80
--- 574,580 ----
  	loop	tbl
  	pop	cx
  	call	docr
! 	lea	si,msg3			! Choose Mode Number
  	call	prtstr
  	pop	si
  	add	cl,#0x80
***************
*** 509,526 ****
  nozero:	sub	al,#0x80
  	dec	al
  	xor	ah,ah
  	add	di,ax
  	inc	di
! 	push	ax
! 	mov	al,(di)
! 	int 	0x10
  	pop	ax
- 	shl	ax,#1
  	add	si,ax
! 	lodsw
  	pop	ds
  	ret
! novid7:
  	mov	ax,#0x1112
  	mov	bl,#0
  	int	0x10		! use 8x8 font set (50 lines on VGA)
--- 590,627 ----
  nozero:	sub	al,#0x80
  	dec	al
  	xor	ah,ah
+ 	shl	ax,#1
+ 	push	ax
  	add	di,ax
  	inc	di
! 	inc	di
! 	mov	ax,(di)			! AX = Mode
! 	cmp	ah,#0
! 	jne	setvesa
! 	int 	0x10			! Set OLD style mode
! 
! retmode:
  	pop	ax
  	add	si,ax
! 	lodsw				! Get COLSxROWS
  	pop	ds
  	ret
! 
! setvesa:
! 	pop	bx
! 	cmp	ah,#0xFF		! Special, mode FF, set 8x8 font
! 	je	set8x8
! 
! 	push	bx
! 	mov	bx,ax			! Mode to set
! 	mov	ax,#0x4f02		! Set VESA mode
! 	int	0x10
! 
! 	jmp	retmode
! 		
! ! If we can't find the adapter in the table, at least set 80x50
! 
! set8x8:
  	mov	ax,#0x1112
  	mov	bl,#0
  	int	0x10		! use 8x8 font set (50 lines on VGA)
***************
*** 541,557 ****
  	mov	ax,#0x5032	! return 80x50
  	ret
  
  ! Routine that 'tabs' to next col.
  
  spcing:	mov	al,#0x2e
- 	call	prnt1
- 	mov	al,#0x20
  	call	prnt1	
! 	mov	al,#0x20
  	call	prnt1	
! 	mov	al,#0x20
  	call	prnt1	
! 	mov	al,#0x20
  	call	prnt1
  	ret	
  
--- 642,724 ----
  	mov	ax,#0x5032	! return 80x50
  	ret
  
+ ! Routine to add mode in ax to VESA selection table
+ 
+ addmod:	push	cx
+ 	push	ds
+ 	push	es
+ 	push	di
+ 	push	bx
+ 	push	dx
+ 	push	ax
+ 
+ 	mov	cx,ax			! CX = VESA mode number
+ 	push	cs
+ 	pop	es
+ 	lea	di,mib			! ES:[DI] -> Mode Information Block
+ 	mov	ax,#0x4f01		! AX = Get VESA Mode Info
+ 	int	0x10	
+ 
+ 	cmp	ax,#0x004f		! If fails, assume it's not a TEXT mode
+ 	jne	adfail
+ 
+ 	push	cs
+ 	pop	ds			! Make DS contain something reasonable
+ 
+ 	mov	ax,mib			! Get Mode Attributes field
+ 	and	al,#0x12		! Mask Text and Extended bits
+ 	cmp	al,#0x02		! Text and Extended info available?
+ 	jne	adfail
+ 
+ 	call	space
+ 
+ 	mov	ax,mib+18		! Horizontal Resolution
+ 	mov	bl,mib+22		! X Char Size
+ 	div	bl
+ ! HACK:  For some reason, my Diamond Stealth card returns 160 cols for its
+ !	 132 coloumn modes, so don't return any sizes > 132?
+ 	sub	al,#132
+ 	jbe	orgcol
+ 	sub	al,al
+ orgcol:	add	al,#132			! MIN(cols, 132)
+ 	mov	dh,al			! Put num cols in DH
+ 	mov	ax,mib+20		! Vertical Resolution
+ 	mov	bl,mib+23		! Y Char Size
+ 	div	bl
+ 	mov	dl,al			! Put num rows in DL
+ 
+ 	mov	bx,movesa		! Get current number of video modes
+ 	lea	di,movesa
+ 	inc	(di)			! This is a NEW mode
+ 	add	bx,bx
+ 	add	di,bx
+ 	add	di,#2
+ 	pop	ax			! Get Mode number back
+ 	push	ax
+ 	mov	(di),ax			! Mode number
+ 	lea	di,dscvesa
+ 	add	di,bx
+ 	mov	(di),dx			! Screen resolution
+ 
+ adfail:	pop	ax
+ 	pop	dx
+ 	pop	bx
+ 	pop	di
+ 	pop	es
+ 	pop	ds
+ 	pop	cx
+ 
+ 	ret
+ 
  ! Routine that 'tabs' to next col.
  
  spcing:	mov	al,#0x2e
  	call	prnt1	
! space3:	mov	al,#0x20
  	call	prnt1	
! space2:	mov	al,#0x20
  	call	prnt1	
! space:	mov	al,#0x20
  	call	prnt1
  	ret	
  
***************
*** 564,569 ****
--- 731,769 ----
  	jmp	prtstr
  fin:	ret
  
+ ! Routine to print out HEX values on screen.
+ ! The value to be printed is in the AX register.
+ 
+ hprntl:	xchg	ah,al
+ 	call	hprnt
+ 	xchg	ah,al
+ 	call	hprnt
+ 	ret
+ 
+ ! Routine to print out HEX values on the screen
+ ! The valueto be printed is in the AL register.  AH is preserved.
+ 
+ hprnt:	push	ax
+ 	shr	al,4
+ 	and	al,#0xf
+ 	call	hprnt1
+ 	pop	ax
+ 	push	ax
+ 	and	al,#0xf
+ 	call	hprnt1
+ 	pop	ax
+ 	ret
+ 
+ ! Routine to print out one HEX digit on the screen.
+ ! The value to be printed is in al (0-F)
+ 
+ hprnt1:	cmp	al,#10
+ 	jl	hdec
+ 	add	al,#7			! Convert 10-15 to A-F
+ hdec:	add	al,#0x30		! Convert to ASCII
+ 	call	prnt1			! print it
+ 	ret
+ 
  ! Routine to print a decimal value on screen, the value to be
  ! printed is put in al (i.e 0-255). 
  
***************
*** 635,641 ****
  
  msg1:		.ascii	"Press <RETURN> to see SVGA-modes available or any other key to continue."
  		db	0x0d, 0x0a, 0x0a, 0x00
! msg2:		.ascii	"Mode:  COLSxROWS:"
  		db	0x0d, 0x0a, 0x0a, 0x00
  msg3:		.ascii	"Choose mode by pressing the corresponding number."
  		db	0x0d, 0x0a, 0x00
--- 835,841 ----
  
  msg1:		.ascii	"Press <RETURN> to see SVGA-modes available or any other key to continue."
  		db	0x0d, 0x0a, 0x0a, 0x00
! msg2:		.ascii	"Numb:   Mode:  COLSxROWS:"
  		db	0x0d, 0x0a, 0x0a, 0x00
  msg3:		.ascii	"Choose mode by pressing the corresponding number."
  		db	0x0d, 0x0a, 0x00
***************
*** 647,662 ****
  
  ! Manufacturer:	  Numofmodes:	Mode:
  
! moati:		.byte	0x02,	0x23, 0x33 
! moahead:	.byte	0x05,	0x22, 0x23, 0x24, 0x2f, 0x34
! mocandt:	.byte	0x02,	0x60, 0x61
! mocirrus:	.byte	0x04,	0x1f, 0x20, 0x22, 0x31
! moeverex:	.byte	0x0a,	0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
! mogenoa:	.byte	0x0a,	0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
! moparadise:	.byte	0x02,	0x55, 0x54
! motrident:	.byte	0x07,	0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
! motseng:	.byte	0x05,	0x26, 0x2a, 0x23, 0x24, 0x22
! movideo7:	.byte	0x06,	0x40, 0x43, 0x44, 0x41, 0x42, 0x45
  
  !			msb = Cols lsb = Rows:
  
--- 847,863 ----
  
  ! Manufacturer:	  Numofmodes:	Mode:
  
! moati:		.word	0x02,	0x23, 0x33 
! moahead:	.word	0x05,	0x22, 0x23, 0x24, 0x2f, 0x34
! mocandt:	.word	0x02,	0x60, 0x61
! mocirrus:	.word	0x04,	0x1f, 0x20, 0x22, 0x31
! moeverex:	.word	0x0a,	0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
! mogenoa:	.word	0x0a,	0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
! moparadise:	.word	0x02,	0x55, 0x54
! motrident:	.word	0x07,	0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
! motseng:	.word	0x05,	0x26, 0x2a, 0x23, 0x24, 0x22
! movideo7:	.word	0x06,	0x40, 0x43, 0x44, 0x41, 0x42, 0x45
! movesa:		.word	0x02,	0x03, 0xFFFF, 254*0
  
  !			msb = Cols lsb = Rows:
  
***************
*** 670,676 ****
--- 871,881 ----
  dsctrident:	.word 	0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
  dsctseng:	.word	0x503c, 0x6428, 0x8419, 0x841c, 0x842c
  dscvideo7:	.word	0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
+ dscvesa:	.word	0x5019, 0x5032, 254*0
  	
+ vib:		.word	256*0
+ mib:		.word	256*0
+ 
  .text
  endtext:
  .data
*** 0.96c/linux/fs/inode.c	Thu Jul  2 00:42:04 1992
--- linux/fs/inode.c	Sat Jul 11 01:37:05 1992
***************
*** 252,257 ****
--- 252,258 ----
  	}
  	inode->i_dev = dev;
  	inode->i_ino = nr;
+ 	inode->i_flags = inode->i_sb->s_flags;
  	read_inode(inode);
  	return inode;
  }
*** 0.96c/linux/fs/open.c	Thu Jul  2 00:42:04 1992
--- linux/fs/open.c	Sat Jul 11 03:58:46 1992
***************
*** 73,78 ****
--- 73,82 ----
  		iput(inode);
  		return -EACCES;
  	}
+ 	if (IS_RDONLY(inode)) {
+ 		iput(inode);
+ 		return -EROFS;
+ 	}
  	inode->i_size = length;
  	if (inode->i_op && inode->i_op->truncate)
  		inode->i_op->truncate(inode);
***************
*** 91,97 ****
  		return -EBADF;
  	if (!(inode = file->f_inode))
  		return -ENOENT;
! 	if (S_ISDIR(inode->i_mode) || !(file->f_flags & 2))
  		return -EACCES;
  	inode->i_size = length;
  	if (inode->i_op && inode->i_op->truncate)
--- 95,101 ----
  		return -EBADF;
  	if (!(inode = file->f_inode))
  		return -ENOENT;
! 	if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
  		return -EACCES;
  	inode->i_size = length;
  	if (inode->i_op && inode->i_op->truncate)
***************
*** 112,117 ****
--- 116,125 ----
  
  	if (!(inode=namei(filename)))
  		return -ENOENT;
+ 	if (IS_RDONLY(inode)) {
+ 		iput(inode);
+ 		return -EROFS;
+ 	}
  	if (times) {
  		if ((current->euid != inode->i_uid) && !suser()) {
  			iput(inode);
***************
*** 215,220 ****
--- 223,230 ----
  		return -ENOENT;
  	if ((current->euid != inode->i_uid) && !suser())
  		return -EPERM;
+ 	if (IS_RDONLY(inode))
+ 		return -EROFS;
  	inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
  	inode->i_dirt = 1;
  	return 0;
***************
*** 230,235 ****
--- 240,249 ----
  		iput(inode);
  		return -EPERM;
  	}
+ 	if (IS_RDONLY(inode)) {
+ 		iput(inode);
+ 		return -EROFS;
+ 	}
  	inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
  	inode->i_dirt = 1;
  	iput(inode);
***************
*** 245,250 ****
--- 259,266 ----
  		return -EBADF;
  	if (!(inode = file->f_inode))
  		return -ENOENT;
+ 	if (IS_RDONLY(inode))
+ 		return -EROFS;
  	if ((current->euid == inode->i_uid && user == inode->i_uid &&
  	     (in_group_p(group) || group == inode->i_gid)) ||
  	    suser()) {
***************
*** 262,267 ****
--- 278,287 ----
  
  	if (!(inode = lnamei(filename)))
  		return -ENOENT;
+ 	if (IS_RDONLY(inode)) {
+ 		iput(inode);
+ 		return -EROFS;
+ 	}
  	if ((current->euid == inode->i_uid && user == inode->i_uid &&
  	     (in_group_p(group) || group == inode->i_gid)) ||
  	    suser()) {
***************
*** 325,330 ****
--- 345,351 ----
  int sys_close(unsigned int fd)
  {	
  	struct file * filp;
+ 	struct inode * inode;
  
  	if (fd >= NR_OPEN)
  		return -EINVAL;
***************
*** 340,348 ****
  		filp->f_count--;
  		return 0;
  	}
  	if (filp->f_op && filp->f_op->release)
! 		filp->f_op->release(filp->f_inode,filp);
! 	iput(filp->f_inode);
  	filp->f_count--;
  	return 0;
  }
--- 361,370 ----
  		filp->f_count--;
  		return 0;
  	}
+ 	inode = filp->f_inode;
  	if (filp->f_op && filp->f_op->release)
! 		filp->f_op->release(inode,filp);
  	filp->f_count--;
+ 	iput(inode);
  	return 0;
  }
*** 0.96c/linux/fs/exec.c	Thu Jul  2 01:30:00 1992
--- linux/fs/exec.c	Sat Jul 11 00:49:32 1992
***************
*** 183,189 ****
  		iput(inode);
  		return -EACCES;
  	}
! 	if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
  		iput(inode);
  		return -EACCES;
  	}
--- 183,189 ----
  		iput(inode);
  		return -EACCES;
  	}
! 	if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
  		iput(inode);
  		return -EACCES;
  	}
***************
*** 406,412 ****
--- 406,422 ----
  		retval = -EACCES;
  		goto exec_error2;
  	}
+ 	if (IS_NOEXEC(inode)) { /* FS mustn't be mounted noexec */
+ 		retval = -EPERM;
+ 		goto exec_error2;
+ 	}
  	i = inode->i_mode;
+ 	if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
+ 	    euid) || ((i & S_ISGID) && inode->i_gid != current->egid)) &&
+ 	    !suser()) {
+ 		retval = -EPERM;
+ 		goto exec_error2;
+ 	}
  	/* make sure we don't let suid, sgid files be ptraced. */
  	if (current->flags & PF_PTRACED) {
  		e_uid = current->euid;
***************
*** 424,430 ****
  		retval = -EACCES;
  		goto exec_error2;
  	}
! 	if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
  		retval = -EACCES;
  		goto exec_error2;
  	}
--- 434,440 ----
  		retval = -EACCES;
  		goto exec_error2;
  	}
! 	if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
  		retval = -EACCES;
  		goto exec_error2;
  	}
*** 0.96c/linux/fs/super.c	Fri Jul  3 03:09:37 1992
--- linux/fs/super.c	Sat Jul 11 15:56:17 1992
***************
*** 11,16 ****
--- 11,17 ----
  #include <linux/sched.h>
  #include <linux/minix_fs.h>
  #include <linux/ext_fs.h>
+ /* #include <linux/msdos_fs.h> */
  #include <linux/kernel.h>
  #include <linux/stat.h>
  #include <asm/system.h>
***************
*** 18,23 ****
--- 19,25 ----
  
  #include <errno.h>
  
+ 
  int sync_dev(int dev);
  void wait_for_keypress(void);
  
***************
*** 36,41 ****
--- 38,44 ----
  static struct file_system_type file_systems[] = {
  	{minix_read_super,"minix"},
  	{ext_read_super,"ext"},
+  /*	{msdos_read_super,"msdos"}, */
  	{NULL,NULL}
  };
  
***************
*** 112,118 ****
  		sb->s_op->put_super(sb);
  }
  
! static struct super_block * read_super(int dev,char *name,void *data)
  {
  	struct super_block * s;
  	struct file_system_type *type;
--- 115,121 ----
  		sb->s_op->put_super(sb);
  }
  
! static struct super_block * read_super(int dev,char *name,int flags,void *data)
  {
  	struct super_block * s;
  	struct file_system_type *type;
***************
*** 133,138 ****
--- 136,142 ----
  			break;
  	}
  	s->s_dev = dev;
+ 	s->s_flags = flags;
  	if (!type->read_super(s,data))
  		return(NULL);
  	s->s_dev = dev;
***************
*** 183,209 ****
  	return 0;
  }
  
! int sys_mount(char * dev_name, char * dir_name, char * type, int rw_flag)
  {
! 	struct inode * dev_i, * dir_i;
  	struct super_block * sb;
- 	int dev;
- 	char tmp[100],*t;
- 	int i;
  
! 	if (!suser())
! 		return -EPERM;
! 	if (!(dev_i = namei(dev_name)))
  		return -ENOENT;
! 	dev = dev_i->i_rdev;
! 	if (!S_ISBLK(dev_i->i_mode)) {
! 		iput(dev_i);
! 		return -EPERM;
! 	}
! 	iput(dev_i);
! 	if (!(dir_i=namei(dir_name)))
! 		return -ENOENT;
! 	if (dir_i->i_count != 1 || dir_i->i_ino == MINIX_ROOT_INO) {
  		iput(dir_i);
  		return -EBUSY;
  	}
--- 187,209 ----
  	return 0;
  }
  
! /*
!  * do_mount() does the actual mounting after sys_mount has done the ugly
!  * parameter parsing. When enough time has gone by, and everything uses the
!  * new mount() parameters, sys_mount() can then be cleaned up.
!  *
!  * We cannot mount a filesystem if it has active, used, or dirty inodes.
!  * We also have to flush all inode-data for this device, as the new mount
!  * might need new info.
!  */
! static int do_mount(int dev, const char * dir, char * type, int flags, void * data)
  {
! 	struct inode * inode, * dir_i;
  	struct super_block * sb;
  
! 	if (!(dir_i = namei(dir)))
  		return -ENOENT;
! 	if (dir_i->i_count != 1 || dir_i->i_mount) {
  		iput(dir_i);
  		return -EBUSY;
  	}
***************
*** 211,239 ****
  		iput(dir_i);
  		return -EPERM;
  	}
! 	if (dir_i->i_mount) {
  		iput(dir_i);
  		return -EPERM;
  	}
  	if (type) {
! 		i = 0;
! 		while (i < 100 && (tmp[i] = get_fs_byte(type++)))
! 			i++;
  		t = tmp;
  	} else
  		t = "minix";
! 	if (!(sb = read_super(dev,t,NULL))) {
! 		iput(dir_i);
! 		return -EBUSY;
! 	}
! 	if (sb->s_covered) {
! 		iput(dir_i);
! 		return -EBUSY;
! 	}
! 	sb->s_covered = dir_i;
! 	dir_i->i_mount = 1;
! 	dir_i->i_dirt = 1;		/* NOTE! we don't iput(dir_i) */
! 	return 0;			/* we do that in umount */
  }
  
  void mount_root(void)
--- 211,292 ----
  		iput(dir_i);
  		return -EPERM;
  	}
! 	for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
! 		if (inode->i_dev != dev)
! 			continue;
! 		if (inode->i_count || inode->i_dirt || inode->i_lock) {
! 			iput(dir_i);
! 			return -EBUSY;
! 		}
! 		inode->i_dev = 0;
! 	}
! 	sb = read_super(dev,type,flags,data);
! 	if (!sb || sb->s_covered) {
  		iput(dir_i);
+ 		return -EBUSY;
+ 	}
+ 	sb->s_flags = flags;
+ 	sb->s_covered = dir_i;
+ 	dir_i->i_mount = 1;
+ 	return 0;		/* we don't iput(dir_i) - see umount */
+ }
+ 
+ /*
+  * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
+  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
+  *
+  * data is a (void *) that can point to any structure up to 4095 bytes, which
+  * can contain arbitrary fs-dependent information (or be NULL).
+  *
+  * NOTE! As old versions of mount() didn't use this setup, the flags has to have
+  * a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
+  * isn't present, the flags and data info isn't used, as the syscall assumes we
+  * are talking to an older version that didn't understand them.
+  */
+ int sys_mount(char * dev_name, char * dir_name, char * type,
+ 	unsigned long new_flags, void *data)
+ {
+ 	struct inode * inode;
+ 	int dev;
+ 	int retval = 0;
+ 	char tmp[100],*t;
+ 	int i;
+ 	unsigned long flags = 0;
+ 	unsigned long page = 0;
+ 
+ 	if (!suser())
  		return -EPERM;
+ 	if (!(inode = namei(dev_name)))
+ 		return -ENOENT;
+ 	dev = inode->i_rdev;
+ 	if (!S_ISBLK(inode->i_mode))
+ 		retval = -EPERM;
+ 	else if (IS_NODEV(inode))
+ 		retval = -EACCES;
+ 	iput(inode);
+ 	if (retval)
+ 		return retval;
+ 	if ((new_flags & 0xffff0000) == 0xC0ED0000) {
+ 		flags = new_flags & 0xffff;
+ 		if (data && (unsigned long) data < TASK_SIZE)
+ 			page = get_free_page();
  	}
+ 	if (page) {
+ 		i = TASK_SIZE - (unsigned long) data;
+ 		if (i < 0 || i > 4095)
+ 			i = 4095;
+ 		memcpy_fromfs((void *) page,data,i);
+ 	}
  	if (type) {
! 		for (i = 0 ; i < 100 ; i++)
! 			if (!(tmp[i] = get_fs_byte(type++)))
! 				break;
  		t = tmp;
  	} else
  		t = "minix";
! 	retval = do_mount(dev,dir_name,t,flags,(void *) page);
! 	free_page(page);
! 	return retval;
  }
  
  void mount_root(void)
***************
*** 255,261 ****
  		p->s_lock = 0;
  		p->s_wait = NULL;
  	}
! 	if (!(p=read_super(ROOT_DEV,"minix",NULL)))
  		panic("Unable to mount root");
   	/*wait_for_keypress();
  	if (!(mi=iget(ROOT_DEV,MINIX_ROOT_INO)))
--- 308,314 ----
  		p->s_lock = 0;
  		p->s_wait = NULL;
  	}
! 	if (!(p=read_super(ROOT_DEV,"minix",0,NULL)))
  		panic("Unable to mount root");
   	/*wait_for_keypress();
  	if (!(mi=iget(ROOT_DEV,MINIX_ROOT_INO)))
***************
*** 264,269 ****
--- 317,323 ----
  	mi=p->s_mounted;
  	mi->i_count += 3 ;	/* NOTE! it is logically used 4 times, not 1 */
  	p->s_mounted = p->s_covered = mi;
+ 	p->s_flags = 0;
  	current->pwd = mi;
  	current->root = mi;
  	free=0;
*** 0.96c/linux/fs/namei.c	Thu Jul  2 00:42:04 1992
--- linux/fs/namei.c	Sat Jul 11 03:57:49 1992
***************
*** 229,234 ****
--- 229,238 ----
  			iput(dir);
  			return -EACCES;
  		}
+ 		if (IS_RDONLY(dir)) {
+ 			iput(dir);
+ 			return -EROFS;
+ 		}
  		return dir->i_op->create(dir,basename,namelen,mode,res_inode);
  	}
  	if (flag & O_EXCL) {
***************
*** 238,254 ****
  	}
  	if (!(inode = follow_link(dir,inode)))
  		return -ELOOP;
  	if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
  	    !permission(inode,ACC_MODE(flag))) {
  		iput(inode);
  		return -EPERM;
  	}
- 	inode->i_atime = CURRENT_TIME;
  	if (flag & O_TRUNC)
  		if (inode->i_op && inode->i_op->truncate) {
  			inode->i_size = 0;
  			inode->i_op->truncate(inode);
  		}
  	*res_inode = inode;
  	return 0;
  }
--- 242,272 ----
  	}
  	if (!(inode = follow_link(dir,inode)))
  		return -ELOOP;
+ 	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
+ 		if (IS_NODEV(inode)) {
+ 			iput(inode);
+ 			return -EACCES;
+ 		}
+ 	} else {
+ 		if (IS_RDONLY(inode) && (flag & (O_TRUNC | O_ACCMODE))) {
+ 			iput(inode);
+ 			return -EROFS;
+ 		}
+ 	}
  	if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
  	    !permission(inode,ACC_MODE(flag))) {
  		iput(inode);
  		return -EPERM;
  	}
  	if (flag & O_TRUNC)
  		if (inode->i_op && inode->i_op->truncate) {
  			inode->i_size = 0;
  			inode->i_op->truncate(inode);
  		}
+ 	if (!IS_RDONLY(inode)) {
+ 		inode->i_atime = CURRENT_TIME;
+ 		inode->i_dirt = 1;
+ 	}
  	*res_inode = inode;
  	return 0;
  }
***************
*** 265,270 ****
--- 283,292 ----
  		iput(dir);
  		return -ENOENT;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (!permission(dir,MAY_WRITE)) {
  		iput(dir);
  		return -EACCES;
***************
*** 295,300 ****
--- 317,326 ----
  		iput(dir);
  		return -ENOENT;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (!permission(dir,MAY_WRITE)) {
  		iput(dir);
  		return -EACCES;
***************
*** 318,323 ****
--- 344,353 ----
  		iput(dir);
  		return -ENOENT;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (!permission(dir,MAY_WRITE)) {
  		iput(dir);
  		return -EACCES;
***************
*** 341,346 ****
--- 371,380 ----
  		iput(dir);
  		return -EPERM;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (!permission(dir,MAY_WRITE)) {
  		iput(dir);
  		return -EACCES;
***************
*** 365,370 ****
--- 399,408 ----
  		iput(dir);
  		return -ENOENT;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (!permission(dir,MAY_WRITE)) {
  		iput(dir);
  		return -EACCES;
***************
*** 395,400 ****
--- 433,443 ----
  		iput(dir);
  		return -EPERM;
  	}
+ 	if (IS_RDONLY(dir)) {
+ 		iput(oldinode);
+ 		iput(dir);
+ 		return -EROFS;
+ 	}
  	if (dir->i_dev != oldinode->i_dev) {
  		iput(dir);
  		iput(oldinode);
***************
*** 453,458 ****
--- 496,506 ----
  		iput(old_dir);
  		iput(new_dir);
  		return -EXDEV;
+ 	}
+ 	if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
+ 		iput(old_dir);
+ 		iput(new_dir);
+ 		return -EROFS;
  	}
  	if (!old_dir->i_op || !old_dir->i_op->rename) {
  		iput(old_dir);
*** 0.96c/linux/fs/ioctl.c	Thu Jul  2 00:42:04 1992
--- linux/fs/ioctl.c	Sat Jul 11 00:49:32 1992
***************
*** 6,11 ****
--- 6,12 ----
  
  #include <errno.h>
  
+ #include <asm/segment.h>
  #include <linux/string.h>
  #include <linux/stat.h>
  #include <linux/sched.h>
***************
*** 13,21 ****
--- 14,30 ----
  int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  {	
  	struct file * filp;
+ 	int block;
  
  	if (fd >= NR_OPEN || !(filp = current->filp[fd]))
  		return -EBADF;
+ 	if (S_ISREG(filp->f_inode->i_mode) && cmd == BMAP_IOCTL &&
+ 	    filp->f_inode->i_op->bmap) {
+ 		block = get_fs_long((long *) arg);
+ 		block = filp->f_inode->i_op->bmap(filp->f_inode,block);
+ 		put_fs_long(block,(long *) arg);
+ 		return 0;
+ 	}
  	if (filp->f_op && filp->f_op->ioctl)
  		return filp->f_op->ioctl(filp->f_inode, filp, cmd,arg);
  	return -EINVAL;
*** 0.96c/linux/fs/ext/bitmap.c	Fri Jul  3 03:18:53 1992
--- linux/fs/ext/bitmap.c	Sat Jul 11 05:04:14 1992
***************
*** 203,208 ****
--- 203,209 ----
  		iput(inode);
  		return NULL;
  	}
+ 	inode->i_flags = inode->i_sb->s_flags;
  	j = 8192;
  	for (i=0 ; i<8 ; i++)
  		if (bh=inode->i_sb->s_imap[i])
*** 0.96c/linux/fs/ext/file.c	Fri Jul  3 16:24:07 1992
--- linux/fs/ext/file.c	Sat Jul 11 00:49:32 1992
***************
*** 153,160 ****
  	} while (left > 0);
  	if (!read)
  		return -EIO;
! 	inode->i_atime = CURRENT_TIME;
! 	inode->i_dirt = 1;
  	return read;
  }
  
--- 153,162 ----
  	} while (left > 0);
  	if (!read)
  		return -EIO;
! 	if (!IS_RDONLY(inode)) {
! 		inode->i_atime = CURRENT_TIME;
! 		inode->i_dirt = 1;
! 	}
  	return read;
  }
  
*** 0.96c/linux/fs/ext/freelists.c	Fri Jul  3 03:08:06 1992
--- linux/fs/ext/freelists.c	Sat Jul 11 05:04:14 1992
***************
*** 70,81 ****
  		if (bh->b_count)
  			brelse(bh);
  	}
! 	efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
! 	if (efb->count == 254) {
  #ifdef EXTFS_DEBUG
  printk("ext_free_block: block full, skipping to %d\n", block);
  #endif
! 		brelse (sb->s_zmap[1]);
  		if (!(sb->s_zmap[1] = bread (dev, block)))
  			panic ("ext_free_block: unable to read block to free\n");
  		efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
--- 70,83 ----
  		if (bh->b_count)
  			brelse(bh);
  	}
! 	if (sb->s_zmap[1])
! 		efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
! 	if (!sb->s_zmap[1] || efb->count == 254) {
  #ifdef EXTFS_DEBUG
  printk("ext_free_block: block full, skipping to %d\n", block);
  #endif
! 		if (sb->s_zmap[1])
! 			brelse (sb->s_zmap[1]);
  		if (!(sb->s_zmap[1] = bread (dev, block)))
  			panic ("ext_free_block: unable to read block to free\n");
  		efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
***************
*** 209,221 ****
  		free_super (inode->i_sb);
  		return;
  	}
! 	efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
! 		(((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
! 	if (efi->count == 14) {
  #ifdef EXTFS_DEBUG
  printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
  #endif
! 		brelse (inode->i_sb->s_imap[1]);
  		block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
  		if (!(bh = bread(inode->i_dev, block)))
  			panic("ext_free_inode: unable to read inode block\n");
--- 211,225 ----
  		free_super (inode->i_sb);
  		return;
  	}
! 	if (inode->i_sb->s_imap[1])
! 		efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
! 			(((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
! 	if (!inode->i_sb->s_imap[1] || efi->count == 14) {
  #ifdef EXTFS_DEBUG
  printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
  #endif
! 		if (inode->i_sb->s_imap[1])
! 			brelse (inode->i_sb->s_imap[1]);
  		block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
  		if (!(bh = bread(inode->i_dev, block)))
  			panic("ext_free_inode: unable to read inode block\n");
***************
*** 249,254 ****
--- 253,259 ----
  		iput(inode);
  		return NULL;
  	}
+ 	inode->i_flags = inode->i_sb->s_flags;
  	if (!inode->i_sb->s_imap[1])
  		return 0;
  	lock_super (inode->i_sb);
*** 0.96c/linux/fs/ext/namei.c	Fri Jul  3 16:28:36 1992
--- linux/fs/ext/namei.c	Sat Jul 11 12:35:28 1992
***************
*** 808,813 ****
--- 808,817 ----
  		retval = 0;
  		goto end_rename;
  	}
+ 	if (S_ISDIR(new_inode->i_mode)) {
+ 		retval = -EEXIST;
+ 		goto end_rename;
+ 	}
  	if (S_ISDIR(old_inode->i_mode)) {
  		retval = -EEXIST;
  		if (new_bh)
*** 0.96c/linux/fs/minix/bitmap.c	Thu Jul  2 00:44:28 1992
--- linux/fs/minix/bitmap.c	Sat Jul 11 05:03:11 1992
***************
*** 191,196 ****
--- 191,197 ----
  		iput(inode);
  		return NULL;
  	}
+ 	inode->i_flags = inode->i_sb->s_flags;
  	j = 8192;
  	for (i=0 ; i<8 ; i++)
  		if (bh=inode->i_sb->s_imap[i])
*** 0.96c/linux/fs/minix/file.c	Thu Jul  2 00:44:28 1992
--- linux/fs/minix/file.c	Sat Jul 11 00:49:33 1992
***************
*** 153,160 ****
  	} while (left > 0);
  	if (!read)
  		return -EIO;
! 	inode->i_atime = CURRENT_TIME;
! 	inode->i_dirt = 1;
  	return read;
  }
  
--- 153,162 ----
  	} while (left > 0);
  	if (!read)
  		return -EIO;
! 	if (!IS_RDONLY(inode)) {
! 		inode->i_atime = CURRENT_TIME;
! 		inode->i_dirt = 1;
! 	}
  	return read;
  }
  
*** 0.96c/linux/fs/minix/namei.c	Fri Jul  3 16:28:36 1992
--- linux/fs/minix/namei.c	Sat Jul 11 12:35:28 1992
***************
*** 676,681 ****
--- 676,685 ----
  		retval = 0;
  		goto end_rename;
  	}
+ 	if (S_ISDIR(new_inode->i_mode)) {
+ 		retval = -EEXIST;
+ 		goto end_rename;
+ 	}
  	if (S_ISDIR(old_inode->i_mode)) {
  		retval = -EEXIST;
  		if (new_bh)
*** 0.96c/linux/init/main.c	Sun Jul  5 00:57:47 1992
--- linux/init/main.c	Tue Jul  7 17:06:59 1992
***************
*** 53,58 ****
--- 53,59 ----
  
  extern int vsprintf();
  extern void init(void);
+ extern void init_IRQ(void);
  extern long blk_dev_init(long,long);
  extern long chr_dev_init(long,long);
  extern void hd_init(void);
***************
*** 164,169 ****
--- 165,171 ----
  		buffer_memory_end = 1*1024*1024;
  	main_memory_start = buffer_memory_end;
  	trap_init();
+ 	init_IRQ();
  	sched_init();
  	main_memory_start = chr_dev_init(main_memory_start,memory_end);
  	main_memory_start = blk_dev_init(main_memory_start,memory_end);
***************
*** 183,196 ****
  		init();
  	}
  /*
!  *   NOTE!!   For any other task 'pause()' would mean we have to get a
!  * signal to awaken, but task0 is the sole exception (see 'schedule()')
!  * as task 0 gets activated at every idle moment (when no other tasks
!  * can run). For task0 'pause()' just means we go check if some other
!  * task can run, and if not we return here.
   */
  	for(;;)
! 		__asm__("int $0x80"::"a" (__NR_pause):"ax");
  }
  
  static int printf(const char *fmt, ...)
--- 185,200 ----
  		init();
  	}
  /*
!  * task[0] is meant to be used as an "idle" task: it may not sleep, but
!  * it might do some general things like count free pages or it could be
!  * used to implement a reasonable LRU algorithm for the paging routines:
!  * anything that can be useful, but shouldn't take time from the real
!  * processes.
!  *
!  * Right now task[0] just does a infinite loop in user mode.
   */
  	for(;;)
! 		/* nothing */ ;
  }
  
  static int printf(const char *fmt, ...)
*** 0.96c/linux/kernel/Makefile	Sun Jul  5 03:09:42 1992
--- linux/kernel/Makefile	Sat Jul 11 20:12:09 1992
***************
*** 18,24 ****
  
  SUBDIRS	= chr_drv blk_drv math
  
! OBJS  = sched.o sys_call.o traps.o asm.o fork.o \
  	panic.o printk.o vsprintf.o sys.o exit.o \
  	signal.o mktime.o ptrace.o ioport.o itimer.o
  
--- 18,24 ----
  
  SUBDIRS	= chr_drv blk_drv math
  
! OBJS  = sched.o sys_call.o traps.o irq.o fork.o \
  	panic.o printk.o vsprintf.o sys.o exit.o \
  	signal.o mktime.o ptrace.o ioport.o itimer.o
  
***************
*** 73,78 ****
--- 73,85 ----
    /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
    /usr/src/linux/include/sys/param.h /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h \
    /usr/src/linux/include/sys/resource.h /usr/src/linux/include/errno.h 
+ irq.o : irq.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
+   /usr/src/linux/include/stddef.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/ptrace.h \
+   /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h \
+   /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
+   /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/sys/param.h \
+   /usr/src/linux/include/sys/time.h /usr/src/linux/include/time.h /usr/src/linux/include/sys/resource.h \
+   /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/irq.h 
  itimer.o : itimer.c /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
    /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
    /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
*** 0.96c/linux/kernel/sched.c	Sun Jul  5 01:27:18 1992
--- linux/kernel/sched.c	Tue Jul  7 18:53:54 1992
***************
*** 10,15 ****
--- 10,18 ----
   * call functions (type getpid(), which just extracts a field from
   * current-task
   */
+ 
+ #define TIMER_IRQ 0
+ 
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/kernel.h>
***************
*** 369,375 ****
  unsigned long timer_active = 0;
  struct timer_struct timer_table[32];
  
! void do_timer(long cpl)
  {
  	unsigned long mask;
  	struct timer_struct *tp = timer_table+0;
--- 372,378 ----
  unsigned long timer_active = 0;
  struct timer_struct timer_table[32];
  
! static void do_timer(int cpl)
  {
  	unsigned long mask;
  	struct timer_struct *tp = timer_table+0;
***************
*** 376,393 ****
  	struct task_struct ** task_p;
  	static int avg_cnt = 0;
  
! 	for (mask = 1 ; mask ; tp++,mask += mask) {
! 		if (mask > timer_active)
! 			break;
! 		if (!(mask & timer_active))
! 			continue;
! 		if (tp->expires > jiffies)
! 			continue;
! 		timer_active &= ~mask;
! 		tp->fn();
! 		sti();
  	}
! 
  	/* Update ITIMER_REAL for every task */
  	for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
  		if (*task_p && (*task_p)->it_real_value
--- 379,397 ----
  	struct task_struct ** task_p;
  	static int avg_cnt = 0;
  
! 	jiffies++;
! 	if (!cpl)
! 		current->stime++;
! 	else
! 		current->utime++;
! 	if (--avg_cnt < 0) {
! 		avg_cnt = 500;
! 		update_avg();
  	}
! 	if ((--current->counter)<=0) {
! 		current->counter=0;
! 		need_resched = 1;
! 	}
  	/* Update ITIMER_REAL for every task */
  	for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
  		if (*task_p && (*task_p)->it_real_value
***************
*** 402,417 ****
  		send_sig(SIGPROF,current,1);
  	}
  	/* Update ITIMER_VIRT for current task if not in a system call */
! 	if (cpl && current->it_virt_value && !(--current->it_virt_value)) {
  		current->it_virt_value = current->it_virt_incr;
  		send_sig(SIGVTALRM,current,1);
  	}
! 
! 	if (cpl)
! 		current->utime++;
! 	else
! 		current->stime++;
! 
  	if (next_timer) {
  		next_timer->jiffies--;
  		while (next_timer && next_timer->jiffies <= 0) {
--- 406,426 ----
  		send_sig(SIGPROF,current,1);
  	}
  	/* Update ITIMER_VIRT for current task if not in a system call */
! 	if (current->it_virt_value && !(--current->it_virt_value)) {
  		current->it_virt_value = current->it_virt_incr;
  		send_sig(SIGVTALRM,current,1);
  	}
! 	for (mask = 1 ; mask ; tp++,mask += mask) {
! 		if (mask > timer_active)
! 			break;
! 		if (!(mask & timer_active))
! 			continue;
! 		if (tp->expires > jiffies)
! 			continue;
! 		timer_active &= ~mask;
! 		tp->fn();
! 		sti();
! 	}
  	if (next_timer) {
  		next_timer->jiffies--;
  		while (next_timer && next_timer->jiffies <= 0) {
***************
*** 425,438 ****
  	}
  	if (current_DOR & 0xf0)
  		do_floppy_timer();
- 	if (--avg_cnt < 0) {
- 		avg_cnt = 500;
- 		update_avg();
- 	}
- 	if ((--current->counter)<=0) {
- 		current->counter=0;
- 		need_resched = 1;
- 	}
  }
  
  int sys_alarm(long seconds)
--- 434,439 ----
***************
*** 496,501 ****
--- 497,503 ----
  		panic("Struct sigaction MUST be 16 bytes");
  	set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
  	set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
+ 	set_system_gate(0x80,&system_call);
  	p = gdt+2+FIRST_TSS_ENTRY;
  	for(i=1 ; i<NR_TASKS ; i++) {
  		task[i] = NULL;
***************
*** 511,517 ****
  	outb_p(0x36,0x43);		/* binary, mode 3, LSB/MSB, ch 0 */
  	outb_p(LATCH & 0xff , 0x40);	/* LSB */
  	outb(LATCH >> 8 , 0x40);	/* MSB */
! 	set_intr_gate(0x20,&timer_interrupt);
! 	outb(inb_p(0x21)&~0x01,0x21);
! 	set_system_gate(0x80,&system_call);
  }
--- 513,517 ----
  	outb_p(0x36,0x43);		/* binary, mode 3, LSB/MSB, ch 0 */
  	outb_p(LATCH & 0xff , 0x40);	/* LSB */
  	outb(LATCH >> 8 , 0x40);	/* MSB */
! 	request_irq(TIMER_IRQ,do_timer);
  }
*** 0.96c/linux/kernel/traps.c	Thu May 21 12:53:42 1992
--- linux/kernel/traps.c	Fri Jul 10 16:34:12 1992
***************
*** 57,63 ****
  void page_fault(void);
  void coprocessor_error(void);
  void reserved(void);
- void parallel_interrupt(void);
  void irq13(void);
  void alignment_check(void);
  
--- 57,62 ----
***************
*** 116,122 ****
  
  void do_nmi(long esp, long error_code)
  {
! 	die("nmi",esp,error_code);
  }
  
  void do_debug(long esp, long error_code)
--- 115,121 ----
  
  void do_nmi(long esp, long error_code)
  {
! 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
  }
  
  void do_debug(long esp, long error_code)
***************
*** 201,207 ****
  	for (i=18;i<48;i++)
  		set_trap_gate(i,&reserved);
  	set_trap_gate(45,&irq13);
- 	outb_p(inb_p(0x21)&0xfb,0x21);
- 	outb(inb_p(0xA1)&0xdf,0xA1);
- 	set_trap_gate(39,&parallel_interrupt);
  }
--- 200,203 ----
*** 0.96c/linux/kernel/chr_drv/keyboard.c	Sun Jul  5 01:20:58 1992
--- linux/kernel/chr_drv/keyboard.c	Tue Jul  7 18:33:38 1992
***************
*** 58,64 ****
  static void kb_wait(void), kb_ack(void);
  static unsigned int handle_diacr(unsigned int);
  
! void do_keyboard(void)
  {
  	static unsigned char rep = 0xff, repke0 = 0;
  	unsigned char scancode, x;
--- 58,64 ----
  static void kb_wait(void), kb_ack(void);
  static unsigned int handle_diacr(unsigned int);
  
! void keyboard_interrupt(int cpl)
  {
  	static unsigned char rep = 0xff, repke0 = 0;
  	unsigned char scancode, x;
***************
*** 874,880 ****
  }
  		
  
! #if defined KBD_FR || defined KBD_US
  static unsigned char num_table[] = "789-456+1230.";
  #else
  static unsigned char num_table[] = "789-456+1230,";
--- 874,880 ----
  }
  		
  
! #if defined KBD_FR || defined KBD_US || defined KBD_UK
  static unsigned char num_table[] = "789-456+1230.";
  #else
  static unsigned char num_table[] = "789-456+1230,";
*** 0.96c/linux/kernel/chr_drv/console.c	Mon Jun 29 05:10:41 1992
--- linux/kernel/chr_drv/console.c	Sat Jul 11 12:41:53 1992
***************
*** 30,35 ****
--- 30,37 ----
   * <g-hunt@ee.utah.edu>
   */
  
+ #define KEYBOARD_IRQ 1
+ 
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/tty.h>
***************
*** 68,74 ****
  #define NPAR 16
  
  extern void vt_init(void);
! extern void keyboard_interrupt(void);
  extern void set_leds(void);
  extern unsigned char kapplic;
  extern unsigned char ckmode;
--- 70,76 ----
  #define NPAR 16
  
  extern void vt_init(void);
! extern void keyboard_interrupt(int cpl);
  extern void set_leds(void);
  extern unsigned char kapplic;
  extern unsigned char ckmode;
***************
*** 241,248 ****
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	" !\"#$%&'()*+,-./0123456789:;<=>?"
  	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
! 	"\004\261\007\007\007\007\370\361\007\007\275\267\326\323\327\304"
! 	"\304\304\304\304\307\266\320\322\272\363\362\343\007\234\007\0"
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
--- 243,250 ----
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	" !\"#$%&'()*+,-./0123456789:;<=>?"
  	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
! 	"\004\261\007\007\007\007\370\361\040\007\331\277\332\300\305\007"
! 	"\007\304\007\007\303\264\301\302\263\007\007\007\007\007\234\0"
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  	"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
***************
*** 250,260 ****
  	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  	"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
  	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
! 	"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230"
  };
  
  #define NORM_TRANS (translations[0])
  #define GRAF_TRANS (translations[1])
  
  static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  				       8,12,10,14, 9,13,11,15 };
--- 252,280 ----
  	"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  	"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
  	"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
! 	"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
! /* IBM grapgics: minimal translations (CR, LF, LL and ESC) */
! 	"\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
! 	"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
! 	"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
! 	"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
! 	"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
! 	"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
! 	"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
! 	"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
! 	"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
! 	"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
! 	"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
! 	"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
! 	"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
! 	"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
! 	"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
! 	"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
  };
  
  #define NORM_TRANS (translations[0])
  #define GRAF_TRANS (translations[1])
+ #define NULL_TRANS (translations[2])
  
  static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  				       8,12,10,14, 9,13,11,15 };
***************
*** 605,611 ****
  static void respond_string(char * p, int currcons, struct tty_struct * tty)
  {
  	while (*p) {
! 		PUTCH(*p,tty->read_q);
  		p++;
  	}
  	TTY_READ_FLUSH(tty);
--- 625,631 ----
  static void respond_string(char * p, int currcons, struct tty_struct * tty)
  {
  	while (*p) {
! 		put_tty_queue(*p,tty->read_q);
  		p++;
  	}
  	TTY_READ_FLUSH(tty);
***************
*** 621,627 ****
  		n /= 10;
  	} while(n && i < 3);	/* We'll take no chances */
  	while (i--) {
! 		PUTCH(buff[i],tty->read_q);
  	}
  	/* caller must flush */
  }
--- 641,647 ----
  		n /= 10;
  	} while(n && i < 3);	/* We'll take no chances */
  	while (i--) {
! 		put_tty_queue(buff[i],tty->read_q);
  	}
  	/* caller must flush */
  }
***************
*** 628,639 ****
  
  static void cursor_report(int currcons, struct tty_struct * tty)
  {
! 	PUTCH('\033', tty->read_q);
! 	PUTCH('[', tty->read_q);
  	respond_num(y + (decom ? top+1 : 1), currcons, tty);
! 	PUTCH(';', tty->read_q);
  	respond_num(x+1, currcons, tty);
! 	PUTCH('R', tty->read_q);
  	TTY_READ_FLUSH(tty);
  }
  
--- 648,659 ----
  
  static void cursor_report(int currcons, struct tty_struct * tty)
  {
! 	put_tty_queue('\033', tty->read_q);
! 	put_tty_queue('[', tty->read_q);
  	respond_num(y + (decom ? top+1 : 1), currcons, tty);
! 	put_tty_queue(';', tty->read_q);
  	respond_num(x+1, currcons, tty);
! 	put_tty_queue('R', tty->read_q);
  	TTY_READ_FLUSH(tty);
  }
  
***************
*** 905,911 ****
  		printk("con_write: illegal tty\n\r");
  		return;
  	}
! 	while (!tty->stopped &&	(c = GETCH(tty->write_q)) >= 0) {
  		if (state == ESnormal && translate[c]) {
  			if (need_wrap) {
  				cr(currcons);
--- 925,931 ----
  		printk("con_write: illegal tty\n\r");
  		return;
  	}
! 	while (!tty->stopped &&	(c = get_tty_queue(tty->write_q)) >= 0) {
  		if (state == ESnormal && translate[c]) {
  			if (need_wrap) {
  				cr(currcons);
***************
*** 1176,1181 ****
--- 1196,1203 ----
  					G0_charset = GRAF_TRANS;
  				else if (c == 'B')
  					G0_charset = NORM_TRANS;
+ 				else if (c == 'U')
+ 					G0_charset = NULL_TRANS;
  				if (charset == 0)
  					translate = G0_charset;
  				state = ESnormal;
***************
*** 1185,1190 ****
--- 1207,1214 ----
  					G1_charset = GRAF_TRANS;
  				else if (c == 'B')
  					G1_charset = NORM_TRANS;
+ 				else if (c == 'U')
+ 					G1_charset = NULL_TRANS;
  				if (charset == 1)
  					translate = G1_charset;
  				state = ESnormal;
***************
*** 1338,1345 ****
  	gotoxy(currcons,orig_x,orig_y);
  	update_screen(fg_console);
  
! 	set_trap_gate(0x21,&keyboard_interrupt);
! 	outb_p(inb_p(0x21)&0xfd,0x21);
  	a=inb_p(0x61);
  	outb_p(a|0x80,0x61);
  	outb_p(a,0x61);
--- 1362,1369 ----
  	gotoxy(currcons,orig_x,orig_y);
  	update_screen(fg_console);
  
! 	if (request_irq(KEYBOARD_IRQ,keyboard_interrupt))
! 		printk("Unable to get IRQ%d for keyboard driver\n",KEYBOARD_IRQ);
  	a=inb_p(0x61);
  	outb_p(a|0x80,0x61);
  	outb_p(a,0x61);
*** 0.96c/linux/kernel/chr_drv/tty_ioctl.c	Fri Jul  3 04:26:08 1992
--- linux/kernel/chr_drv/tty_ioctl.c	Wed Jul  8 17:12:50 1992
***************
*** 65,71 ****
  	}
  }
  
! static void wait_until_sent(struct tty_struct * tty)
  {
  	while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
  		TTY_WRITE_FLUSH(tty);
--- 65,71 ----
  	}
  }
  
! void wait_until_sent(struct tty_struct * tty)
  {
  	while (!(current->signal & ~current->blocked) && !EMPTY(tty->write_q)) {
  		TTY_WRITE_FLUSH(tty);
***************
*** 122,127 ****
--- 122,128 ----
  			int channel)
  {
  	int i;
+ 	unsigned short old_cflag = tty->termios.c_cflag;
  
  	/* If we try to set the state of terminal and we're not in the
  	   foreground, send a SIGTTOU.  If the signal is blocked or
***************
*** 135,141 ****
  	}
  	for (i=0 ; i< (sizeof (*termios)) ; i++)
  		((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
! 	if (IS_A_SERIAL(channel))
  		change_speed(channel-64);
  	return 0;
  }
--- 136,142 ----
  	}
  	for (i=0 ; i< (sizeof (*termios)) ; i++)
  		((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
! 	if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
  		change_speed(channel-64);
  	return 0;
  }
***************
*** 166,171 ****
--- 167,173 ----
  {
  	int i;
  	struct termio tmp_termio;
+ 	unsigned short old_cflag = tty->termios.c_cflag;
  
  	if ((current->tty == channel) &&
  	    (tty->pgrp > 0) &&
***************
*** 184,190 ****
  	tty->termios.c_line = tmp_termio.c_line;
  	for(i=0 ; i < NCC ; i++)
  		tty->termios.c_cc[i] = tmp_termio.c_cc[i];
! 	if (IS_A_SERIAL(channel))
  		change_speed(channel-64);
  	return 0;
  }
--- 186,192 ----
  	tty->termios.c_line = tmp_termio.c_line;
  	for(i=0 ; i < NCC ; i++)
  		tty->termios.c_cc[i] = tmp_termio.c_cc[i];
! 	if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
  		change_speed(channel-64);
  	return 0;
  }
***************
*** 232,243 ****
  	int pgrp;
  	int dev;
  
! 	if (MAJOR(inode->i_rdev) == 5) {
! 		dev = current->tty;
! 		if (dev<0)
! 			return -EINVAL;
! 	} else
! 		dev = MINOR(inode->i_rdev);
  	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
  
  	if (IS_A_PTY(dev))
--- 234,244 ----
  	int pgrp;
  	int dev;
  
! 	if (MAJOR(file->f_rdev) != 4) {
! 		printk("tty_ioctl: tty pseudo-major != 4\n");
! 		return -EINVAL;
! 	}
! 	dev = MINOR(file->f_rdev);
  	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
  
  	if (IS_A_PTY(dev))
***************
*** 286,296 ****
  				return 0;
  			case TCIOFF:
  				if (STOP_CHAR(tty))
! 					PUTCH(STOP_CHAR(tty),tty->write_q);
  				return 0;
  			case TCION:
  				if (START_CHAR(tty))
! 					PUTCH(START_CHAR(tty),tty->write_q);
  				return 0;
  			}
  			return -EINVAL; /* not implemented */
--- 287,297 ----
  				return 0;
  			case TCIOFF:
  				if (STOP_CHAR(tty))
! 					put_tty_queue(STOP_CHAR(tty),tty->write_q);
  				return 0;
  			case TCION:
  				if (START_CHAR(tty))
! 					put_tty_queue(START_CHAR(tty),tty->write_q);
  				return 0;
  			}
  			return -EINVAL; /* not implemented */
*** 0.96c/linux/kernel/chr_drv/tty_io.c	Sat Jul  4 03:21:41 1992
--- linux/kernel/chr_drv/tty_io.c	Wed Jul  8 18:00:50 1992
***************
*** 154,160 ****
  	while (1) {
  		if (FULL(tty->secondary))
  			break;
! 		c = GETCH(tty->read_q);
  		if (c < 0)
  			break;
  		if (I_STRP(tty))
--- 154,160 ----
  	while (1) {
  		if (FULL(tty->secondary))
  			break;
! 		c = get_tty_queue(tty->read_q);
  		if (c < 0)
  			break;
  		if (I_STRP(tty))
***************
*** 178,190 ****
  					 (c==EOF_CHAR(tty))))) {
  					if (L_ECHO(tty)) {
  						if (c<32) {
! 							PUTCH(8,tty->write_q);
! 							PUTCH(' ',tty->write_q);
! 							PUTCH(8,tty->write_q);
  						}
! 						PUTCH(8,tty->write_q);
! 						PUTCH(' ',tty->write_q);
! 						PUTCH(8,tty->write_q);
  						TTY_WRITE_FLUSH(tty);
  					}
  					DEC(tty->secondary->head);
--- 178,190 ----
  					 (c==EOF_CHAR(tty))))) {
  					if (L_ECHO(tty)) {
  						if (c<32) {
! 							put_tty_queue(8,tty->write_q);
! 							put_tty_queue(' ',tty->write_q);
! 							put_tty_queue(8,tty->write_q);
  						}
! 						put_tty_queue(8,tty->write_q);
! 						put_tty_queue(' ',tty->write_q);
! 						put_tty_queue(8,tty->write_q);
  						TTY_WRITE_FLUSH(tty);
  					}
  					DEC(tty->secondary->head);
***************
*** 200,212 ****
  					continue;
  				if (L_ECHO(tty)) {
  					if (c<32) {
! 						PUTCH(8,tty->write_q);
! 						PUTCH(' ',tty->write_q);
! 						PUTCH(8,tty->write_q);
  					}
! 					PUTCH(8,tty->write_q);
! 					PUTCH(32,tty->write_q);
! 					PUTCH(8,tty->write_q);
  					TTY_WRITE_FLUSH(tty);
  				}
  				DEC(tty->secondary->head);
--- 200,212 ----
  					continue;
  				if (L_ECHO(tty)) {
  					if (c<32) {
! 						put_tty_queue(8,tty->write_q);
! 						put_tty_queue(' ',tty->write_q);
! 						put_tty_queue(8,tty->write_q);
  					}
! 					put_tty_queue(8,tty->write_q);
! 					put_tty_queue(32,tty->write_q);
! 					put_tty_queue(8,tty->write_q);
  					TTY_WRITE_FLUSH(tty);
  				}
  				DEC(tty->secondary->head);
***************
*** 250,265 ****
  		    c==EOF_CHAR(tty)))
  			tty->secondary->data++;
  		if ((L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty))) && (c==10)) {
! 			PUTCH(10,tty->write_q);
! 			PUTCH(13,tty->write_q);
  		} else if (L_ECHO(tty)) {
  			if (c<32 && L_ECHOCTL(tty)) {
! 				PUTCH('^',tty->write_q);
! 				PUTCH(c+64,tty->write_q);
  			} else
! 				PUTCH(c,tty->write_q);
  		}
! 		PUTCH(c,tty->secondary);
  		TTY_WRITE_FLUSH(tty);
  	}
  	TTY_WRITE_FLUSH(tty);
--- 250,265 ----
  		    c==EOF_CHAR(tty)))
  			tty->secondary->data++;
  		if ((L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty))) && (c==10)) {
! 			put_tty_queue(10,tty->write_q);
! 			put_tty_queue(13,tty->write_q);
  		} else if (L_ECHO(tty)) {
  			if (c<32 && L_ECHOCTL(tty)) {
! 				put_tty_queue('^',tty->write_q);
! 				put_tty_queue(c+64,tty->write_q);
  			} else
! 				put_tty_queue(c,tty->write_q);
  		}
! 		put_tty_queue(c,tty->secondary);
  		TTY_WRITE_FLUSH(tty);
  	}
  	TTY_WRITE_FLUSH(tty);
***************
*** 299,305 ****
  static int read_chan(unsigned int channel, struct file * file, char * buf, int nr)
  {
  	struct tty_struct * tty;
- 	struct tty_struct * other_tty = NULL;
  	int c;
  	char * b=buf;
  	int minimum,time;
--- 299,304 ----
***************
*** 316,323 ****
  			return -EIO;
  		else
  			return(tty_signal(SIGTTIN, tty));
- 	if (channel & 0x80)
- 		other_tty = tty_table + (channel ^ 0x40);
  	time = 10L*tty->termios.c_cc[VTIME];
  	minimum = tty->termios.c_cc[VMIN];
  	if (L_CANON(tty)) {
--- 315,320 ----
***************
*** 338,345 ****
  		minimum = nr;
  	TTY_READ_FLUSH(tty);
  	while (nr>0) {
! 		if (other_tty && other_tty->write)
! 			TTY_WRITE_FLUSH(other_tty);
  		cli();
  		if (EMPTY(tty->secondary) || (L_CANON(tty) &&
  		    !FULL(tty->read_q) && !tty->secondary->data)) {
--- 335,342 ----
  		minimum = nr;
  	TTY_READ_FLUSH(tty);
  	while (nr>0) {
! 		if (tty->link && tty->link->write)
! 			TTY_WRITE_FLUSH(tty->link);
  		cli();
  		if (EMPTY(tty->secondary) || (L_CANON(tty) &&
  		    !FULL(tty->read_q) && !tty->secondary->data)) {
***************
*** 347,356 ****
  				break;
  			if (current->signal & ~current->blocked) 
  				break;
! 			if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
  				break;
- 			if (other_tty && !other_tty->count)
- 				break;
  			interruptible_sleep_on(&tty->secondary->proc_list);
  			sti();
  			TTY_READ_FLUSH(tty);
--- 344,351 ----
  				break;
  			if (current->signal & ~current->blocked) 
  				break;
! 			if (tty->link && !tty->link->count)
  				break;
  			interruptible_sleep_on(&tty->secondary->proc_list);
  			sti();
  			TTY_READ_FLUSH(tty);
***************
*** 358,364 ****
  		}
  		sti();
  		do {
! 			c = GETCH(tty->secondary);
  			if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
  			     c==EOF_CHAR(tty)) || c==10)
  				tty->secondary->data--;
--- 353,359 ----
  		}
  		sti();
  		do {
! 			c = get_tty_queue(tty->secondary);
  			if ((EOF_CHAR(tty) != __DISABLED_CHAR &&
  			     c==EOF_CHAR(tty)) || c==10)
  				tty->secondary->data--;
***************
*** 381,388 ****
  	}
  	sti();
  	TTY_READ_FLUSH(tty);
! 	if (other_tty && other_tty->write)
! 		TTY_WRITE_FLUSH(other_tty);
  	current->timeout = 0;
  	if (b-buf)
  		return b-buf;
--- 376,383 ----
  	}
  	sti();
  	TTY_READ_FLUSH(tty);
! 	if (tty->link && tty->link->write)
! 		TTY_WRITE_FLUSH(tty->link);
  	current->timeout = 0;
  	if (b-buf)
  		return b-buf;
***************
*** 419,424 ****
--- 414,423 ----
  	while (nr>0) {
  		if (current->signal & ~current->blocked)
  			break;
+ 		if (tty->link && !tty->link->count) {
+ 			send_sig(SIGPIPE,current,0);
+ 			break;
+ 		}
  		if (FULL(tty->write_q)) {
  			TTY_WRITE_FLUSH(tty);
  			cli();
***************
*** 436,442 ****
  					c='\r';
  				if (c=='\n' && !(tty->flags & TTY_CR_PENDING) && O_NLCR(tty)) {
  					tty->flags |= TTY_CR_PENDING;
! 					PUTCH(13,tty->write_q);
  					continue;
  				}
  				if (O_LCUC(tty))
--- 435,441 ----
  					c='\r';
  				if (c=='\n' && !(tty->flags & TTY_CR_PENDING) && O_NLCR(tty)) {
  					tty->flags |= TTY_CR_PENDING;
! 					put_tty_queue(13,tty->write_q);
  					continue;
  				}
  				if (O_LCUC(tty))
***************
*** 444,450 ****
  			}
  			b++; nr--;
  			tty->flags &= ~TTY_CR_PENDING;
! 			PUTCH(c,tty->write_q);
  		}
  		if (nr>0)
  			schedule();
--- 443,449 ----
  			}
  			b++; nr--;
  			tty->flags &= ~TTY_CR_PENDING;
! 			put_tty_queue(c,tty->write_q);
  		}
  		if (nr>0)
  			schedule();
***************
*** 452,457 ****
--- 451,458 ----
  	TTY_WRITE_FLUSH(tty);
  	if (b-buf)
  		return b-buf;
+ 	if (tty->link && !tty->link->count)
+ 		return -EPIPE;
  	if (current->signal & ~current->blocked)
  		return -ERESTARTSYS;
  	return 0;
***************
*** 460,477 ****
  static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
  {
  	int i;
- 	
- 	i = read_chan(current->tty,file,buf,count);
- 	if (i > 0)
- 		inode->i_atime = CURRENT_TIME;
- 	return i;
- }
  
! static int ttyx_read(struct inode * inode, struct file * file, char * buf, int count)
! {
! 	int i;
! 	
! 	i = read_chan(MINOR(inode->i_rdev),file,buf,count);
  	if (i > 0)
  		inode->i_atime = CURRENT_TIME;
  	return i;
--- 461,472 ----
  static int tty_read(struct inode * inode, struct file * file, char * buf, int count)
  {
  	int i;
  
! 	if (MAJOR(file->f_rdev) != 4) {
! 		printk("tty_read: pseudo-major != 4\n");
! 		return -EINVAL;
! 	}
! 	i = read_chan(MINOR(file->f_rdev),file,buf,count);
  	if (i > 0)
  		inode->i_atime = CURRENT_TIME;
  	return i;
***************
*** 481,502 ****
  {
  	int i;
  	
! 	i = write_chan(current->tty,file,buf,count);
  	if (i > 0)
  		inode->i_mtime = CURRENT_TIME;
  	return i;
  }
  
- static int ttyx_write(struct inode * inode, struct file * file, char * buf, int count)
- {
- 	int i;
- 	
- 	i = write_chan(MINOR(inode->i_rdev),file,buf,count);
- 	if (i > 0)
- 		inode->i_mtime = CURRENT_TIME;
- 	return i;
- }
- 
  static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
  {
  	return -EBADF;
--- 476,491 ----
  {
  	int i;
  	
! 	if (MAJOR(file->f_rdev) != 4) {
! 		printk("tty_write: pseudo-major != 4\n");
! 		return -EINVAL;
! 	}
! 	i = write_chan(MINOR(file->f_rdev),file,buf,count);
  	if (i > 0)
  		inode->i_mtime = CURRENT_TIME;
  	return i;
  }
  
  static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
  {
  	return -EBADF;
***************
*** 522,536 ****
  		dev = MINOR(dev);
  	if (dev < 0)
  		return -ENODEV;
  	tty = TTY_TABLE(dev);
  	if (IS_A_PTY_MASTER(dev)) {
  		if (tty->count)
  			return -EAGAIN;
  	}
- 	if (!tty->count && (!tty->link || !tty->link->count)) {
- 		flush_input(tty);
- 		flush_output(tty);
- 	}
  	tty->count++;
  	retval = 0;
  	if (!(filp->f_flags & O_NOCTTY) &&
--- 511,528 ----
  		dev = MINOR(dev);
  	if (dev < 0)
  		return -ENODEV;
+ 	filp->f_rdev = 0x0400 | dev;
  	tty = TTY_TABLE(dev);
+ 	if (!tty->count && !(tty->link && tty->link->count)) {
+ 		flush_input(tty);
+ 		flush_output(tty);
+ 	}
  	if (IS_A_PTY_MASTER(dev)) {
  		if (tty->count)
  			return -EAGAIN;
+ 		if (tty->link)
+ 			tty->link->count++;
  	}
  	tty->count++;
  	retval = 0;
  	if (!(filp->f_flags & O_NOCTTY) &&
***************
*** 541,576 ****
  		tty->session = current->session;
  		tty->pgrp = current->pgrp;
  	}
! 	if (IS_A_SERIAL(dev))
  		retval = serial_open(dev-64,filp);
  	else if (IS_A_PTY(dev))
  		retval = pty_open(dev,filp);
! 	if (retval)
  		tty->count--;
  	return retval;
  }
  
  static void tty_release(struct inode * inode, struct file * filp)
  {
  	int dev;
  	struct tty_struct * tty;
  
! 	dev = inode->i_rdev;
! 	if (MAJOR(dev) == 5)
! 		dev = current->tty;
! 	else
! 		dev = MINOR(dev);
! 	if (dev < 0)
  		return;
  	tty = TTY_TABLE(dev);
! 	if (--tty->count)
  		return;
! 	if (tty == redirect)
! 		redirect = NULL;
! 	if (IS_A_SERIAL(dev))
  		serial_close(dev-64,filp);
! 	else if (IS_A_PTY(dev))
  		pty_close(dev,filp);
  }
  
  static struct file_operations tty_fops = {
--- 533,582 ----
  		tty->session = current->session;
  		tty->pgrp = current->pgrp;
  	}
! 	if (IS_A_SERIAL(dev) && tty->count < 2)
  		retval = serial_open(dev-64,filp);
  	else if (IS_A_PTY(dev))
  		retval = pty_open(dev,filp);
! 	if (retval) {
  		tty->count--;
+ 		if (IS_A_PTY_MASTER(dev) && tty->link)
+ 			tty->link->count++;
+ 	}
  	return retval;
  }
  
+ /*
+  * Note that releasing a pty master also releases the child, so
+  * we have to make the redirection checks after that and on both
+  * sides of a pty.
+  */
  static void tty_release(struct inode * inode, struct file * filp)
  {
  	int dev;
  	struct tty_struct * tty;
  
! 	dev = filp->f_rdev;
! 	if (MAJOR(dev) != 4) {
! 		printk("tty_close: tty pseudo-major != 4\n");
  		return;
+ 	}
+ 	dev = MINOR(filp->f_rdev);
  	tty = TTY_TABLE(dev);
! 	if (IS_A_PTY_MASTER(dev) && tty->link)
! 		tty->link->count--;
! 	tty->count--;
! 	if (tty->count)
  		return;
! 	if (IS_A_SERIAL(dev)) {
! 		wait_until_sent(tty);
  		serial_close(dev-64,filp);
! 	} else if (IS_A_PTY(dev))
  		pty_close(dev,filp);
+ 	if (!tty->count && (tty == redirect))
+ 		redirect = NULL;
+ 	if (tty = tty->link)
+ 		if (!tty->count && (tty == redirect))
+ 			redirect = NULL;
  }
  
  static struct file_operations tty_fops = {
***************
*** 584,600 ****
  	tty_release
  };
  
- static struct file_operations ttyx_fops = {
- 	tty_lseek,
- 	ttyx_read,
- 	ttyx_write,
- 	NULL,		/* ttyx_readdir */
- 	NULL,		/* ttyx_select */
- 	tty_ioctl,	/* ttyx_ioctl */
- 	tty_open,
- 	tty_release
- };
- 
  long tty_init(long kmem_start)
  {
  	int i;
--- 590,595 ----
***************
*** 603,609 ****
  	kmem_start += QUEUES * (sizeof (struct tty_queue));
  	table_list[0] = con_queues + 0;
  	table_list[1] = con_queues + 1;
! 	chrdev_fops[4] = &ttyx_fops;
  	chrdev_fops[5] = &tty_fops;
  	for (i=0 ; i < QUEUES ; i++)
  		tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
--- 598,604 ----
  	kmem_start += QUEUES * (sizeof (struct tty_queue));
  	table_list[0] = con_queues + 0;
  	table_list[1] = con_queues + 1;
! 	chrdev_fops[4] = &tty_fops;
  	chrdev_fops[5] = &tty_fops;
  	for (i=0 ; i < QUEUES ; i++)
  		tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
*** 0.96c/linux/kernel/chr_drv/serial.c	Thu Jun 25 18:22:24 1992
--- linux/kernel/chr_drv/serial.c	Tue Jul  7 18:32:46 1992
***************
*** 26,41 ****
  
  #define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
  
- /*
-  * note that IRQ9 is what many docs call IRQ2 - on the AT hardware
-  * the old IRQ2 line has been changed to IRQ9. The serial_table
-  * structure considers IRQ2 to be the same as IRQ9.
-  */
- extern void IRQ9_interrupt(void);
- extern void IRQ3_interrupt(void);
- extern void IRQ4_interrupt(void);
- extern void IRQ5_interrupt(void);
- 
  struct serial_struct serial_table[NR_SERIALS] = {
  	{ PORT_UNKNOWN, 0, 0x3F8, 4, NULL},
  	{ PORT_UNKNOWN, 1, 0x2F8, 3, NULL},
--- 26,31 ----
***************
*** 43,62 ****
  	{ PORT_UNKNOWN, 3, 0x2E8, 3, NULL},
  };
  
- static struct serial_struct * irq_info[16] = { NULL, };
- 
  static void modem_status_intr(struct serial_struct * info)
  {
  	unsigned char status = inb(info->port+6);
  
! 	if ((status & 0x88) == 0x08 && info->tty->pgrp > 0)
! 		kill_pg(info->tty->pgrp,SIGHUP,1);
  #if 0
! 	if ((status & 0x10) == 0x10)
! 		info->tty->stopped = 0;
! 	else
! 		info->tty->stopped = 1;
  #endif
  }
  
  void send_break(unsigned int line)
--- 33,52 ----
  	{ PORT_UNKNOWN, 3, 0x2E8, 3, NULL},
  };
  
  static void modem_status_intr(struct serial_struct * info)
  {
  	unsigned char status = inb(info->port+6);
  
! 	if (!(info->tty->termios.c_cflag & CLOCAL)) {
! 		if ((status & 0x88) == 0x08 && info->tty->pgrp > 0)
! 			kill_pg(info->tty->pgrp,SIGHUP,1);
  #if 0
! 		if ((status & 0x10) == 0x10)
! 			info->tty->stopped = 0;
! 		else
! 			info->tty->stopped = 1;
  #endif
+ 	}
  }
  
  void send_break(unsigned int line)
***************
*** 94,108 ****
  	int c, i = 0;
  
  	timer_active &= ~(1 << timer);
! 	do {
! 		if ((c = GETCH(queue)) < 0)
! 			return;
  		outb(c,port);
! 		i++;
! 	} while (info->type == PORT_16550A &&
! 		  i < 14 && !EMPTY(queue));
  	timer_table[timer].expires = jiffies + 10;
  	timer_active |= 1 << timer;
  	if (LEFT(queue) > WAKEUP_CHARS)
  		wake_up(&queue->proc_list);
  }
--- 84,102 ----
  	int c, i = 0;
  
  	timer_active &= ~(1 << timer);
! 	while (inb_p(info->port+5) & 0x20) {
! 		if (queue->tail == queue->head)
! 			goto end_send;
! 		c = queue->buf[queue->tail];
! 		queue->tail++;
! 		queue->tail &= TTY_BUF_SIZE-1;
  		outb(c,port);
! 		if ((info->type != PORT_16550A) || (++i >= 14))
! 			break;
! 	}
  	timer_table[timer].expires = jiffies + 10;
  	timer_active |= 1 << timer;
+ end_send:
  	if (LEFT(queue) > WAKEUP_CHARS)
  		wake_up(&queue->proc_list);
  }
***************
*** 111,120 ****
  {
  	unsigned short port = info->port;
  	struct tty_queue * queue = info->tty->read_q;
  
  	do {
! 		PUTCH(inb(port),queue);
  	} while (inb(port+5) & 1);
  	timer_active |= (1<<SER1_TIMER)<<info->line;
  }
  
--- 105,122 ----
  {
  	unsigned short port = info->port;
  	struct tty_queue * queue = info->tty->read_q;
+ 	int head = queue->head;
+ 	int maxhead = (queue->tail-1) & (TTY_BUF_SIZE-1);
  
+ 	timer_active &= ~((1<<SER1_TIMER)<<info->line);
  	do {
! 		queue->buf[head] = inb(port);
! 		if (head != maxhead) {
! 			head++;
! 			head &= TTY_BUF_SIZE-1;
! 		}
  	} while (inb(port+5) & 1);
+ 	queue->head = head;
  	timer_active |= (1<<SER1_TIMER)<<info->line;
  }
  
***************
*** 149,159 ****
  	}
  }
  
! void do_IRQ(int irq)
  {
! 	check_tty(irq_info[irq]);
  }
  
  static void com1_timer(void)
  {
  	TTY_READ_FLUSH(tty_table+64);
--- 151,197 ----
  	}
  }
  
! /*
!  * Again, we disable interrupts to be sure there aren't any races:
!  * see send_intr for details.
!  */
! static inline void do_rs_write(struct serial_struct * info)
  {
! 	if (!info->tty || !info->port)
! 		return;
! 	if (!info->tty->write_q || EMPTY(info->tty->write_q))
! 		return;
! 	cli();
! 	send_intr(info);
! 	sti();
  }
  
+ /*
+  * IRQ routines: one per line
+  */
+ static void com1_IRQ(int cpl)
+ {
+ 	check_tty(serial_table+0);
+ }
+ 
+ static void com2_IRQ(int cpl)
+ {
+ 	check_tty(serial_table+1);
+ }
+ 
+ static void com3_IRQ(int cpl)
+ {
+ 	check_tty(serial_table+2);
+ }
+ 
+ static void com4_IRQ(int cpl)
+ {
+ 	check_tty(serial_table+3);
+ }
+ 
+ /*
+  * Receive timer routines: one per line
+  */
  static void com1_timer(void)
  {
  	TTY_READ_FLUSH(tty_table+64);
***************
*** 175,201 ****
  }
  
  /*
!  * Again, we disable interrupts to be sure there aren't any races:
!  * see send_intr for details.
   */
- static inline void do_rs_write(struct serial_struct * info)
- {
- 	if (!info->tty || !info->port)
- 		return;
- 	if (!info->tty->write_q || EMPTY(info->tty->write_q))
- 		return;
- 	cli();
- 	if (inb_p(info->port+5) & 0x20)
- 		send_intr(info);
- 	else {
- 		unsigned int timer = SER1_TIMEOUT+info->line;
- 
- 		timer_table[timer].expires = jiffies + 10;
- 		timer_active |= 1 << timer;
- 	}
- 	sti();
- }
- 
  static void com1_timeout(void)
  {
  	do_rs_write(serial_table);
--- 213,220 ----
  }
  
  /*
!  * Send timeout routines: one per line
   */
  static void com1_timeout(void)
  {
  	do_rs_write(serial_table);
***************
*** 276,288 ****
  	irq = info->irq;
  	if (irq == 2)
  		irq = 9;
! 	if (irq_info[irq] == info) {
! 		irq_info[irq] = NULL;
! 		if (irq < 8)
! 			outb(inb_p(0x21) | (1<<irq),0x21);
! 		else
! 			outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
! 	}
  }
  
  static void startup(unsigned short port)
--- 295,301 ----
  	irq = info->irq;
  	if (irq == 2)
  		irq = 9;
! 	free_irq(irq);
  }
  
  static void startup(unsigned short port)
***************
*** 300,306 ****
  {
  	struct serial_struct * info;
  	unsigned short port,quot;
! 	unsigned cflag;
  	static unsigned short quotient[] = {
  		0, 2304, 1536, 1047, 857,
  		768, 576, 384, 192, 96,
--- 313,319 ----
  {
  	struct serial_struct * info;
  	unsigned short port,quot;
! 	unsigned cflag,cval;
  	static unsigned short quotient[] = {
  		0, 2304, 1536, 1047, 857,
  		768, 576, 384, 192, 96,
***************
*** 318,339 ****
  		outb(0x00,port+4);
  	else if (!inb(port+4))
  		startup(port);
  	cli();
! 	outb_p(0x80,port+3);		/* set DLAB */
  	outb_p(quot & 0xff,port);	/* LS of divisor */
  	outb_p(quot >> 8,port+1);	/* MS of divisor */
! 	outb(0x03,port+3);		/* reset DLAB */
  	sti();
- /* set byte size and parity */
- 	quot = cflag & (CSIZE | CSTOPB);
- 	quot >>= 4;
- 	if (cflag & PARENB)
- 		quot |= 8;
- 	if (!(cflag & PARODD))
- 		quot |= 16;
- 	outb(quot,port+3);
  }
  
  /*
   * this routine enables interrupts on 'line', and disables them for any
   * other serial line that shared the same IRQ. Braindamaged AT hardware.
--- 331,355 ----
  		outb(0x00,port+4);
  	else if (!inb(port+4))
  		startup(port);
+ /* byte size and parity */
+ 	cval = cflag & (CSIZE | CSTOPB);
+ 	cval >>= 4;
+ 	if (cflag & PARENB)
+ 		cval |= 8;
+ 	if (!(cflag & PARODD))
+ 		cval |= 16;
  	cli();
! 	outb_p(cval | 0x80,port+3);	/* set DLAB */
  	outb_p(quot & 0xff,port);	/* LS of divisor */
  	outb_p(quot >> 8,port+1);	/* MS of divisor */
! 	outb(cval,port+3);		/* reset DLAB */
  	sti();
  }
  
+ static void (*serial_handler[NR_SERIALS])(int) = {
+ 	com1_IRQ,com2_IRQ,com3_IRQ,com4_IRQ
+ };
+ 
  /*
   * this routine enables interrupts on 'line', and disables them for any
   * other serial line that shared the same IRQ. Braindamaged AT hardware.
***************
*** 341,348 ****
  int serial_open(unsigned line, struct file * filp)
  {
  	struct serial_struct * info;
! 	int irq;
  	unsigned short port;
  
  	if (line >= NR_SERIALS)
  		return -ENODEV;
--- 357,365 ----
  int serial_open(unsigned line, struct file * filp)
  {
  	struct serial_struct * info;
! 	int irq,retval;
  	unsigned short port;
+ 	void (*handler)(int) = serial_handler[line];
  
  	if (line >= NR_SERIALS)
  		return -ENODEV;
***************
*** 352,367 ****
  	irq = info->irq;
  	if (irq == 2)
  		irq = 9;
! 	if (irq_info[irq] && irq_info[irq] != info)
! 		return -EBUSY;
! 	cli();
  	startup(port);
- 	irq_info[irq] = info;
- 	if (irq < 8)
- 		outb(inb_p(0x21) & ~(1<<irq),0x21);
- 	else
- 		outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
- 	sti();
  	return 0;
  }
  
--- 369,377 ----
  	irq = info->irq;
  	if (irq == 2)
  		irq = 9;
! 	if (retval = request_irq(irq,handler))
! 		return retval;
  	startup(port);
  	return 0;
  }
  
***************
*** 380,385 ****
--- 390,397 ----
  	struct serial_struct tmp;
  	unsigned new_port;
  	unsigned irq,new_irq;
+ 	int retval;
+ 	void (*handler)(int) = serial_handler[line];
  
  	if (!suser())
  		return -EPERM;
***************
*** 401,420 ****
  	if (irq == 2)
  		irq = 9;
  	if (irq != new_irq) {
! 		if (irq_info[new_irq])
! 			return -EBUSY;
! 		cli();
! 		irq_info[new_irq] = irq_info[irq];
! 		irq_info[irq] = NULL;
! 		info->irq = new_irq;
! 		if (irq < 8)
! 			outb(inb_p(0x21) | (1<<irq),0x21);
! 		else
! 			outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
! 		if (new_irq < 8)
! 			outb(inb_p(0x21) & ~(1<<new_irq),0x21);
! 		else
! 			outb(inb_p(0xA1) & ~(1<<(new_irq-8)),0xA1);
  	}
  	cli();
  	if (new_port != info->port) {
--- 413,422 ----
  	if (irq == 2)
  		irq = 9;
  	if (irq != new_irq) {
! 		retval = request_irq(new_irq,handler);
! 		if (retval)
! 			return retval;
! 		free_irq(irq);
  	}
  	cli();
  	if (new_port != info->port) {
***************
*** 450,459 ****
  	timer_table[SER3_TIMEOUT].expires = 0;
  	timer_table[SER4_TIMEOUT].fn = com4_timeout;
  	timer_table[SER4_TIMEOUT].expires = 0;
- 	set_intr_gate(0x23,IRQ3_interrupt);
- 	set_intr_gate(0x24,IRQ4_interrupt);
- 	set_intr_gate(0x25,IRQ5_interrupt);
- 	set_intr_gate(0x29,IRQ9_interrupt);
  	for (i = 0, info = serial_table; i < NR_SERIALS; i++,info++) {
  		info->tty = (tty_table+64) + i;
  		init(info);
--- 452,457 ----
*** 0.96c/linux/kernel/chr_drv/pty.c	Sun Jul  5 03:15:12 1992
--- linux/kernel/chr_drv/pty.c	Wed Jul  8 14:18:16 1992
***************
*** 31,40 ****
  	wake_up(&tty->read_q->proc_list);
  	if (filp->f_flags & O_NDELAY)
  		return 0;
- 	if (IS_A_PTY_MASTER(dev)) {
- 		tty->link->count++;
- 		return 0;
- 	}
  	while (!tty->link->count && !(current->signal & ~current->blocked))
  		interruptible_sleep_on(&tty->link->read_q->proc_list);
  	if (!tty->link->count)
--- 31,36 ----
***************
*** 48,55 ****
  
  	tty = tty_table + dev;
  	wake_up(&tty->read_q->proc_list);
  	if (IS_A_PTY_MASTER(dev)) {
- 		tty->link->count--;
  		if (tty->link->pgrp > 0)
  			kill_pg(tty->link->pgrp,SIGHUP,1);
  	}
--- 44,51 ----
  
  	tty = tty_table + dev;
  	wake_up(&tty->read_q->proc_list);
+ 	wake_up(&tty->link->write_q->proc_list);
  	if (IS_A_PTY_MASTER(dev)) {
  		if (tty->link->pgrp > 0)
  			kill_pg(tty->link->pgrp,SIGHUP,1);
  	}
***************
*** 66,73 ****
  			TTY_READ_FLUSH(to);
  			continue;
  		}
! 		c = GETCH(from->write_q);
! 		PUTCH(c,to->read_q);
  		if (current->signal & ~current->blocked)
  			break;
  	}
--- 62,69 ----
  			TTY_READ_FLUSH(to);
  			continue;
  		}
! 		c = get_tty_queue(from->write_q);
! 		put_tty_queue(c,to->read_q);
  		if (current->signal & ~current->blocked)
  			break;
  	}
*** 0.96c/linux/kernel/blk_drv/hd.c	Wed Jun  3 04:00:19 1992
--- linux/kernel/blk_drv/hd.c	Sat Jul 11 00:49:35 1992
***************
*** 16,22 ****
--- 16,25 ----
   *  in the early extended-partition checks and added DM partitions
   */
  
+ #define HD_IRQ 14
+ 
  #include <errno.h>
+ #include <signal.h>
  
  #include <linux/config.h>
  #include <linux/sched.h>
***************
*** 82,88 ****
  #define port_write(port,buf,nr) \
  __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
  
- extern void hd_interrupt(void);
  extern void rd_load(void);
  
  static unsigned int current_minor;
--- 85,90 ----
***************
*** 279,285 ****
--- 281,289 ----
  	blk_size[MAJOR_NR] = hd_sizes;
  	if (NR_HD)
  		printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
+ #ifdef RAMDISK
  	rd_load();
+ #endif
  	mount_root();
  	return (0);
  }
***************
*** 517,523 ****
   */
  static void hd_times_out(void)
  {	
! 	do_hd = NULL;
  	reset = 1;
  	if (!CURRENT)
  		return;
--- 521,527 ----
   */
  static void hd_times_out(void)
  {	
! 	DEVICE_INTR = NULL;
  	reset = 1;
  	if (!CURRENT)
  		return;
***************
*** 601,607 ****
--- 605,614 ----
  				(char *) &loc->sectors);
  			put_fs_word(hd_info[dev].cyl,
  				(short *) &loc->cylinders);
+ 			put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
+ 				(long *) &loc->start);
  			return 0;
+ 		RO_IOCTLS(inode->i_rdev,arg);
  		default:
  			return -EINVAL;
  	}
***************
*** 627,638 ****
  	hd_release		/* release */
  };
  
  void hd_init(void)
  {
  	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
  	blkdev_fops[MAJOR_NR] = &hd_fops;
! 	set_intr_gate(0x2E,&hd_interrupt);
! 	outb_p(inb_p(0x21)&0xfb,0x21);
! 	outb(inb_p(0xA1)&0xbf,0xA1);
  	timer_table[HD_TIMER].fn = hd_times_out;
  }
--- 634,668 ----
  	hd_release		/* release */
  };
  
+ static void hd_interrupt(int cpl)
+ {
+ 	void (*handler)(void) = DEVICE_INTR;
+ 
+ 	DEVICE_INTR = NULL;
+ 	timer_active &= ~(1<<HD_TIMER);
+ 	if (!handler)
+ 		handler = unexpected_hd_interrupt;
+ 	handler();
+ }
+ 
+ /*
+  * This is the harddisk IRQ descruption. The SA_INTERRUPT in sa_flags
+  * means we run the IRQ-handler with interrupts disabled: this is bad for
+  * interrupt latency, but anything else has led to problems on some
+  * machines...
+  */
+ static struct sigaction hd_sigaction = {
+ 	hd_interrupt,
+ 	0,
+ 	SA_INTERRUPT,
+ 	NULL
+ };
+ 
  void hd_init(void)
  {
  	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
  	blkdev_fops[MAJOR_NR] = &hd_fops;
! 	if (irqaction(HD_IRQ,&hd_sigaction))
! 		printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
  	timer_table[HD_TIMER].fn = hd_times_out;
  }
*** 0.96c/linux/kernel/blk_drv/ll_rw_blk.c	Sun Jul  5 00:54:14 1992
--- linux/kernel/blk_drv/ll_rw_blk.c	Sat Jul 11 00:49:36 1992
***************
*** 8,13 ****
--- 8,14 ----
   * This handles all read/write requests to block devices
   */
  #include <errno.h>
+ #include <linux/string.h>
  #include <linux/sched.h>
  #include <linux/kernel.h>
  #include <asm/system.h>
***************
*** 70,75 ****
--- 71,101 ----
  	wake_up(&bh->b_wait);
  }
  
+ /* RO fail safe mechanism */
+ 
+ static long ro_bits[NR_BLK_DEV][8];
+ 
+ int is_read_only(int dev)
+ {
+ 	int minor,major;
+ 
+ 	major = MAJOR(dev);
+ 	minor = MINOR(dev);
+ 	if (major < 0 || major >= NR_BLK_DEV) return 0;
+ 	return ro_bits[major][minor >> 5] & (1 << (minor & 31));
+ }
+ 
+ void set_device_ro(int dev,int flag)
+ {
+ 	int minor,major;
+ 
+ 	major = MAJOR(dev);
+ 	minor = MINOR(dev);
+ 	if (major < 0 || major >= NR_BLK_DEV) return;
+ 	if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
+ 	else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
+ }
+ 
  /*
   * add-request adds a request to the linked list.
   * It disables interrupts so that it can muck with the
***************
*** 203,208 ****
--- 229,238 ----
  	}
  	if (rw!=READ && rw!=WRITE)
  		panic("Bad block dev command, must be R/W");
+ 	if (rw == WRITE && is_read_only(dev)) {
+ 		printk("Can't page to read-only device 0x%X\n\r",dev);
+ 		return;
+ 	}
  	cli();
  repeat:
  	req = request+NR_REQUEST;
***************
*** 238,245 ****
--- 268,281 ----
  	if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
  	!(blk_dev[major].request_fn)) {
  		printk("ll_rw_block: Trying to read nonexistent block-device\n\r");
+ 		bh->b_dirt = bh->b_uptodate = 0;
  		return;
  	}
+ 	if ((rw == WRITE || rw == WRITEA) && is_read_only(bh->b_dev)) {
+ 		printk("Can't write to read-only device 0x%X\n\r",bh->b_dev);
+ 		bh->b_dirt = bh->b_uptodate = 0;
+ 		return;
+ 	}
  	make_request(major,rw,bh);
  }
  
***************
*** 251,256 ****
--- 287,293 ----
  		request[i].dev = -1;
  		request[i].next = NULL;
  	}
+ 	memset(ro_bits,0,sizeof(ro_bits));
  #ifdef RAMDISK
  	mem_start += rd_init(mem_start, RAMDISK*1024);
  #endif
***************
*** 270,275 ****
--- 307,316 ----
  
  	if (rw!=READ && rw!=WRITE) {
  		printk("ll_rw_swap: bad block dev command, must be R/W");
+ 		return;
+ 	}
+ 	if (rw == WRITE && is_read_only(dev)) {
+ 		printk("Can't swap to read-only device 0x%X\n\r",dev);
  		return;
  	}
  	
*** 0.96c/linux/kernel/blk_drv/floppy.c	Sat Jul  4 20:44:26 1992
--- linux/kernel/blk_drv/floppy.c	Sat Jul 11 00:49:35 1992
***************
*** 38,43 ****
--- 38,45 ----
   * the floppy-change signal detection.
   */
  
+ #define FLOPPY_IRQ 6
+ 
  #include <linux/sched.h>
  #include <linux/fs.h>
  #include <linux/kernel.h>
***************
*** 205,211 ****
   * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
   */
  
- extern void floppy_interrupt(void);
  extern char tmp_floppy_area[1024];
  extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
  
--- 207,212 ----
***************
*** 560,566 ****
  	else redo_fd_request();
  }
  
! void unexpected_floppy_interrupt(void)
  {
  	current_track = NO_TRACK;
  	output_byte(FD_SENSEI);
--- 561,567 ----
  	else redo_fd_request();
  }
  
! static void unexpected_floppy_interrupt(void)
  {
  	current_track = NO_TRACK;
  	output_byte(FD_SENSEI);
***************
*** 831,836 ****
--- 832,840 ----
  	int drive,cnt,okay;
  	struct floppy_struct *this;
  
+ 	switch (cmd) {
+ 		RO_IOCTLS(inode->i_rdev,param);
+ 	}
  	if (!suser()) return -EPERM;
  	drive = MINOR(inode->i_rdev);
  	switch (cmd) {
***************
*** 975,980 ****
--- 979,1006 ----
  	floppy_release		/* release */
  };
  
+ static void floppy_interrupt(int cpl)
+ {
+ 	void (*handler)(void) = DEVICE_INTR;
+ 
+ 	DEVICE_INTR = NULL;
+ 	if (!handler)
+ 		handler = unexpected_floppy_interrupt;
+ 	handler();
+ }
+ 
+ /*
+  * This is the harddisk IRQ descruption. The SA_INTERRUPT in sa_flags
+  * means we run the IRQ-handler with interrupts disabled: this is bad for
+  * interrupt latency, but may be safer...
+  */
+ static struct sigaction floppy_sigaction = {
+ 	floppy_interrupt,
+ 	0,
+ 	SA_INTERRUPT,
+ 	NULL
+ };
+ 
  void floppy_init(void)
  {
  	outb(current_DOR,FD_DOR);
***************
*** 984,989 ****
  	timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
  	timer_active &= ~(1 << FLOPPY_TIMER);
  	config_types();
! 	set_intr_gate(0x26,&floppy_interrupt);
! 	outb(inb_p(0x21)&~0x40,0x21);
  }
--- 1010,1015 ----
  	timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
  	timer_active &= ~(1 << FLOPPY_TIMER);
  	config_types();
! 	if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
! 		printk("Unable to grab IRQ%d for the floppy driver\n",FLOPPY_IRQ);
  }
*** 0.96c/linux/kernel/blk_drv/blk.h	Wed Jun  3 04:23:19 1992
--- linux/kernel/blk_drv/blk.h	Sat Jul 11 00:49:34 1992
***************
*** 54,59 ****
--- 54,67 ----
  
  extern int * blk_size[NR_BLK_DEV];
  
+ extern int is_read_only(int dev);
+ extern void set_device_ro(int dev,int flag);
+ 
+ #define RO_IOCTLS(dev,where) \
+   case BLKROSET: if (!suser()) return -EPERM; \
+ 		 set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
+   case BLKROGET: put_fs_long(is_read_only(dev),(long *) (where)); return 0;
+ 		 
  #ifdef MAJOR_NR
  
  /*
*** 0.96c/linux/kernel/blk_drv/ramdisk.c	Thu Jun 18 14:16:39 1992
--- linux/kernel/blk_drv/ramdisk.c	Tue Jul  7 16:03:33 1992
***************
*** 84,90 ****
  void rd_load(void)
  {
  	struct buffer_head *bh;
! 	struct super_block	s;
  	int		block = 256;	/* Start at block 256 */
  	int		i = 1;
  	int		nblocks;
--- 84,90 ----
  void rd_load(void)
  {
  	struct buffer_head *bh;
! 	struct minix_super_block s;
  	int		block = 256;	/* Start at block 256 */
  	int		i = 1;
  	int		nblocks;
*** 0.96c/linux/kernel/blk_drv/scsi/aha1542.c	Thu Jul  2 01:54:30 1992
--- linux/kernel/blk_drv/scsi/aha1542.c	Thu Jul  9 19:44:56 1992
***************
*** 8,13 ****
--- 8,14 ----
  #include <linux/kernel.h>
  #include <linux/head.h>
  #include <linux/string.h>
+ #include <linux/sched.h>
  #include <asm/system.h>
  #include <asm/io.h>
  #include <sys/types.h>
***************
*** 34,40 ****
  long WAITtimeout, WAITnexttimeout = 3000000;
  
  void (*do_done)() = NULL;
- extern void aha1542_interrupt();
  
  #define aha1542_intr_reset()  outb(IRST, CONTROL)
  #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
--- 35,40 ----
***************
*** 192,198 ****
  }
  
  /* A "high" level interrupt handler */
! void aha1542_intr_handle(void)
  {
      int flag = inb(INTRFLAGS);
      void (*my_done)() = do_done;
--- 192,198 ----
  }
  
  /* A "high" level interrupt handler */
! static void aha1542_interrupt(int cpl)
  {
      int flag = inb(INTRFLAGS);
      void (*my_done)() = do_done;
***************
*** 200,206 ****
  
      do_done = NULL;
  #ifdef DEBUG
!     printk("aha1542_intr_handle: ");
      if (!(flag&ANYINTR)) printk("no interrupt?");
      if (flag&MBIF) printk("MBIF ");
      if (flag&MBOA) printk("MBOF ");
--- 200,206 ----
  
      do_done = NULL;
  #ifdef DEBUG
!     printk("aha1542_interrupt: ");
      if (!(flag&ANYINTR)) printk("no interrupt?");
      if (flag&MBIF) printk("MBIF ");
      if (flag&MBOA) printk("MBOF ");
***************
*** 212,218 ****
  #endif
      aha1542_intr_reset();
      if (!my_done) {
! 	printk("aha1542_intr_handle: Unexpected interrupt\n");
  	return;
      }
  
--- 212,218 ----
  #endif
      aha1542_intr_reset();
      if (!my_done) {
! 	printk("aha1542_interrupt: Unexpected interrupt\n");
  	return;
      }
  
***************
*** 219,225 ****
      /* is there mail :-) */
  	
      if (!mb[1].status) {
! 	DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
  	my_done(DID_TIME_OUT << 16);
  	return;
      }
--- 219,225 ----
      /* is there mail :-) */
  	
      if (!mb[1].status) {
! 	DEB(printk("aha1542_interrupt: strange: mbif but no mail!\n"));
  	my_done(DID_TIME_OUT << 16);
  	return;
      }
***************
*** 235,252 ****
  
      if (ccb.tarstat == 2) {
  	int i;
! 	DEB(printk("aha1542_intr_handle: sense:"));
  	for (i = 0; i < 12; i++)
  	  printk("%02x ", ccb.cdb[ccb.cdblen+i]);
  	printk("\n");
  /*
! 	DEB(printk("aha1542_intr_handle: buf:"));
  	for (i = 0; i < bufflen; i++)
  	  printk("%02x ", ((unchar *)buff)[i]);
  	printk("\n");
  */
      }
!     DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
      my_done(errstatus);
      return;
  }
--- 235,252 ----
  
      if (ccb.tarstat == 2) {
  	int i;
! 	DEB(printk("aha1542_interrupt: sense:"));
  	for (i = 0; i < 12; i++)
  	  printk("%02x ", ccb.cdb[ccb.cdblen+i]);
  	printk("\n");
  /*
! 	DEB(printk("aha1542_interrupt: buf:"));
  	for (i = 0; i < bufflen; i++)
  	  printk("%02x ", ((unchar *)buff)[i]);
  	printk("\n");
  */
      }
!     DEB(if (errstatus) printk("aha1542_interrupt: returning %6x\n", errstatus));
      my_done(errstatus);
      return;
  }
***************
*** 355,361 ****
  
  void call_buh()
  {
!     set_intr_gate(0x2b,&aha1542_interrupt);
  }
  
  /* return non-zero on detection */
--- 355,368 ----
  
  void call_buh()
  {
! 	struct sigaction sa;
! 
! 	sa.sa_handler = aha1542_interrupt;
! 	sa.sa_flags = SA_INTERRUPT;
! 	sa.sa_mask = 0;
! 	sa.sa_restorer = NULL;
! 	if (irqaction(intr_chan,&sa))
! 		printk("Unable to allocate IRQ%d for aha controller\n", intr_chan);
  }
  
  /* return non-zero on detection */
***************
*** 448,482 ****
      DEB(printk("aha1542_reset called\n"));
      return 0;
  }
- 
- __asm__("
- _aha1542_interrupt:
- 	cld
- 	pushl %eax
- 	pushl %ecx
- 	pushl %edx
- 	push %ds
- 	push %es
- 	push %fs
- 	movl $0x10,%eax
- 	mov %ax,%ds
- 	mov %ax,%es
- 	movl $0x17,%eax
- 	mov %ax,%fs
- 	movb $0x20,%al
- 	outb %al,$0xA0		# EOI to interrupt controller #1
- 	jmp 1f			# give port chance to breathe
- 1:	jmp 1f
- 1:	outb %al,$0x20
- # Please, someone, change this to use the timer
- #	andl $0xfffeffff,_timer_active
- 	movl $_aha1542_intr_handle,%edx
- 	call *%edx		# ``interesting'' way of handling intr.
- 	pop %fs
- 	pop %es
- 	pop %ds
- 	popl %edx
- 	popl %ecx
- 	popl %eax
- 	iret
- ");
--- 455,457 ----
*** 0.96c/linux/kernel/blk_drv/scsi/sd_ioctl.c	Sat May  2 18:37:38 1992
--- linux/kernel/blk_drv/scsi/sd_ioctl.c	Sat Jul 11 00:49:36 1992
***************
*** 3,8 ****
--- 3,11 ----
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/fs.h>
+ #include <asm/segment.h>
+ #include "../blk.h"
+ #include <errno.h>
  #include "scsi.h"
  #include "sd.h"
  
***************
*** 13,18 ****
--- 16,22 ----
  	int dev = inode->i_rdev;
  	
  	switch (cmd) {
+ 		RO_IOCTLS(dev,arg);
  		default:
  			return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device,cmd,(void *) arg);
  	}
*** 0.96c/linux/kernel/blk_drv/scsi/ultrastor.c	Fri May 29 00:26:06 1992
--- linux/kernel/blk_drv/scsi/ultrastor.c	Thu Jul  9 19:27:15 1992
***************
*** 156,162 ****
  };
  #endif
  
! void ultrastor_interrupt(void);
  
  static void (*ultrastor_done)(int, int) = 0;
  
--- 156,162 ----
  };
  #endif
  
! void ultrastor_interrupt(int cpl);
  
  static void (*ultrastor_done)(int, int) = 0;
  
***************
*** 293,303 ****
      host_number = hostnum;
      scsi_hosts[hostnum].this_id = config.ha_scsi_id;
  #if USE_QUEUECOMMAND
!     set_intr_gate(0x20 + config.interrupt, ultrastor_interrupt);
!     /* gate to PIC 2 */
!     outb_p(inb_p(0x21) & ~BIT(2), 0x21);
!     /* enable the interrupt */
!     outb(inb_p(0xA1) & ~BIT(config.interrupt - 8), 0xA1);
  #endif
      return TRUE;
  }
--- 293,309 ----
      host_number = hostnum;
      scsi_hosts[hostnum].this_id = config.ha_scsi_id;
  #if USE_QUEUECOMMAND
!     {
!    	struct sigaction sa;
!    	sa.sa_handler = ultrastor_interrupt;
!    	sa.sa_flags = SA_INTERRUPT;
!    	sa.sa_mask = 0;
!    	sa.sa_restorer = NULL;
!    	if (irqaction(config.interrupt,&sa)) {
!    		printk("unable to get IRQ%d for ultrastor controller\n",config.interrupt);
!    		return FALSE;
!    	}
!     }
  #endif
      return TRUE;
  }
***************
*** 421,427 ****
  }
  
  #if USE_QUEUECOMMAND
! void ultrastor_interrupt_service(void)
  {
      if (ultrastor_done == 0) {
  	printk("US14F: unexpected ultrastor interrupt\n\r");
--- 427,433 ----
  }
  
  #if USE_QUEUECOMMAND
! void ultrastor_interrupt(int cpl)
  {
      if (ultrastor_done == 0) {
  	printk("US14F: unexpected ultrastor interrupt\n\r");
***************
*** 434,470 ****
  		   (mscp.adapter_status << 16) | mscp.target_status);
      ultrastor_done = 0;
  }
- 
- __asm__("
- _ultrastor_interrupt:
- 	cld
- 	pushl %eax
- 	pushl %ecx
- 	pushl %edx
- 	push %ds
- 	push %es
- 	push %fs
- 	movl $0x10,%eax
- 	mov %ax,%ds
- 	mov %ax,%es
- 	movl $0x17,%eax
- 	mov %ax,%fs
- 	movb $0x20,%al
- 	outb %al,$0xA0		# EOI to interrupt controller #1
- 	outb %al,$0x80		# give port chance to breathe
- 	outb %al,$0x80
- 	outb %al,$0x80
- 	outb %al,$0x80
- 	outb %al,$0x20
- 	call _ultrastor_interrupt_service
- 	pop %fs
- 	pop %es
- 	pop %ds
- 	popl %edx
- 	popl %ecx
- 	popl %eax
- 	iret
- ");
  #endif
  
  #endif
--- 440,445 ----
*** 0.96c/linux/kernel/sys_call.S	Thu Jun 25 16:40:29 1992
--- linux/kernel/sys_call.S	Tue Jul  7 18:39:02 1992
***************
*** 81,87 ****
   * Ok, I get parallel printer interrupts while using the floppy for some
   * strange reason. Urgel. Now I just ignore them.
   */
! .globl _system_call,_timer_interrupt,_sys_execve
  .globl _device_not_available, _coprocessor_error
  .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  .globl _double_fault,_coprocessor_segment_overrun
--- 81,87 ----
   * Ok, I get parallel printer interrupts while using the floppy for some
   * strange reason. Urgel. Now I just ignore them.
   */
! .globl _system_call,_sys_execve
  .globl _device_not_available, _coprocessor_error
  .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  .globl _double_fault,_coprocessor_segment_overrun
***************
*** 88,95 ****
  .globl _invalid_TSS,_segment_not_present,_stack_segment
  .globl _general_protection,_irq13,_reserved
  .globl _alignment_check,_page_fault
! .globl _keyboard_interrupt,_hd_interrupt
! .globl _IRQ3_interrupt,_IRQ4_interrupt,_IRQ5_interrupt,_IRQ9_interrupt
  
  #define SAVE_ALL \
  	cld; \
--- 88,94 ----
  .globl _invalid_TSS,_segment_not_present,_stack_segment
  .globl _general_protection,_irq13,_reserved
  .globl _alignment_check,_page_fault
! .globl ret_from_sys_call
  
  #define SAVE_ALL \
  	cld; \
***************
*** 170,184 ****
  	jne 2f
  	cmpw $0x17,OLDSS(%esp)		# was stack segment = 0x17 ?
  	jne 2f
! 1:	movl _current,%eax
! 	cmpl _task,%eax			# task[0] cannot have signals
! 	je 2f
! 	cmpl $0,_need_resched
  	jne reschedule
  	cmpl $0,state(%eax)		# state
  	jne reschedule
  	cmpl $0,counter(%eax)		# counter
  	je reschedule
  	movl signal(%eax),%ebx
  	movl blocked(%eax),%ecx
  	notl %ecx
--- 169,185 ----
  	jne 2f
  	cmpw $0x17,OLDSS(%esp)		# was stack segment = 0x17 ?
  	jne 2f
! 1:	cmpl $0,_need_resched
  	jne reschedule
+ 	movl _current,%eax
  	cmpl $0,state(%eax)		# state
  	jne reschedule
  	cmpl $0,counter(%eax)		# counter
  	je reschedule
+ 	movl $1,_need_resched
+ 	cmpl _task,%eax			# task[0] cannot have signals
+ 	je 2f
+ 	movl $0,_need_resched
  	movl signal(%eax),%ebx
  	movl blocked(%eax),%ecx
  	notl %ecx
***************
*** 240,340 ****
  	call _math_emulate
  	addl $4,%esp
  	ret
- 
- .align 2
- _keyboard_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_FIRST(0x02)
- 	sti
- 	call _do_keyboard
- 	cli
- 	UNBLK_FIRST(0x02)
- 	jmp ret_from_sys_call
- 
- .align 2
- _IRQ3_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_FIRST(0x08)
- 	sti
- 	pushl $3
- 	call _do_IRQ
- 	addl $4,%esp
- 	cli
- 	UNBLK_FIRST(0x08)
- 	jmp ret_from_sys_call
- 
- .align 2
- _IRQ4_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_FIRST(0x10)
- 	sti
- 	pushl $4
- 	call _do_IRQ
- 	addl $4,%esp
- 	cli
- 	UNBLK_FIRST(0x10)
- 	jmp ret_from_sys_call
- 
- .align 2
- _IRQ5_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_FIRST(0x20)
- 	sti
- 	pushl $5
- 	call _do_IRQ
- 	addl $4,%esp
- 	cli
- 	UNBLK_FIRST(0x20)
- 	jmp ret_from_sys_call
- 
- .align 2
- _IRQ9_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_SECOND(0x02)
- 	sti
- 	pushl $9
- 	call _do_IRQ
- 	addl $4,%esp
- 	cli
- 	UNBLK_SECOND(0x02)
- 	jmp ret_from_sys_call
- 
- .align 2
- _timer_interrupt:
- 	pushl $-1		# mark this as an int
- 	SAVE_ALL
- 	ACK_FIRST(0x01)
- 	sti
- 	incl _jiffies
- 	movl CS(%esp),%eax
- 	andl $3,%eax		# %eax is CPL (0 or 3, 0=supervisor)
- 	pushl %eax
- 	call _do_timer		# 'do_timer(long CPL)' does everything from
- 	addl $4,%esp		# task switching to accounting ...
- 	cli
- 	UNBLK_FIRST(0x01)
- 	jmp ret_from_sys_call
- 
- .align 2
- _hd_interrupt:
- 	pushl $-1
- 	SAVE_ALL
- 	ACK_SECOND(0x40)
- 	andl $0xfffeffff,_timer_active
- 	xorl %edx,%edx
- 	xchgl _do_hd,%edx
- 	testl %edx,%edx
- 	jne 1f
- 	movl $_unexpected_hd_interrupt,%edx
- 1:	call *%edx		# "interesting" way of handling intr.
- 	cli
- 	UNBLK_SECOND(0x40)
- 	jmp ret_from_sys_call
  
  .align 2
  _sys_execve:
--- 241,246 ----
*** /dev/null	Sat Jul 11 22:43:15 1992
--- linux/kernel/irq.c	Thu Jul  9 14:43:34 1992
***************
*** 0 ****
--- 1,171 ----
+ /*
+  *	linux/kernel/irq.c
+  *
+  *	(C) 1992 Linus Torvalds
+  *
+  * This file contains the code used by various IRQ handling routines:
+  * asking for different IRQ's should be done through these routines
+  * instead of just grabbing them. Thus setups with different IRQ numbers
+  * shouldn't result in any weird surprises, and installing new handlers
+  * should be easier.
+  */
+ 
+ /*
+  * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+  * The same sigaction struct is used, and with similar semantics (ie there
+  * is a SA_INTERRUPT flag etc). Naturally it's not a 1:1 relation, but there
+  * are similarities.
+  *
+  * sa_handler(int irq_NR) is the default function called.
+  * sa_mask is 0 if nothing uses this IRQ
+  * sa_flags contains various info: SA_INTERRUPT etc
+  * sa_restorer is the unused
+  */
+ 
+ #include <signal.h>
+ #include <errno.h>
+ 
+ #include <sys/ptrace.h>
+ 
+ #include <linux/sched.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ 
+ struct sigaction irq_sigaction[16] = {
+ 	{ NULL, 0, 0, NULL },
+ };
+ 
+ /*
+  * This builds up the IRQ handler stubs using some ugly macros in irq.h
+  */
+ BUILD_IRQ(FIRST,0,0x01)
+ BUILD_IRQ(FIRST,1,0x02)
+ BUILD_IRQ(FIRST,2,0x04)
+ BUILD_IRQ(FIRST,3,0x08)
+ BUILD_IRQ(FIRST,4,0x10)
+ BUILD_IRQ(FIRST,5,0x20)
+ BUILD_IRQ(FIRST,6,0x40)
+ BUILD_IRQ(FIRST,7,0x80)
+ BUILD_IRQ(SECOND,8,0x01)
+ BUILD_IRQ(SECOND,9,0x02)
+ BUILD_IRQ(SECOND,10,0x04)
+ BUILD_IRQ(SECOND,11,0x08)
+ BUILD_IRQ(SECOND,12,0x10)
+ BUILD_IRQ(SECOND,13,0x20)
+ BUILD_IRQ(SECOND,14,0x40)
+ BUILD_IRQ(SECOND,15,0x80)
+ 
+ /*
+  * This routine gets called at every IRQ request. Interrupts
+  * are enabled, the interrupt has been accnowledged and this
+  * particular interrupt is disabled when this is called.
+  *
+  * The routine has to call the appropriate handler (disabling
+  * interrupts if needed first), and then re-enable this interrupt-
+  * line if the handler was ok. If no handler exists, the IRQ isn't
+  * re-enabled.
+  *
+  * Note similarities on a very low level between this and the
+  * do_signal() function. Naturally this is simplified, but they
+  * get similar arguments, use them similarly etc... Note that
+  * unlike the signal-handlers, the IRQ-handlers don't get the IRQ
+  * (signal) number as argument, but the cpl value at the time of
+  * the interrupt.
+  */
+ void do_IRQ(int irq, struct pt_regs * regs)
+ {
+ 	struct sigaction * sa = irq + irq_sigaction;
+ 	void (*handler)(int);
+ 
+ 	if (!(handler = sa->sa_handler))
+ 		return;
+ 	if (sa->sa_flags & SA_INTERRUPT)
+ 		cli();
+ 	handler(regs->cs & 3);
+ 	cli();
+ 	if (irq < 8)
+ 		outb(inb_p(0x21) & ~(1<<irq),0x21);
+ 	else
+ 		outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
+ 	sti();
+ }
+ 
+ int irqaction(unsigned int irq, struct sigaction * new)
+ {
+ 	struct sigaction * sa;
+ 	unsigned long flags;
+ 
+ 	if (irq > 15)
+ 		return -EINVAL;
+ 	if (irq == 2)
+ 		irq = 9;
+ 	sa = irq + irq_sigaction;
+ 	if (sa->sa_mask)
+ 		return -EBUSY;
+ 	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
+ 	*sa = *new;
+ 	sa->sa_mask = 1;
+ 	if (irq < 8)
+ 		outb(inb_p(0x21) & ~(1<<irq),0x21);
+ 	else
+ 		outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
+ 	__asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
+ 	return 0;
+ }
+ 		
+ int request_irq(unsigned int irq, void (*handler)(int))
+ {
+ 	struct sigaction sa;
+ 
+ 	sa.sa_handler = handler;
+ 	sa.sa_flags = 0;
+ 	sa.sa_mask = 0;
+ 	sa.sa_restorer = NULL;
+ 	return irqaction(irq,&sa);
+ }
+ 
+ void free_irq(unsigned int irq)
+ {
+ 	struct sigaction * sa = irq + irq_sigaction;
+ 	unsigned long flags;
+ 
+ 	if (irq > 15) {
+ 		printk("Trying to free IRQ%d\n",irq);
+ 		return;
+ 	}
+ 	if (!sa->sa_mask) {
+ 		printk("Trying to free free IRQ%d\n",irq);
+ 		return;
+ 	}
+ 	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
+ 	if (irq < 8)
+ 		outb(inb_p(0x21) | (1<<irq),0x21);
+ 	else
+ 		outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
+ 	sa->sa_handler = NULL;
+ 	sa->sa_flags = 0;
+ 	sa->sa_mask = 0;
+ 	sa->sa_restorer = NULL;
+ 	__asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
+ }
+ 
+ void init_IRQ(void)
+ {
+ 	set_trap_gate(0x20,IRQ0_interrupt);
+ 	set_trap_gate(0x21,IRQ1_interrupt);
+ 	set_trap_gate(0x22,IRQ2_interrupt);
+ 	set_trap_gate(0x23,IRQ3_interrupt);
+ 	set_trap_gate(0x24,IRQ4_interrupt);
+ 	set_trap_gate(0x25,IRQ5_interrupt);
+ 	set_trap_gate(0x26,IRQ6_interrupt);
+ 	set_trap_gate(0x27,IRQ7_interrupt);
+ 	set_trap_gate(0x28,IRQ8_interrupt);
+ 	set_trap_gate(0x29,IRQ10_interrupt);
+ 	set_trap_gate(0x2a,IRQ10_interrupt);
+ 	set_trap_gate(0x2b,IRQ11_interrupt);
+ 	set_trap_gate(0x2c,IRQ12_interrupt);
+ 	set_trap_gate(0x2d,IRQ13_interrupt);
+ 	set_trap_gate(0x2e,IRQ14_interrupt);
+ 	set_trap_gate(0x2f,IRQ15_interrupt);
+ }
*** 0.96c/linux/kernel/ptrace.c	Wed Jun 17 13:37:55 1992
--- linux/kernel/ptrace.c	Thu Jul  9 19:18:53 1992
***************
*** 39,45 ****
  {
  	int i;
  
! 	for (i = 0; i < NR_TASKS; i++) {
  		if (task[i] != NULL && (task[i]->pid == pid))
  			return task[i];
  	}
--- 39,45 ----
  {
  	int i;
  
! 	for (i = 1; i < NR_TASKS; i++) {
  		if (task[i] != NULL && (task[i]->pid == pid))
  			return task[i];
  	}
***************
*** 238,243 ****
--- 238,245 ----
  	if (request == PTRACE_ATTACH) {
  		long tmp;
  
+ 		if (child == current)
+ 			return -EPERM;
  		if ((!current->dumpable || (current->uid != child->euid) ||
  	 	    (current->gid != child->egid)) && !suser())
  			return -EPERM;
*** 0.96c/linux/lib/Makefile	Sun Jul  5 03:11:58 1992
--- linux/lib/Makefile	Sat Jul 11 20:14:30 1992
***************
*** 14,20 ****
  	$(CC) $(CFLAGS) -c $<
  
  OBJS  = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
! 	execve.o wait.o string.o malloc.o itimer.o
  
  lib.a: $(OBJS)
  	$(AR) rcs lib.a $(OBJS)
--- 14,20 ----
  	$(CC) $(CFLAGS) -c $<
  
  OBJS  = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
! 	execve.o wait.o string.o malloc.o
  
  lib.a: $(OBJS)
  	$(AR) rcs lib.a $(OBJS)
***************
*** 36,43 ****
  dup.o : dup.c /usr/src/linux/include/linux/unistd.h 
  errno.o : errno.c 
  execve.o : execve.c /usr/src/linux/include/linux/unistd.h 
- itimer.o : itimer.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/sys/time.h \
-   /usr/src/linux/include/time.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h 
  malloc.o : malloc.c /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/mm.h \
    /usr/src/linux/include/linux/fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
    /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/limits.h /usr/src/linux/include/sys/vfs.h \
--- 36,41 ----
*** 0.96c/linux/include/sys/time.h	Mon May 25 22:18:54 1992
--- linux/include/sys/time.h	Wed Jul  8 15:17:52 1992
***************
*** 55,61 ****
  };
  
  int getitimer(int which, struct itimerval *value);
! int setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
  
  #include <time.h>
  #include <sys/types.h>
--- 55,61 ----
  };
  
  int getitimer(int which, struct itimerval *value);
! int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
  
  #include <time.h>
  #include <sys/types.h>
*** 0.96c/linux/include/linux/hdreg.h	Fri Apr 24 18:26:25 1992
--- linux/include/linux/hdreg.h	Sat Jul 11 00:49:34 1992
***************
*** 69,73 ****
--- 69,74 ----
        unsigned char heads;
        unsigned char sectors;
        unsigned short cylinders;
+       unsigned long start;
  };
  #endif
*** 0.96c/linux/include/linux/sched.h	Sun Jul  5 01:27:18 1992
--- linux/include/linux/sched.h	Mon Jul  6 00:18:21 1992
***************
*** 228,233 ****
--- 228,237 ----
  extern void wake_up(struct task_struct ** p);
  extern int in_group_p(gid_t grp);
  
+ extern int request_irq(unsigned int irq,void (*handler)(int));
+ extern void free_irq(unsigned int irq);
+ extern int irqaction(unsigned int irq,struct sigaction * new);
+ 
  /*
   * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
   * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
*** 0.96c/linux/include/linux/tty.h	Sat Jul  4 03:28:16 1992
--- linux/include/linux/tty.h	Tue Jul  7 14:54:51 1992
***************
*** 69,76 ****
  extern void put_tty_queue(char c, struct tty_queue * queue);
  extern int get_tty_queue(struct tty_queue * queue);
  
- #define PUTCH(c,queue) put_tty_queue((c),(queue))
- #define GETCH(queue) get_tty_queue(queue)
  #define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])
  #define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])
  #define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])
--- 69,74 ----
***************
*** 166,171 ****
--- 164,170 ----
  
  extern void flush_input(struct tty_struct * tty);
  extern void flush_output(struct tty_struct * tty);
+ extern void wait_until_sent(struct tty_struct * tty);
  extern void copy_to_cooked(struct tty_struct * tty);
  
  extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
*** 0.96c/linux/include/linux/fs.h	Fri Jul  3 03:09:37 1992
--- linux/include/linux/fs.h	Sat Jul 11 01:27:13 1992
***************
*** 43,49 ****
  
  #define NR_OPEN 32
  #define NR_INODE 128
! #define NR_FILE 64
  #define NR_SUPER 8
  #define NR_HASH 307
  #define NR_BUFFERS nr_buffers
--- 43,49 ----
  
  #define NR_OPEN 32
  #define NR_INODE 128
! #define NR_FILE 128
  #define NR_SUPER 8
  #define NR_HASH 307
  #define NR_BUFFERS nr_buffers
***************
*** 71,76 ****
--- 71,103 ----
  #define SEL_OUT		2
  #define SEL_EX		4
  
+ /*
+  * These are the fs-independent mount-flags: up to 16 flags are supported
+  */
+ #define MS_RDONLY    1 /* mount read-only */
+ #define MS_NOSUID    2 /* ignore suid and sgid bits */
+ #define MS_NODEV     4 /* disallow access to device special files */
+ #define MS_NOEXEC    8 /* disallow program execution */
+ 
+ /*
+  * Note that read-only etc flags are inode-specific: setting some file-system
+  * flags just means all the inodes inherit those flags by default. It might be
+  * possible to overrride it sevelctively if you really wanted to with some
+  * ioctl() that is not currently implemented.
+  */
+ #define IS_RDONLY(inode) ((inode)->i_flags & MS_RDONLY)
+ #define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID)
+ #define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
+ #define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
+ 
+ /* the read-only stuff doesn't really belong here, but any other place is
+    probably as bad and I don't want to create yet another include file. */
+ 
+ #define BLKROSET 4701 /* set device read-only (0 = read-write) */
+ #define BLKROGET 4702 /* get read-only status (0 = read_write) */
+ 
+ #define BMAP_IOCTL 1
+ 
  typedef char buffer_block[BLOCK_SIZE];
  
  struct buffer_head {
***************
*** 107,112 ****
--- 134,140 ----
  	struct task_struct * i_wait;
  	struct task_struct * i_wait2;	/* for pipes */
  	unsigned short i_count;
+ 	unsigned short i_flags;
  	unsigned char i_lock;
  	unsigned char i_dirt;
  	unsigned char i_pipe;
***************
*** 120,125 ****
--- 148,154 ----
  	unsigned short f_flags;
  	unsigned short f_count;
  	unsigned short f_reada;
+ 	unsigned short f_rdev;		/* needed for /dev/tty */
  	struct inode * f_inode;
  	struct file_operations * f_op;
  	off_t f_pos;
***************
*** 159,164 ****
--- 188,194 ----
  	unsigned char s_dirt;
  	/* TUBE */
  	struct super_operations *s_op;
+ 	int s_flags;
  };
  
  struct file_operations {
*** 0.96c/linux/include/linux/config.h	Sun Jul  5 01:28:18 1992
--- linux/include/linux/config.h	Sat Jul 11 20:16:04 1992
***************
*** 26,32 ****
  #define DEF_INITSEG	0x9000
  #define DEF_SYSSEG	0x1000
  #define DEF_SETUPSEG	0x9020
! #define DEF_SYSSIZE	0x4000
  
  /*
   * The root-device is no longer hard-coded. You can change the default
--- 26,32 ----
  #define DEF_INITSEG	0x9000
  #define DEF_SYSSEG	0x1000
  #define DEF_SETUPSEG	0x9020
! #define DEF_SYSSIZE	0x5000
  
  /*
   * The root-device is no longer hard-coded. You can change the default
*** /dev/null	Sat Jul 11 22:43:15 1992
--- linux/include/asm/irq.h	Tue Jul  7 18:45:48 1992
***************
*** 0 ****
--- 1,75 ----
+ #ifndef _ASM_IRQ_H
+ #define _ASM_IRQ_H
+ 
+ /*
+  *	linux/include/asm/irq.h
+  *
+  *	(C) 1992 Linus Torvalds
+  */
+  
+ #define SAVE_ALL \
+ 	"cld\n\t" \
+ 	"push %gs\n\t" \
+ 	"push %fs\n\t" \
+ 	"push %es\n\t" \
+ 	"push %ds\n\t" \
+ 	"pushl %eax\n\t" \
+ 	"pushl %ebp\n\t" \
+ 	"pushl %edi\n\t" \
+ 	"pushl %esi\n\t" \
+ 	"pushl %edx\n\t" \
+ 	"pushl %ecx\n\t" \
+ 	"pushl %ebx\n\t" \
+ 	"movl $0x10,%edx\n\t" \
+ 	"mov %dx,%ds\n\t" \
+ 	"mov %dx,%es\n\t" \
+ 	"movl $0x17,%edx\n\t" \
+ 	"mov %dx,%fs\n\t"
+ 
+ #define ACK_FIRST(mask) \
+ 	"inb $0x21,%al\n\t" \
+ 	"jmp 1f\n" \
+ 	"1:\tjmp 1f\n" \
+ 	"1:\torb $" #mask ",%al\n\t" \
+ 	"outb %al,$0x21\n\t" \
+ 	"jmp 1f\n" \
+ 	"1:\tjmp 1f\n" \
+ 	"1:\tmovb $0x20,%al\n\t" \
+ 	"outb %al,$0x20\n\t"
+ 
+ #define ACK_SECOND(mask) \
+ 	"inb $0xA1,%al\n\t" \
+ 	"jmp 1f\n" \
+ 	"1:\tjmp 1f\n" \
+ 	"1:\torb $" #mask ",%al\n\t" \
+ 	"outb %al,$0xA1\n\t" \
+ 	"jmp 1f\n" \
+ 	"1:\tjmp 1f\n" \
+ 	"1:\tmovb $0x20,%al\n\t" \
+ 	"outb %al,$0xA0" \
+ 	"jmp 1f\n" \
+ 	"1:\tjmp 1f\n" \
+ 	"1:\toutb %al,$0x20\n\t"
+ 
+ #define IRQ_NAME2(nr) nr##_interrupt()
+ #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+ 	
+ #define BUILD_IRQ(chip,nr,mask) \
+ extern void IRQ_NAME(nr); \
+ __asm__( \
+ "\n.align 2\n" \
+ ".globl _IRQ" #nr "_interrupt\n" \
+ "_IRQ" #nr "_interrupt:\n\t" \
+ 	"pushl $-1\n\t" \
+ 	SAVE_ALL \
+ 	"cli\n\t" \
+ 	ACK_##chip(mask) \
+ 	"sti\n\t" \
+ 	"movl %esp,%ebx\n\t" \
+ 	"pushl %ebx\n\t" \
+ 	"pushl $" #nr "\n\t" \
+ 	"call _do_IRQ\n\t" \
+ 	"addl $8,%esp\n\t" \
+ 	"jmp ret_from_sys_call");
+ 
+ #endif