Linux v. 0.97 is out

Linux version 0.97 is available as both a complete source-tree
(linux-0.97.tar.Z) and a bootimage (bootimage-0.97.Z) on the normal
ftp-sites. It's in incoming on tsx-11.mit.edu, so it will take a day or
two to actually show up, but it's available right now on

	nic.funet.fi:
		pub/OS/Linux/testing/Linus/
	banjo.concert.net:
		pub/Linux/Linus/

The nic.funet.fi-directory is under 'testing' not so much because this
would be a testing-release, but because the directory-setup is in
testing :-). I think 'testing' is unreadable, so you have to cd to the
directory blindly.

There is also a kernel-compilation README (written by Lars Wirzenius),
as well as a COPYING (which is just a pointer to the GNU copyleft). The
latter not because anything has changed, but because I got a few mails
pointing out that the copyright of linux wasn't too clear. That also
resulted in changing the '(C)'s in the source to 'Copyright'.

Changes in 0.97:

 - The VESA-support was removed. I'd be happy to put it back once it
   works on all hardware. Instead of the VESA-code, I finally put in
   the automatic SVGA setup patches. See the top-level Makefile.

 - The IRQ code has solidified, and should work on all machines. Not
   all of the SCSI drivers use it yet, so I expect patches for that..

 - Serial interrupts are handled slightly differently, and performance
   should be up. I've sent out a few alpha-releases, and testing seems
   to indicate that's actually true this time. Reactions have ranged
   from "nice" to "wonderful" :-)

 - The buffer-cache and memory management code has been edited quite a
   bit. ps/free etc programs that reads kernel memory directly no
   longer work, and even a recompilation won't be enough. They actually
   need editing before they work.

   The buffer-cache now grows and shrinks dynamically depending on how
   much free memory there is. Shift+PrintScreen will give some memory
   statistics. (Ctrl+PrSc gives task-info, ALT+PrSc gives current
   register values).

   The mm code changes removed some race-conditions in the VM code, and
   I also tried to make the Out-of-swapspace error less severe (better
   thrashing-detection etc).

 - The super-block code has been cleaned up. Especially the extended fs
   needs to be edited a bit to take advantage of the new setup, and I
   expect Remy Card will have a patch out eventually.

 - include-files have been moved around some more: there are still some
   names that clash with the standard headers, but not many.

 - Unswappable processes implemented: by default only 'init' is
   unswappable. This is a bit safer in low-memory conditions, as at
   least init won't die due to low memory. I also made killing init
   impossible: if init doesn't recognize a signal, it simply won't get
   it. Some other changes ("while (1) fork();" won't kill the machine
   for non-root users etc)

 - The new SCSI drivers are in. These make the kernel noticeably
   bigger, but you can leave them out if you don't want them.

 - The floppy- and hd-drivers print out more debugging-info in case of
   errors: this might be irritating if you have hardware that works, but
   often gives soft-errors. On the other hand, some old debugging-info
   was removed - notably for user-level protection errors etc.

 - Various minor fixes. I haven't made cdiffs (and I haven't gotten any
   requests for them, so I probably never will), but they would be
   pretty big.

Things that I didn't have time for:

 - I wanted to rewrite the tty drivers to be more "streams-like" (ie not
   an actual streams-implementation, but some of the ideas from
   streams). I never got around to it: there was simply too much else
   to do.

 - I got a lot of patches, and some went in, others didn't. If you
   think your patch was important, please re-send it relative to the new
   version.

I'd like comments on the new system: performance / clarity of code etc.
0.97 should correct all known bugs (at least the ones I know about), but
I guess that's just wishful thinking.

Note that the dynamic buffer-code also handles differently-sized
buffers, but that the rest of the system (block device drivers,
filesystem code etc) cannot yet take advantage of this - there is still
some coding needed.

		Linus
diff --git a/Makefile b/Makefile
index ec70574..39e87db 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,7 @@
 # KEYBOARD = -DKBD_DVORAK -DKBDFLAGS=0
 # KEYBOARD = -DKBD_SG -DKBDFLAGS=0
 # KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x9F
+# KEYBOARD = -DKDB_NO
 
 #
 # comment this line if you don't want the emulation-code
@@ -59,6 +60,14 @@
 AS86	=as86 -0 -a
 LD86	=ld86 -0
 
+#
+# If you want to preset the SVGA mode, uncomment the next line and
+# set SVGA_MODE to whatever number you want.
+# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
+# The number is the same as you would ordinarily press at bootup.
+#
+#SVGA_MODE=	-DSVGA_MODE=1
+
 AS	=as
 LD	=ld
 HOSTCC	=gcc -static
@@ -86,12 +95,12 @@
 
 all:	Version Image
 
-subdirs: dummy
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
+linuxsubdirs: dummy
+	@for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE)) || exit; done
 
 Version:
 	@./makever.sh
-	@echo \#define UTS_RELEASE \"0.96c.pl2-`cat .version`\" > include/linux/config_rel.h
+	@echo \#define UTS_RELEASE \"0.97-`cat .version`\" > include/linux/config_rel.h
 	@echo \#define UTS_VERSION \"`date +%D`\" > include/linux/config_ver.h
 	touch include/linux/config.h
 
@@ -103,7 +112,7 @@
 	sync
 
 disk: Image
-	dd bs=8192 if=Image of=/dev/PS0
+	dd bs=8192 if=Image of=/dev/fd0
 
 tools/build: tools/build.c
 	$(HOSTCC) $(CFLAGS) \
@@ -111,7 +120,7 @@
 
 boot/head.o: boot/head.s
 
-tools/system:	boot/head.o init/main.o subdirs
+tools/system:	boot/head.o init/main.o linuxsubdirs
 	$(LD) $(LDFLAGS) -M boot/head.o init/main.o \
 		$(ARCHIVES) \
 		$(FILESYSTEMS) \
@@ -125,7 +134,7 @@
 	$(LD86) -s -o boot/setup boot/setup.o
 
 boot/setup.s:	boot/setup.S include/linux/config.h
-	$(CPP) -traditional boot/setup.S -o boot/setup.s
+	$(CPP) -traditional $(SVGA_MODE) boot/setup.S -o boot/setup.s
 
 boot/bootsect.s:	boot/bootsect.S include/linux/config.h
 	$(CPP) -traditional boot/bootsect.S -o boot/bootsect.s
@@ -134,6 +143,9 @@
 	$(AS86) -o boot/bootsect.o boot/bootsect.s
 	$(LD86) -s -o boot/bootsect boot/bootsect.o
 
+fs: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=fs
+
 clean:
 	rm -f Image System.map tmp_make core boot/bootsect boot/setup \
 		boot/bootsect.s boot/setup.s init/main.s
@@ -148,18 +160,19 @@
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
 	for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done >> tmp_make
 	cp tmp_make Makefile
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
+	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep) || exit; done
 
 dummy:
 
 ### Dependencies:
-init/main.o : init/main.c /usr/src/linux/include/stddef.h /usr/src/linux/include/stdarg.h \
-  /usr/src/linux/include/time.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/asm/system.h \
-  /usr/src/linux/include/asm/io.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/config.h \
-  /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
-  /usr/src/linux/include/linux/config.dist.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/signal.h /usr/src/linux/include/sys/param.h \
-  /usr/src/linux/include/sys/time.h /usr/src/linux/include/sys/resource.h /usr/src/linux/include/linux/tty.h \
-  /usr/src/linux/include/termios.h /usr/src/linux/include/linux/unistd.h 
+init/main.o : init/main.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/time.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/linux/unistd.h 
diff --git a/boot/bootsect.S b/boot/bootsect.S
index 22ebdea..b69e95c 100644
--- a/boot/bootsect.S
+++ b/boot/bootsect.S
@@ -6,7 +6,7 @@
 #include <linux/config.h>
 SYSSIZE = DEF_SYSSIZE
 !
-!	bootsect.s		(C) 1991 Linus Torvalds
+!	bootsect.s		Copyright (C) 1991, 1992 Linus Torvalds
 !	modified by Drew Eckhardt
 !	modified by Bruce Evans (bde)
 !
diff --git a/boot/head.s b/boot/head.s
index 0377139..30ef2d8 100644
--- a/boot/head.s
+++ b/boot/head.s
@@ -1,7 +1,7 @@
 /*
  *  linux/boot/head.s
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -13,6 +13,9 @@
  */
 .text
 .globl _idt,_gdt,_pg_dir,_tmp_floppy_area,_floppy_track_buffer
+/*
+ * pg_dir is the main page directory, address 0x00000000
+ */
 _pg_dir:
 startup_32:
 	cld
@@ -148,6 +151,23 @@
 
 .org 0x5000
 /*
+ * empty_bad_page is a bogus page that will be used when out of memory,
+ * so that a process isn't accidentally killed due to a page fault when
+ * it is running in kernel mode..
+ */
+.globl _empty_bad_page
+_empty_bad_page:
+
+.org 0x6000
+/*
+ * empty_bad_page_table is similar to the above, but is used when the
+ * system needs a bogus page-table
+ */
+.globl _empty_bad_page_table
+_empty_bad_page_table:
+
+.org 0x7000
+/*
  * tmp_floppy_area is used by the floppy-driver when DMA cannot
  * reach to a buffer-block. It needs to be aligned, so that it isn't
  * on a 64kB border.
diff --git a/boot/setup.S b/boot/setup.S
index 88c23cd..cf4ae0e 100644
--- a/boot/setup.S
+++ b/boot/setup.S
@@ -1,5 +1,5 @@
 !
-!	setup.s		(C) 1991 Linus Torvalds
+!	setup.s		Copyright (C) 1991, 1992 Linus Torvalds
 !
 ! setup.s is responsible for getting the system data from the BIOS,
 ! and putting them into the appropriate places in system memory.
@@ -14,6 +14,7 @@
 
 ! NOTE! These had better be the same as in bootsect.s!
 #include <linux/config.h>
+#define NORMAL_VGA 0xffff
 
 INITSEG  = DEF_INITSEG	! we move boot here - out of the way
 SYSSEG   = DEF_SYSSEG	! system loaded at 0x10000 (65536).
@@ -242,75 +243,11 @@
 	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 	ax,#0xc000
 	mov	es,ax
 	lea	si,msg1
-	call	prtstr			! Press <RETURN> to see SVGA-modes ...
+	call	prtstr
+#ifndef SVGA_MODE
 flush:	in	al,#0x60		! Flush the keyboard buffer
 	cmp	al,#0x82
 	jb	nokey
@@ -322,9 +259,12 @@
 	ja	nokey
 	cmp	al,#0x9c
 	je	svga
+#endif
+#if !defined(SVGA_MODE) || SVGA_MODE == NORMAL_VGA
 	mov	ax,#0x5019
 	pop	ds
 	ret
+#endif
 svga:	cld
 	lea 	si,idati		! Check ATI 'clues'
 	mov	di,#0x31
@@ -529,38 +469,23 @@
 	mov	al,#0x55
 	xor	al,#0xea
 	cmp	al,bh
-	je	isvideo7
-	lea	cx,set8x8
-	jmp	cx
-isvideo7:
+	jne	novid7
 	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
+	lea	si,msg2
 	call	prtstr
-	mov	cx,(di)			! This gets Number of Modes in list
+	xor	cx,cx
+	mov	cl,(di)
 	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
+	mov	al,bl
+	sub	al,cl
+	call	dprnt
 	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
@@ -574,10 +499,13 @@
 	loop	tbl
 	pop	cx
 	call	docr
-	lea	si,msg3			! Choose Mode Number
+	lea	si,msg3
 	call	prtstr
 	pop	si
 	add	cl,#0x80
+#if defined(SVGA_MODE) && SVGA_MODE != NORMAL_VGA
+	mov	al,#SVGA_MODE		! Preset SVGA mode 
+#else
 nonum:	call	getkey
 	cmp	al,#0x82
 	jb	nonum
@@ -589,39 +517,20 @@
 zero:	sub	al,#0x0a
 nozero:	sub	al,#0x80
 	dec	al
+#endif
 	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:
+	push	ax
+	mov	al,(di)
+	int 	0x10
 	pop	ax
+	shl	ax,#1
 	add	si,ax
-	lodsw				! Get COLSxROWS
+	lodsw
 	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:
+novid7:
 	mov	ax,#0x1112
 	mov	bl,#0
 	int	0x10		! use 8x8 font set (50 lines on VGA)
@@ -642,83 +551,17 @@
 	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
+	mov	al,#0x20
 	call	prnt1	
-space3:	mov	al,#0x20
+	mov	al,#0x20
 	call	prnt1	
-space2:	mov	al,#0x20
+	mov	al,#0x20
 	call	prnt1	
-space:	mov	al,#0x20
+	mov	al,#0x20
 	call	prnt1
 	ret	
 
@@ -731,39 +574,6 @@
 	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). 
 
@@ -835,7 +645,7 @@
 
 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:"
+msg2:		.ascii	"Mode:  COLSxROWS:"
 		db	0x0d, 0x0a, 0x0a, 0x00
 msg3:		.ascii	"Choose mode by pressing the corresponding number."
 		db	0x0d, 0x0a, 0x00
@@ -847,17 +657,16 @@
 
 ! 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
+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:
 
@@ -871,11 +680,7 @@
 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
diff --git a/fs/Makefile b/fs/Makefile
index 6a8403d..bfe604b 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -20,13 +20,13 @@
 	block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
 	select.o fifo.o
 
-all: fs.o subdirs
+all: fs.o fssubdirs
 
 fs.o: $(OBJS)
 	$(LD) -r -o fs.o $(OBJS)
 
-subdirs: dummy
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
+fssubdirs: dummy
+	@for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE)) || exit; done
 
 clean:
 	rm -f core *.o *.a tmp_make
@@ -37,118 +37,137 @@
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
 	for i in *.c;do $(CPP) -M $$i;done >> tmp_make
 	cp tmp_make Makefile
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
+	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep) || exit; done
 
 dummy:
 
 ### Dependencies:
-block_dev.o : block_dev.c /usr/src/linux/include/errno.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/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 /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/asm/segment.h \
-  /usr/src/linux/include/asm/system.h 
+block_dev.o : block_dev.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h 
 buffer.o : buffer.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/linux/config.h \
   /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
   /usr/src/linux/include/linux/config.dist.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/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 /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/asm/system.h \
-  /usr/src/linux/include/asm/io.h 
-exec.o : exec.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/a.out.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h \
-  /usr/src/linux/include/linux/fcntl.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/sched.h \
-  /usr/src/linux/include/linux/head.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/segment.h /usr/src/linux/include/sys/user.h 
-fcntl.o : fcntl.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/string.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/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 
-fifo.o : fifo.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/fcntl.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.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/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 
-file_table.o : file_table.c /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 
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.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/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/asm/system.h 
-ioctl.o : ioctl.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/string.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.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/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 
-namei.o : namei.c /usr/src/linux/include/errno.h /usr/src/linux/include/const.h \
-  /usr/src/linux/include/asm/segment.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/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 \
-  /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/linux/string.h \
-  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h 
-open.o : open.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/utime.h /usr/src/linux/include/sys/vfs.h \
-  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/string.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/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/asm/segment.h 
-pipe.o : pipe.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/termios.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/fcntl.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 
-read_write.o : read_write.c /usr/src/linux/include/errno.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/linux/stat.h /usr/src/linux/include/linux/kernel.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/vfs.h \
-  /usr/src/linux/include/linux/mm.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/linux/minix_fs.h /usr/src/linux/include/asm/segment.h 
-select.o : select.c /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 /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/sched.h \
-  /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.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/linux/string.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/const.h \
-  /usr/src/linux/include/errno.h 
-stat.o : stat.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.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 \
+  /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h 
+exec.o : exec.c /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
   /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /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/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/a.out.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/ptrace.h \
+  /usr/src/linux/include/linux/user.h /usr/src/linux/include/asm/segment.h 
+fcntl.o : fcntl.c /usr/src/linux/include/asm/segment.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/string.h 
+fifo.o : fifo.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/fcntl.h 
+file_table.o : file_table.c /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/string.h 
+inode.o : inode.c /usr/src/linux/include/linux/stat.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/system.h 
+ioctl.o : ioctl.c /usr/src/linux/include/asm/segment.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h 
+namei.o : namei.c /usr/src/linux/include/const.h /usr/src/linux/include/asm/segment.h \
+  /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h 
+open.o : open.c /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/utime.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/string.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
   /usr/src/linux/include/asm/segment.h 
+pipe.o : pipe.c /usr/src/linux/include/asm/segment.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/termios.h 
+read_write.o : read_write.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/kernel.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h /usr/src/linux/include/linux/minix_fs.h \
+  /usr/src/linux/include/asm/segment.h 
+select.o : select.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/segment.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/const.h 
+stat.o : stat.c /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/stat.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/sched.h \
+  /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h /usr/src/linux/include/asm/segment.h 
 super.o : super.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
   /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.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/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 /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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
   /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/ext_fs.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/errno.h 
+  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/stat.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c102c94..8bb0add 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1,11 +1,10 @@
 /*
  *  linux/fs/block_dev.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
@@ -36,7 +35,7 @@
 		if (chars > count)
 			chars=count;
 		if (chars == BLOCK_SIZE)
-			bh = getblk(dev,block);
+			bh = getblk(dev, block, BLOCK_SIZE);
 		else
 			bh = breada(dev,block,block+1,block+2,-1);
 		block++;
diff --git a/fs/buffer.c b/fs/buffer.c
index 571c3b5..f8efd1f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/buffer.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -23,15 +23,18 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 
-extern int end;
-static struct buffer_head * start_buffer = (struct buffer_head *) &end;
 static struct buffer_head * hash_table[NR_HASH];
-static struct buffer_head * free_list;
+static struct buffer_head * free_list = NULL;
+static struct buffer_head * unused_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
-int NR_BUFFERS = 0;
+
+int nr_buffers = 0;
+int nr_buffer_heads = 0;
 
 static inline void wait_on_buffer(struct buffer_head * bh)
 {
@@ -47,7 +50,7 @@
 	struct buffer_head * bh;
 
 	bh = free_list;
-	for (i = NR_BUFFERS*2 ; i-- > 0 ; bh = bh->b_next_free) {
+	for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
 		if (bh->b_lock)
 			continue;
 		if (!bh->b_dirt)
@@ -89,8 +92,8 @@
 	int i;
 	struct buffer_head * bh;
 
-	bh = start_buffer;
-	for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
+	bh = free_list;
+	for (i = nr_buffers*2 ; --i > 0 ; bh = bh->b_next_free) {
 		if (bh->b_dev != dev)
 			continue;
 		wait_on_buffer(bh);
@@ -120,7 +123,7 @@
 
 	if (MAJOR(dev) != 2)
 		return;
-	if (!(bh = getblk(dev,0)))
+	if (!(bh = getblk(dev,0,1024)))
 		return;
 	i = floppy_change(bh);
 	brelse(bh);
@@ -211,13 +214,18 @@
 		bh->b_next->b_prev = bh;
 }
 
-static struct buffer_head * find_buffer(int dev, int block)
+static struct buffer_head * find_buffer(int dev, int block, int size)
 {		
 	struct buffer_head * tmp;
 
 	for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
 		if (tmp->b_dev==dev && tmp->b_blocknr==block)
-			return tmp;
+			if (tmp->b_size == size)
+				return tmp;
+			else {
+				printk("wrong block-size on device %04x\n",dev);
+				return NULL;
+			}
 	return NULL;
 }
 
@@ -228,16 +236,16 @@
  * will force it bad). This shouldn't really happen currently, but
  * the code is ready.
  */
-struct buffer_head * get_hash_table(int dev, int block)
+struct buffer_head * get_hash_table(int dev, int block, int size)
 {
 	struct buffer_head * bh;
 
 	for (;;) {
-		if (!(bh=find_buffer(dev,block)))
+		if (!(bh=find_buffer(dev,block,size)))
 			return NULL;
 		bh->b_count++;
 		wait_on_buffer(bh);
-		if (bh->b_dev == dev && bh->b_blocknr == block) {
+		if (bh->b_dev == dev && bh->b_blocknr == block && bh->b_size == size) {
 			put_last_free(bh);
 			return bh;
 		}
@@ -256,17 +264,23 @@
  * when the filesystem starts to get full of dirty blocks (I hope).
  */
 #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
-struct buffer_head * getblk(int dev,int block)
+struct buffer_head * getblk(int dev, int block, int size)
 {
 	struct buffer_head * bh, * tmp;
 	int buffers;
 
 repeat:
-	if (bh = get_hash_table(dev,block))
+	if (bh = get_hash_table(dev, block, size))
 		return bh;
-	buffers = NR_BUFFERS;
-	for (tmp = free_list ; buffers-- > 0 ; tmp = tmp->b_next_free) {
-		if (tmp->b_count)
+
+	if (nr_free_pages > 30)
+		grow_buffers(size);
+
+	buffers = nr_buffers;
+	bh = NULL;
+
+	for (tmp = free_list; buffers-- > 0 ; tmp = tmp->b_next_free) {
+		if (tmp->b_count || tmp->b_size != size)
 			continue;
 		if (!bh || BADNESS(tmp)<BADNESS(bh)) {
 			bh = tmp;
@@ -278,13 +292,19 @@
 			ll_rw_block(WRITEA,tmp);
 #endif
 	}
+
+	if (!bh && nr_free_pages > 5) {
+		grow_buffers(size);
+		goto repeat;
+	}
+	
 /* and repeat until we find something good */
 	if (!bh) {
 		sleep_on(&buffer_wait);
 		goto repeat;
 	}
 	wait_on_buffer(bh);
-	if (bh->b_count)
+	if (bh->b_count || bh->b_size != size)
 		goto repeat;
 	if (bh->b_dirt) {
 		sync_buffers(bh->b_dev);
@@ -292,7 +312,7 @@
 	}
 /* NOTE!! While we slept waiting for this block, somebody else might */
 /* already have added "this" block to the cache. check it */
-	if (find_buffer(dev,block))
+	if (find_buffer(dev,block,size))
 		goto repeat;
 /* OK, FINALLY we know that this buffer is the only one of it's kind, */
 /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
@@ -320,12 +340,14 @@
  * bread() reads a specified block and returns the buffer that contains
  * it. It returns NULL if the block was unreadable.
  */
-struct buffer_head * bread(int dev,int block)
+struct buffer_head * bread(int dev, int block, int size)
 {
 	struct buffer_head * bh;
 
-	if (!(bh=getblk(dev,block)))
-		panic("bread: getblk returned NULL\n");
+	if (!(bh = getblk(dev, block, size))) {
+		printk("bread: getblk returned NULL\n");
+		return NULL;
+	}
 	if (bh->b_uptodate)
 		return bh;
 	ll_rw_block(READ,bh);
@@ -356,7 +378,7 @@
 
 	for (i=0 ; i<4 ; i++)
 		if (b[i]) {
-			if (bh[i] = getblk(dev,b[i]))
+			if (bh[i] = getblk(dev, b[i], 1024))
 				if (!bh[i]->b_uptodate)
 					ll_rw_block(READ,bh[i]);
 		} else
@@ -381,12 +403,14 @@
 	struct buffer_head * bh, *tmp;
 
 	va_start(args,first);
-	if (!(bh=getblk(dev,first)))
-		panic("bread: getblk returned NULL\n");
+	if (!(bh = getblk(dev, first, 1024))) {
+		printk("breada: getblk returned NULL\n");
+		return NULL;
+	}
 	if (!bh->b_uptodate)
 		ll_rw_block(READ,bh);
 	while ((first=va_arg(args,int))>=0) {
-		tmp=getblk(dev,first);
+		tmp = getblk(dev, first, 1024);
 		if (tmp) {
 			if (!tmp->b_uptodate)
 				ll_rw_block(READA,tmp);
@@ -401,42 +425,201 @@
 	return (NULL);
 }
 
-void buffer_init(long buffer_end)
+static void put_unused_buffer_head(struct buffer_head * bh)
 {
-	struct buffer_head * h = start_buffer;
-	void * b;
+	memset((void *) bh,0,sizeof(*bh));
+	bh->b_next_free = unused_list;
+	unused_list = bh;
+}
+
+static void get_more_buffer_heads(void)
+{
+	unsigned long page;
+	struct buffer_head * bh;
+
+	if (unused_list)
+		return;
+	page = get_free_page(GFP_KERNEL);
+	if (!page)
+		return;
+	bh = (struct buffer_head *) page;
+	while ((unsigned long) (bh+1) <= page+4096) {
+		put_unused_buffer_head(bh);
+		bh++;
+		nr_buffer_heads++;
+	}
+}
+
+static struct buffer_head * get_unused_buffer_head(void)
+{
+	struct buffer_head * bh;
+
+	get_more_buffer_heads();
+	if (!unused_list)
+		return NULL;
+	bh = unused_list;
+	unused_list = bh->b_next_free;
+	bh->b_next_free = NULL;
+	bh->b_data = NULL;
+	bh->b_size = 0;
+	return bh;
+}
+
+/*
+ * Try to increase the number of buffers available: the size argument
+ * is used to determine what kind of buffers we want. Currently only
+ * 1024-byte buffers are supported by the rest of the system, but I
+ * think this will change eventually.
+ */
+void grow_buffers(int size)
+{
+	unsigned long page;
+	int i;
+	struct buffer_head *bh, *tmp;
+
+	if ((size & 511) || (size > 4096)) {
+		printk("grow_buffers: size = %d\n",size);
+		return;
+	}
+	page = get_free_page(GFP_BUFFER);
+	if (!page)
+		return;
+	tmp = NULL;
+	i = 0;
+	for (i = 0 ; i+size <= 4096 ; i += size) {
+		bh = get_unused_buffer_head();
+		if (!bh)
+			goto no_grow;
+		bh->b_this_page = tmp;
+		tmp = bh;
+		bh->b_data = (char * ) (page+i);
+		bh->b_size = size;
+		i += size;
+	}
+	tmp = bh;
+	while (1) {
+		tmp->b_next_free = free_list;
+		tmp->b_prev_free = free_list->b_prev_free;
+		free_list->b_prev_free->b_next_free = tmp;
+		free_list->b_prev_free = tmp;
+		free_list = tmp;
+		++nr_buffers;
+		if (tmp->b_this_page)
+			tmp = tmp->b_this_page;
+		else
+			break;
+	}
+	tmp->b_this_page = bh;
+	return;
+/*
+ * In case anything failed, we just free everything we got.
+ */
+no_grow:
+	bh = tmp;
+	while (bh) {
+		tmp = bh;
+		bh = bh->b_this_page;
+		put_unused_buffer_head(tmp);
+	}	
+	free_page(page);
+}
+
+/*
+ * try_to_free() checks if all the buffers on this particular page
+ * are unused, and free's the page if so.
+ */
+static int try_to_free(struct buffer_head * bh)
+{
+	unsigned long page;
+	struct buffer_head * tmp, * p;
+
+	tmp = bh;
+	do {
+		if (!tmp)
+			return 0;
+		if (tmp->b_count || tmp->b_dirt || tmp->b_lock)
+			return 0;
+		tmp = tmp->b_this_page;
+	} while (tmp != bh);
+	page = (unsigned long) bh->b_data;
+	page &= 0xfffff000;
+	tmp = bh;
+	do {
+		p = tmp;
+		tmp = tmp->b_this_page;
+		nr_buffers--;
+		remove_from_queues(p);
+		put_unused_buffer_head(p);
+	} while (tmp != bh);
+	free_page(page);
+	return 1;
+}
+
+/*
+ * Try to free up some pages by shrinking the buffer-cache
+ */
+int shrink_buffers(void)
+{
+	struct buffer_head *bh;
 	int i;
 
-	if (buffer_end == 1<<20)
-		b = (void *) (640*1024);
-	else
-		b = (void *) buffer_end;
-	while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
-		if (((unsigned long) (h+1)) > 0xA0000) {
-			printk("buffer-list doesn't fit in low meg - contact Linus\n");
-			break;
+	bh = free_list;
+	for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
+		wait_on_buffer(bh);
+		if (bh->b_count || !bh->b_this_page)
+			continue;
+		if (bh->b_dirt) {
+			ll_rw_block(WRITEA,bh);
+			continue;
 		}
-		h->b_dev = 0;
-		h->b_dirt = 0;
-		h->b_count = 0;
-		h->b_lock = 0;
-		h->b_uptodate = 0;
-		h->b_wait = NULL;
-		h->b_next = NULL;
-		h->b_prev = NULL;
-		h->b_data = (char *) b;
-		h->b_reqnext = NULL;
-		h->b_prev_free = h-1;
-		h->b_next_free = h+1;
-		h++;
-		NR_BUFFERS++;
-		if (b == (void *) 0x100000)
-			b = (void *) 0xA0000;
+		if (try_to_free(bh))
+			return 1;
 	}
-	h--;
-	free_list = start_buffer;
-	free_list->b_prev_free = h;
-	h->b_next_free = free_list;
-	for (i=0;i<NR_HASH;i++)
+	return 0;
+}
+
+/*
+ * This initializes the low 1M that isn't used by the kernel to buffer
+ * cache. It should really be used for paging memory, but it takes a lot
+ * of special-casing, which I don't want to do.
+ *
+ * The biggest problem with this approach is that all low-mem buffers
+ * have a fixed size of 1024 chars: not good if/when the other sizes
+ * are implemented.
+ */
+void buffer_init(void)
+{
+	struct buffer_head * bh;
+	extern int end;
+	unsigned long mem;
+	int i;
+
+	for (i = 0 ; i < NR_HASH ; i++)
 		hash_table[i] = NULL;
-}	
+	mem = (unsigned long) & end;
+	mem += BLOCK_SIZE-1;
+	mem &= ~(BLOCK_SIZE-1);
+	free_list = get_unused_buffer_head();
+	if (!free_list)
+		panic("unable to get a single buffer-head");
+	free_list->b_prev_free = free_list;
+	free_list->b_next_free = free_list;
+	free_list->b_data = (char *) mem;
+	free_list->b_size = BLOCK_SIZE;
+	mem += BLOCK_SIZE;
+	while (mem + 1024 < 0xA0000) {
+		bh = get_unused_buffer_head();
+		if (!bh)
+			break;
+		bh->b_data = (char *) mem;
+		bh->b_size = BLOCK_SIZE;
+		mem += BLOCK_SIZE;
+		bh->b_next_free = free_list;
+		bh->b_prev_free = free_list->b_prev_free;
+		free_list->b_prev_free->b_next_free = bh;
+		free_list->b_prev_free = bh;
+		free_list = bh;
+		++nr_buffers;
+	}
+	return;
+}
diff --git a/fs/exec.c b/fs/exec.c
index 8a5b0af..2be1aa3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/exec.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -17,20 +17,20 @@
  * was less than 2 hours work to get demand-loading completely implemented.
  */
 
-#include <signal.h>
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <a.out.h>
-
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
 #include <asm/segment.h>
-#include <sys/user.h>
 
 extern int sys_exit(int exit_code);
 extern int sys_close(int fd);
@@ -169,8 +169,6 @@
 	struct inode * inode;
 	struct buffer_head * bh;
 	struct exec ex;
-	int i;
-	struct file * f;
 
 	if (get_limit(0x17) != TASK_SIZE)
 		return -EINVAL;
@@ -182,23 +180,18 @@
 		inode = NULL;
 	if (!inode)
 		return -ENOENT;
-	if (!S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
+	if (!inode->i_sb || !S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
 		iput(inode);
 		return -EACCES;
 	}
- 	if (inode->i_count > 1) {		/* check for writers */
- 		f=0+file_table;
- 		for (i=0 ; i<NR_FILE ; i++,f++ )
- 			if (f->f_count && (f->f_mode & 2))
- 				if (inode == f->f_inode) {
- 					iput(inode);
- 					return -ETXTBSY;
- 				}
- 	}
-	if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
+	if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
 		iput(inode);
 		return -EACCES;
 	}
+	if (!IS_RDONLY(inode)) {
+		inode->i_atime = CURRENT_TIME;
+		inode->i_dirt = 1;
+	}
 	ex = *(struct exec *) bh->b_data;
 	brelse(bh);
 	if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
@@ -320,7 +313,7 @@
 					set_fs(old_fs);
 				if (!(pag = (char *) page[p/PAGE_SIZE]) &&
 				    !(pag = (char *) page[p/PAGE_SIZE] =
-				      (unsigned long *) get_free_page())) 
+				      (unsigned long *) get_free_page(GFP_USER))) 
 					return 0;
 				if (from_kmem==2)
 					set_fs(new_fs);
@@ -363,13 +356,17 @@
 	struct buffer_head *bh;
 	int n, blkno, blk = 0;
 	char *dest = (char *) 0;
+	unsigned int block_size;
 
+	block_size = 1024;
+	if (inode->i_sb)
+		block_size = inode->i_sb->s_blocksize;
 	while (bytes > 0) {
 		if (!(blkno = bmap(inode, blk)))
 			sys_exit(-1);
-		if (!(bh = bread(inode->i_dev, blkno)))
+		if (!(bh = bread(inode->i_dev, blkno, block_size)))
 			sys_exit(-1);
-		n = (blk ? BLOCK_SIZE : BLOCK_SIZE - sizeof(struct exec));
+		n = (blk ? block_size : block_size - sizeof(struct exec));
 		if (bytes < n)
 			n = bytes;
 
@@ -403,7 +400,6 @@
 	int sh_bang = 0;
 	unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
 	int ch;
-	struct file * f;
 
 	if ((0xffff & eip[1]) != 0x000f)
 		panic("execve called from supervisor mode");
@@ -411,15 +407,6 @@
 		page[i]=0;
 	if (!(inode=namei(filename)))		/* get executables inode */
 		return -ENOENT;
-	if (inode->i_count > 1) {		/* check for writers */
-		f=0+file_table;
-		for (i=0 ; i<NR_FILE ; i++,f++ )
-			if (f->f_count && (f->f_mode & 2))
-				if (inode == f->f_inode) {
-					retval = -ETXTBSY;
-					goto exec_error2;
-				}
-	}
 	argc = count(argv);
 	envc = count(envp);
 	
@@ -432,6 +419,10 @@
 		retval = -EPERM;
 		goto exec_error2;
 	}
+	if (!inode->i_sb) {
+		retval = -EACCES;
+		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)) &&
@@ -456,10 +447,14 @@
 		retval = -EACCES;
 		goto exec_error2;
 	}
-	if (!(bh = bread(inode->i_dev,bmap(inode,0)))) {
+	if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
 		retval = -EACCES;
 		goto exec_error2;
 	}
+	if (!IS_RDONLY(inode)) {
+		inode->i_atime = CURRENT_TIME;
+		inode->i_dirt = 1;
+	}
 	ex = *((struct exec *) bh->b_data);	/* read exec-header */
 	if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
 		/*
diff --git a/fs/ext/Makefile b/fs/ext/Makefile
index d498dda..43fc4e1 100644
--- a/fs/ext/Makefile
+++ b/fs/ext/Makefile
@@ -30,79 +30,99 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-bitmap.o : bitmap.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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/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/linux/ext_fs.h 
+bitmap.o : bitmap.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/string.h 
 blkdev.o : blkdev.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 \
-  /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/linux/ext_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/errno.h 
 chrdev.o : chrdev.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 \
-  /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/linux/ext_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h 
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.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 \
-  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/stat.h 
-fifo.o : fifo.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 \
-  /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/linux/ext_fs.h 
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/dirent.h \
-  /usr/src/linux/include/limits.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.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/vfs.h /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/linux/ext_fs.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/errno.h 
+dir.o : dir.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/ext_fs.h \
   /usr/src/linux/include/linux/stat.h 
-freelists.o : freelists.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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/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/linux/ext_fs.h 
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.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/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/linux/ext_fs.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h 
-namei.o : namei.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 \
-  /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/linux/ext_fs.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h /usr/src/linux/include/const.h 
-symlink.o : symlink.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
+fifo.o : fifo.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h 
+file.o : file.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.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/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 /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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/stat.h 
+freelists.o : freelists.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/string.h 
+inode.o : inode.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h 
+namei.o : namei.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/const.h 
+symlink.o : symlink.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
   /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/stat.h 
 truncate.o : truncate.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 \
-  /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/linux/ext_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/errno.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ext_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/errno.h 
diff --git a/fs/ext/bitmap.c b/fs/ext/bitmap.c
index f5bad9f..ee68e68 100644
--- a/fs/ext/bitmap.c
+++ b/fs/ext/bitmap.c
@@ -1,22 +1,22 @@
 /*
  *  linux/fs/ext/bitmap.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/bitmap.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /* bitmap.c contains the code that handles the inode and block bitmaps */
 
 
-#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #ifdef EXTFS_BITMAP
 
diff --git a/fs/ext/blkdev.c b/fs/ext/blkdev.c
index 9931276..74dd9fe 100644
--- a/fs/ext/blkdev.c
+++ b/fs/ext/blkdev.c
@@ -1,13 +1,13 @@
 /*
  *  linux/fs/ext/blkdev.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/blkdev.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
@@ -15,8 +15,7 @@
 #include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-
-#include <errno.h>
+#include <linux/errno.h>
 
 /*
  * Called every time an ext block special file is opened
diff --git a/fs/ext/chrdev.c b/fs/ext/chrdev.c
index 537972e..b1b55ea 100644
--- a/fs/ext/chrdev.c
+++ b/fs/ext/chrdev.c
@@ -1,13 +1,13 @@
 /*
  *  linux/fs/ext/chrdev.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/chrdev.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
@@ -15,8 +15,7 @@
 #include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-
-#include <errno.h>
+#include <linux/errno.h>
 
 /*
  * Called every time an ext character special file is opened
diff --git a/fs/ext/dir.c b/fs/ext/dir.c
index 730d5a1..54bc7ad 100644
--- a/fs/ext/dir.c
+++ b/fs/ext/dir.c
@@ -1,21 +1,20 @@
 /*
  *  linux/fs/ext/dir.c
  *
- *  (C) 1992 Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/dir.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  ext directory handling functions
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
 
+#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ext_fs.h>
 #include <linux/stat.h>
@@ -68,7 +67,7 @@
 	while (filp->f_pos < inode->i_size) {
 		offset = filp->f_pos & 1023;
 		block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
-		if (!block || !(bh = bread(inode->i_dev,block))) {
+		if (!block || !(bh = bread(inode->i_dev, block, BLOCK_SIZE))) {
 			filp->f_pos += 1024-offset;
 			continue;
 		}
diff --git a/fs/ext/file.c b/fs/ext/file.c
index 3fe77d3..ec366aa 100644
--- a/fs/ext/file.c
+++ b/fs/ext/file.c
@@ -1,28 +1,25 @@
 /*
  *  linux/fs/ext/file.c
  *
- *  (C) 1992 Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/file.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  ext regular file handling primitives
  */
 
-#include <errno.h>
-
-#include <sys/dirent.h>
-
 #include <asm/segment.h>
 #include <asm/system.h>
 
-#include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
 #include <linux/stat.h>
 
 #define	NBUF	16
@@ -108,7 +105,7 @@
 		if (blocks) {
 			--blocks;
 			if (nr = ext_bmap(inode,block++)) {
-				*bhb = getblk(inode->i_dev,nr);
+				*bhb = getblk(inode->i_dev, nr, BLOCK_SIZE);
 				if (!(*bhb)->b_uptodate)
 					ll_rw_block(READ,*bhb);
 			} else
@@ -194,9 +191,9 @@
 		if (c > count-written)
 			c = count-written;
 		if (c == BLOCK_SIZE)
-			bh = getblk(inode->i_dev, block);
+			bh = getblk(inode->i_dev, block, BLOCK_SIZE);
 		else
-			bh = bread(inode->i_dev,block);
+			bh = bread(inode->i_dev, block, BLOCK_SIZE);
 		if (!bh) {
 			if (!written)
 				written = -EIO;
diff --git a/fs/ext/freelists.c b/fs/ext/freelists.c
index 118fe09..e39f442 100644
--- a/fs/ext/freelists.c
+++ b/fs/ext/freelists.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/ext/freelists.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  */
 
@@ -15,7 +15,7 @@
    free blocks and the number of the next block in the list.
 
    When an ext fs is mounted, the number of the first free block is stored
-   in s->s_zmap[0] and the block header is stored in s->s_zmap[1]. s_zmap[2]
+   in s->u.ext_sb.s_zmap[0] and the block header is stored in s->u.ext_sb.s_zmap[1]. u.ext_sb.s_zmap[2]
    contains the count of free blocks.
 
    Currently, it is a hack to allow this kind of management with the super_block
@@ -27,17 +27,16 @@
    super block contains the number of the first free inode. This inode contains
    14 numbers of other free inodes and the number of the next inode in the list.
    
-   The number of the first free inode is stored in s->s_imap[0] and the header
-   of the block containing the inode is stored in s->s_imap[1]. s_imap[2] contains
+   The number of the first free inode is stored in s->u.ext_sb.s_imap[0] and the header
+   of the block containing the inode is stored in s->u.ext_sb.s_imap[1]. u.ext_sb.s_imap[2] contains
    the count of free inodes.
 
 */
 
-#include <linux/string.h>
-
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #ifdef EXTFS_FREELIST
 
@@ -56,9 +55,9 @@
 	if (!(sb = get_super(dev)))
 		panic("trying to free block on nonexistent device");
 	lock_super (sb);
-	if (block < sb->s_firstdatazone || block >= sb->s_nzones)
+	if (block < sb->u.ext_sb.s_firstdatazone || block >= sb->u.ext_sb.s_nzones)
 		panic("trying to free block not in datazone");
-	bh = get_hash_table(dev,block);
+	bh = get_hash_table(dev, block, sb->s_blocksize);
 	if (bh) {
 		if (bh->b_count > 1) {
 			brelse(bh);
@@ -70,26 +69,26 @@
 		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) {
+	if (sb->u.ext_sb.s_zmap[1])
+		efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data;
+	if (!sb->u.ext_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)))
+		if (sb->u.ext_sb.s_zmap[1])
+			brelse (sb->u.ext_sb.s_zmap[1]);
+		if (!(sb->u.ext_sb.s_zmap[1] = bread (dev, block, sb->s_blocksize)))
 			panic ("ext_free_block: unable to read block to free\n");
-		efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
-		efb->next = (unsigned long) sb->s_zmap[0];
+		efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data;
+		efb->next = (unsigned long) sb->u.ext_sb.s_zmap[0];
 		efb->count = 0;
-		sb->s_zmap[0] = (struct buffer_head *) block;
+		sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) block;
 	} else {
 		efb->free[efb->count++] = block;
 	}
-	sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) + 1);
+	sb->u.ext_sb.s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->u.ext_sb.s_zmap[2]) + 1);
 	sb->s_dirt = 1;
-	sb->s_zmap[1]->b_dirt = 1;
+	sb->u.ext_sb.s_zmap[1]->b_dirt = 1;
 	free_super (sb);
 	return 1;
 }
@@ -103,35 +102,35 @@
 
 	if (!(sb = get_super(dev)))
 		panic("trying to get new block from nonexistant device");
-	if (!sb->s_zmap[1])
+	if (!sb->u.ext_sb.s_zmap[1])
 		return 0;
 	lock_super (sb);
-	efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
+	efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data;
 	if (efb->count) {
 		j = efb->free[--efb->count];
-		sb->s_zmap[1]->b_dirt = 1;
+		sb->u.ext_sb.s_zmap[1]->b_dirt = 1;
 	} else {
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: block empty, skipping to %d\n", efb->next);
 #endif
-		j = (unsigned long) sb->s_zmap[0];
-		sb->s_zmap[0] = (struct buffer_head *) efb->next;
-		brelse (sb->s_zmap[1]);
-		if (!sb->s_zmap[0]) {
-			sb->s_zmap[1] = NULL;
+		j = (unsigned long) sb->u.ext_sb.s_zmap[0];
+		sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) efb->next;
+		brelse (sb->u.ext_sb.s_zmap[1]);
+		if (!sb->u.ext_sb.s_zmap[0]) {
+			sb->u.ext_sb.s_zmap[1] = NULL;
 		} else {
-			if (!(sb->s_zmap[1] = bread (dev, (unsigned long) sb->s_zmap[0])))
+			if (!(sb->u.ext_sb.s_zmap[1] = bread (dev, (unsigned long) sb->u.ext_sb.s_zmap[0], sb->s_blocksize)))
 				panic ("ext_new_block: unable to read next free block\n");
 		}
 	}
-	if (j < sb->s_firstdatazone || j > sb->s_nzones) {
+	if (j < sb->u.ext_sb.s_firstdatazone || j > sb->u.ext_sb.s_nzones) {
 		printk ("ext_new_block: blk = %d\n", j);
 		panic ("allocating block not in data zone\n");
 	}
-	sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) - 1);
+	sb->u.ext_sb.s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->u.ext_sb.s_zmap[2]) - 1);
 	sb->s_dirt = 1;
 
-	if (!(bh=getblk(dev,j)))
+	if (!(bh=getblk(dev, j, sb->s_blocksize)))
 		panic("new_block: cannot get block");
 	if (bh->b_count != 1)
 		panic("new block: count is != 1");
@@ -154,14 +153,14 @@
 	unsigned long count, block;
 
 	lock_super (sb);
-	if (!sb->s_zmap[1])
+	if (!sb->u.ext_sb.s_zmap[1])
 		count = 0;
 	else {
-		efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
+		efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data;
 		count = efb->count + 1;
 		block = efb->next;
 		while (block) {
-			if (!(bh = bread (sb->s_dev, block))) {
+			if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
 				printk ("ext_count_free: error while reading free blocks list\n");
 				block = 0;
 			} else {
@@ -173,11 +172,11 @@
 		}
 	}
 printk("ext_count_free_blocks: stored = %d, computed = %d\n",
-	(unsigned long) sb->s_zmap[2], count);
+	(unsigned long) sb->u.ext_sb.s_zmap[2], count);
 	free_super (sb);
 	return count;
 #else
-	return (unsigned long) sb->s_zmap[2];
+	return (unsigned long) sb->u.ext_sb.s_zmap[2];
 #endif
 }
 
@@ -206,35 +205,35 @@
 		return;
 	}
 	lock_super (inode->i_sb);
-	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
+	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.ext_sb.s_ninodes) {
 		printk("free_inode: inode 0 or nonexistent inode\n");
 		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) {
+	if (inode->i_sb->u.ext_sb.s_imap[1])
+		efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) +
+			(((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK;
+	if (!inode->i_sb->u.ext_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]);
+		if (inode->i_sb->u.ext_sb.s_imap[1])
+			brelse (inode->i_sb->u.ext_sb.s_imap[1]);
 		block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
-		if (!(bh = bread(inode->i_dev, block)))
+		if (!(bh = bread(inode->i_dev, block, inode->i_sb->s_blocksize)))
 			panic("ext_free_inode: unable to read inode block\n");
 		efi = ((struct ext_free_inode *) bh->b_data) +
 			(inode->i_ino - 1) % EXT_INODES_PER_BLOCK;
-		efi->next = (unsigned long) inode->i_sb->s_imap[0];
+		efi->next = (unsigned long) inode->i_sb->u.ext_sb.s_imap[0];
 		efi->count = 0;
-		inode->i_sb->s_imap[0] = (struct buffer_head *) inode->i_ino;
-		inode->i_sb->s_imap[1] = bh;
+		inode->i_sb->u.ext_sb.s_imap[0] = (struct buffer_head *) inode->i_ino;
+		inode->i_sb->u.ext_sb.s_imap[1] = bh;
 	} else {
 		efi->free[efi->count++] = inode->i_ino;
 	}
-	inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) + 1);
+	inode->i_sb->u.ext_sb.s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->u.ext_sb.s_imap[2]) + 1);
 	inode->i_sb->s_dirt = 1;
-	inode->i_sb->s_imap[1]->b_dirt = 1;
+	inode->i_sb->u.ext_sb.s_imap[1]->b_dirt = 1;
 	free_super (inode->i_sb);
 	memset(inode,0,sizeof(*inode));
 }
@@ -254,34 +253,34 @@
 		return NULL;
 	}
 	inode->i_flags = inode->i_sb->s_flags;
-	if (!inode->i_sb->s_imap[1])
+	if (!inode->i_sb->u.ext_sb.s_imap[1])
 		return 0;
 	lock_super (inode->i_sb);
-	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;
+	efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) +
+		(((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK;
 	if (efi->count) {
 		j = efi->free[--efi->count];
-		inode->i_sb->s_imap[1]->b_dirt = 1;
+		inode->i_sb->u.ext_sb.s_imap[1]->b_dirt = 1;
 	} else {
 #ifdef EXTFS_DEBUG
 printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
 #endif
-		j = (unsigned long) inode->i_sb->s_imap[0];
-		if (efi->next < 1 || efi->next > inode->i_sb->s_ninodes) {
+		j = (unsigned long) inode->i_sb->u.ext_sb.s_imap[0];
+		if (efi->next > inode->i_sb->u.ext_sb.s_ninodes) {
 			printk ("efi->next = %d\n", efi->next);
 			panic ("ext_new_inode: bad inode number in free list\n");
 		}
-		inode->i_sb->s_imap[0] = (struct buffer_head *) efi->next;
+		inode->i_sb->u.ext_sb.s_imap[0] = (struct buffer_head *) efi->next;
 		block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
-		brelse (inode->i_sb->s_imap[1]);
-		if (!inode->i_sb->s_imap[0]) {
-			inode->i_sb->s_imap[1] = NULL;
+		brelse (inode->i_sb->u.ext_sb.s_imap[1]);
+		if (!inode->i_sb->u.ext_sb.s_imap[0]) {
+			inode->i_sb->u.ext_sb.s_imap[1] = NULL;
 		} else {
-			if (!(inode->i_sb->s_imap[1] = bread (dev, block)))
+			if (!(inode->i_sb->u.ext_sb.s_imap[1] = bread (dev, block, inode->i_sb->s_blocksize)))
 				panic ("ext_new_inode: unable to read next free inode block\n");
 		}
 	}
-	inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) - 1);
+	inode->i_sb->u.ext_sb.s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->u.ext_sb.s_imap[2]) - 1);
 	inode->i_sb->s_dirt = 1;
 	inode->i_count = 1;
 	inode->i_nlink = 1;
@@ -307,21 +306,21 @@
 	unsigned long count, block, ino;
 
 	lock_super (sb);
-	if (!sb->s_imap[1])
+	if (!sb->u.ext_sb.s_imap[1])
 		count = 0;
 	else {
-		efi = ((struct ext_free_inode *) sb->s_imap[1]->b_data) +
-			((((unsigned long) sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK);
+		efi = ((struct ext_free_inode *) sb->u.ext_sb.s_imap[1]->b_data) +
+			((((unsigned long) sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK);
 		count = efi->count + 1;
 		ino = efi->next;
 		while (ino) {
-			if (ino < 1 || ino > sb->s_ninodes) {
-				printk ("s_imap[0] = %d, ino = %d\n", 
-					(int) sb->s_imap[0],ino);
+			if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
+				printk ("u.ext_sb.s_imap[0] = %d, ino = %d\n", 
+					(int) sb->u.ext_sb.s_imap[0],ino);
 				panic ("ext_count_fre_inodes: bad inode number in free list\n");
 			}
 			block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
-			if (!(bh = bread (sb->s_dev, block))) {
+			if (!(bh = bread (sb->s_dev, block, sb->s_blocksize))) {
 				printk ("ext_count_free_inodes: error while reading free inodes list\n");
 				block = 0;
 			} else {
@@ -334,11 +333,11 @@
 		}
 	}
 printk("ext_count_free_inodes: stored = %d, computed = %d\n",
-	(unsigned long) sb->s_imap[2], count);
+	(unsigned long) sb->u.ext_sb.s_imap[2], count);
 	free_super (sb);
 	return count;
 #else
-	return (unsigned long) sb->s_imap[2];
+	return (unsigned long) sb->u.ext_sb.s_imap[2];
 #endif
 }
 
diff --git a/fs/ext/inode.c b/fs/ext/inode.c
index 807f883..dae86ae 100644
--- a/fs/ext/inode.c
+++ b/fs/ext/inode.c
@@ -1,21 +1,22 @@
 /*
  *  linux/fs/ext/inode.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/inode.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/string.h>
-#include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/ext_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
 
@@ -38,15 +39,15 @@
 	sb->s_dev = 0;
 #ifdef EXTFS_BITMAP
 	for(i = 0 ; i < EXT_I_MAP_SLOTS ; i++)
-		brelse(sb->s_imap[i]);
+		brelse(sb->u.ext_sb.s_imap[i]);
 	for(i = 0 ; i < EXT_Z_MAP_SLOTS ; i++)
-		brelse(sb->s_zmap[i]);
+		brelse(sb->u.ext_sb.s_zmap[i]);
 #endif
 #ifdef EXTFS_FREELIST
-	if (sb->s_imap[1])
-		brelse (sb->s_imap[1]);
-	if (sb->s_zmap[1])
-		brelse (sb->s_zmap[1]);
+	if (sb->u.ext_sb.s_imap[1])
+		brelse (sb->u.ext_sb.s_imap[1]);
+	if (sb->u.ext_sb.s_zmap[1])
+		brelse (sb->u.ext_sb.s_zmap[1]);
 #endif
 	free_super(sb);
 	return;
@@ -65,13 +66,13 @@
 {
 	struct buffer_head *bh;
 	struct ext_super_block *es;
-	int dev=s->s_dev,block;
+	int dev = s->s_dev,block;
 #ifdef EXTFS_BITMAP
 	int i;
 #endif
 
 	lock_super(s);
-	if (!(bh = bread(dev,1))) {
+	if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
 		s->s_dev=0;
 		free_super(s);
 		printk("bread failed\n");
@@ -80,21 +81,22 @@
 /*	*((struct ext_super_block *) s) =
 		*((struct ext_super_block *) bh->b_data); */
 	es = (struct ext_super_block *) bh->b_data;
-	s->s_ninodes = es->s_ninodes;
-	s->s_nzones = es->s_nzones;
+	s->s_blocksize = 1024;
+	s->u.ext_sb.s_ninodes = es->s_ninodes;
+	s->u.ext_sb.s_nzones = es->s_nzones;
 #ifdef EXTFS_BITMAP
-	s->s_imap_blocks = es->s_imap_blocks;
-	s->s_zmap_blocks = es->s_zmap_blocks;
+	s->u.ext_sb.s_imap_blocks = es->s_imap_blocks;
+	s->u.ext_sb.s_zmap_blocks = es->s_zmap_blocks;
 #endif
-	s->s_firstdatazone = es->s_firstdatazone;
-	s->s_log_zone_size = es->s_log_zone_size;
-	s->s_max_size = es->s_max_size;
+	s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
+	s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
+	s->u.ext_sb.s_max_size = es->s_max_size;
 	s->s_magic = es->s_magic;
 #ifdef EXTFS_FREELIST
-	s->s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock;
-	s->s_zmap[2] = (struct buffer_head *) es->s_freeblockscount;
-	s->s_imap[0] = (struct buffer_head *) es->s_firstfreeinode;
-	s->s_imap[2] = (struct buffer_head *) es->s_freeinodescount;
+	s->u.ext_sb.s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock;
+	s->u.ext_sb.s_zmap[2] = (struct buffer_head *) es->s_freeblockscount;
+	s->u.ext_sb.s_imap[0] = (struct buffer_head *) es->s_firstfreeinode;
+	s->u.ext_sb.s_imap[2] = (struct buffer_head *) es->s_freeinodescount;
 #endif
 	brelse(bh);
 	if (s->s_magic != EXT_SUPER_MAGIC) {
@@ -105,50 +107,50 @@
 	}
 #ifdef EXTFS_BITMAP
 	for (i=0;i < EXT_I_MAP_SLOTS;i++)
-		s->s_imap[i] = NULL;
+		s->u.ext_sb.s_imap[i] = NULL;
 	for (i=0;i < EXT_Z_MAP_SLOTS;i++)
-		s->s_zmap[i] = NULL;
+		s->u.ext_sb.s_zmap[i] = NULL;
 	block=2;
-	for (i=0 ; i < s->s_imap_blocks ; i++)
-		if (s->s_imap[i]=bread(dev,block))
+	for (i=0 ; i < s->u.ext_sb.s_imap_blocks ; i++)
+		if (s->u.ext_sb.s_imap[i]=bread(dev, block, BLOCK_SIZE))
 			block++;
 		else
 			break;
-	for (i=0 ; i < s->s_zmap_blocks ; i++)
-		if (s->s_zmap[i]=bread(dev,block))
+	for (i=0 ; i < s->u.ext_sb.s_zmap_blocks ; i++)
+		if (s->u.ext_sb.s_zmap[i]=bread(dev, block, BLOCK_SIZE))
 			block++;
 		else
 			break;
-	if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
+	if (block != 2+s->u.ext_sb.s_imap_blocks+s->u.ext_sb.s_zmap_blocks) {
 		for(i=0;i<EXT_I_MAP_SLOTS;i++)
-			brelse(s->s_imap[i]);
+			brelse(s->u.ext_sb.s_imap[i]);
 		for(i=0;i<EXT_Z_MAP_SLOTS;i++)
-			brelse(s->s_zmap[i]);
+			brelse(s->u.ext_sb.s_zmap[i]);
 		s->s_dev=0;
 		free_super(s);
 		printk("block failed\n");
 		return NULL;
 	}
-	s->s_imap[0]->b_data[0] |= 1;
-	s->s_zmap[0]->b_data[0] |= 1;
+	s->u.ext_sb.s_imap[0]->b_data[0] |= 1;
+	s->u.ext_sb.s_zmap[0]->b_data[0] |= 1;
 #endif
 #ifdef EXTFS_FREELIST
-	if (!s->s_zmap[0])
-		s->s_zmap[1] = NULL;
+	if (!s->u.ext_sb.s_zmap[0])
+		s->u.ext_sb.s_zmap[1] = NULL;
 	else
-		if (!(s->s_zmap[1] = bread (dev, (unsigned long) s->s_zmap[0]))) {
+		if (!(s->u.ext_sb.s_zmap[1] = bread(dev, (unsigned long) s->u.ext_sb.s_zmap[0], BLOCK_SIZE))) {
 			printk ("ext_read_super: unable to read first free block\n");
 			s->s_dev = 0;
 			free_super(s);
 			return NULL;
 		}
-	if (!s->s_imap[0])
-		s->s_imap[1] = NULL;
+	if (!s->u.ext_sb.s_imap[0])
+		s->u.ext_sb.s_imap[1] = NULL;
 	else {
-		block = 2 + (((unsigned long) s->s_imap[0]) - 1) / EXT_INODES_PER_BLOCK;
-		if (!(s->s_imap[1] = bread (dev, block))) {
+		block = 2 + (((unsigned long) s->u.ext_sb.s_imap[0]) - 1) / EXT_INODES_PER_BLOCK;
+		if (!(s->u.ext_sb.s_imap[1] = bread(dev, block, BLOCK_SIZE))) {
 			printk ("ext_read_super: unable to read first free inode block\n");
-			brelse(s->s_zmap[1]);
+			brelse(s->u.ext_sb.s_zmap[1]);
 			s->s_dev = 0;
 			free_super (s);
 			return NULL;
@@ -177,15 +179,15 @@
 #ifdef EXTFS_DEBUG
 	printk ("ext_write_super called\n");
 #endif
-	if (!(bh = bread (sb->s_dev, 1))) {
+	if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
 		printk ("ext_write_super: bread failed\n");
 		return;
 	}
 	es = (struct ext_super_block *) bh->b_data;
-	es->s_firstfreeblock = (unsigned long) sb->s_zmap[0];
-	es->s_freeblockscount = (unsigned long) sb->s_zmap[2];
-	es->s_firstfreeinode = (unsigned long) sb->s_imap[0];
-	es->s_freeinodescount = (unsigned long) sb->s_imap[2];
+	es->s_firstfreeblock = (unsigned long) sb->u.ext_sb.s_zmap[0];
+	es->s_freeblockscount = (unsigned long) sb->u.ext_sb.s_zmap[2];
+	es->s_firstfreeinode = (unsigned long) sb->u.ext_sb.s_imap[0];
+	es->s_freeinodescount = (unsigned long) sb->u.ext_sb.s_imap[2];
 	bh->b_dirt = 1;
 	brelse (bh);
 	sb->s_dirt = 0;
@@ -198,11 +200,11 @@
 
 	put_fs_long(EXT_SUPER_MAGIC, &buf->f_type);
 	put_fs_long(1024, &buf->f_bsize);
-	put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
+	put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size, &buf->f_blocks);
 	tmp = ext_count_free_blocks(sb);
 	put_fs_long(tmp, &buf->f_bfree);
 	put_fs_long(tmp, &buf->f_bavail);
-	put_fs_long(sb->s_ninodes, &buf->f_files);
+	put_fs_long(sb->u.ext_sb.s_ninodes, &buf->f_files);
 	put_fs_long(ext_count_free_inodes(sb), &buf->f_ffree);
 	/* Don't know what value to put in buf->f_fsid */
 }
@@ -237,7 +239,7 @@
 			}
 		if (!inode->i_data[9])
 			return 0;
-		if (!(bh = bread(inode->i_dev,inode->i_data[9])))
+		if (!(bh = bread(inode->i_dev, inode->i_data[9], BLOCK_SIZE)))
 			return 0;
 		i = ((unsigned long *) (bh->b_data))[block];
 		if (create && !i)
@@ -257,7 +259,7 @@
 			}
 		if (!inode->i_data[10])
 			return 0;
-		if (!(bh=bread(inode->i_dev,inode->i_data[10])))
+		if (!(bh=bread(inode->i_dev, inode->i_data[10], BLOCK_SIZE)))
 			return 0;
 		i = ((unsigned long *)bh->b_data)[block>>8];
 		if (create && !i)
@@ -268,7 +270,7 @@
 		brelse(bh);
 		if (!i)
 			return 0;
-		if (!(bh=bread(inode->i_dev,i)))
+		if (!(bh=bread(inode->i_dev, i, BLOCK_SIZE)))
 			return 0;
 		i = ((unsigned long *)bh->b_data)[block&255];
 		if (create && !i)
@@ -279,6 +281,46 @@
 		brelse(bh);
 		return i;
 	}
+	if (create && !inode->i_data[11])
+		if (inode->i_data[11] = ext_new_block(inode->i_dev)) {
+			inode->i_dirt = 1;
+			inode->i_ctime = CURRENT_TIME;
+		}
+	if (!inode->i_data[11])
+		return 0;
+	if (!(bh = bread(inode->i_dev, inode->i_data[11], BLOCK_SIZE)))
+		return 0;
+	i = ((unsigned long *) bh->b_data)[block >> 16];
+	if (create && !i)
+		if (i = ext_new_block(inode->i_dev)) {
+			((unsigned long *) bh->b_data)[block >> 16] = i;
+			bh->b_dirt = 1;
+		}
+	brelse (bh);
+	if (!i)
+		return 0;
+	if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE)))
+		return 0;
+	i = ((unsigned long *) bh->b_data)[(block >> 8) & 255];
+	if (create && !i)
+		if (i = ext_new_block(inode->i_dev)) {
+			((unsigned long *) bh->b_data)[(block >> 8) & 255] = i;
+			bh->b_dirt = 1;
+		}
+	brelse (bh);
+	if (!i)
+		return 0;
+	if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE)))
+		return 0;
+	i = ((unsigned long *) bh->b_data)[block & 255];
+	if (create && !i)
+		if (i = ext_new_block(inode->i_dev)) {
+			((unsigned long *) bh->b_data)[block & 255] = i;
+			bh->b_dirt = 1;
+		}
+	brelse (bh);
+	return i;
+	
 	printk("ext_bmap: triple indirection not yet implemented\n");
 	return 0;
 }
@@ -300,13 +342,13 @@
 	int block;
 
 #ifdef EXTFS_BITMAP
-	block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
+	block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks +
 		(inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 #endif
 #ifdef EXTFS_FREELIST
 	block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 #endif
-	if (!(bh=bread(inode->i_dev,block)))
+	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 		panic("unable to read i-node block");
 	raw_inode = ((struct ext_inode *) bh->b_data) +
 		(inode->i_ino-1)%EXT_INODES_PER_BLOCK;
@@ -348,13 +390,13 @@
 	int block;
 
 #ifdef EXTFS_BITMAP
-	block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
+	block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks +
 		(inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 #endif
 #ifdef EXTFS_FREELIST
 	block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 #endif
-	if (!(bh=bread(inode->i_dev,block)))
+	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 		panic("unable to read i-node block");
 	raw_inode = ((struct ext_inode *)bh->b_data) +
 		(inode->i_ino-1)%EXT_INODES_PER_BLOCK;
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index d4d44c4..bea8dc0 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -1,13 +1,13 @@
 /*
  *  linux/fs/ext/namei.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/namei.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
@@ -16,9 +16,10 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
+#include <linux/errno.h>
+
 #include <asm/segment.h>
 
-#include <errno.h>
 #include <const.h>
 
 /*
@@ -110,7 +111,7 @@
 /*	entries = dir->i_size / (sizeof (struct ext_dir_entry)); */
 	if (!(block = dir->i_data[0]))
 		return NULL;
-	if (!(bh = bread(dir->i_dev,block)))
+	if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
 		return NULL;
 	if (prev_dir)
 		*prev_dir = NULL;
@@ -124,7 +125,7 @@
 			brelse(bh);
 			bh = NULL;
 			if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) ||
-			    !(bh = bread(dir->i_dev,block))) {
+			    !(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
 /*				i += EXT_DIR_ENTRIES_PER_BLOCK; */
 /* 				offset += BLOCK_SIZE; */
 				continue;
@@ -214,7 +215,7 @@
 		return NULL;
 	if (!(block = dir->i_data[0]))
 		return NULL;
-	if (!(bh = bread(dir->i_dev,block)))
+	if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
 		return NULL;
 	rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
 /*	i = 0; */
@@ -230,7 +231,7 @@
 			block = ext_create_block(dir,offset>>BLOCK_SIZE_BITS);
 			if (!block)
 				return NULL;
-			if (!(bh = bread(dir->i_dev,block))) {
+			if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
 /*				i += EXT_DIR_ENTRIES_PER_BLOCK; */
 				offset += BLOCK_SIZE;
 				continue;
@@ -263,7 +264,7 @@
 #endif
 				if (!block)
 					return NULL;
-				if (!(bh = bread(dir->i_dev,block)))
+				if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
 					return NULL; /* Other thing to do ??? */
 				de = (struct ext_dir_entry *) bh->b_data;
 			}
@@ -428,7 +429,7 @@
 		return -ENOSPC;
 	}
 	inode->i_dirt = 1;
-	if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
+	if (!(dir_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		inode->i_nlink--;
 		inode->i_dirt = 1;
@@ -481,7 +482,7 @@
 
 /*	len = inode->i_size / sizeof (struct ext_dir_entry); */
 	if (inode->i_size < 2 * 12 || !inode->i_data[0] ||
-	    !(bh=bread(inode->i_dev,inode->i_data[0]))) {
+	    !(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);
 		return 0;
 	}
@@ -503,7 +504,7 @@
 				offset += BLOCK_SIZE;
 				continue;
 			}
-			if (!(bh=bread(inode->i_dev,block)))
+			if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 				return 0;
 			de = (struct ext_dir_entry *) bh->b_data;
 		}
@@ -643,7 +644,7 @@
 		return -ENOSPC;
 	}
 	inode->i_dirt = 1;
-	if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
+	if (!(name_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		inode->i_nlink--;
 		inode->i_dirt = 1;
@@ -825,7 +826,7 @@
 		retval = -EIO;
 		if (!old_inode->i_data[0])
 			goto end_rename;
-		if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0])))
+		if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0], BLOCK_SIZE)))
 			goto end_rename;
 		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 			goto end_rename;
@@ -845,8 +846,8 @@
 /* ok, that's it */
 	old_de->inode = 0;
 	old_de->name_len = 0;
-	ext_merge_entries (old_de, pde, nde);
 	new_de->inode = old_inode->i_ino;
+	ext_merge_entries (old_de, pde, nde);
 	if (new_inode) {
 		new_inode->i_nlink--;
 		new_inode->i_dirt = 1;
diff --git a/fs/ext/symlink.c b/fs/ext/symlink.c
index eeef2b4..1daf1cb 100644
--- a/fs/ext/symlink.c
+++ b/fs/ext/symlink.c
@@ -1,21 +1,20 @@
 /*
  *  linux/fs/ext/symlink.c
  *
- *  (C) 1992 Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/symlink.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  ext symlink handling code
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/ext_fs.h>
@@ -63,7 +62,7 @@
 	}
 	__asm__("mov %%fs,%0":"=r" (fs));
 	if ((current->link_count > 5) || !inode->i_data[0] ||
-	   !(bh = bread(inode->i_dev, inode->i_data[0]))) {
+	   !(bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		iput(inode);
 		return NULL;
@@ -91,7 +90,7 @@
 	if (buflen > 1023)
 		buflen = 1023;
 	if (inode->i_data[0])
-		bh = bread(inode->i_dev, inode->i_data[0]);
+		bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE);
 	else
 		bh = NULL;
 	iput(inode);
diff --git a/fs/ext/truncate.c b/fs/ext/truncate.c
index 04c0b2e..3e647e8 100644
--- a/fs/ext/truncate.c
+++ b/fs/ext/truncate.c
@@ -1,13 +1,13 @@
 /*
  *  linux/fs/ext/truncate.c
  *
- *  (C) 1992  Remy Card (card@masi.ibp.fr)
+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
  *
  *  from
  *
  *  linux/fs/minix/truncate.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
@@ -15,8 +15,7 @@
 #include <linux/tty.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-
-#include <errno.h>
+#include <linux/errno.h>
 
 /*
  * Truncate has the most races in the whole filesystem: coding it is
@@ -59,7 +58,7 @@
 #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
 
 	if (*p)
-		bh = bread(inode->i_dev,*p);
+		bh = bread(inode->i_dev, *p, BLOCK_SIZE);
 	if (!bh)
 		return 0;
 repeat:
@@ -88,16 +87,16 @@
 	return result;
 }
 		
-static int trunc_dindirect(struct inode * inode)
+static int trunc_dindirect(struct inode * inode, int offset, unsigned long * p)
 {
 	int i;
 	struct buffer_head * bh = NULL;
 	unsigned long * dind;
 	int result = 0;
-#define DINDIRECT_BLOCK ((DIRECT_BLOCK-(256+9))>>8)
+#define DINDIRECT_BLOCK ((DIRECT_BLOCK-offset)>>8)
 
-	if (inode->i_data[10])
-		bh = bread(inode->i_dev,inode->i_data[10]);
+	if (*p)
+		bh = bread(inode->i_dev, *p, BLOCK_SIZE);
 	if (!bh)
 		return 0;
 repeat:
@@ -109,7 +108,7 @@
 		dind = i+(unsigned long *) bh->b_data;
 		if (!*dind)
 			continue;
-		result |= trunc_indirect(inode,9+256+(i<<8),dind);
+		result |= trunc_indirect(inode,offset+(i<<8),dind);
 	}
 	dind = (unsigned long *) bh->b_data;
 	for (i = 0; i < 256; i++)
@@ -118,8 +117,44 @@
 	brelse(bh);
 	if (i >= 256) {
 		result = 1;
-		if (ext_free_block(inode->i_dev,inode->i_data[10]))
-			inode->i_data[10] = 0;
+		if (ext_free_block(inode->i_dev,*p))
+			*p = 0;
+	}
+	return result;
+}
+
+static int trunc_tindirect(struct inode * inode)
+{
+	int i;
+	struct buffer_head * bh = NULL;
+	unsigned long * tind;
+	int result = 0;
+#define TINDIRECT_BLOCK ((DIRECT_BLOCK-(256*256+256+9))>>16)
+
+	if (inode->i_data[11])
+		bh = bread(inode->i_dev, inode->i_data[11], BLOCK_SIZE);
+	if (!bh)
+		return 0;
+repeat:
+	for (i = TINDIRECT_BLOCK ; i < 256 ; i ++) {
+		if (i < 0)
+			i = 0;
+		if (i < TINDIRECT_BLOCK)
+			goto repeat;
+		tind = i+(unsigned long *) bh->b_data;
+		if (!*tind)
+			continue;
+		result |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
+	}
+	tind = (unsigned long *) bh->b_data;
+	for (i = 0; i < 256; i++)
+		if (*(tind++))
+			break;
+	brelse(bh);
+	if (i >= 256) {
+		result = 1;
+		if (ext_free_block(inode->i_dev,inode->i_data[11]))
+			inode->i_data[11] = 0;
 	}
 	return result;
 }
@@ -136,7 +171,8 @@
 	while (1) {
 		flag = trunc_direct(inode);
 		flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]);
-		flag |= trunc_dindirect(inode);
+		flag |= trunc_dindirect(inode,9+256,(unsigned long *)&inode->i_data[10]);
+		flag |= trunc_tindirect(inode);
 		if (!flag)
 			break;
 		current->counter = 0;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 02b5af1..7e61dd9 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1,18 +1,17 @@
 /*
  *  linux/fs/fcntl.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
 
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
 
 extern int sys_close(int fd);
 
diff --git a/fs/fifo.c b/fs/fifo.c
index 8e1a7d2..84da040 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -4,11 +4,10 @@
  *  written by Paul H. Hargrove
  */
 
-#include <errno.h>
-
-#include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
 
 extern struct file_operations read_pipe_fops;
 extern struct file_operations write_pipe_fops;
@@ -87,7 +86,7 @@
 		wake_up(&PIPE_WRITE_WAIT(*inode));
 	if (retval || inode->i_size)
 		return retval;
-	page = get_free_page();
+	page = get_free_page(GFP_KERNEL);
 	if (inode->i_size) {
 		free_page(page);
 		return 0;
diff --git a/fs/file_table.c b/fs/file_table.c
index e0589ac..fe0f44a 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -1,9 +1,24 @@
 /*
  *  linux/fs/file_table.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/fs.h>
+#include <linux/string.h>
 
 struct file file_table[NR_FILE];
+
+struct file * get_empty_filp(void)
+{
+	int i;
+	struct file * f = file_table+0;
+
+	for (i = 0; i++ < NR_FILE; f++)
+		if (!f->f_count) {
+			memset(f,0,sizeof(*f));
+			f->f_count = 1;
+			return f;
+		}
+	return NULL;
+}
diff --git a/fs/inode.c b/fs/inode.c
index 65637df..eaf3093 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1,14 +1,14 @@
 /*
  *  linux/fs/inode.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/string.h>
 
 #include <asm/system.h>
 
@@ -188,7 +188,7 @@
 
 	if (!(inode = get_empty_inode()))
 		return NULL;
-	if (!(inode->i_size = get_free_page())) {
+	if (!(inode->i_size = get_free_page(GFP_USER))) {
 		inode->i_count = 0;
 		return NULL;
 	}
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 6c9ef40..243b604 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -1,15 +1,15 @@
 /*
  *  linux/fs/ioctl.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/stat.h>
-#include <linux/sched.h>
 
 int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index 0fdd188..f834539 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -30,74 +30,88 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-bitmap.o : bitmap.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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/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/linux/minix_fs.h 
-blkdev.o : blkdev.c /usr/src/linux/include/errno.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/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 /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/linux/minix_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
-chrdev.o : chrdev.c /usr/src/linux/include/errno.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/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 /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/linux/minix_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.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 \
-  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/stat.h 
-fifo.o : fifo.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 \
-  /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/linux/minix_fs.h 
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/dirent.h \
-  /usr/src/linux/include/limits.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.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/vfs.h /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/linux/minix_fs.h \
+bitmap.o : bitmap.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/string.h 
+blkdev.o : blkdev.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
+chrdev.o : chrdev.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
+dir.o : dir.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/minix_fs.h \
   /usr/src/linux/include/linux/stat.h 
-inode.o : inode.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.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/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/linux/minix_fs.h /usr/src/linux/include/asm/system.h \
-  /usr/src/linux/include/asm/segment.h 
-namei.o : namei.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 \
-  /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/linux/minix_fs.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h /usr/src/linux/include/const.h 
-symlink.o : symlink.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
+fifo.o : fifo.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h 
+file.o : file.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.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/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 /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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h 
+inode.o : inode.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h 
+namei.o : namei.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/string.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/const.h 
+symlink.o : symlink.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
   /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/stat.h 
-truncate.o : truncate.c /usr/src/linux/include/errno.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/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 /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/linux/minix_fs.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
+truncate.o : truncate.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/minix_fs.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fcntl.h 
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 4d560d4..57bed4b 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -1,15 +1,15 @@
 /*
  *  linux/fs/minix/bitmap.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /* bitmap.c contains the code that handles the inode and block bitmaps */
 
-#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #define clear_block(addr) \
 __asm__("cld\n\t" \
@@ -81,9 +81,9 @@
 
 	if (!(sb = get_super(dev)))
 		panic("trying to free block on nonexistent device");
-	if (block < sb->s_firstdatazone || block >= sb->s_nzones)
+	if (block < sb->u.minix_sb.s_firstdatazone || block >= sb->u.minix_sb.s_nzones)
 		panic("trying to free block not in datazone");
-	bh = get_hash_table(dev,block);
+	bh = get_hash_table(dev,block,BLOCK_SIZE);
 	if (bh) {
 		if (bh->b_count > 1) {
 			brelse(bh);
@@ -94,10 +94,10 @@
 		if (bh->b_count)
 			brelse(bh);
 	}
-	zone = block - sb->s_firstdatazone + 1;
+	zone = block - sb->u.minix_sb.s_firstdatazone + 1;
 	bit = zone & 8191;
 	zone >>= 13;
-	bh = sb->s_zmap[zone];
+	bh = sb->u.minix_sb.s_zmap[zone];
 	if (clear_bit(bit,bh->b_data))
 		printk("free_block (%04x:%d): bit already cleared\n",dev,block);
 	bh->b_dirt = 1;
@@ -114,18 +114,18 @@
 		panic("trying to get new block from nonexistant device");
 	j = 8192;
 	for (i=0 ; i<8 ; i++)
-		if (bh=sb->s_zmap[i])
+		if (bh=sb->u.minix_sb.s_zmap[i])
 			if ((j=find_first_zero(bh->b_data))<8192)
 				break;
 	if (i>=8 || !bh || j>=8192)
 		return 0;
-	if (set_bit(j,bh->b_data))
+	if (set_bit(j,bh->b_data)) 
 		panic("new_block: bit already set");
 	bh->b_dirt = 1;
-	j += i*8192 + sb->s_firstdatazone-1;
-	if (j >= sb->s_nzones)
+	j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
+	if (j >= sb->u.minix_sb.s_nzones)
 		return 0;
-	if (!(bh=getblk(dev,j)))
+	if (!(bh=getblk(dev,j,BLOCK_SIZE)))
 		panic("new_block: cannot get block");
 	if (bh->b_count != 1)
 		panic("new block: count is != 1");
@@ -138,8 +138,8 @@
 
 unsigned long minix_count_free_blocks(struct super_block *sb)
 {
-	return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
-		 << sb->s_log_zone_size;
+	return (sb->u.minix_sb.s_nzones - count_used(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks,sb->u.minix_sb.s_nzones))
+		 << sb->u.minix_sb.s_log_zone_size;
 }
 
 void minix_free_inode(struct inode * inode)
@@ -164,11 +164,11 @@
 		printk("free_inode: inode on nonexistent device\n");
 		return;
 	}
-	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
+	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) {
 		printk("free_inode: inode 0 or nonexistent inode\n");
 		return;
 	}
-	if (!(bh=inode->i_sb->s_imap[inode->i_ino>>13])) {
+	if (!(bh=inode->i_sb->u.minix_sb.s_imap[inode->i_ino>>13])) {
 		printk("free_inode: nonexistent imap in superblock\n");
 		return;
 	}
@@ -194,10 +194,10 @@
 	inode->i_flags = inode->i_sb->s_flags;
 	j = 8192;
 	for (i=0 ; i<8 ; i++)
-		if (bh=inode->i_sb->s_imap[i])
+		if (bh=inode->i_sb->u.minix_sb.s_imap[i])
 			if ((j=find_first_zero(bh->b_data))<8192)
 				break;
-	if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->s_ninodes) {
+	if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->u.minix_sb.s_ninodes) {
 		iput(inode);
 		return NULL;
 	}
@@ -221,5 +221,5 @@
 
 unsigned long minix_count_free_inodes(struct super_block *sb)
 {
-	return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
+	return sb->u.minix_sb.s_ninodes - count_used(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks,sb->u.minix_sb.s_ninodes);
 }
diff --git a/fs/minix/blkdev.c b/fs/minix/blkdev.c
index 144d19f..c8fae84 100644
--- a/fs/minix/blkdev.c
+++ b/fs/minix/blkdev.c
@@ -1,11 +1,10 @@
 /*
  *  linux/fs/minix/blkdev.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/tty.h>
diff --git a/fs/minix/chrdev.c b/fs/minix/chrdev.c
index c9e61d3..f179796 100644
--- a/fs/minix/chrdev.c
+++ b/fs/minix/chrdev.c
@@ -1,11 +1,10 @@
 /*
  *  linux/fs/minix/chrdev.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/tty.h>
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index bfa3551..1a894f8 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -1,15 +1,14 @@
 /*
  *  linux/fs/minix/dir.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  minix directory handling functions
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
 
+#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
@@ -62,7 +61,7 @@
 	while (filp->f_pos < inode->i_size) {
 		offset = filp->f_pos & 1023;
 		block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
-		if (!block || !(bh = bread(inode->i_dev,block))) {
+		if (!block || !(bh = bread(inode->i_dev,block,BLOCK_SIZE))) {
 			filp->f_pos += 1024-offset;
 			continue;
 		}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index cc7e33a..eb8c1b0 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -1,22 +1,19 @@
 /*
  *  linux/fs/minix/file.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  minix regular file handling primitives
  */
 
-#include <errno.h>
-
-#include <sys/dirent.h>
-
 #include <asm/segment.h>
 #include <asm/system.h>
 
-#include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
 #include <linux/stat.h>
 
 #define	NBUF	16
@@ -108,7 +105,7 @@
 		if (blocks) {
 			--blocks;
 			if (nr = minix_bmap(inode,block++)) {
-				*bhb = getblk(inode->i_dev,nr);
+				*bhb = getblk(inode->i_dev,nr,BLOCK_SIZE);
 				if (!(*bhb)->b_uptodate)
 					ll_rw_block(READ,*bhb);
 			} else
@@ -194,9 +191,9 @@
 		if (c > count-written)
 			c = count-written;
 		if (c == BLOCK_SIZE)
-			bh = getblk(inode->i_dev, block);
+			bh = getblk(inode->i_dev, block, BLOCK_SIZE);
 		else
-			bh = bread(inode->i_dev,block);
+			bh = bread(inode->i_dev,block, BLOCK_SIZE);
 		if (!bh) {
 			if (!written)
 				written = -EIO;
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 71b45bc..b90a4e8 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -1,15 +1,16 @@
 /*
  *  linux/fs/minix/inode.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/string.h>
-#include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
 
@@ -29,9 +30,9 @@
 	lock_super(sb);
 	sb->s_dev = 0;
 	for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
-		brelse(sb->s_imap[i]);
+		brelse(sb->u.minix_sb.s_imap[i]);
 	for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++)
-		brelse(sb->s_zmap[i]);
+		brelse(sb->u.minix_sb.s_zmap[i]);
 	free_super(sb);
 	return;
 }
@@ -52,20 +53,21 @@
 	int i,dev=s->s_dev,block;
 
 	lock_super(s);
-	if (!(bh = bread(dev,1))) {
+	if (!(bh = bread(dev,1,BLOCK_SIZE))) {
 		s->s_dev=0;
 		free_super(s);
 		printk("bread failed\n");
 		return NULL;
 	}
 	ms = (struct minix_super_block *) bh->b_data;
-	s->s_ninodes = ms->s_ninodes;
-	s->s_nzones = ms->s_nzones;
-	s->s_imap_blocks = ms->s_imap_blocks;
-	s->s_zmap_blocks = ms->s_zmap_blocks;
-	s->s_firstdatazone = ms->s_firstdatazone;
-	s->s_log_zone_size = ms->s_log_zone_size;
-	s->s_max_size = ms->s_max_size;
+	s->s_blocksize = 1024;
+	s->u.minix_sb.s_ninodes = ms->s_ninodes;
+	s->u.minix_sb.s_nzones = ms->s_nzones;
+	s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
+	s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks;
+	s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone;
+	s->u.minix_sb.s_log_zone_size = ms->s_log_zone_size;
+	s->u.minix_sb.s_max_size = ms->s_max_size;
 	s->s_magic = ms->s_magic;
 	brelse(bh);
 	if (s->s_magic != MINIX_SUPER_MAGIC) {
@@ -75,32 +77,32 @@
 		return NULL;
 	}
 	for (i=0;i < MINIX_I_MAP_SLOTS;i++)
-		s->s_imap[i] = NULL;
+		s->u.minix_sb.s_imap[i] = NULL;
 	for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
-		s->s_zmap[i] = NULL;
+		s->u.minix_sb.s_zmap[i] = NULL;
 	block=2;
-	for (i=0 ; i < s->s_imap_blocks ; i++)
-		if (s->s_imap[i]=bread(dev,block))
+	for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++)
+		if (s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE))
 			block++;
 		else
 			break;
-	for (i=0 ; i < s->s_zmap_blocks ; i++)
-		if (s->s_zmap[i]=bread(dev,block))
+	for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++)
+		if (s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE))
 			block++;
 		else
 			break;
-	if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
+	if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) {
 		for(i=0;i<MINIX_I_MAP_SLOTS;i++)
-			brelse(s->s_imap[i]);
+			brelse(s->u.minix_sb.s_imap[i]);
 		for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
-			brelse(s->s_zmap[i]);
+			brelse(s->u.minix_sb.s_zmap[i]);
 		s->s_dev=0;
 		free_super(s);
 		printk("block failed\n");
 		return NULL;
 	}
-	s->s_imap[0]->b_data[0] |= 1;
-	s->s_zmap[0]->b_data[0] |= 1;
+	s->u.minix_sb.s_imap[0]->b_data[0] |= 1;
+	s->u.minix_sb.s_zmap[0]->b_data[0] |= 1;
 	free_super(s);
 	/* set up enough so that it can read an inode */
 	s->s_dev = dev;
@@ -119,11 +121,11 @@
 
 	put_fs_long(MINIX_SUPER_MAGIC, &buf->f_type);
 	put_fs_long(1024, &buf->f_bsize);
-	put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
+	put_fs_long(sb->u.minix_sb.s_nzones << sb->u.minix_sb.s_log_zone_size, &buf->f_blocks);
 	tmp = minix_count_free_blocks(sb);
 	put_fs_long(tmp, &buf->f_bfree);
 	put_fs_long(tmp, &buf->f_bavail);
-	put_fs_long(sb->s_ninodes, &buf->f_files);
+	put_fs_long(sb->u.minix_sb.s_ninodes, &buf->f_files);
 	put_fs_long(minix_count_free_inodes(sb), &buf->f_ffree);
 	/* Don't know what value to put in buf->f_fsid */
 }
@@ -158,7 +160,7 @@
 			}
 		if (!inode->i_data[7])
 			return 0;
-		if (!(bh = bread(inode->i_dev,inode->i_data[7])))
+		if (!(bh = bread(inode->i_dev,inode->i_data[7],BLOCK_SIZE)))
 			return 0;
 		i = ((unsigned short *) (bh->b_data))[block];
 		if (create && !i)
@@ -177,7 +179,7 @@
 		}
 	if (!inode->i_data[8])
 		return 0;
-	if (!(bh=bread(inode->i_dev,inode->i_data[8])))
+	if (!(bh=bread(inode->i_dev,inode->i_data[8], BLOCK_SIZE)))
 		return 0;
 	i = ((unsigned short *)bh->b_data)[block>>9];
 	if (create && !i)
@@ -188,7 +190,7 @@
 	brelse(bh);
 	if (!i)
 		return 0;
-	if (!(bh=bread(inode->i_dev,i)))
+	if (!(bh=bread(inode->i_dev,i,BLOCK_SIZE)))
 		return 0;
 	i = ((unsigned short *)bh->b_data)[block&511];
 	if (create && !i)
@@ -216,9 +218,9 @@
 	struct minix_inode * raw_inode;
 	int block;
 
-	block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
+	block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
 		(inode->i_ino-1)/MINIX_INODES_PER_BLOCK;
-	if (!(bh=bread(inode->i_dev,block)))
+	if (!(bh=bread(inode->i_dev,block, BLOCK_SIZE)))
 		panic("unable to read i-node block");
 	raw_inode = ((struct minix_inode *) bh->b_data) +
 		(inode->i_ino-1)%MINIX_INODES_PER_BLOCK;
@@ -259,9 +261,9 @@
 	struct minix_inode * raw_inode;
 	int block;
 
-	block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
+	block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
 		(inode->i_ino-1)/MINIX_INODES_PER_BLOCK;
-	if (!(bh=bread(inode->i_dev,block)))
+	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 		panic("unable to read i-node block");
 	raw_inode = ((struct minix_inode *)bh->b_data) +
 		(inode->i_ino-1)%MINIX_INODES_PER_BLOCK;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index a00c8cd..1a51c87 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/minix/namei.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
@@ -10,9 +10,10 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
+#include <linux/errno.h>
+
 #include <asm/segment.h>
 
-#include <errno.h>
 #include <const.h>
 
 /*
@@ -77,7 +78,7 @@
 	entries = dir->i_size / (sizeof (struct minix_dir_entry));
 	if (!(block = dir->i_data[0]))
 		return NULL;
-	if (!(bh = bread(dir->i_dev,block)))
+	if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
 		return NULL;
 	i = 0;
 	de = (struct minix_dir_entry *) bh->b_data;
@@ -86,7 +87,7 @@
 			brelse(bh);
 			bh = NULL;
 			if (!(block = minix_bmap(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK)) ||
-			    !(bh = bread(dir->i_dev,block))) {
+			    !(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
 				i += MINIX_DIR_ENTRIES_PER_BLOCK;
 				continue;
 			}
@@ -162,7 +163,7 @@
 		return NULL;
 	if (!(block = dir->i_data[0]))
 		return NULL;
-	if (!(bh = bread(dir->i_dev,block)))
+	if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
 		return NULL;
 	i = 0;
 	de = (struct minix_dir_entry *) bh->b_data;
@@ -173,7 +174,7 @@
 			block = minix_create_block(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK);
 			if (!block)
 				return NULL;
-			if (!(bh = bread(dir->i_dev,block))) {
+			if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
 				i += MINIX_DIR_ENTRIES_PER_BLOCK;
 				continue;
 			}
@@ -321,7 +322,7 @@
 		return -ENOSPC;
 	}
 	inode->i_dirt = 1;
-	if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
+	if (!(dir_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		inode->i_nlink--;
 		inode->i_dirt = 1;
@@ -368,7 +369,7 @@
 
 	len = inode->i_size / sizeof (struct minix_dir_entry);
 	if (len<2 || !inode->i_data[0] ||
-	    !(bh=bread(inode->i_dev,inode->i_data[0]))) {
+	    !(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);
 		return 0;
 	}
@@ -388,7 +389,7 @@
 				nr += MINIX_DIR_ENTRIES_PER_BLOCK;
 				continue;
 			}
-			if (!(bh=bread(inode->i_dev,block)))
+			if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 				return 0;
 			de = (struct minix_dir_entry *) bh->b_data;
 		}
@@ -515,7 +516,7 @@
 		return -ENOSPC;
 	}
 	inode->i_dirt = 1;
-	if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
+	if (!(name_block = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		inode->i_nlink--;
 		inode->i_dirt = 1;
@@ -693,7 +694,7 @@
 		retval = -EIO;
 		if (!old_inode->i_data[0])
 			goto end_rename;
-		if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0])))
+		if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0], BLOCK_SIZE)))
 			goto end_rename;
 		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 			goto end_rename;
diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c
index 1f99b07..65263a0 100644
--- a/fs/minix/symlink.c
+++ b/fs/minix/symlink.c
@@ -1,15 +1,14 @@
 /*
  *  linux/fs/minix/symlink.c
  *
- *  (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  minix symlink handling code
  */
 
-#include <errno.h>
-
 #include <asm/segment.h>
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
@@ -57,7 +56,7 @@
 	}
 	__asm__("mov %%fs,%0":"=r" (fs));
 	if ((current->link_count > 5) || !inode->i_data[0] ||
-	   !(bh = bread(inode->i_dev, inode->i_data[0]))) {
+	   !(bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
 		iput(dir);
 		iput(inode);
 		return NULL;
@@ -85,7 +84,7 @@
 	if (buflen > 1023)
 		buflen = 1023;
 	if (inode->i_data[0])
-		bh = bread(inode->i_dev, inode->i_data[0]);
+		bh = bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE);
 	else
 		bh = NULL;
 	iput(inode);
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index e9c7a82..767dd3d 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -1,11 +1,10 @@
 /*
  *  linux/fs/truncate.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/tty.h>
@@ -53,7 +52,7 @@
 #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
 
 	if (*p)
-		bh = bread(inode->i_dev,*p);
+		bh = bread(inode->i_dev, *p, BLOCK_SIZE);
 	if (!bh)
 		return 0;
 repeat:
@@ -91,7 +90,7 @@
 #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
 
 	if (inode->i_data[8])
-		bh = bread(inode->i_dev,inode->i_data[8]);
+		bh = bread(inode->i_dev, inode->i_data[8], BLOCK_SIZE);
 	if (!bh)
 		return 0;
 repeat:
diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile
index 204791e..485a62b 100644
--- a/fs/msdos/Makefile
+++ b/fs/msdos/Makefile
@@ -26,52 +26,56 @@
 
 dep:
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
-	(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
+	for i in *.c;do $(CPP) -M $$i;done >> tmp_make
 	cp tmp_make Makefile
 
 ### Dependencies:
-dir.o : dir.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
-  /usr/src/linux/include/linux/wait.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 \
-  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/sched.h \
-  /usr/src/linux/include/linux/head.h /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 
-fat.o : fat.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.h \
-  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.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/kernel.h 
-file.o : file.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/sched.h \
+dir.o : dir.c /usr/src/linux/include/asm/segment.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/linux/limits.h \
-  /usr/src/linux/include/linux/wait.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/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/linux/msdos_fs.h 
-inode.o : inode.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/string.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/stat.h \
-  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
-  /usr/src/linux/include/linux/wait.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/kernel.h /usr/src/linux/include/linux/sched.h \
-  /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.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/asm/segment.h 
-misc.o : misc.c /usr/src/linux/include/errno.h /usr/src/linux/include/limits.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/msdos_fs.h \
-  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
-  /usr/src/linux/include/sys/dirent.h /usr/src/linux/include/sys/vfs.h /usr/src/linux/include/linux/sched.h \
-  /usr/src/linux/include/linux/head.h /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 
-namei.o : namei.c /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/linux/stat.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/linux/limits.h /usr/src/linux/include/linux/wait.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/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/linux/msdos_fs.h 
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/stat.h 
+fat.o : fat.c /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/fs.h \
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/stat.h 
+file.o : file.c /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/linux/stat.h 
+inode.o : inode.c /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/fs.h \
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h \
+  /usr/src/linux/include/asm/segment.h 
+misc.o : misc.c /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/fs.h \
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h 
+namei.o : namei.c /usr/src/linux/include/asm/segment.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/msdos_fs.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h 
diff --git a/fs/msdos/dir.c b/fs/msdos/dir.c
index 999610d..e3caef2 100644
--- a/fs/msdos/dir.c
+++ b/fs/msdos/dir.c
@@ -6,14 +6,13 @@
  *  MS-DOS directory handling functions
  */
 
-#include <errno.h>
 #include <asm/segment.h>
-#include <linux/stat.h>
+
+#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
-
-/* for compatibility warnings */
-#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
 
 static int msdos_dummy_read(struct inode *inode,struct file *filp,char *buf,
     int count);
diff --git a/fs/msdos/fat.c b/fs/msdos/fat.c
index 7336ca6..b1a120e 100644
--- a/fs/msdos/fat.c
+++ b/fs/msdos/fat.c
@@ -4,15 +4,13 @@
  *  Written 1992 by Werner Almesberger
  */
 
-#include <errno.h>
-#include <linux/stat.h>
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
-
+#include <linux/errno.h>
+#include <linux/stat.h>
 
 static struct fat_cache *fat_cache,cache[FAT_CACHE];
 
-
 /* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
    new_value is != -1, that FAT entry is replaced by it. */
 
diff --git a/fs/msdos/file.c b/fs/msdos/file.c
index 449b40d..eb48bbd 100644
--- a/fs/msdos/file.c
+++ b/fs/msdos/file.c
@@ -6,20 +6,19 @@
  *  MS-DOS regular file handling primitives
  */
 
-#include <errno.h>
 #include <asm/segment.h>
 #include <asm/system.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
+
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
-
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
 
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
 
-
 static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
     int count);
 static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
@@ -202,7 +201,6 @@
 {
 	int cluster;
 
-	if (!S_ISREG(inode->i_mode)) return;
 	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 	inode->i_data[D_ATTRS] |= ATTR_ARCH;
diff --git a/fs/msdos/inode.c b/fs/msdos/inode.c
index 0b43c72..451cb37 100644
--- a/fs/msdos/inode.c
+++ b/fs/msdos/inode.c
@@ -4,14 +4,14 @@
  *  Written 1992 by Werner Almesberger
  */
 
-#include <errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
 
+#include <asm/segment.h>
 
 void msdos_put_inode(struct inode *inode)
 {
@@ -66,7 +66,7 @@
 		if (!strcmp(this,"check") && value) {
 			if (value[0] && !value[1] && strchr("rns",*value))
 				*check = *value;
-			else if (!strcmp(value,"releaxed")) *check = 'r';
+			else if (!strcmp(value,"relaxed")) *check = 'r';
 			else if (!strcmp(value,"normal")) *check = 'n';
 			else if (!strcmp(value,"strict")) *check = 's';
 			else return 0;
@@ -100,7 +100,7 @@
 	}
 	cache_init();
 	lock_super(s);
-	bh = bread(s->s_dev,0);
+	bh = bread(s->s_dev, 0, BLOCK_SIZE);
 	free_super(s);
 	if (bh == NULL) {
 		s->s_dev = 0;
@@ -108,6 +108,7 @@
 		return NULL;
 	}
 	b = (struct msdos_boot_sector *) bh->b_data;
+	s->s_blocksize = 1024;	/* we cannot handle anything else yet */
 	MSDOS_SB(s)->cluster_size = b->cluster_size;
 	MSDOS_SB(s)->fats = b->fats;
 	MSDOS_SB(s)->fat_start = b->reserved;
@@ -122,7 +123,7 @@
 	    0;
 	MSDOS_SB(s)->fat_bits = MSDOS_SB(s)->clusters > MSDOS_FAT12 ? 16 : 12;
 	brelse(bh);
-printk("[MS-DOS FS Rel. alpha.5, FAT %d, check=%c, conv=%c]\r\n",
+printk("[MS-DOS FS Rel. alpha.6, FAT %d, check=%c, conv=%c]\r\n",
   MSDOS_SB(s)->fat_bits,check,conversion);
 printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,se=%d,ts=%d]\r\n",
   b->media,MSDOS_SB(s)->cluster_size,MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start,
@@ -214,7 +215,7 @@
 		inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 		return;
 	}
-	if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS)))
+	if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS, BLOCK_SIZE)))
 	    panic("unable to read i-node block");
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 	    [inode->i_ino & (MSDOS_DPB-1)];
@@ -255,7 +256,7 @@
 
 	inode->i_dirt = 0;
 	if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
-	if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS)))
+	if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS, BLOCK_SIZE)))
 	    panic("unable to read i-node block");
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 	    [inode->i_ino & (MSDOS_DPB-1)];
diff --git a/fs/msdos/misc.c b/fs/msdos/misc.c
index 563be03..65d3ee9 100644
--- a/fs/msdos/misc.c
+++ b/fs/msdos/misc.c
@@ -4,19 +4,17 @@
  *  Written 1992 by Werner Almesberger
  */
 
-#include <errno.h>
-#include <limits.h>
-#include <linux/string.h>
-#include <linux/stat.h>
 #include <linux/msdos_fs.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
 
 static char bin_extensions[] =
   "EXECOMAPPSYSOVLOBJLIB"		/* program code */
-  "ARCZIPLHALZHZOOTARZ  ARJ"		/* common archivers */
-  "GIFBMPTIFGL JPG"			/* graphics */
+  "ARCZIPLHALZHZOOTARZ  ARJTZ "		/* common archivers */
+  "GIFBMPTIFGL JPGPCX"			/* graphics */
   "TFMVF GF PK PXLDVI";			/* TeX */
 
 
@@ -100,7 +98,7 @@
 	else {
 		last = 0;
 		if (current = inode->i_data[D_START]) {
-			cache_lookup(inode,INT_MAX,&last,&current);
+			cache_lookup(inode,0x7fffffff,&last,&current);
 			while (current && current != -1)
 				if (!(current = fat_access(inode->i_sb,
 				    last = current,-1)))
@@ -127,7 +125,7 @@
 #endif
 		if (current < MSDOS_SB(inode->i_sb)->cluster_size-1 &&
 		    !(sector & 1)) {
-			if (!(bh = getblk(inode->i_dev,sector >> 1)))
+			if (!(bh = getblk(inode->i_dev,sector >> 1, BLOCK_SIZE)))
 				printk("getblk failed\r\n");
 			else {
 				memset(bh->b_data,0,BLOCK_SIZE);
@@ -171,7 +169,7 @@
 {
 	int month,year;
 
-	month = ((date >> 5) & 4)-1;
+	month = ((date >> 5) & 15)-1;
 	year = date >> 9;
 	return (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
 	    ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
@@ -220,10 +218,13 @@
 		offset = *pos;
 		if ((sector = msdos_smap(dir,*pos >> SECTOR_BITS)) == -1)
 			return -1;
-		if (!sector) return -1; /* FAT error ... */
+		if (!sector)
+			return -1; /* FAT error ... */
 		*pos += sizeof(struct msdos_dir_entry);
-		if (*bh) brelse(*bh);
-		if (!(*bh = msdos_sread(dir->i_dev,sector,&data))) continue;
+		if (*bh)
+			brelse(*bh);
+		if (!(*bh = msdos_sread(dir->i_dev,sector,&data)))
+			continue;
 		*de = (struct msdos_dir_entry *) (data+(offset &
 		    (SECTOR_SIZE-1)));
 		return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index ebe9bf3..0c4cc4f 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -4,14 +4,14 @@
  *  Written 1992 by Werner Almesberger
  */
 
-#include <errno.h>
 #include <asm/segment.h>
-#include <linux/string.h>
-#include <linux/stat.h>
+
 #include <linux/sched.h>
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
-
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
 
 /* MS-DOS "device special files" */
 
@@ -280,14 +280,17 @@
 	res = -EBUSY;
 	if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done;
 	if (inode->i_count > 1) goto rmdir_done;
-	res = -ENOTEMPTY;
-	pos = 0;
-	dbh = NULL;
-	while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1)
-		if (dde->name[0] && ((unsigned char *) dde->name)[0] !=
-		    DELETED_FLAG && strncmp(dde->name,MSDOS_DOT,MSDOS_NAME) &&
-		    strncmp(dde->name,MSDOS_DOTDOT,MSDOS_NAME)) goto rmdir_done;
-	if (dbh) brelse(dbh);
+	if (inode->i_data[D_START]) { /* may be zero in mkdir */
+		res = -ENOTEMPTY;
+		pos = 0;
+		dbh = NULL;
+		while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1)
+			if (dde->name[0] && ((unsigned char *) dde->name)[0] !=
+			    DELETED_FLAG && strncmp(dde->name,MSDOS_DOT,
+			    MSDOS_NAME) && strncmp(dde->name,MSDOS_DOTDOT,
+			    MSDOS_NAME)) goto rmdir_done;
+		if (dbh) brelse(dbh);
+	}
 	inode->i_nlink = 0;
 	dir->i_mtime = CURRENT_TIME;
 	inode->i_dirt = dir->i_dirt = 1;
diff --git a/fs/namei.c b/fs/namei.c
index 17bdd29..42eb868 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1,18 +1,18 @@
 /*
  *  linux/fs/namei.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
  * Some corrections by tytso.
  */
 
-#include <errno.h>
 #include <const.h>
 
 #include <asm/segment.h>
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff --git a/fs/open.c b/fs/open.c
index 275e429..538f7ae 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1,20 +1,19 @@
 /*
  *  linux/fs/open.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-#include <sys/types.h>
-#include <utime.h>
-
-#include <sys/vfs.h>
-
+#include <linux/vfs.h>
+#include <linux/types.h>
+#include <linux/utime.h>
+#include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/signal.h>
 
 #include <asm/segment.h>
 
@@ -307,20 +306,17 @@
 	if (fd>=NR_OPEN)
 		return -EMFILE;
 	current->close_on_exec &= ~(1<<fd);
-	f=0+file_table;
-	for (i=0 ; i<NR_FILE ; i++,f++)
-		if (!f->f_count) break;
-	if (i>=NR_FILE)
+	f = get_empty_filp();
+	if (!f)
 		return -ENFILE;
-	(current->filp[fd] = f)->f_count++;
+	current->filp[fd] = f;
 	if ((i = open_namei(filename,flag,mode,&inode))<0) {
 		current->filp[fd]=NULL;
-		f->f_count=0;
+		f->f_count--;
 		return i;
 	}
 	f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
 	f->f_flags = flag;
-	f->f_count = 1;
 	f->f_inode = inode;
 	f->f_pos = 0;
 	f->f_reada = 0;
@@ -330,7 +326,7 @@
 	if (f->f_op && f->f_op->open)
 		if (i = f->f_op->open(inode,f)) {
 			iput(inode);
-			f->f_count=0;
+			f->f_count--;
 			current->filp[fd]=NULL;
 			return i;
 		}
@@ -365,6 +361,12 @@
 	if (filp->f_op && filp->f_op->release)
 		filp->f_op->release(inode,filp);
 	filp->f_count--;
+	filp->f_inode = NULL;
 	iput(inode);
 	return 0;
 }
+
+int sys_vhangup(void)
+{
+	return -ENOSYS;
+}
diff --git a/fs/pipe.c b/fs/pipe.c
index 29f43bf..014f690 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1,18 +1,17 @@
 /*
  *  linux/fs/pipe.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <signal.h>
-#include <errno.h>
-#include <termios.h>
-
 #include <asm/segment.h>
 
-#include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/termios.h>
 
 static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
@@ -208,14 +207,13 @@
 	int i,j;
 
 	verify_area(fildes,8);
-	j=0;
-	for(i=0;j<2 && i<NR_FILE;i++)
-		if (!file_table[i].f_count)
-			(f[j++]=i+file_table)->f_count++;
+	for(j=0 ; j<2 ; j++)
+		if (!(f[j] = get_empty_filp()))
+			break;
 	if (j==1)
-		f[0]->f_count=0;
+		f[0]->f_count--;
 	if (j<2)
-		return -1;
+		return -ENFILE;
 	j=0;
 	for(i=0;j<2 && i<NR_OPEN;i++)
 		if (!current->filp[i]) {
@@ -225,14 +223,16 @@
 	if (j==1)
 		current->filp[fd[0]]=NULL;
 	if (j<2) {
-		f[0]->f_count=f[1]->f_count=0;
-		return -1;
+		f[0]->f_count--;
+		f[1]->f_count--;
+		return -EMFILE;
 	}
 	if (!(inode=get_pipe_inode())) {
-		current->filp[fd[0]] =
-			current->filp[fd[1]] = NULL;
-		f[0]->f_count = f[1]->f_count = 0;
-		return -1;
+		current->filp[fd[0]] = NULL;
+		current->filp[fd[1]] = NULL;
+		f[0]->f_count--;
+		f[1]->f_count--;
+		return -ENFILE;
 	}
 	f[0]->f_inode = f[1]->f_inode = inode;
 	f[0]->f_pos = f[1]->f_pos = 0;
diff --git a/fs/read_write.c b/fs/read_write.c
index f7919fd..e72e6b2 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1,17 +1,16 @@
 /*
  *  linux/fs/read_write.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/dirent.h>
-
+#include <linux/types.h>
+#include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
+
 #include <asm/segment.h>
 
 /*
diff --git a/fs/select.c b/fs/select.c
index d5fa7e8..5cd8e0f 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -5,21 +5,20 @@
  * patches by Peter MacDonald. Heavily edited by Linus.
  */
 
+#include <linux/types.h>
+#include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 
-#include <sys/types.h>
-#include <sys/time.h>
-
 #include <const.h>
-#include <errno.h>
-#include <signal.h>
 
 /*
  * Ok, Peter made a complicated, but straightforward multiple_wait() function.
@@ -33,8 +32,6 @@
  * functions have to call it to add an entry to the select table.
  */
 
-static select_table * sel_tables = NULL;
-
 static void free_wait(select_table * p)
 {
 	struct select_table_entry * entry = p->entry + p->nr;
@@ -134,9 +131,9 @@
 }
 
 /*
- * Note that we cannot return -ERESTARTSYS, as we change our input
- * parameters. Sad, but there you are. We could do some tweaking in
- * the library function ...
+ * We can actually return ERESTARTSYS insetad of EINTR, but I'd
+ * like to be certain this leads to no problems. So I return
+ * EINTR just for safety.
  */
 int sys_select( unsigned long *buffer )
 {
@@ -178,8 +175,17 @@
 	else
 		timeout = 0;
 	current->timeout = 0;
+	if (tvp) {
+		verify_area(tvp, sizeof(*tvp));
+		put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
+		timeout %= HZ;
+		timeout *= (1000000/HZ);
+		put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
+	}
 	if (i < 0)
 		return i;
+	if (!i && (current->signal & ~current->blocked))
+		return -EINTR;
 	if (inp) {
 		verify_area(inp, 4);
 		put_fs_long(res_in,inp);
@@ -192,16 +198,5 @@
 		verify_area(exp,4);
 		put_fs_long(res_ex,exp);
 	}
-	if (tvp) {
-		verify_area(tvp, sizeof(*tvp));
-		put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
-		timeout %= HZ;
-		timeout *= (1000000/HZ);
-		put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
-	}
-	if (i)
-		return i;
-	if (current->signal & ~current->blocked)
-		return -EINTR;
-	return 0;
+	return i;
 }
diff --git a/fs/stat.c b/fs/stat.c
index 3f1dbf6..225f9d3 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -1,11 +1,10 @@
 /*
  *  linux/fs/stat.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
diff --git a/fs/super.c b/fs/super.c
index 970ce2e..4d0e030 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/super.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -14,12 +14,11 @@
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
+#include <linux/errno.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
 
-#include <errno.h>
-
-
 int sync_dev(int dev);
 void wait_for_keypress(void);
 
@@ -139,28 +138,16 @@
 		return(NULL);
 	s->s_dev = dev;
 	s->s_covered = NULL;
-	s->s_time = 0;
 	s->s_rd_only = 0;
 	s->s_dirt = 0;
 	return(s);
 }
 
-int sys_umount(char * dev_name)
+static int do_umount(int dev)
 {
-	struct inode * inode;
 	struct super_block * sb;
-	int dev;
+	struct inode * inode;
 
-	if (!suser())
-		return -EPERM;
-	if (!(inode = namei(dev_name)))
-		return -ENOENT;
-	dev = inode->i_rdev;
-	if (!S_ISBLK(inode->i_mode)) {
-		iput(inode);
-		return -ENOTBLK;
-	}
-	iput(inode);
 	if (dev==ROOT_DEV)
 		return -EBUSY;
 	if (!(sb=get_super(dev)) || !(sb->s_covered))
@@ -181,6 +168,29 @@
 	if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
 		sb->s_op->write_super (sb);
         put_super(dev);
+	return 0;
+}
+
+int sys_umount(char * dev_name)
+{
+	struct inode * inode;
+	int dev,retval;
+
+	if (!suser())
+		return -EPERM;
+	if (!(inode = namei(dev_name)))
+		return -ENOENT;
+	dev = inode->i_rdev;
+	if (!S_ISBLK(inode->i_mode)) {
+		iput(inode);
+		return -ENOTBLK;
+	}
+	retval = do_umount(dev);
+	if (!retval && MAJOR(dev) < MAX_BLKDEV &&
+	    blkdev_fops[MAJOR(dev)]->release)
+		blkdev_fops[MAJOR(dev)]->release(inode,NULL);
+	iput(inode);
+	if (retval) return retval;
         sync_dev(dev);
 	return 0;
 }
@@ -261,13 +271,16 @@
 		retval = -EPERM;
 	else if (IS_NODEV(inode))
 		retval = -EACCES;
-	iput(inode);
-	if (retval)
+	if (!retval && blkdev_fops[MAJOR(dev)]->open)
+		retval = blkdev_fops[MAJOR(dev)]->open(inode,NULL);
+	if (retval) {
+		iput(inode);
 		return retval;
+	}
 	if ((new_flags & 0xffff0000) == 0xC0ED0000) {
 		flags = new_flags & 0xffff;
 		if (data && (unsigned long) data < TASK_SIZE)
-			page = get_free_page();
+			page = get_free_page(GFP_KERNEL);
 	}
 	if (page) {
 		i = TASK_SIZE - (unsigned long) data;
@@ -284,12 +297,16 @@
 		t = "minix";
 	retval = do_mount(dev,dir_name,t,flags,(void *) page);
 	free_page(page);
+	if (retval && blkdev_fops[MAJOR(dev)]->release)
+		blkdev_fops[MAJOR(dev)]->release(inode,NULL);
+	iput(inode);
 	return retval;
 }
 
 void mount_root(void)
 {
-	int i,free;
+	int i;
+	struct file_system_type * fs_type = file_systems;
 	struct super_block * p;
 	struct inode * mi;
 
@@ -303,31 +320,23 @@
 	}
 	for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
 		p->s_dev = 0;
+		p->s_blocksize = 0;
 		p->s_lock = 0;
 		p->s_wait = NULL;
+		p->s_mounted = p->s_covered = 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)))
-		panic("Unable to read root i-node");
-	wait_for_keypress();*/
-	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;
-	i=p->s_nzones;
-	while (-- i >= 0)
-		if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
-			free++;
-	printk("%d/%d free blocks\n\r",free,p->s_nzones);
-	free=0;
-	i=p->s_ninodes+1;
-	while (-- i >= 0)
-		if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
-			free++;
-	printk("%d/%d free inodes\n\r",free,p->s_ninodes);
+	while (fs_type->read_super && fs_type->name) {
+		p = read_super(ROOT_DEV,fs_type->name,0,NULL);
+		if (p) {
+			mi = p->s_mounted;
+			mi->i_count += 3 ;	/* NOTE! it is logically used 4 times, not 1 */
+			p->s_covered = mi;
+			p->s_flags = 0;
+			current->pwd = mi;
+			current->root = mi;
+			return;
+		}
+		fs_type++;
+	}
+	panic("Unable to mount root");
 }
diff --git a/include/asm/irq.h b/include/asm/irq.h
index f9fbe02..7e2b524 100644
--- a/include/asm/irq.h
+++ b/include/asm/irq.h
@@ -26,6 +26,39 @@
 	"movl $0x17,%edx\n\t" \
 	"mov %dx,%fs\n\t"
 
+/*
+ * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
+ * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
+ * call the routines that do signal handling etc on return, and can have
+ * more relaxed register-saving etc. They are also atomic, and are thus
+ * suited for small, fast interrupts like the serial lines or the harddisk
+ * drivers, which don't actually need signal handling etc.
+ *
+ * Also note that we actually save only those registers that are used in
+ * C subroutines (%eax, %edx and %ecx), so if you do something weird,
+ * you're on your own. The only segments that are saved (not counting the
+ * automatic stack and code segment handling) are %ds and %es, and they
+ * point to kernel space. No messing around with %fs here.
+ */
+#define SAVE_MOST \
+	"cld\n\t" \
+	"push %es\n\t" \
+	"push %ds\n\t" \
+	"pushl %eax\n\t" \
+	"pushl %edx\n\t" \
+	"pushl %ecx\n\t" \
+	"movl $0x10,%edx\n\t" \
+	"mov %dx,%ds\n\t" \
+	"mov %dx,%es\n\t"
+
+#define RESTORE_MOST \
+	"popl %ecx\n\t" \
+	"popl %edx\n\t" \
+	"popl %eax\n\t" \
+	"pop %ds\n\t" \
+	"pop %es\n\t" \
+	"iret"
+
 #define ACK_FIRST(mask) \
 	"inb $0x21,%al\n\t" \
 	"jmp 1f\n" \
@@ -67,16 +100,18 @@
 
 #define IRQ_NAME2(nr) nr##_interrupt()
 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
+#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
 	
 #define BUILD_IRQ(chip,nr,mask) \
-extern void IRQ_NAME(nr); \
+void IRQ_NAME(nr); \
+void FAST_IRQ_NAME(nr); \
+void BAD_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" \
@@ -88,7 +123,25 @@
 	"jne ret_from_sys_call\n\t" \
 	"cli\n\t" \
 	UNBLK_##chip(mask) \
-	"sti\n\t" \
-	"jmp ret_from_sys_call");
+	"jmp ret_from_sys_call\n" \
+"\n.align 2\n" \
+"_fast_IRQ" #nr "_interrupt:\n\t" \
+	SAVE_MOST \
+	ACK_##chip(mask) \
+	"pushl $" #nr "\n\t" \
+	"call _do_fast_IRQ\n\t" \
+	"addl $4,%esp\n\t" \
+	"testl %eax,%eax\n\t" \
+	"jne 2f\n\t" \
+	"cli\n\t" \
+	UNBLK_##chip(mask) \
+	"\n2:\t" \
+	RESTORE_MOST \
+"\n\n.align 2\n" \
+"_bad_IRQ" #nr "_interrupt:\n\t" \
+	"pushl %eax\n\t" \
+	ACK_##chip(mask) \
+	"popl %eax\n\t" \
+	"iret");
 
 #endif
diff --git a/include/errno.h b/include/errno.h
deleted file mode 100644
index fdb1b14..0000000
--- a/include/errno.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _ERRNO_H
-#define _ERRNO_H
-
-/*
- * ok, as I hadn't got any other source of information about
- * possible error numbers, I was forced to use the same numbers
- * as minix.
- * Hopefully these are posix or something. I wouldn't know (and posix
- * isn't telling me - they want $$$ for their f***ing standard).
- *
- * We don't use the _SIGN cludge of minix, so kernel returns must
- * see to the sign by themselves.
- *
- * NOTE! Remember to change strerror() if you change this file!
- */
-
-extern int errno;
-
-#define EPERM		 1
-#define ENOENT		 2
-#define ESRCH		 3
-#define EINTR		 4
-#define EIO		 5
-#define ENXIO		 6
-#define E2BIG		 7
-#define ENOEXEC		 8
-#define EBADF		 9
-#define ECHILD		10
-#define EAGAIN		11
-#define ENOMEM		12
-#define EACCES		13
-#define EFAULT		14
-#define ENOTBLK		15
-#define EBUSY		16
-#define EEXIST		17
-#define EXDEV		18
-#define ENODEV		19
-#define ENOTDIR		20
-#define EISDIR		21
-#define EINVAL		22
-#define ENFILE		23
-#define EMFILE		24
-#define ENOTTY		25
-#define ETXTBSY		26
-#define EFBIG		27
-#define ENOSPC		28
-#define ESPIPE		29
-#define EROFS		30
-#define EMLINK		31
-#define EPIPE		32
-#define EDOM		33
-#define ERANGE		34
-#define EDEADLK		35
-#define ENAMETOOLONG	36
-#define ENOLCK		37
-#define ENOSYS		38
-#define ENOTEMPTY	39
-#define ELOOP		40
-
-/* Should never be seen by user programs */
-#define ERESTARTSYS	512
-#define ERESTARTNOINTR	513
-
-#endif
diff --git a/include/limits.h b/include/limits.h
deleted file mode 100644
index 1303adf..0000000
--- a/include/limits.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef _LIMITS_H
-#define _LIMITS_H
-
-#define RAND_MAX 0x7ffffffd	/* don't ask - see rand.c */
-
-#define CHAR_BIT 8
-#define MB_LEN_MAX 1
-
-#define SCHAR_MIN (-128)
-#define SCHAR_MAX 127
-
-#define UCHAR_MAX 255U
-
-#ifdef __CHAR_UNSIGNED__
-#define CHAR_MIN 0
-#define CHAR_MAX UCHAR_MAX
-#else
-#define CHAR_MIN SCHAR_MIN
-#define CHAR_MAX SCHAR_MAX
-#endif
-
-#define SHRT_MIN (-32768)
-#define SHRT_MAX 32767
-
-#define USHRT_MAX 65535U
-
-#define INT_MIN (-2147483648)
-#define INT_MAX 2147483647
-
-#define UINT_MAX 4294967295U
-
-#define LONG_MIN (-2147483648)
-#define LONG_MAX 2147483647
-
-#define ULONG_MAX 4294967295U
-
-/*
- * Why are these different from the section below?  -- TYT
- */
-#define _POSIX_ARG_MAX 40960	/* exec() may have 40K worth of args */
-#define _POSIX_CHILD_MAX   6	/* a process may have 6 children */
-#define _POSIX_LINK_MAX    8	/* a file may have 8 links */
-#define _POSIX_MAX_CANON 255	/* size of the canonical input queue */
-#define _POSIX_MAX_INPUT 255	/* you can type 255 chars ahead */
-#define _POSIX_NAME_MAX   14	/* a file name may have 14 chars */
-#define _POSIX_NGROUPS_MAX 32	/* supplementary group IDs are optional */
-#define _POSIX_OPEN_MAX   16	/* a process may have 16 files open */
-#define _POSIX_PATH_MAX  255	/* a pathname may contain 255 chars */
-#define _POSIX_PIPE_BUF  512	/* pipes writes of 512 bytes must be atomic */
-
-#define NGROUPS_MAX       32	/* supplemental group IDs are available */
-#define ARG_MAX        40960	/* # bytes of args + environ for exec() */
-#define CHILD_MAX        999    /* no limit :-) */
-#define OPEN_MAX          20	/* # open files a process may have */
-#define LINK_MAX         127	/* # links a file may have */
-#define MAX_CANON        255	/* size of the canonical input queue */
-#define MAX_INPUT        255	/* size of the type-ahead buffer */
-#define NAME_MAX         255	/* # chars in a file name */
-#define PATH_MAX        1024	/* # chars in a path name */
-#define PIPE_BUF        4095	/* # bytes in atomic write to a pipe */
-
-#endif
diff --git a/include/a.out.h b/include/linux/a.out.h
similarity index 100%
rename from include/a.out.h
rename to include/linux/a.out.h
diff --git a/include/linux/config.dist.h b/include/linux/config.dist.h
index 4a84fbf..15b6e4b 100644
--- a/include/linux/config.dist.h
+++ b/include/linux/config.dist.h
@@ -17,7 +17,11 @@
 #define CONFIG_SCSI_SEAGATE
 #undef CONFIG_SCSI_ULTRASTOR
 #define CONFIG_SCSI_ULTRASTOR
+#undef CONFIG_SCSI_7000FASST
+#define CONFIG_SCSI_7000FASST
 
+#undef CONFIG_BLK_DEV_HD
+#define CONFIG_BLK_DEV_HD
 #undef CONFIG_BLK_DEV_SD
 #define CONFIG_BLK_DEV_SD
 #undef CONFIG_BLK_DEV_ST
diff --git a/include/linux/config.h b/include/linux/config.h
index 0e5f4cd..ef79c38 100644
--- a/include/linux/config.h
+++ b/include/linux/config.h
@@ -66,9 +66,11 @@
 
 #undef HD_TYPE
 
+#define CONFIG_BLK_DEV_HD
 #undef CONFIG_BLK_DEV_SD
 #undef CONFIG_BLK_DEV_ST
 
+
 /*
 	Choose supported SCSI adapters here.
 */
@@ -80,23 +82,25 @@
 #undef CONFIG_SCSI_FUTURE_DOMAIN
 #undef CONFIG_SCSI_SEAGATE
 #undef CONFIG_SCSI_ULTRASTOR
+#undef CONFIG_SCSI_7000FASST
 
-#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_ST)
-	#ifndef CONFIG_SCSI
-		#define CONFIG_SCSI
-	#endif
-	
-	#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
-		!defined(CONFIG_SCSI_FUTURE_DOMAIN) &&  !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR) 
+#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_CD) || \
+defined(CONFIG_CHR_DEV_ST)
+#ifndef CONFIG_SCSI
+	#define CONFIG_SCSI
+#endif
 
-	#error  Error : SCSI devices enabled, but no low level drivers have been enabled.
-	#endif
+#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \
+		!defined(CONFIG_SCSI_FUTURE_DOMAIN) &&  !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR) && \
+		!defined(CONFIG_SCSI_7000FASST)
+#error  Error : SCSI devices enabled, but no low level drivers have been enabled.
+#endif
 #endif
 
 #ifdef CONFIG_DISTRIBUTION
-	#include <linux/config.dist.h>
+#include <linux/config.dist.h>
 #else
-	#include <linux/config.site.h>
+#include <linux/config.site.h>
 #endif
 
 /*
diff --git a/include/linux/config_rel.h b/include/linux/config_rel.h
index c286ac2..bd66dee 100644
--- a/include/linux/config_rel.h
+++ b/include/linux/config_rel.h
@@ -1 +1 @@
-#define UTS_RELEASE "0.96b-63"
+#define UTS_RELEASE "0.97-11"
diff --git a/include/linux/config_ver.h b/include/linux/config_ver.h
index d32d8b2..e09eeab 100644
--- a/include/linux/config_ver.h
+++ b/include/linux/config_ver.h
@@ -1 +1 @@
-#define UTS_VERSION "07/04/92"
+#define UTS_VERSION "08/01/92"
diff --git a/include/linux/dirent.h b/include/linux/dirent.h
new file mode 100644
index 0000000..01d16c8
--- /dev/null
+++ b/include/linux/dirent.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_DIRENT_H
+#define _LINUX_DIRENT_H
+
+struct dirent {
+	long		d_ino;
+	off_t		d_off;
+	unsigned short	d_reclen;
+	char		d_name[NAME_MAX+1];
+};
+
+#endif
diff --git a/include/linux/errno.h b/include/linux/errno.h
new file mode 100644
index 0000000..420d5ff
--- /dev/null
+++ b/include/linux/errno.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_ERRNO_H
+#define _LINUX_ERRNO_H
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	41	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+#define	EDEADLOCK	58	/* File locking deadlock error */
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+
+/* Should never be seen by user programs */
+#define ERESTARTSYS	512
+#define ERESTARTNOINTR	513
+
+#endif
diff --git a/include/linux/ext_fs.h b/include/linux/ext_fs.h
index 0877bdb..c4b3cf4 100644
--- a/include/linux/ext_fs.h
+++ b/include/linux/ext_fs.h
@@ -1,11 +1,9 @@
-/*
- * The ext filesystem constants/structures
- */
-
 #ifndef _EXT_FS_H
 #define _EXT_FS_H
 
-#include <sys/types.h>
+/*
+ * The ext filesystem constants/structures
+ */
 
 /*
  * Free blocks/inodes management style
diff --git a/include/linux/ext_fs_sb.h b/include/linux/ext_fs_sb.h
new file mode 100644
index 0000000..8aff1ff
--- /dev/null
+++ b/include/linux/ext_fs_sb.h
@@ -0,0 +1,19 @@
+#ifndef _EXT_FS_SB
+#define _EXT_FS_SB
+
+/*
+ * extended-fs super-block data in memory (same as minix: has to change)
+ */
+struct ext_sb_info {
+			unsigned long s_ninodes;
+			unsigned long s_nzones;
+			unsigned long s_imap_blocks;
+			unsigned long s_zmap_blocks;
+			unsigned long s_firstdatazone;
+			unsigned long s_log_zone_size;
+			unsigned long s_max_size;
+			struct buffer_head * s_imap[8];
+			struct buffer_head * s_zmap[8];
+};
+
+#endif
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index dcf49e3..e477370 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -1,8 +1,6 @@
 #ifndef _FCNTL_H
 #define _FCNTL_H
 
-#include <sys/types.h>
-
 /* open/fcntl - O_SYNC isn't implemented yet */
 #define O_ACCMODE	  0003
 #define O_RDONLY	    00
diff --git a/include/linux/fd.h b/include/linux/fd.h
index d490194..4828db0 100644
--- a/include/linux/fd.h
+++ b/include/linux/fd.h
@@ -1,5 +1,5 @@
-#ifndef _FD_H
-#define _FD_H
+#ifndef _LINUX_FD_H
+#define _LINUX_FD_H
 
 #define FDCLRPRM 0 /* clear user-defined parameters */
 #define FDSETPRM 1 /* set user-defined parameters for current media */
@@ -10,6 +10,7 @@
 #define FDFMTBEG 6 /* begin formatting a disk */
 #define	FDFMTTRK 7 /* format the specified track */
 #define FDFMTEND 8 /* end formatting a disk */
+#define FDSETEMSGTRESH	10	/* set fdc error reporting treshold */
 
 #define FD_FILL_BYTE 0xF6 /* format fill byte */
 
@@ -20,13 +21,20 @@
 #define FORMAT_ERROR	4	/* formatting error */
 
 struct floppy_struct {
-	unsigned int size, sect, head, track, stretch;
-	unsigned char gap,rate,spec1,fmt_gap;
-	char *name; /* used only for predefined formats */
+	unsigned int	size,		/* nr of 512-byte sectors total */
+			sect,		/* sectors per track */
+			head,		/* nr of heads */
+			track,		/* nr of tracks */
+			stretch;	/* !=0 means double track steps */
+	unsigned char	gap,		/* gap1 size */
+			rate,		/* data rate. |= 0x40 for perpendicular */
+			spec1,		/* stepping rate, head unload time */
+			fmt_gap;	/* gap2 size */
+	char 	      * name; /* used only for predefined formats */
 };
 
 struct format_descr {
-    unsigned int device,head,track;
+	unsigned int device,head,track;
 };
 
 #endif
diff --git a/include/linux/fdreg.h b/include/linux/fdreg.h
index 77a270e..6d172b6 100644
--- a/include/linux/fdreg.h
+++ b/include/linux/fdreg.h
@@ -1,10 +1,10 @@
+#ifndef _LINUX_FDREG_H
+#define _LINUX_FDREG_H
 /*
  * This file contains some defines for the floppy disk controller.
  * Various sources. Mostly "IBM Microcomputers: A Programmers
  * Handbook", Sanches and Canton.
  */
-#ifndef _FDREG_H
-#define _FDREG_H
 
 extern int ticks_to_floppy_on(unsigned int nr);
 extern void floppy_on(unsigned int nr);
@@ -57,16 +57,23 @@
 #define ST3_WP		0x40		/* Write Protect */
 
 /* Values for FD_COMMAND */
-#define FD_RECALIBRATE	0x07		/* move to track 0 */
-#define FD_SEEK		0x0F		/* seek track */
-#define FD_READ		0xE6		/* read with MT, MFM, SKip deleted */
-#define FD_WRITE	0xC5		/* write with MT, MFM */
-#define FD_SENSEI	0x08		/* Sense Interrupt Status */
-#define FD_SPECIFY	0x03		/* specify HUT etc */
-#define FD_FORMAT	0x4D		/* format one track */
+#define FD_RECALIBRATE		0x07	/* move to track 0 */
+#define FD_SEEK			0x0F	/* seek track */
+#define FD_READ			0xE6	/* read with MT, MFM, SKip deleted */
+#define FD_WRITE		0xC5	/* write with MT, MFM */
+#define FD_SENSEI		0x08	/* Sense Interrupt Status */
+#define FD_SPECIFY		0x03	/* specify HUT etc */
+#define FD_FORMAT		0x4D	/* format one track */
+#define FD_VERSION		0x10	/* get version code */
+#define FD_CONFIGURE		0x13	/* configure FIFO operation */
+#define FD_PERPENDICULAR	0x12	/* perpendicular r/w mode */
 
 /* DMA commands */
 #define DMA_READ	0x46
 #define DMA_WRITE	0x4A
 
+/* FDC version return types */
+#define FDC_TYPE_STD	0x80	/* normal 8272A clone FDC */
+#define FDC_TYPE_82077	0x90	/* FIFO + perpendicular support */
+
 #endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 925f64a..86cb92a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1,17 +1,16 @@
+#ifndef _LINUX_FS_H
+#define _LINUX_FS_H
+
 /*
  * This file has definitions for some important file table
  * structures etc.
  */
 
-#ifndef _FS_H
-#define _FS_H
-
 #include <linux/limits.h>
 #include <linux/wait.h>
-
-#include <sys/types.h>
-#include <sys/dirent.h>
-#include <sys/vfs.h>
+#include <linux/types.h>
+#include <linux/dirent.h>
+#include <linux/vfs.h>
 
 /* devices are as follows: (same as minix, so we can use the minix
  * file system. These are major numbers.)
@@ -39,7 +38,7 @@
 #define READA 2		/* read-ahead - don't pause */
 #define WRITEA 3	/* "write-ahead" - silly, but somewhat useful */
 
-void buffer_init(long buffer_end);
+extern void buffer_init(void);
 
 #define MAJOR(a) (((unsigned)(a))>>8)
 #define MINOR(a) ((a)&0xff)
@@ -96,18 +95,20 @@
 
 struct buffer_head {
 	char * b_data;			/* pointer to data block (1024 bytes) */
+	unsigned long b_size;		/* block size */
 	unsigned long b_blocknr;	/* block number */
 	unsigned short b_dev;		/* device (0 = free) */
+	unsigned short b_count;		/* users using this block */
 	unsigned char b_uptodate;
 	unsigned char b_dirt;		/* 0-clean,1-dirty */
-	unsigned char b_count;		/* users using this block */
 	unsigned char b_lock;		/* 0 - ok, 1 -locked */
 	struct wait_queue * b_wait;
-	struct buffer_head * b_prev;
+	struct buffer_head * b_prev;		/* doubly linked list of hash-queue */
 	struct buffer_head * b_next;
-	struct buffer_head * b_prev_free;
+	struct buffer_head * b_prev_free;	/* doubly linked list of buffers */
 	struct buffer_head * b_next_free;
-	struct buffer_head * b_reqnext;
+	struct buffer_head * b_this_page;	/* circular list of buffers in one page */
+	struct buffer_head * b_reqnext;		/* request queue */
 };
 
 struct inode {
@@ -148,29 +149,28 @@
 	off_t f_pos;
 };
 
+#include <linux/minix_fs_sb.h>
+#include <linux/ext_fs_sb.h>
+#include <linux/msdos_fs_sb.h>
+
 struct super_block {
-	unsigned long s_ninodes;
-	unsigned long s_nzones;
-	unsigned long s_imap_blocks;
-	unsigned long s_zmap_blocks;
-	unsigned long s_firstdatazone;
-	unsigned long s_log_zone_size;
-	unsigned long s_max_size;
-	unsigned short s_magic;
-/* These are only in memory */
-	struct buffer_head * s_imap[8];
-	struct buffer_head * s_zmap[8];
 	unsigned short s_dev;
-	struct inode * s_covered;
-	struct inode * s_mounted;
-	unsigned long s_time;
-	struct wait_queue * s_wait;
+	unsigned long s_blocksize;
 	unsigned char s_lock;
 	unsigned char s_rd_only;
 	unsigned char s_dirt;
-	/* TUBE */
 	struct super_operations *s_op;
-	int s_flags;
+	unsigned long s_flags;
+	unsigned long s_magic;
+	unsigned long s_time;
+	struct inode * s_covered;
+	struct inode * s_mounted;
+	struct wait_queue * s_wait;
+	union {
+		struct minix_sb_info minix_sb;
+		struct ext_sb_info ext_sb;
+		struct msdos_sb_info msdos_sb;
+	} u;
 };
 
 struct file_operations {
@@ -223,8 +223,12 @@
 extern struct inode inode_table[NR_INODE];
 extern struct file file_table[NR_FILE];
 extern struct super_block super_block[NR_SUPER];
-extern struct buffer_head * start_buffer;
+
+extern void grow_buffers(int size);
+extern int shrink_buffers(void);
+
 extern int nr_buffers;
+extern int nr_buffer_heads;
 
 extern void check_disk_change(int dev);
 extern void invalidate_inodes(int dev);
@@ -247,13 +251,14 @@
 extern struct inode * iget(int dev,int nr);
 extern struct inode * get_empty_inode(void);
 extern struct inode * get_pipe_inode(void);
-extern struct buffer_head * get_hash_table(int dev, int block);
-extern struct buffer_head * getblk(int dev, int block);
+extern struct file * get_empty_filp(void);
+extern struct buffer_head * get_hash_table(int dev, int block, int size);
+extern struct buffer_head * getblk(int dev, int block, int size);
 extern void ll_rw_block(int rw, struct buffer_head * bh);
 extern void ll_rw_page(int rw, int dev, int nr, char * buffer);
 extern void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buffer);
 extern void brelse(struct buffer_head * buf);
-extern struct buffer_head * bread(int dev,int block);
+extern struct buffer_head * bread(int dev, int block, int size);
 extern void bread_page(unsigned long addr,int dev,int b[4]);
 extern struct buffer_head * breada(int dev,int block,...);
 extern int sync_dev(int dev);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
new file mode 100644
index 0000000..c1d1b4e
--- /dev/null
+++ b/include/linux/genhd.h
@@ -0,0 +1,52 @@
+#ifndef _GENHD_H
+#define _GENHD_H
+
+/*
+ * 	genhd.h Copyright (C) 1992 Drew Eckhardt
+ *	Generic hard disk header file by  
+ * 		Drew Eckhardt
+ *
+ *		<drew@colorado.edu>
+ */
+	
+#define EXTENDED_PARTITION 5
+	
+struct partition {
+	unsigned char boot_ind;		/* 0x80 - active */
+	unsigned char head;		/* starting head */
+	unsigned char sector;		/* starting sector */
+	unsigned char cyl;		/* starting cylinder */
+	unsigned char sys_ind;		/* What partition type */
+	unsigned char end_head;		/* end head */
+	unsigned char end_sector;	/* end sector */
+	unsigned char end_cyl;		/* end cylinder */
+	unsigned int start_sect;	/* starting sector counting from 0 */
+	unsigned int nr_sects;		/* nr of sectors in partition */
+};
+
+struct hd_struct {
+	long start_sect;
+	long nr_sects;
+};
+
+struct gendisk {
+	int major;			/* major number of driver */
+	char *major_name;		/* name of major driver */
+	int minor_shift;		/* number of times minor is shifted to
+					   get real minor */
+	int max_p;			/* maximum partitions per device */
+	int max_nr;			/* maximum number of real devices */
+
+	void (*init)(void);		/* Initialization called before we do our thing */
+	struct hd_struct *part;		/* partition table */
+	int *sizes;			/* block sizes */
+	int nr_real;			/* number of real devices */
+
+	void *real_devices;		/* internal use */
+	struct gendisk *next;
+};
+
+extern int NR_GENDISKS;			/* total */
+extern struct gendisk *gendisk_head;	/* linked list of disks */
+
+#endif
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index 67e5386..28e3054 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -1,10 +1,11 @@
+#ifndef _LINUX_HDREG_H
+#define _LINUX_HDREG_H
+
 /*
  * This file contains some defines for the AT-hd-controller.
  * Various sources. Check out some definitions (see comments with
  * a ques).
  */
-#ifndef _HDREG_H
-#define _HDREG_H
 
 /* Hd controller regs. Ref: IBM AT Bios-listing */
 #define HD_DATA		0x1f0	/* _CTL when writing */
@@ -49,20 +50,6 @@
 #define ECC_ERR		0x40	/* ? */
 #define	BBD_ERR		0x80	/* ? */
 
-#define EXTENDED_PARTITION 5
-
-struct partition {
-	unsigned char boot_ind;		/* 0x80 - active */
-	unsigned char head;		/* starting head */
-	unsigned char sector;		/* starting sector */
-	unsigned char cyl;		/* starting cylinder */
-	unsigned char sys_ind;		/* What partition type */
-	unsigned char end_head;		/* end head */
-	unsigned char end_sector;	/* end sector */
-	unsigned char end_cyl;		/* end cylinder */
-	unsigned int start_sect;	/* starting sector counting from 0 */
-	unsigned int nr_sects;		/* nr of sectors in partition */
-};
 
 #define HDIO_REQ 0x301
 struct hd_geometry {
diff --git a/include/linux/head.h b/include/linux/head.h
index db3dda2..b871742 100644
--- a/include/linux/head.h
+++ b/include/linux/head.h
@@ -1,5 +1,5 @@
-#ifndef _HEAD_H
-#define _HEAD_H
+#ifndef _LINUX_HEAD_H
+#define _LINUX_HEAD_H
 
 typedef struct desc_struct {
 	unsigned long a,b;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index ef27d83..cf77d54 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -1,6 +1,10 @@
+#ifndef _LINUX_KERNEL_H
+#define _LINUX_KERNEL_H
+
 /*
  * 'kernel.h' contains some often-used function prototypes etc
  */
+
 void verify_area(void * addr,int count);
 volatile void panic(const char * str);
 volatile void do_exit(long error_code);
@@ -19,3 +23,4 @@
  */
 #define suser() (current->euid == 0)
 
+#endif
diff --git a/include/linux/limits.h b/include/linux/limits.h
index 97450b7..9b04df7 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -1,16 +1,27 @@
 #ifndef _LINUX_LIMITS_H
 #define _LINUX_LIMITS_H
 
+#define NAME_MAX 255
+
 #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
 #define BLOCK_SIZE 1024
 #define BLOCK_SIZE_BITS 10
 #define MAX_CHRDEV 16
 #define MAX_BLKDEV 16
 
+#define NGROUPS_MAX       32	/* supplemental group IDs are available */
+#define ARG_MAX        40960	/* # bytes of args + environ for exec() */
+#define CHILD_MAX        999    /* no limit :-) */
+#define OPEN_MAX          32	/* # open files a process may have */
+#define LINK_MAX         127	/* # links a file may have */
+#define MAX_CANON        255	/* size of the canonical input queue */
+#define MAX_INPUT        255	/* size of the type-ahead buffer */
+#define NAME_MAX         255	/* # chars in a file name */
+#define PATH_MAX        1024	/* # chars in a path name */
+#define PIPE_BUF        4095	/* # bytes in atomic write to a pipe */
 
 #endif
diff --git a/include/linux/lp.h b/include/linux/lp.h
index 785b17d..2fef688 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -1,10 +1,14 @@
+#ifndef _LINUX_LP_H
+#define _LINUX_LP_H
+
 /*
 $Header: /usr/src/linux/include/linux/lp.h,v 1.2 1992/01/21 23:59:24 james_r_wiegand Exp james_r_wiegand $
 */
 
-#include <errno.h>
+#include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+
 #include <asm/io.h>
 #include <asm/segment.h>
 
@@ -37,9 +41,6 @@
 since we are dealing with a horribly slow device
 I don't see the need for a queue
 */
-#ifndef __LP_C__
-	extern
-#endif
 struct lp_struct {
 	int base;
 	int flags;
@@ -52,9 +53,6 @@
  * please let me know if you have different equipment
  * if you have more than 3 printers, remember to increase LP_NO
  */
-#ifndef __LP_C__
-	extern
-#endif   
 struct lp_struct lp_table[] = {
 	{ 0x3bc, 0, },
 	{ 0x378, 0, },
@@ -101,3 +99,5 @@
  */
 
 extern long lp_init(long);
+
+#endif
diff --git a/include/linux/math_emu.h b/include/linux/math_emu.h
index 64e734c..827e9c9 100644
--- a/include/linux/math_emu.h
+++ b/include/linux/math_emu.h
@@ -1,8 +1,3 @@
-/*
- * linux/include/linux/math_emu.h
- *
- * (C) 1991 Linus Torvalds
- */
 #ifndef _LINUX_MATH_EMU_H
 #define _LINUX_MATH_EMU_H
 
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index 99b9f45..1205d6e 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -1,11 +1,9 @@
-/*
- * The minix filesystem constants/structures
- */
-
 #ifndef _MINIX_FS_H
 #define _MINIX_FS_H
 
-#include <sys/types.h>
+/*
+ * The minix filesystem constants/structures
+ */
 
 #define MINIX_NAME_LEN 14
 #define MINIX_ROOT_INO 1
@@ -27,6 +25,9 @@
 	unsigned short i_zone[9];
 };
 
+/*
+ * minix super-block data on disk
+ */
 struct minix_super_block {
 	unsigned short s_ninodes;
 	unsigned short s_nzones;
diff --git a/include/linux/minix_fs_sb.h b/include/linux/minix_fs_sb.h
new file mode 100644
index 0000000..18de6ef
--- /dev/null
+++ b/include/linux/minix_fs_sb.h
@@ -0,0 +1,19 @@
+#ifndef _MINIX_FS_SB
+#define _MINIX_FS_SB
+
+/*
+ * minix super-block data in memory
+ */
+struct minix_sb_info {
+			unsigned long s_ninodes;
+			unsigned long s_nzones;
+			unsigned long s_imap_blocks;
+			unsigned long s_zmap_blocks;
+			unsigned long s_firstdatazone;
+			unsigned long s_log_zone_size;
+			unsigned long s_max_size;
+			struct buffer_head * s_imap[8];
+			struct buffer_head * s_zmap[8];
+};
+
+#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4b3b61b..256f032 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -5,11 +5,49 @@
 
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <signal.h>
+#include <linux/signal.h>
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ */
+extern unsigned long inline __bad_page(void)
+{
+	extern char empty_bad_page[PAGE_SIZE];
+
+	__asm__ __volatile__("cld ; rep ; stosl"
+		::"a" (0),
+		  "D" ((long) empty_bad_page),
+		  "c" (1024)
+		:"di","cx");
+	return (unsigned long) empty_bad_page;
+}
+#define BAD_PAGE __bad_page()
+
+extern unsigned long inline __bad_pagetable(void)
+{
+	extern char empty_bad_page_table[PAGE_SIZE];
+
+	__asm__ __volatile__("cld ; rep ; stosl"
+		::"a" (7+BAD_PAGE),
+		  "D" ((long) empty_bad_page_table),
+		  "c" (1024)
+		:"di","cx");
+	return (unsigned long) empty_bad_page_table;
+}
+#define BAD_PAGETABLE __bad_pagetable()
 
 extern unsigned int swap_device;
 extern struct inode * swap_file;
 
+extern int nr_free_pages;
+
 extern void rw_swap_page(int rw, unsigned int nr, char * buf);
 
 #define read_swap_page(nr,buf) \
@@ -19,7 +57,7 @@
 
 /* memory.c */
 	
-extern unsigned long get_free_page(void);
+extern unsigned long get_free_page(int priority);
 extern unsigned long put_dirty_page(unsigned long page,unsigned long address);
 extern void free_page(unsigned long addr);
 extern int free_page_tables(unsigned long from,unsigned long size);
@@ -27,38 +65,34 @@
 extern int unmap_page_range(unsigned long from, unsigned long size);
 extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
 	 int permiss);
-extern void un_wp_page(unsigned long * table_entry);
-extern void do_wp_page(unsigned long error_code,unsigned long address);
 extern void write_verify(unsigned long address);
+
+extern void do_wp_page(unsigned long error_code, unsigned long address,
+	struct task_struct *tsk, unsigned long user_esp);
 extern void do_no_page(unsigned long error_code, unsigned long address,
 	struct task_struct *tsk, unsigned long user_esp);
-extern void mem_init(long start_mem, long end_mem);
+
+extern unsigned long mem_init(unsigned long start_mem, unsigned long end_mem);
 extern void show_mem(void);
 extern void do_page_fault(unsigned long *esp, unsigned long error_code);
+extern void oom(struct task_struct * task);
 
 /* swap.c */
 
-extern void swap_free(int page_nr);
+extern void swap_free(unsigned int page_nr);
 extern void swap_in(unsigned long *table_ptr);
 
-extern inline volatile void oom(void)
-{
-	printk("out of memory\n\r");
-	do_exit(SIGSEGV);
-}
-
 #define invalidate() \
 __asm__("movl %%eax,%%cr3"::"a" (0))
 
-/* these are not to be changed without changing head.s etc */
-#define LOW_MEM 0x100000
-extern unsigned long HIGH_MEMORY;
-#define PAGING_MEMORY (15*1024*1024)
-#define PAGING_PAGES (PAGING_MEMORY>>12)
-#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
+extern unsigned long low_memory;
+extern unsigned long high_memory;
+extern unsigned long paging_pages;
+
+#define MAP_NR(addr) (((addr)-low_memory)>>12)
 #define USED 100
 
-extern unsigned char mem_map [ PAGING_PAGES ];
+extern unsigned char * mem_map;
 
 #define PAGE_DIRTY	0x40
 #define PAGE_ACCESSED	0x20
@@ -66,4 +100,8 @@
 #define PAGE_RW		0x02
 #define PAGE_PRESENT	0x01
 
+#define GFP_BUFFER	0x00
+#define GFP_USER	0x01
+#define GFP_KERNEL	0x02
+
 #endif
diff --git a/include/linux/mouse.h b/include/linux/mouse.h
index 913123c..4723a54 100644
--- a/include/linux/mouse.h
+++ b/include/linux/mouse.h
@@ -1,3 +1,6 @@
+#ifndef _LINUX_MOUSE_H
+#define _LINUX_MOUSE_H
+
 /*
  * linux/include/linux/mouse.h: header file for Logitech Bus Mouse driver
  * by James Banks
@@ -11,9 +14,6 @@
  *
  */
 
-#ifndef _MOUSE_H
-#define _MOUSE_H
-
 #define MOUSE_IRQ		5
 
 #define	MSE_DATA_PORT		0x23c
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 719dcc3..0eebbf4 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -1,14 +1,13 @@
+#ifndef _MSDOS_FS_H
+#define _MSDOS_FS_H
+
 /*
  * The MS-DOS filesystem constants/structures
  */
 
-#ifndef _MSDOS_FS_H
-#define _MSDOS_FS_H
-
-#include <sys/types.h>
 #include <linux/fs.h>
 
-#define MSDOS_ROOT_INO  1
+#define MSDOS_ROOT_INO  1 /* == MINIX_ROOT_INO */
 #define SECTOR_SIZE     512 /* sector size (bytes) */
 #define SECTOR_BITS	9 /* log2(SECTOR_SIZE) */
 #define MSDOS_DPB	(MSDOS_DPS*2) /* dir entries per block */
@@ -29,7 +28,7 @@
 #define ATTR_ARCH    32 /* archived */
 
 #define ATTR_NONE    0 /* no attribute bits */
-#define ATTR_UNUSED  (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS)
+#define ATTR_UNUSED  (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
 	/* attribute bits that are copied "as is" */
 
 #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
@@ -44,9 +43,7 @@
 				   on */
 #define D_BINARY   5 /* i_data[5]: file contains non-text data */
 
-#define SET_DIRTY(i) (i)->i_dirt = (i)->i_data[D_DIRT] = 1
-
-#define MSDOS_SB(s) ((struct msdos_sb_info *) s)
+#define MSDOS_SB(s) (&((s)->u.msdos_sb))
 
 #define MSDOS_NAME 11 /* maximum name length */
 #define MSDOS_DOT    ".          " /* ".", padded to MSDOS_NAME chars */
@@ -69,20 +66,6 @@
 	unsigned long total_sect;   /* number of sectors (if sectors == 0) */
 };
 
-struct msdos_sb_info { /* space in struct super_block is 28 bytes */
-	unsigned short cluster_size; /* sectors/cluster */
-	unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
-	unsigned short fat_start,fat_length; /* FAT start & length (sec.) */
-	unsigned short dir_start,dir_entries; /* root dir start & entries */
-	unsigned short data_start;   /* first data sector */
-	unsigned long clusters;      /* number of clusters */
-	uid_t fs_uid;
-	gid_t fs_gid;
-	unsigned short fs_umask;
-	unsigned char name_check; /* r = releaxed, n = normal, s = strict */
-	unsigned char conversion; /* b = binary, t = text, a = auto */
-}; /* 28 bytes */
-
 struct msdos_dir_entry {
 	char name[8],ext[3]; /* name and extension */
 	unsigned char attr;  /* attribute bits */
@@ -106,20 +89,19 @@
 
 /* Convert attribute bits and a mask to the UNIX mode. */
 
-#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? 0444 : (a & ATTR_HIDDEN ? 0 : \
-    0777)))
+#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? 0444 : 0777))
 
 /* Convert the UNIX mode to MS-DOS attribute bits. */
 
-#define MSDOS_MKATTR(m) (!(m & 0600) ? ATTR_HIDDEN : ((m & 0600) == 0400 ? \
-    ATTR_RO : ATTR_NONE))
+#define MSDOS_MKATTR(m) (!(m & 0200) ? ATTR_RO : ATTR_NONE)
 
 
 static inline struct buffer_head *msdos_sread(int dev,int sector,void **start)
 {
  	struct buffer_head *bh;
 
-	if (!(bh = bread(dev,sector >> 1))) return NULL;
+	if (!(bh = bread(dev,sector >> 1, 1024)))
+		return NULL;
     	*start = bh->b_data+((sector & 1) << SECTOR_BITS);
 	return bh;
 }
diff --git a/include/linux/msdos_fs_sb.h b/include/linux/msdos_fs_sb.h
new file mode 100644
index 0000000..c02db86
--- /dev/null
+++ b/include/linux/msdos_fs_sb.h
@@ -0,0 +1,18 @@
+#ifndef _MSDOS_FS_SB
+#define _MSDOS_FS_SB
+
+struct msdos_sb_info { /* space in struct super_block is 28 bytes */
+	unsigned short cluster_size; /* sectors/cluster */
+	unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
+	unsigned short fat_start,fat_length; /* FAT start & length (sec.) */
+	unsigned short dir_start,dir_entries; /* root dir start & entries */
+	unsigned short data_start;   /* first data sector */
+	unsigned long clusters;      /* number of clusters */
+	uid_t fs_uid;
+	gid_t fs_gid;
+	unsigned short fs_umask;
+	unsigned char name_check; /* r = relaxed, n = normal, s = strict */
+	unsigned char conversion; /* b = binary, t = text, a = auto */
+};
+
+#endif
diff --git a/include/sys/param.h b/include/linux/param.h
similarity index 100%
rename from include/sys/param.h
rename to include/linux/param.h
diff --git a/include/sys/ptrace.h b/include/linux/ptrace.h
similarity index 93%
rename from include/sys/ptrace.h
rename to include/linux/ptrace.h
index 9d9defb..ad26e03 100644
--- a/include/sys/ptrace.h
+++ b/include/linux/ptrace.h
@@ -1,8 +1,8 @@
+#ifndef _LINUX_PTRACE_H
+#define _LINUX_PTRACE_H
 /* ptrace.h */
 /* structs and defines to help the user use the ptrace system call. */
 
-#ifndef _SYS_PTRACE_H
-#define _SYS_PTRACE_H
 /* has the defines to get at the registers. */
 
 #define PTRACE_TRACEME		   0
@@ -64,4 +64,4 @@
   long ss;
 };
 
-#endif /* _SYS_PTRACE_H */
+#endif
diff --git a/include/sys/resource.h b/include/linux/resource.h
similarity index 95%
rename from include/sys/resource.h
rename to include/linux/resource.h
index 3f34379..4fa0f41 100644
--- a/include/sys/resource.h
+++ b/include/linux/resource.h
@@ -1,10 +1,10 @@
+#ifndef _LINUX_RESOURCE_H
+#define _LINUX_RESOURCE_H
+
 /*
  * Resource control/accounting header file for linux
  */
 
-#ifndef _SYS_RESOURCE_H
-#define _SYS_RESOURCE_H
-
 /*
  * Definition of struct rusage taken from BSD 4.3 Reno
  * 
@@ -67,4 +67,4 @@
 #define	PRIO_PGRP	1
 #define	PRIO_USER	2
 
-#endif /* _SYS_RESOURCE_H */
+#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8065edd..5de4d65 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1,5 +1,5 @@
-#ifndef _SCHED_H
-#define _SCHED_H
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
 
 #define HZ 100
 
@@ -39,10 +39,10 @@
 #include <linux/head.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <signal.h>
+#include <linux/signal.h>
+#include <linux/time.h>
+#include <linux/param.h>
+#include <linux/resource.h>
 
 #if (NR_OPEN > 32)
 #error "Currently the close-on-exec-flags and select masks are in one long, max 32 files/proc"
@@ -117,7 +117,8 @@
 	long blocked;	/* bitmap of masked signals */
 /* various fields */
 	int exit_code;
-	int dumpable;
+	int dumpable:1;
+	int swappable:1;
 	unsigned long start_code,end_code,end_data,brk,start_stack;
 	long pid,pgrp,session,leader;
 	int	groups[NGROUPS];
@@ -183,7 +184,7 @@
 #define INIT_TASK \
 /* state etc */	{ 0,15,15, \
 /* signals */	0,{{},},0, \
-/* ec,brk... */	0,0,0,0,0,0,0, \
+/* ec,brk... */	0,0,0,0,0,0,0,0, \
 /* pid etc.. */	0,0,0,0, \
 /* suppl grps*/ {NOGROUP,}, \
 /* proc links*/ &init_task.task,&init_task.task,NULL,NULL,NULL, \
diff --git a/include/signal.h b/include/linux/signal.h
similarity index 61%
rename from include/signal.h
rename to include/linux/signal.h
index 00ef568..24f098f 100644
--- a/include/signal.h
+++ b/include/linux/signal.h
@@ -1,9 +1,6 @@
-#ifndef _SIGNAL_H
-#define _SIGNAL_H
+#ifndef _LINUX_SIGNAL_H
+#define _LINUX_SIGNAL_H
 
-#include <sys/types.h>
-
-typedef int sig_atomic_t;
 typedef unsigned int sigset_t;		/* 32 bits */
 
 #define _NSIG             32
@@ -54,7 +51,6 @@
 #define SIGLOST		29
 */
 
-/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
 #define SA_NOCLDSTOP	1
 #define SA_INTERRUPT	0x20000000
 #define SA_NOMASK	0x40000000
@@ -68,11 +64,6 @@
 #define SIG_IGN		((void (*)(int))1)	/* ignore signal */
 #define SIG_ERR		((void (*)(int))-1)	/* error return from signal */
 
-#ifdef notdef
-#define sigemptyset(mask) ((*(mask) = 0), 1)
-#define sigfillset(mask) ((*(mask) = ~0), 1)
-#endif
-
 struct sigaction {
 	void (*sa_handler)(int);
 	sigset_t sa_mask;
@@ -80,25 +71,4 @@
 	void (*sa_restorer)(void);
 };
 
-#ifdef __cplusplus
-extern "C" {
 #endif
-
-void (*signal(int _sig, void (*_func)(int)))(int);
-int raise(int sig);
-int kill(pid_t pid, int sig);
-int sigaddset(sigset_t *mask, int signo);
-int sigdelset(sigset_t *mask, int signo);
-int sigemptyset(sigset_t *mask);
-int sigfillset(sigset_t *mask);
-int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */
-int sigpending(sigset_t *set);
-int sigprocmask(int how, sigset_t *set, sigset_t *oldset);
-int sigsuspend(sigset_t *sigmask);
-int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SIGNAL_H */
diff --git a/include/linux/socket.h b/include/linux/socket.h
new file mode 100644
index 0000000..e07703e
--- /dev/null
+++ b/include/linux/socket.h
@@ -0,0 +1,30 @@
+#ifndef _LINUX_SOCKET_H
+#define _LINUX_SOCKET_H
+
+struct sockaddr {
+	u_short sa_family;		/* address family, AF_xxx */
+	char sa_data[14];		/* 14 bytes of protocol address */
+};
+
+/*
+ * socket types
+ */
+#define SOCK_STREAM	1		/* stream (connection) socket */
+#define SOCK_DGRAM	2		/* datagram (connectionless) socket */
+#define SOCK_SEQPACKET	3		/* sequential packet socket */
+#define SOCK_RAW	4		/* raw socket */
+
+/*
+ * supported address families
+ */
+#define AF_UNSPEC	0
+#define AF_UNIX		1
+#define AF_INET		2
+
+/*
+ * protocol families, same as address families
+ */
+#define PF_UNIX		AF_UNIX
+#define PF_INET		AF_INET
+
+#endif
diff --git a/include/stddef.h b/include/linux/stddef.h
similarity index 63%
rename from include/stddef.h
rename to include/linux/stddef.h
index 2828f8e..c6221e7 100644
--- a/include/stddef.h
+++ b/include/linux/stddef.h
@@ -1,10 +1,5 @@
-#ifndef _STDDEF_H
-#define _STDDEF_H
-
-#ifndef _PTRDIFF_T
-#define _PTRDIFF_T
-typedef long ptrdiff_t;
-#endif
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
 
 #ifndef _SIZE_T
 #define _SIZE_T
@@ -14,5 +9,7 @@
 #undef NULL
 #define NULL ((void *)0)
 
+#undef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
 #endif
diff --git a/include/linux/string.h b/include/linux/string.h
index 73c4ee2..cdff971 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -1,14 +1,10 @@
-#ifndef _STRING_H_
-#define _STRING_H_
-
-#include <sys/types.h>
+#ifndef _LINUX_STRING_H_
+#define _LINUX_STRING_H_
 
 #ifndef NULL
 #define NULL ((void *) 0)
 #endif
 
-extern char * strerror(int errno);
-
 /*
  * This string-include defines all string functions as inline
  * functions. Use gcc. It also assumes ds=es=data space, this should be
@@ -18,7 +14,7 @@
  * set, making the functions fast and clean. String instructions have been
  * used through-out, making for "slightly" unclear code :-)
  *
- *		(C) 1991 Linus Torvalds
+ *		Copyright (C) 1991, 1992 Linus Torvalds
  */
  
 extern inline char * strcpy(char * dest,const char *src)
diff --git a/include/linux/sys.h b/include/linux/sys.h
index 736ad01..deae36f 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -113,6 +113,7 @@
 extern int sys_newfstat();
 extern int sys_newuname();
 extern int sys_iopl();
+extern int sys_vhangup();
 
 fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
 sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
@@ -134,7 +135,7 @@
 sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
 sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
 sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat,
-sys_newlstat, sys_newfstat, sys_newuname, sys_iopl };
+sys_newlstat, sys_newfstat, sys_newuname, sys_iopl, sys_vhangup };
 
 /* So we don't have to do any more manual updating.... */
 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/include/termios.h b/include/linux/termios.h
similarity index 86%
rename from include/termios.h
rename to include/linux/termios.h
index da7b09a..372cda1 100644
--- a/include/termios.h
+++ b/include/linux/termios.h
@@ -1,7 +1,5 @@
-#ifndef _TERMIOS_H
-#define _TERMIOS_H
-
-#include <sys/types.h>
+#ifndef _LINUX_TERMIOS_H
+#define _LINUX_TERMIOS_H
 
 /* 0x54 is just a magic number to make these relatively uniqe ('T') */
 
@@ -37,6 +35,17 @@
 #define TIOCCONS	0x541D
 #define TIOCGSERIAL	0x541E
 #define TIOCSSERIAL	0x541F
+#define TIOCPKT		0x5420
+#define FIONBIO		0x5421
+#define TIOCNOTTY	0x5422
+
+/* Used for packet mode */
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_DOSTOP		16
+#define TIOCPKT_NOSTOP		32
 
 struct winsize {
 	unsigned short ws_row;
@@ -213,24 +222,4 @@
 #define	TCSADRAIN	1
 #define	TCSAFLUSH	2
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern speed_t cfgetispeed(struct termios *termios_p);
-extern speed_t cfgetospeed(struct termios *termios_p);
-extern int cfsetispeed(struct termios *termios_p, speed_t speed);
-extern int cfsetospeed(struct termios *termios_p, speed_t speed);
-extern int tcdrain(int fildes);
-extern int tcflow(int fildes, int action);
-extern int tcflush(int fildes, int queue_selector);
-extern int tcgetattr(int fildes, struct termios *termios_p);
-extern int tcsendbreak(int fildes, int duration);
-extern int tcsetattr(int fildes, int optional_actions,
-	struct termios *termios_p);
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/include/linux/time.h b/include/linux/time.h
new file mode 100644
index 0000000..f154e5d
--- /dev/null
+++ b/include/linux/time.h
@@ -0,0 +1,33 @@
+#ifndef _LINUX_TIME_H
+#define _LINUX_TIME_H
+
+struct timeval {
+	long	tv_sec;		/* seconds */
+	long	tv_usec;	/* microseconds */
+};
+
+struct timezone {
+	int	tz_minuteswest;	/* minutes west of Greenwich */
+	int	tz_dsttime;	/* type of dst correction */
+};
+
+#define FD_SETSIZE		(8*sizeof(fd_set))
+#define FD_SET(fd,fdsetp)	(*(fdsetp) |= (1 << (fd)))
+#define FD_CLR(fd,fdsetp)	(*(fdsetp) &= ~(1 << (fd)))
+#define FD_ISSET(fd,fdsetp)	((*(fdsetp) >> fd) & 1)
+#define FD_ZERO(fdsetp)		(*(fdsetp) = 0)
+
+/*
+ * Names of the interval timers, and structure
+ * defining a timer setting.
+ */
+#define	ITIMER_REAL	0
+#define	ITIMER_VIRTUAL	1
+#define	ITIMER_PROF	2
+
+struct	itimerval {
+	struct	timeval it_interval;	/* timer interval */
+	struct	timeval it_value;	/* current value */
+};
+
+#endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index aa92aa3..84d6aa8 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -1,5 +1,5 @@
-#ifndef _TIMER_H
-#define _TIMER_H
+#ifndef _LINUX_TIMER_H
+#define _LINUX_TIMER_H
 
 /*
  * DON'T CHANGE THESE!! Most of them are hardcoded into some assembly language
diff --git a/include/linux/times.h b/include/linux/times.h
new file mode 100644
index 0000000..e7ae2fa
--- /dev/null
+++ b/include/linux/times.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_TIMES_H
+#define _LINUX_TIMES_H
+
+struct tms {
+	time_t tms_utime;
+	time_t tms_stime;
+	time_t tms_cutime;
+	time_t tms_cstime;
+};
+
+#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 329165e..d6c1f6e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -1,3 +1,6 @@
+#ifndef _LINUX_TTY_H
+#define _LINUX_TTY_H
+
 /*
  * 'tty.h' defines some structures used by tty_io.c and some defines.
  *
@@ -6,8 +9,7 @@
  * offsets into 'tty_queue'
  */
 
-#ifndef _TTY_H
-#define _TTY_H
+#include <linux/termios.h>
 
 #include <asm/system.h>
 
@@ -16,14 +18,46 @@
 #define NR_PTYS		4
 
 /*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+	unsigned char  orig_x;
+	unsigned char  orig_y;
+	unsigned char  unused1[2];
+	unsigned short orig_video_page;
+	unsigned char  orig_video_mode;
+	unsigned char  orig_video_cols;
+	unsigned short orig_video_ega_ax;
+	unsigned short orig_video_ega_bx;
+	unsigned short orig_video_ega_cx;
+	unsigned char  orig_video_lines;
+};
+
+extern struct screen_info screen_info;
+
+#define ORIG_X			(screen_info.orig_x)
+#define ORIG_Y			(screen_info.orig_y)
+#define ORIG_VIDEO_PAGE		(screen_info.orig_video_page)
+#define ORIG_VIDEO_MODE		(screen_info.orig_video_mode)
+#define ORIG_VIDEO_COLS 	(screen_info.orig_video_cols)
+#define ORIG_VIDEO_EGA_AX	(screen_info.orig_video_ega_ax)
+#define ORIG_VIDEO_EGA_BX	(screen_info.orig_video_ega_bx)
+#define ORIG_VIDEO_EGA_CX	(screen_info.orig_video_ega_cx)
+#define ORIG_VIDEO_LINES	(screen_info.orig_video_lines)
+
+#define VIDEO_TYPE_MDA		0x10	/* Monochrome Text Display	*/
+#define VIDEO_TYPE_CGA		0x11	/* CGA Display 			*/
+#define VIDEO_TYPE_EGAM		0x20	/* EGA/VGA in Monochrome Mode	*/
+#define VIDEO_TYPE_EGAC		0x21	/* EGA/VGA in Color Mode	*/
+
+/*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
  * isn't in use (eg VINTR ahs no character etc)
  */
 #define __DISABLED_CHAR '\0'
 
-#include <termios.h>
-
 #define TTY_BUF_SIZE 2048
 
 struct tty_queue {
diff --git a/include/sys/types.h b/include/linux/types.h
similarity index 95%
rename from include/sys/types.h
rename to include/linux/types.h
index 46b57b5..53088a2 100644
--- a/include/sys/types.h
+++ b/include/linux/types.h
@@ -1,7 +1,5 @@
-#ifndef _SYS_TYPES_H
-#define _SYS_TYPES_H
-
-#include <stddef.h>
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
 
 #ifndef _SIZE_T
 #define _SIZE_T
diff --git a/include/sys/un.h b/include/linux/un.h
similarity index 74%
rename from include/sys/un.h
rename to include/linux/un.h
index 26a51f4..5c41503 100644
--- a/include/sys/un.h
+++ b/include/linux/un.h
@@ -1,5 +1,5 @@
-#ifndef _UN_H
-#define _UN_H
+#ifndef _LINUX_UN_H
+#define _LINUX_UN_H
 
 struct sockaddr_un {
 	u_short sun_family;		/* AF_UNIX */
diff --git a/include/sys/user.h b/include/linux/user.h
similarity index 97%
rename from include/sys/user.h
rename to include/linux/user.h
index 1a3c292..106e710 100644
--- a/include/sys/user.h
+++ b/include/linux/user.h
@@ -1,4 +1,7 @@
-#include <sys/ptrace.h>
+#ifndef _LINUX_USER_H
+#define _LINUX_USER_H
+
+#include <linux/ptrace.h>
 /* Core file format: The core file is written in such a way that gdb
    can understand it and provide useful information to the user (under
    linux we use the 'trad-core' bfd).  There are quite a number of
@@ -68,3 +71,5 @@
 #define UPAGES 1
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+
+#endif
diff --git a/include/linux/utime.h b/include/linux/utime.h
new file mode 100644
index 0000000..c6bf27b
--- /dev/null
+++ b/include/linux/utime.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_UTIME_H
+#define _LINUX_UTIME_H
+
+struct utimbuf {
+	time_t actime;
+	time_t modtime;
+};
+
+#endif
diff --git a/include/sys/vfs.h b/include/linux/vfs.h
similarity index 83%
rename from include/sys/vfs.h
rename to include/linux/vfs.h
index c7e113e..6d1f625 100644
--- a/include/sys/vfs.h
+++ b/include/linux/vfs.h
@@ -1,5 +1,5 @@
-#ifndef _SYS_VFS_H_
-#define _SYS_VFS_H_
+#ifndef _LINUX_VFS_H
+#define _LINUX_VFS_H
 
 typedef struct {
 	long    val[2];
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 77ad9a3..0c13811 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -3,6 +3,9 @@
 
 #include <linux/limits.h>
 
+#define WNOHANG		1
+#define WUNTRACED	2
+
 struct wait_queue {
 	struct task_struct * task;
 	struct wait_queue * next;
diff --git a/include/stdarg.h b/include/stdarg.h
old mode 100755
new mode 100644
diff --git a/include/sys/dirent.h b/include/sys/dirent.h
deleted file mode 100644
index 2df2c83..0000000
--- a/include/sys/dirent.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _SYS_DIRENT_H
-#define _SYS_DIRENT_H
-
-#include <limits.h>
-#include <sys/types.h>
-
-struct dirent {
-	long		d_ino;
-	off_t		d_off;
-	unsigned short	d_reclen;
-	char		d_name[NAME_MAX+1];
-};
-
-#endif
diff --git a/include/sys/socket.h b/include/sys/socket.h
deleted file mode 100644
index 7d840a6..0000000
--- a/include/sys/socket.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _SOCKET_H
-#define _SOCKET_H
-
-struct sockaddr {
-	u_short sa_family;		/* address family, AF_xxx */
-	char sa_data[14];		/* 14 bytes of protocol address */
-};
-
-/*
- * socket types
- */
-#define SOCK_STREAM	1		/* stream (connection) socket */
-#define SOCK_DGRAM	2		/* datagram (connectionless) socket */
-#define SOCK_SEQPACKET	3		/* sequential packet socket */
-#define SOCK_RAW	4		/* raw socket */
-
-/*
- * supported address families
- */
-#define AF_UNSPEC	0
-#define AF_UNIX		1
-#define AF_INET		2
-
-/*
- * protocol families, same as address families
- */
-#define PF_UNIX		AF_UNIX
-#define PF_INET		AF_INET
-
-int socket(int family, int type, int protocol);
-int socketpair(int family, int type, int protocol, int sockvec[2]);
-int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
-int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
-int listen(int sockfd, int backlog);
-int accept(int sockfd, struct sockaddr *peer, int *paddrlen);
-int getsockname(int sockfd, struct sockaddr *addr, int *paddrlen);
-int getpeername(int sockfd, struct sockaddr *peer, int *paddrlen);
-
-#endif /* _SOCKET_H */
diff --git a/include/sys/time.h b/include/sys/time.h
deleted file mode 100644
index 1ef722b..0000000
--- a/include/sys/time.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef _SYS_TIME_H
-#define _SYS_TIME_H
-
-/* gettimofday returns this */
-struct timeval {
-	long	tv_sec;		/* seconds */
-	long	tv_usec;	/* microseconds */
-};
-
-struct timezone {
-	int	tz_minuteswest;	/* minutes west of Greenwich */
-	int	tz_dsttime;	/* type of dst correction */
-};
-
-#define	DST_NONE	0	/* not on dst */
-#define	DST_USA		1	/* USA style dst */
-#define	DST_AUST	2	/* Australian style dst */
-#define	DST_WET		3	/* Western European dst */
-#define	DST_MET		4	/* Middle European dst */
-#define	DST_EET		5	/* Eastern European dst */
-#define	DST_CAN		6	/* Canada */
-#define	DST_GB		7	/* Great Britain and Eire */
-#define	DST_RUM		8	/* Rumania */
-#define	DST_TUR		9	/* Turkey */
-#define	DST_AUSTALT	10	/* Australian style with shift in 1986 */
-
-#define FD_SETSIZE		(8*sizeof(fd_set))
-#define FD_SET(fd,fdsetp)	(*(fdsetp) |= (1 << (fd)))
-#define FD_CLR(fd,fdsetp)	(*(fdsetp) &= ~(1 << (fd)))
-#define FD_ISSET(fd,fdsetp)	((*(fdsetp) >> fd) & 1)
-#define FD_ZERO(fdsetp)		(*(fdsetp) = 0)
-
-/*
- * Operations on timevals.
- *
- * NB: timercmp does not work for >= or <=.
- */
-#define	timerisset(tvp)		((tvp)->tv_sec || (tvp)->tv_usec)
-#define	timercmp(tvp, uvp, cmp)	\
-	((tvp)->tv_sec cmp (uvp)->tv_sec || \
-	 (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
-#define	timerclear(tvp)		((tvp)->tv_sec = (tvp)->tv_usec = 0)
-
-/*
- * Names of the interval timers, and structure
- * defining a timer setting.
- */
-#define	ITIMER_REAL	0
-#define	ITIMER_VIRTUAL	1
-#define	ITIMER_PROF	2
-
-struct	itimerval {
-	struct	timeval it_interval;	/* timer interval */
-	struct	timeval it_value;	/* current value */
-};
-
-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>
-
-int gettimeofday(struct timeval * tp, struct timezone * tz);
-int select(int width, fd_set * readfds, fd_set * writefds,
-	fd_set * exceptfds, struct timeval * timeout);
-
-#endif /*_SYS_TIME_H*/
diff --git a/include/sys/times.h b/include/sys/times.h
deleted file mode 100644
index 68d5bfb..0000000
--- a/include/sys/times.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _TIMES_H
-#define _TIMES_H
-
-#include <sys/types.h>
-
-struct tms {
-	time_t tms_utime;
-	time_t tms_stime;
-	time_t tms_cutime;
-	time_t tms_cstime;
-};
-
-extern time_t times(struct tms * tp);
-
-#endif
diff --git a/include/sys/wait.h b/include/sys/wait.h
deleted file mode 100644
index d6c3360..0000000
--- a/include/sys/wait.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _SYS_WAIT_H
-#define _SYS_WAIT_H
-
-#include <sys/types.h>
-
-#define _LOW(v)		( (v) & 0377)
-#define _HIGH(v)	( ((v) >> 8) & 0377)
-
-/* options for waitpid, WUNTRACED not supported */
-#define WNOHANG		1
-#define WUNTRACED	2
-
-#define WIFEXITED(s)	(!((s)&0xFF))
-#define WIFSTOPPED(s)	(((s)&0xFF)==0x7F)
-#define WEXITSTATUS(s)	(((s)>>8)&0xFF)
-#define WTERMSIG(s)	((s)&0x7F)
-#define WCOREDUMP(s)	((s)&0x80)
-#define WSTOPSIG(s)	(((s)>>8)&0xFF)
-#define WIFSIGNALED(s)	(((unsigned int)(s)-1 & 0xFFFF) < 0xFF)
-
-pid_t wait(int *stat_loc);
-pid_t waitpid(pid_t pid, int *stat_loc, int options);
-
-#endif
diff --git a/include/unistd.h b/include/unistd.h
deleted file mode 100644
index 041977b..0000000
--- a/include/unistd.h
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifndef _UNISTD_H
-#define _UNISTD_H
-
-/* ok, this may be a joke, but I'm working on it */
-#define _POSIX_VERSION 198808L
-
-#define _POSIX_CHOWN_RESTRICTED	1    /* only root can do a chown (I think..) */
-#define _POSIX_NO_TRUNC		1    /* no pathname truncation (but see kernel) */
-#define _POSIX_VDISABLE		'\0' /* character to disable things like ^C */
-#define _POSIX_JOB_CONTROL	1
-#define _POSIX_SAVED_IDS	1    /* Implemented, for whatever good it is */
-
-#define STDIN_FILENO	0
-#define STDOUT_FILENO	1
-#define STDERR_FILENO	2
-
-#ifndef NULL
-#define NULL    ((void *)0)
-#endif
-
-/* access */
-#define F_OK	0
-#define X_OK	1
-#define W_OK	2
-#define R_OK	4
-
-/* lseek */
-#define SEEK_SET	0
-#define SEEK_CUR	1
-#define SEEK_END	2
-
-/* _SC stands for System Configuration. We don't use them much */
-#define _SC_ARG_MAX		1
-#define _SC_CHILD_MAX		2
-#define _SC_CLOCKS_PER_SEC	3
-#define _SC_NGROUPS_MAX		4
-#define _SC_OPEN_MAX		5
-#define _SC_JOB_CONTROL		6
-#define _SC_SAVED_IDS		7
-#define _SC_VERSION		8
-
-/* more (possibly) configurable things - now pathnames */
-#define _PC_LINK_MAX		1
-#define _PC_MAX_CANON		2
-#define _PC_MAX_INPUT		3
-#define _PC_NAME_MAX		4
-#define _PC_PATH_MAX		5
-#define _PC_PIPE_BUF		6
-#define _PC_NO_TRUNC		7
-#define _PC_VDISABLE		8
-#define _PC_CHOWN_RESTRICTED	9
-
-#if 0
-/* XXX - <sys/stat.h> illegally <sys/types.h> already.
- * The rest of these includes are also illegal (too much pollution).
- */
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <sys/utsname.h>
-#include <sys/resource.h>
-#include <utime.h>
-
-#ifdef __LIBRARY__
-#include <linux/unistd.h>
-#endif /* __LIBRARY__ */
-
-/* XXX - illegal. */
-extern int errno;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* XXX - several non-POSIX functions here, and POSIX functions that are
- * supposed to be declared elsewhere.  Non-promotion of short types in
- * prototypes may cause trouble.  Arg names should be prefixed by
- * underscores.
- */
-int access(const char * filename, mode_t mode);	/* XXX - short type */
-int acct(const char * filename);
-int brk(void * end_data_segment);
-/* XXX - POSIX says unsigned alarm(unsigned sec) */
-int alarm(int sec);
-void * sbrk(ptrdiff_t increment);
-int chdir(const char * filename);
-int chmod(const char * filename, mode_t mode);	/* XXX - short type */
-int chown(const char * filename, uid_t owner, gid_t group); /* XXX - shorts */
-int chroot(const char * filename);
-int close(int fildes);
-int creat(const char * filename, mode_t mode);	/* XXX - short type */
-int dup(int fildes);
-int execve(const char * filename, char ** argv, char ** envp);
-int execv(const char * pathname, char ** argv);
-int execvp(const char * file, char ** argv);
-int execl(const char * pathname, char * arg0, ...);
-int execlp(const char * file, char * arg0, ...);
-int execle(const char * pathname, char * arg0, ...);
-volatile void exit(int status);
-volatile void _exit(int status);
-int fcntl(int fildes, int cmd, ...);
-pid_t fork(void);
-pid_t getpid(void);
-uid_t getuid(void);
-uid_t geteuid(void);
-gid_t getgid(void);
-gid_t getegid(void);
-int ioctl(int fildes, int cmd, ...);
-int kill(pid_t pid, int signal);
-int link(const char * filename1, const char * filename2);
-off_t lseek(int fildes, off_t offset, int origin);
-int mknod(const char * filename, mode_t mode, dev_t dev); /* XXX - shorts */
-int mount(const char * specialfile, const char * dir, const char * type, int rwflag);
-int nice(int val);
-int open(const char * filename, int flag, ...);
-int pause(void);
-int pipe(int * fildes);
-/* XXX**2 - POSIX says unsigned count */
-int read(int fildes, char * buf, off_t count);
-int setpgrp(void);
-int setpgid(pid_t pid,pid_t pgid);	/* XXX - short types */
-int setuid(uid_t uid);		/* XXX - short type */
-int setgid(gid_t gid);		/* XXX - short type */
-void (*signal(int sig, void (*fn)(int)))(int);
-int stat(const char * filename, struct stat * stat_buf);
-int fstat(int fildes, struct stat * stat_buf);
-int stime(time_t * tptr);
-int sync(void);
-time_t time(time_t * tloc);
-time_t times(struct tms * tbuf);
-int ulimit(int cmd, long limit);
-mode_t umask(mode_t mask);
-int umount(const char * specialfile);
-int uname(struct utsname * name);
-int unlink(const char * filename);
-int ustat(dev_t dev, struct ustat * ubuf);
-int utime(const char * filename, struct utimbuf * times);
-pid_t waitpid(pid_t pid,int * wait_stat,int options);
-pid_t wait(int * wait_stat);
-/* XXX**2 - POSIX says unsigned count */
-int write(int fildes, const char * buf, off_t count);
-int dup2(int oldfd, int newfd);
-int getppid(void);
-pid_t getpgrp(void);
-pid_t setsid(void);
-int sethostname(char *name, int len);
-int setrlimit(int resource, struct rlimit *rlp);
-int getrlimit(int resource, struct rlimit *rlp);
-int getrusage(int who, struct rusage *rusage);
-int gettimeofday(struct timeval *tv, struct timezone *tz);
-int settimeofday(struct timeval *tv, struct timezone *tz);
-int getgroups(int gidsetlen, gid_t *gidset);
-int setgroups(int gidsetlen, gid_t *gidset);
-int select(int width, fd_set * readfds, fd_set * writefds,
-	fd_set * exceptfds, struct timeval * timeout);
-int swapon(const char * specialfile);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/utime.h b/include/utime.h
deleted file mode 100644
index a7b79b3..0000000
--- a/include/utime.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _UTIME_H
-#define _UTIME_H
-
-#include <sys/types.h>	/* I know - shouldn't do this, but .. */
-
-struct utimbuf {
-	time_t actime;
-	time_t modtime;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int utime(const char *filename, struct utimbuf *times);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/init/main.c b/init/main.c
index 1f6174d..aec7bb7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1,18 +1,16 @@
 /*
  *  linux/init/main.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <stddef.h>
 #include <stdarg.h>
 #include <time.h>
 
-#include <sys/types.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
 
+#include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -59,7 +57,6 @@
 extern void hd_init(void);
 extern void floppy_init(void);
 extern void sock_init(void);
-extern void mem_init(long start, long end);
 extern long rd_init(long mem_start, int length);
 extern long kernel_mktime(struct tm * tm);
 
@@ -82,9 +79,8 @@
  * This is set up by the setup-routine at boot-time
  */
 #define EXT_MEM_K (*(unsigned short *)0x90002)
-#define CON_ROWS ((*(unsigned short *)0x9000e) & 0xff)
-#define CON_COLS (((*(unsigned short *)0x9000e) & 0xff00) >> 8)
 #define DRIVE_INFO (*(struct drive_info *)0x90080)
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
 
 /*
@@ -123,9 +119,9 @@
 	startup_time = kernel_mktime(&time);
 }
 
-static long memory_end = 0;
-static long buffer_memory_end = 0;
-static long main_memory_start = 0;
+static unsigned long memory_start = 0;
+static unsigned long memory_end = 0;
+
 static char term[32];
 
 static char * argv_init[] = { "/bin/init", NULL };
@@ -138,6 +134,7 @@
 static char * envp[] = { "HOME=/usr/root", NULL, NULL };
 
 struct drive_info { char dummy[32]; } drive_info;
+struct screen_info screen_info;
 
 void start_kernel(void)
 {
@@ -146,33 +143,26 @@
  * enable them
  */
  	ROOT_DEV = ORIG_ROOT_DEV;
-	sprintf(term, "TERM=con%dx%d", CON_COLS, CON_ROWS);
+ 	drive_info = DRIVE_INFO;
+ 	screen_info = SCREEN_INFO;
+	sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
 	envp[1] = term;	
 	envp_rc[1] = term;
 	envp_init[1] = term;
- 	drive_info = DRIVE_INFO;
 	memory_end = (1<<20) + (EXT_MEM_K<<10);
 	memory_end &= 0xfffff000;
 	if (memory_end > 16*1024*1024)
 		memory_end = 16*1024*1024;
-	if (memory_end >= 12*1024*1024) 
-		buffer_memory_end = 4*1024*1024;
-	else if (memory_end >= 6*1024*1024)
-		buffer_memory_end = 2*1024*1024;
-	else if (memory_end >= 4*1024*1024)
-		buffer_memory_end = 3*512*1024;
-	else
-		buffer_memory_end = 1*1024*1024;
-	main_memory_start = buffer_memory_end;
+	memory_start = 1024*1024;
 	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);
-	mem_init(main_memory_start,memory_end);
+	memory_start = chr_dev_init(memory_start,memory_end);
+	memory_start = blk_dev_init(memory_start,memory_end);
+	memory_start = mem_init(memory_start,memory_end);
+	buffer_init();
 	time_init();
 	printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
-	buffer_init(buffer_memory_end);
 	hd_init();
 	floppy_init();
 	sock_init();
@@ -216,9 +206,9 @@
 	(void) open("/dev/tty1",O_RDWR,0);
 	(void) dup(0);
 	(void) dup(0);
-	printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
-		NR_BUFFERS*BLOCK_SIZE);
-	printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
+	printf("%d buffers = %d bytes buffer space\n\r",nr_buffers,
+		nr_buffers*BLOCK_SIZE);
+	printf("Free mem: %d bytes\n\r",memory_end-memory_start);
 
 	execve("/etc/init",argv_init,envp_init);
 	execve("/bin/init",argv_init,envp_init);
diff --git a/kernel/Makefile b/kernel/Makefile
index 3b1c608..695e77c 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -22,14 +22,14 @@
 	panic.o printk.o vsprintf.o sys.o exit.o \
 	signal.o mktime.o ptrace.o ioport.o itimer.o
 
-all: kernel.o subdirs
+all: kernel.o kernelsubdirs
 
 kernel.o: $(OBJS)
 	$(LD) -r -o kernel.o $(OBJS)
 	sync
 
-subdirs: dummy
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
+kernelsubdirs: dummy
+	@for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE)) || exit; done
 
 sys_call.s: sys_call.S
 
@@ -47,98 +47,116 @@
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
 	for i in *.c;do $(CPP) -M $$i;done >> tmp_make
 	cp tmp_make Makefile
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
+	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep) || exit; done
 
 dummy:
 
 ### Dependencies:
-exit.o : exit.c /usr/src/linux/include/errno.h /usr/src/linux/include/signal.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/wait.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/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
+exit.o : exit.c /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/signal.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/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h \
   /usr/src/linux/include/asm/segment.h 
-fork.o : fork.c /usr/src/linux/include/errno.h /usr/src/linux/include/stddef.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/types.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/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/asm/segment.h \
-  /usr/src/linux/include/asm/system.h 
+fork.o : fork.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/stddef.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h 
 ioport.o : ioport.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 \
-  /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 \
-  /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/linux/string.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h 
+irq.o : irq.c /usr/src/linux/include/linux/ptrace.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/signal.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/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/signal.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/segment.h 
 mktime.o : mktime.c /usr/src/linux/include/time.h 
 panic.o : panic.c /usr/src/linux/include/linux/kernel.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/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 /usr/src/linux/include/linux/mm.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 
-printk.o : printk.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/errno.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.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/types.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/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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
+printk.o : printk.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/asm/segment.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
 ptrace.o : ptrace.c /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/kernel.h \
-  /usr/src/linux/include/linux/sched.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 /usr/src/linux/include/linux/mm.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/asm/segment.h /usr/src/linux/include/asm/system.h \
-  /usr/src/linux/include/errno.h /usr/src/linux/include/sys/ptrace.h 
-sched.o : sched.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 \
-  /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/linux/timer.h /usr/src/linux/include/linux/sys.h \
-  /usr/src/linux/include/linux/fdreg.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h 
+  /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/ptrace.h /usr/src/linux/include/asm/segment.h \
+  /usr/src/linux/include/asm/system.h 
+sched.o : sched.c /usr/src/linux/include/linux/signal.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/sys.h /usr/src/linux/include/linux/fdreg.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/ptrace.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h 
 signal.o : signal.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 \
-  /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/asm/segment.h /usr/src/linux/include/sys/wait.h \
-  /usr/src/linux/include/sys/ptrace.h /usr/src/linux/include/errno.h 
-sys.o : sys.c /usr/src/linux/include/errno.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/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 /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/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/config.h \
-  /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
-  /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/sys/times.h /usr/src/linux/include/linux/utsname.h /usr/src/linux/include/linux/string.h 
-traps.o : traps.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/sched.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/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/asm/system.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/errno.h 
-vsprintf.o : vsprintf.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/linux/string.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/ptrace.h /usr/src/linux/include/asm/segment.h 
+sys.o : sys.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/times.h /usr/src/linux/include/linux/utsname.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/segment.h 
+traps.o : traps.c /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/sched.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/io.h 
+vsprintf.o : vsprintf.c /usr/src/linux/include/stdarg.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/string.h 
diff --git a/kernel/asm.s b/kernel/asm.s
deleted file mode 100644
index f62751c..0000000
--- a/kernel/asm.s
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  linux/kernel/asm.s
- *
- *  (C) 1991  Linus Torvalds
- */
-
-/*
- * asm.s contains the low-level code for interrupts that cannot
- * result in an task-switch. These are things like the hd- and
- * floppy-interrupt etc. With these interrupts, we don't have to
- * care about the stack layout etc.
- */
-
-.globl _floppy_interrupt,_parallel_interrupt
-
-_floppy_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,$0x20		# EOI to interrupt controller #1
-	xorl %eax,%eax
-	xchgl _do_floppy,%eax
-	testl %eax,%eax
-	jne 1f
-	movl $_unexpected_floppy_interrupt,%eax
-1:	call *%eax		# "interesting" way of handling intr.
-	pop %fs
-	pop %es
-	pop %ds
-	popl %edx
-	popl %ecx
-	popl %eax
-	iret
-
-_parallel_interrupt:
-	cld
-	pushl %eax
-	movb $0x20,%al
-	outb %al,$0x20
-	popl %eax
-	iret
diff --git a/kernel/blk_drv/Makefile b/kernel/blk_drv/Makefile
index 99d573a..232a0c8 100644
--- a/kernel/blk_drv/Makefile
+++ b/kernel/blk_drv/Makefile
@@ -18,63 +18,69 @@
 
 SUBDIRS	= scsi
 
-OBJS = hd.o ll_rw_blk.o floppy.o ramdisk.o
+OBJS = hd.o ll_rw_blk.o floppy.o ramdisk.o genhd.o
 
-all: blk_drv.a subdirs
+all: blk_drv.a scsisubdirs
 
 blk_drv.a: $(OBJS)
 	rm -f blk_drv.a
 	$(AR) rcs blk_drv.a $(OBJS)
 	sync
 
-subdirs: dummy
-	for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
+scsisubdirs: dummy
+	@for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE)) || exit; done
 
 clean:
 	rm -f core *.o *.a tmp_make
 	for i in *.c;do rm -f `basename $$i .c`.s;done
-	cd scsi; $(MAKE) clean
+	for i in $(SUBDIRS); do (cd $$i; $(MAKE) clean); done
 
 dep:
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
 	for i in *.c;do $(CPP) -M $$i;done >> tmp_make
 	cp tmp_make Makefile
+	for i in $(SUBDIRS); do (cd $$i; $(MAKE) dep); done
 
 dummy:
 
 ### Dependencies:
 floppy.o : floppy.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 \
-  /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/linux/timer.h /usr/src/linux/include/linux/fdreg.h \
-  /usr/src/linux/include/linux/fd.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
-  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/errno.h blk.h 
-hd.o : hd.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/config.h \
-  /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
-  /usr/src/linux/include/linux/config.dist.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/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 /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/linux/timer.h \
-  /usr/src/linux/include/linux/hdreg.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/fdreg.h /usr/src/linux/include/linux/fd.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
   /usr/src/linux/include/asm/segment.h blk.h 
-ll_rw_blk.o : ll_rw_blk.c /usr/src/linux/include/errno.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/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 /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/asm/system.h \
-  blk.h 
-ramdisk.o : ramdisk.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+genhd.o : genhd.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
   /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.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/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/linux/minix_fs.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/memory.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/genhd.h \
+  /usr/src/linux/include/linux/kernel.h 
+hd.o : hd.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/signal.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/hdreg.h /usr/src/linux/include/linux/genhd.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
   blk.h 
+ll_rw_blk.o : ll_rw_blk.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/system.h \
+  blk.h 
+ramdisk.o : ramdisk.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h 
diff --git a/kernel/blk_drv/blk.h b/kernel/blk_drv/blk.h
index 097c993..70dab1b 100644
--- a/kernel/blk_drv/blk.h
+++ b/kernel/blk_drv/blk.h
@@ -26,6 +26,7 @@
 	int errors;
 	unsigned long sector;
 	unsigned long nr_sectors;
+	unsigned long current_nr_sectors;
 	char * buffer;
 	struct wait_queue * waiting;
 	struct buffer_head * bh;
@@ -39,7 +40,7 @@
  * are much more time-critical than writes.
  */
 #define IN_ORDER(s1,s2) \
-((s1)->cmd<(s2)->cmd || ((s1)->cmd==(s2)->cmd && \
+((s1)->cmd < (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
 ((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \
 (s1)->sector < (s2)->sector)))))
 
@@ -48,6 +49,20 @@
 	struct request * current_request;
 };
 
+
+struct sec_size {
+	unsigned block_size;
+	unsigned block_size_bits;
+};
+
+/*
+ * These will have to be changed to be aware of different buffer
+ * sizes etc..
+ */
+#define SECTOR_MASK ((1 << (BLOCK_SIZE_BITS - 9)) -1)
+#define SUBSECTOR(block) ((block) & SECTOR_MASK)
+
+extern struct sec_size * blk_sec[NR_BLK_DEV];
 extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
 extern struct request request[NR_REQUEST];
 extern struct wait_queue * wait_for_request;
@@ -60,7 +75,8 @@
 #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;
+  case BLKROGET: verify_area((void *) (where), sizeof(long)); \
+		 put_fs_long(is_read_only(dev),(long *) (where)); return 0;
 		 
 #ifdef MAJOR_NR
 
@@ -101,6 +117,7 @@
 /* scsi disk */
 #define DEVICE_NAME "scsidisk"
 #define DEVICE_INTR do_sd  
+#define TIMEOUT_VALUE 200
 #define DEVICE_REQUEST do_sd_request
 #define DEVICE_NR(device) (MINOR(device) >> 4)
 #define DEVICE_ON(device)
@@ -121,7 +138,10 @@
 
 #endif
 
+#ifndef CURRENT
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
+#endif
+
 #define CURRENT_DEV DEVICE_NR(CURRENT->dev)
 
 #ifdef DEVICE_INTR
@@ -168,18 +188,20 @@
 		printk(DEVICE_NAME " I/O error\n\r");
 		printk("dev %04x, sector %d\n\r",req->dev,req->sector);
 		req->nr_sectors--;
-		req->nr_sectors &= ~1;
-		req->sector += 2;
-		req->sector &= ~1;		
+		req->nr_sectors &= ~SECTOR_MASK;
+		req->sector += (BLOCK_SIZE / 512);
+		req->sector &= ~SECTOR_MASK;		
 	}
+
 	if (bh = req->bh) {
 		req->bh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_uptodate = uptodate;
 		unlock_buffer(bh);
 		if (bh = req->bh) {
-			if (req->nr_sectors < 2) {
-				req->nr_sectors = 2;
+			req->current_nr_sectors = bh->b_size >> 9;
+			if (req->nr_sectors < req->current_nr_sectors) {
+				req->nr_sectors = req->current_nr_sectors;
 				printk("end_request: buffer-list destroyed\n");
 			}
 			req->buffer = bh->b_data;
@@ -200,7 +222,6 @@
 #endif
 
 #define INIT_REQUEST \
-repeat: \
 	if (!CURRENT) {\
 		CLEAR_INTR; \
 		return; \
diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c
index 7fb9e57..8bfff57 100644
--- a/kernel/blk_drv/floppy.c
+++ b/kernel/blk_drv/floppy.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/floppy.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -38,6 +38,14 @@
  * the floppy-change signal detection.
  */
 
+/*
+ * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed 
+ * FDC data overrun bug, added some preliminary stuff for vertical
+ * recording support.
+ * TODO: Errors are still not counted properly.
+ */
+
+#define REALLY_SLOW_IO
 #define FLOPPY_IRQ 6
 
 #include <linux/sched.h>
@@ -46,10 +54,14 @@
 #include <linux/timer.h>
 #include <linux/fdreg.h>
 #include <linux/fd.h>
+#include <linux/errno.h>
+#ifdef HHB_SYSMACROS
+#include <linux/system.h>
+#endif
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/segment.h>
-#include <errno.h>
 
 #define MAJOR_NR 2
 #include "blk.h"
@@ -68,6 +80,7 @@
 
 #define TYPE(x) ((x)>>2)
 #define DRIVE(x) ((x)&0x03)
+
 /*
  * Note that MAX_ERRORS=X doesn't imply that we retry every bad read
  * max X times - some types of errors increase the errorcount by 2 or
@@ -79,17 +92,21 @@
  * Maximum disk size (in kilobytes). This default is used whenever the
  * current disk size is unknown.
  */
-
 #define MAX_DISK_SIZE 1440
 
 /*
  * Maximum number of sectors in a track buffer. Track buffering is disabled
  * if tracks are bigger.
  */
-
 #define MAX_BUFFER_SECTORS 18
 
 /*
+ * The DMA channel used by the floppy controller cannot access data at
+ * addresses >= 1MB
+ */
+#define LAST_DMA_ADDR	(0x100000 - BLOCK_SIZE)
+
+/*
  * globals used by 'result()'
  */
 #define MAX_REPLIES 7
@@ -100,16 +117,12 @@
 #define ST3 (reply_buffer[3])
 
 /*
- * This struct defines the different floppy types. Unlike minix
- * linux doesn't have a "search for right type"-type, as the code
- * for that is convoluted and weird. I've got enough problems with
- * this driver as it is.
+ * This struct defines the different floppy types.
  *
- * The 'stretch' tells if the tracks need to be boubled for some
+ * The 'stretch' tells if the tracks need to be doubled for some
  * types (ie 360kB diskette in 1.2MB drive etc). Others should
  * be self-explanatory.
  */
-
 static struct floppy_struct floppy_type[] = {
 	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL },	/* no testing */
 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,NULL },	/* 360kB PC diskettes */
@@ -121,8 +134,11 @@
 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL },	/* 1.44MB diskette */
 };
 
-/* For auto-detection. Each drive type has a pair of formats to try. */
-
+/*
+ * Auto-detection. Each drive type has a pair of formats which are
+ * used in succession to try to read the disk. If the FDC cannot lock onto
+ * the disk, the next format is tried. This uses the variable 'probing'.
+ */
 static struct floppy_struct floppy_types[] = {
 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
@@ -135,16 +151,15 @@
 };
 
 /* Auto-detection: Disk type used until the next media change occurs. */
-
 struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
 
 /* This type is tried first. */
-
 struct floppy_struct *base_type[4];
 
-/* User-provided type information. current_type points to the respective entry
-   of this array. */
-
+/*
+ * User-provided type information. current_type points to
+ * the respective entry of this array.
+ */
 struct floppy_struct user_params[4];
 
 static int floppy_sizes[] ={
@@ -158,48 +173,61 @@
 	1440,1440,1440,1440
 };
 
-/* The driver is trying to determine the correct media format while probing
-   is set. rw_interrupts clears it after a successful access. */
-
+/*
+ * The driver is trying to determine the correct media format
+ * while probing is set. rw_interrupt() clears it after a
+ * successful access.
+ */
 static int probing = 0;
 
-/* (User-provided) media information is _not_ discarded after a media change
-   if the corresponding keep_data flag is non-zero. Positive values are
-   decremented after each probe. */
-
+/*
+ * (User-provided) media information is _not_ discarded after a media change
+ * if the corresponding keep_data flag is non-zero. Positive values are
+ * decremented after each probe.
+ */
 static int keep_data[4] = { 0,0,0,0 };
 
-/* Announce successful media type detection and media information loss after
-   disk changes. */
-
+/*
+ * Announce successful media type detection and media information loss after
+ * disk changes.
+ */
 static ftd_msg[4] = { 1,1,1,1 };
 
-/* Synchronization of FDC access. */
+/* Prevent "aliased" accesses. */
 
+static fd_ref[4] = { 0,0,0,0 };
+static fd_device[4] = { 0,0,0,0 };
+
+/* Synchronization of FDC access. */
 static volatile int format_status = FORMAT_NONE, fdc_busy = 0;
 static struct wait_queue *fdc_wait = NULL, *format_done = NULL;
 
 /* Errors during formatting are counted here. */
-
 static int format_errors;
 
 /* Format request descriptor. */
-
 static struct format_descr format_req;
 
-/* Current device number. Taken either from the block header or from the
-   format request descriptor. */
-
+/*
+ * Current device number. Taken either from the block header or from the
+ * format request descriptor.
+ */
 #define CURRENT_DEVICE (format_status == FORMAT_BUSY ? format_req.device : \
    (CURRENT->dev))
 
 /* Current error count. */
-
 #define CURRENT_ERRORS (format_status == FORMAT_BUSY ? format_errors : \
     (CURRENT->errors))
 
 /*
- * Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps
+ * Treshold for reporting FDC errors to the console.
+ * Setting this to zero may flood your screen when using
+ * ultra cheap floppies ;-)
+ */
+static unsigned short min_report_error_cnt[4] = {2, 2, 2, 2};
+
+/*
+ * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
  * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
  * H is head unload time (1=16ms, 2=32ms, etc)
  *
@@ -207,7 +235,14 @@
  * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
  */
 
-extern char tmp_floppy_area[1024];
+/*
+ * Track buffer and block buffer (in case track buffering doesn't work).
+ * Because these are written to by the DMA controller, they must
+ * not contain a 64k byte boundary crossing, or data will be
+ * corrupted/lost. Alignment of these is enforced in boot/head.s.
+ * Note that you must not change the sizes below without updating head.s.
+ */
+extern char tmp_floppy_area[BLOCK_SIZE];
 extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
 
 static void redo_fd_request(void);
@@ -219,7 +254,7 @@
  */
 #define NO_TRACK 255
 
-static int read_track = 0;	/* flag to indicate if we want to read all track */
+static int read_track = 0;	/* flag to indicate if we want to read entire track */
 static int buffer_track = -1;
 static int buffer_drive = -1;
 static int cur_spec1 = -1;
@@ -232,6 +267,7 @@
 static unsigned char seek_track = 0;
 static unsigned char current_track = NO_TRACK;
 static unsigned char command = 0;
+static unsigned char fdc_version = FDC_TYPE_STD;	/* FDC version code */
 unsigned char selected = 0;
 struct wait_queue * wait_on_floppy_select = NULL;
 
@@ -321,13 +357,14 @@
 		buffer_drive = buffer_track = -1;
 		count = floppy->sect*2*512;
 		addr = (long) floppy_track_buffer;
-	} else if (addr >= 0x100000) {
+	} else if (addr >= LAST_DMA_ADDR) {
 		addr = (long) tmp_floppy_area;
 		if (command == FD_WRITE)
 			copy_buffer(CURRENT->buffer,tmp_floppy_area);
 	}
 /* mask DMA 2 */
 	cli();
+#ifndef HHB_SYSMACROS
 	immoutb_p(4|2,10);
 /* output command byte. I don't know why, but everyone (minix, */
 /* sanches & canton) output this twice, first to 12 then to 11 */
@@ -350,6 +387,14 @@
 	immoutb_p(count,5);
 /* activate DMA 2 */
 	immoutb_p(0|2,10);
+#else			/* just to show off my macros -- hhb */
+	DISABLE_DMA(DMA2);
+	CLEAR_DMA_FF(DMA2);
+	SET_DMA_MODE(DMA2, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
+	SET_DMA_ADDR(DMA2, addr);
+	SET_DMA_COUNT(DMA2, count);
+	ENABLE_DMA(DMA2);
+#endif
 	sti();
 }
 
@@ -380,11 +425,14 @@
 		return -1;
 	for (counter = 0 ; counter < 10000 ; counter++) {
 		status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
-		if (status == STATUS_READY)
+		if (status == STATUS_READY) {
 			return i;
+		}
 		if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
-			if (i >= MAX_REPLIES)
+			if (i >= MAX_REPLIES) {
+				printk("floppy_stat reply overrun\n");
 				break;
+			}
 			reply_buffer[i++] = inb_p(FD_DATA);
 		}
 	}
@@ -409,23 +457,103 @@
 }	
 
 /*
- * Ok, this interrupt is called after a DMA read/write has succeeded,
- * so we check the results, and copy any buffers.
+ * This has only been tested for the case fdc_version == FDC_TYPE_STD.
+ * In case you have a 82077 and want to test it, you'll have to compile
+ * with `FDC_FIFO_UNTESTED' defined. You may also want to add support for
+ * recognizing drives with vertical recording support.
+ */
+static void configure_fdc_mode(void)
+{
+	if (fdc_version == FDC_TYPE_82077) {
+		/* Enhanced version with FIFO & vertical recording. */
+		output_byte(FD_CONFIGURE);
+		output_byte(0);
+		output_byte(0x1A);	/* FIFO on, polling off, 10 byte treshold */
+		output_byte(0);		/* precompensation from track 0 upwards */
+		printk(DEVICE_NAME ": FIFO enabled\n");
+	}
+} /* configure_fdc_mode */
+
+
+static void tell_sector(int nr)
+{
+	if (nr!=7) {
+		printk(" -- FDC reply errror");
+		reset = 1;
+	} else
+		printk(": track %d, head %d, sector %d", reply_buffer[3],
+			reply_buffer[4], reply_buffer[5]);
+} /* tell_sector */
+
+
+/*
+ * Ok, this interrupt is called after a DMA read/write has succeeded
+ * or failed, so we check the results, and copy any buffers.
+ * hhb: Added better error reporting.
  */
 static void rw_interrupt(void)
 {
 	char * buffer_area;
+	int nr;
+	char bad;
 
-	if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {
-		if (ST1 & 0x02) {
-			printk("Drive %d is write protected\n\r",current_drive);
-			floppy_deselect(current_drive);
+	nr = result();
+	/* check IC to find cause of interrupt */
+	switch ((ST0 & ST0_INTR)>>6) {
+		case 1:	/* error occured during command execution */
+			bad = 1;
+			if (ST1 & ST1_WP) {
+				printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive);
+				floppy_deselect(current_drive);
+				request_done(0);
+				bad = 0;
+			} else if (ST1 & ST1_OR) {
+				printk(DEVICE_NAME ": Over/Underrun - retrying\n");
+				/* could continue from where we stopped, but ... */
+				bad = 0;
+			} else if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) {
+				printk(DEVICE_NAME " %d: ", ST0 & ST0_DS);
+				if (ST0 & ST0_ECE) {
+					printk("Recalibrate failed!");
+				} else if (ST2 & ST2_CRC) {
+					printk("data CRC error");
+					tell_sector(nr);
+				} else if (ST1 & ST1_CRC) {
+					printk("CRC error");
+					tell_sector(nr);
+				} else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
+					if (!probing) {
+						printk("sector not found");
+						tell_sector(nr);
+					} else
+						printk("probe failed...");
+				} else if (ST2 & ST2_WC) {	/* seek error */
+					printk("wrong cylinder");
+				} else if (ST2 & ST2_BC) {	/* cylinder marked as bad */
+					printk("bad cylinder");
+				} else {
+					printk("unknown error. ST[0..3] are: 0x%x 0x%x 0x%x 0x%x\n", ST0, ST1, ST2, ST3);
+				}
+				printk("\n");
+
+			}
+			if (bad)
+				bad_flp_intr();
+			redo_fd_request();
+			return;
+		case 2: /* invalid command given */
+			printk(DEVICE_NAME ": Invalid FDC command given!\n");
 			request_done(0);
-		} else
+			return;
+		case 3:
+			printk(DEVICE_NAME ": Abnormal termination caused by polling\n");
 			bad_flp_intr();
-		redo_fd_request();
-		return;
+			redo_fd_request();
+			return;
+		default: /* (0) Normal command termination */
+			break;
 	}
+
 	if (probing) {
 		int drive = MINOR(CURRENT->dev);
 
@@ -443,7 +571,7 @@
 			((sector-1 + head*floppy->sect)<<9);
 		copy_buffer(buffer_area,CURRENT->buffer);
 	} else if (command == FD_READ &&
-		(unsigned long)(CURRENT->buffer) >= 0x100000)
+		(unsigned long)(CURRENT->buffer) >= LAST_DMA_ADDR)
 		copy_buffer(tmp_floppy_area,CURRENT->buffer);
 	floppy_deselect(current_drive);
 	request_done(1);
@@ -499,6 +627,7 @@
 /* sense drive status */
 	output_byte(FD_SENSEI);
 	if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
+		printk(DEVICE_NAME ": seek failed\n");
 		recalibrate = 1;
 		bad_flp_intr();
 		redo_fd_request();
@@ -508,6 +637,34 @@
 	setup_rw_floppy();
 }
 
+/* Set perpendicular mode as required, based on data rate, if supported.
+ * 80277: 1Mbps data rate only possible with 82077-1.
+ * Untested!! TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
+ */
+static void inline perpendicular_mode(unsigned char rate)
+{
+	if (fdc_version == FDC_TYPE_82077) {
+		output_byte(FD_PERPENDICULAR);
+		if (rate & 0x40) {
+			unsigned char r = rate & 0x03;
+			if (r == 0)
+				output_byte(2);	/* perpendicular, 500 kbps */
+			else if (r == 3)
+				output_byte(3);	/* perpendicular, 1Mbps */
+			else {
+				printk(DEVICE_NAME ": Invalid data rate for perpendicular mode!\n");
+				reset = 1;
+			}
+		} else
+			output_byte(0);		/* conventional mode */
+	} else {
+		if (rate & 0x40) {
+			printk(DEVICE_NAME ": perpendicular mode not supported by FDC.\n");
+			reset = 1;
+		}
+	}
+} /* perpendicular_mode */
+
 /*
  * This routine is called when everything should be correctly set up
  * for the transfer (ie floppy motor is on and the correct floppy is
@@ -523,8 +680,11 @@
 		output_byte(cur_spec1);		/* hut etc */
 		output_byte(6);			/* Head load time =6ms, DMA */
 	}
-	if (cur_rate != floppy->rate)
-		outb_p(cur_rate = floppy->rate,FD_DCR);
+	if (cur_rate != floppy->rate) {
+		/* use bit 6 of floppy->rate to indicate perpendicular mode */
+		perpendicular_mode(floppy->rate);
+		outb_p(cur_rate = ((floppy->rate)) & ~0x40, FD_DCR);
+	}
 	if (reset) {
 		redo_fd_request();
 		return;
@@ -548,7 +708,7 @@
  * Special case - used after a unexpected interrupt (or reset)
  */
 
-static void recalibrate_floppy();
+static void recalibrate_floppy(void);
 
 static void recal_interrupt(void)
 {
@@ -565,6 +725,7 @@
 {
 	current_track = NO_TRACK;
 	output_byte(FD_SENSEI);
+	printk(DEVICE_NAME ": unexpected interrupt\n");
 	if (result()!=2 || (ST0 & 0xE0) == 0x60)
 		reset = 1;
 	else
@@ -582,13 +743,21 @@
 		redo_fd_request();
 }
 
+/*
+ * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
+ */
 static void reset_interrupt(void)
 {
-	output_byte(FD_SENSEI);
-	(void) result();
+	short i;
+
+	for (i=0; i<4; i++) {
+		output_byte(FD_SENSEI);
+		(void) result();
+	}
 	output_byte(FD_SPECIFY);
 	output_byte(cur_spec1);		/* hut etc */
 	output_byte(6);			/* Head load time =6ms, DMA */
+	configure_fdc_mode();		/* reprogram if smart fdc */
 	if (!recover) redo_fd_request();
 	else {
 		recalibrate_floppy();
@@ -676,7 +845,8 @@
 			floppy_sizes[current_drive] = MAX_DISK_SIZE;
 		}
 /* Forcing the drive to seek makes the "media changed" condition go away.
-   There should be a cleaner solution for that ... */
+ * There should be a cleaner solution for that ...
+ */
 		if (!reset && !recalibrate) {
 			do_floppy = (current_track && current_track != NO_TRACK)
 			    ?  shake_zero : shake_one;
@@ -711,6 +881,7 @@
     unsigned char *here = (unsigned char *) tmp_floppy_area;
     int count;
 
+    /* XXX: should do a check to see this fits in tmp_floppy_area!! */
     for (count = 1; count <= floppy->sect; count++) {
 	*here++ = track;
 	*here++ = head;
@@ -726,10 +897,12 @@
 	int device;
 
 repeat:
-	if (format_status == FORMAT_WAIT) format_status = FORMAT_BUSY;
+	if (format_status == FORMAT_WAIT)
+		format_status = FORMAT_BUSY;
 	if (format_status != FORMAT_BUSY) {
 		if (!CURRENT) {
-			if (!fdc_busy) panic("FDC access conflict");
+			if (!fdc_busy)
+				printk("FDC access conflict");
 			fdc_busy = 0;
 			wake_up(&fdc_wait);
 			CLEAR_INTR;
@@ -759,9 +932,10 @@
 		}
 	}
 	if (format_status != FORMAT_BUSY) {
-		if (current_drive != CURRENT_DEV)
+		if (current_drive != CURRENT_DEV) {
 			current_track = NO_TRACK;
-		current_drive = CURRENT_DEV;
+			current_drive = CURRENT_DEV;
+		}
 		block = CURRENT->sector;
 		if (block+2 > floppy->size) {
 			request_done(0);
@@ -781,8 +955,7 @@
 			request_done(0);
 			goto repeat;
 		}
-	}
-	else {
+	} else {
 		if (current_drive != (format_req.device & 3))
 			current_track = NO_TRACK;
 		current_drive = format_req.device & 3;
@@ -918,6 +1091,9 @@
 		case FDMSGOFF:
 			ftd_msg[drive] = 0;
 			break;
+		case FDSETEMSGTRESH:
+			min_report_error_cnt[drive] = (unsigned short) (param & 0x0f);
+			break;
 		default:
 			return -EINVAL;
 	}
@@ -956,9 +1132,26 @@
 	printk("\r\n");
 }
 
+/*
+ * floppy_open check for aliasing (/dev/fd0 can be the same as
+ * /dev/PS0 etc), and disallows simultaneous access to the same
+ * drive with different device numbers.
+ */
 static int floppy_open(struct inode * inode, struct file * filp)
 {
-	if (filp->f_mode)
+	int drive;
+	int old_dev;
+
+	drive = inode->i_rdev & 3;
+	old_dev = fd_device[drive];
+	if (fd_ref[drive])
+		if (old_dev != inode->i_rdev)
+			return -EBUSY;
+	fd_ref[drive]++;
+	fd_device[drive] = inode->i_rdev;
+	if (old_dev && old_dev != inode->i_rdev)
+		invalidate_buffers(old_dev);
+	if (filp && filp->f_mode)
 		check_disk_change(inode->i_rdev);
 	return 0;
 }
@@ -966,6 +1159,10 @@
 static void floppy_release(struct inode * inode, struct file * filp)
 {
 	sync_dev(inode->i_rdev);
+	if (!fd_ref[inode->i_rdev & 3]--) {
+		printk("floppy_release with fd_ref == 0");
+		fd_ref[inode->i_rdev & 3] = 0;
+	}
 }
 
 static struct file_operations floppy_fops = {
@@ -979,7 +1176,24 @@
 	floppy_release		/* release */
 };
 
-static void floppy_interrupt(int cpl)
+
+/*
+ * The version command is not supposed to generate an interrupt, but
+ * my FDC does, except when booting in SVGA screen mode.
+ * When it does generate an interrupt, it doesn't return any status bytes.
+ * It appears to have something to do with the version command...
+ */
+static void ignore_interrupt(void)
+{
+	if (result() != 0) {
+		printk(DEVICE_NAME ": weird interrupt ignored\n");
+		reset = 1;
+	}
+	CLEAR_INTR;	/* ignore only once */
+}
+
+
+static void floppy_interrupt(int unused)
 {
 	void (*handler)(void) = DEVICE_INTR;
 
@@ -990,9 +1204,8 @@
 }
 
 /*
- * 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...
+ * This is the floppy IRQ description. The SA_INTERRUPT in sa_flags
+ * means we run the IRQ-handler with interrupts disabled.
  */
 static struct sigaction floppy_sigaction = {
 	floppy_interrupt,
@@ -1012,4 +1225,19 @@
 	config_types();
 	if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
 		printk("Unable to grab IRQ%d for the floppy driver\n",FLOPPY_IRQ);
+
+	/* Try to determine the floppy controller type */
+	DEVICE_INTR = ignore_interrupt;	/* don't ask ... */
+	output_byte(FD_VERSION);	/* get FDC version code */
+	if (result() != 1) {
+		printk(DEVICE_NAME ": FDC failed to return version byte\n");
+		fdc_version = FDC_TYPE_STD;
+	} else
+		fdc_version = reply_buffer[0];
+	if (fdc_version != FDC_TYPE_STD) 
+		printk(DEVICE_NAME ": FDC version 0x%x\n", fdc_version);
+#ifndef FDC_FIFO_UNTESTED
+	fdc_version = FDC_TYPE_STD;	/* force std fdc type; can't test other. */
+#endif
+	configure_fdc_mode();
 }
diff --git a/kernel/blk_drv/genhd.c b/kernel/blk_drv/genhd.c
new file mode 100644
index 0000000..6618ce1
--- /dev/null
+++ b/kernel/blk_drv/genhd.c
@@ -0,0 +1,195 @@
+/*
+ *  Code extracted from
+ *  linux/kernel/hd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+struct gendisk *gendisk_head = NULL;
+
+static int current_minor = 0;
+extern int *blk_size[];
+/*
+ * Create devices for each logical partition in an extended partition.
+ * The logical partitions form a linked list, with each entry being
+ * a partition table with two entries.  The first entry
+ * is the real data partition (with a start relative to the partition
+ * table start).  The second is a pointer to the next logical partition
+ * (with a start relative to the entire extended partition).
+ * We do not create a Linux partition for the partition tables, but
+ * only for the actual data partitions.
+ */
+
+static void extended_partition(struct gendisk *hd, int dev)
+{
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned long first_sector, this_sector;
+	int mask = (1 << hd->minor_shift) - 1;
+
+	first_sector = hd->part[MINOR(dev)].start_sect;
+	this_sector = first_sector;
+
+	while (1) {
+		if ((current_minor & mask) >= (4 + hd->max_p))
+			return;
+		if (!(bh = bread(dev,0,1024))) {
+			printk("Unable to read partition table of device %04x\n",dev);
+			return;
+		}
+	  /*
+	   * This block is from a device that we're about to stomp on.
+	   * So make sure nobody thinks this block is usable.
+	   */
+		bh->b_dirt=0;
+		bh->b_uptodate=0;
+		if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
+			p = 0x1BE + (void *)bh->b_data;
+		/*
+		 * Process the first entry, which should be the real
+		 * data partition.
+		 */
+			if (p->sys_ind == EXTENDED_PARTITION ||
+			    !(hd->part[current_minor].nr_sects = p->nr_sects))
+				goto done;  /* shouldn't happen */
+			hd->part[current_minor].start_sect = this_sector + p->start_sect;
+			printk("  Logical part %d start %d size %d end %d\n\r", 
+			       current_minor, hd->part[current_minor].start_sect, 
+			       hd->part[current_minor].nr_sects,
+			       hd->part[current_minor].start_sect + 
+			       hd->part[current_minor].nr_sects - 1);
+			current_minor++;
+			p++;
+		/*
+		 * Process the second entry, which should be a link
+		 * to the next logical partition.  Create a minor
+		 * for this just long enough to get the next partition
+		 * table.  The minor will be reused for the real
+		 * data partition.
+		 */
+			if (p->sys_ind != EXTENDED_PARTITION ||
+			    !(hd->part[current_minor].nr_sects = p->nr_sects))
+				goto done;  /* no more logicals in this partition */
+			hd->part[current_minor].start_sect = first_sector + p->start_sect;
+			this_sector = first_sector + p->start_sect;
+			dev = ((hd->major) << 8) | current_minor;
+			brelse(bh);
+		} else
+			goto done;
+	}
+done:
+	brelse(bh);
+}
+
+static void check_partition(struct gendisk *hd, unsigned int dev)
+{
+	int i, minor = current_minor;
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned long first_sector;
+
+	first_sector = hd->part[MINOR(dev)].start_sect;
+
+	if (!(bh = bread(dev,0,1024))) {
+		printk("Unable to read partition table of device %04x\n",dev);
+		return;
+	}
+	printk("%s%d :\n\r", hd->major_name, minor >> hd->minor_shift);
+	current_minor += 4;  /* first "extra" minor */
+	if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
+		p = 0x1BE + (void *)bh->b_data;
+		for (i=1 ; i<=4 ; minor++,i++,p++) {
+			if (!(hd->part[minor].nr_sects = p->nr_sects))
+				continue;
+			hd->part[minor].start_sect = first_sector + p->start_sect;
+			printk(" part %d start %d size %d end %d \n\r", i, 
+			       hd->part[minor].start_sect, hd->part[minor].nr_sects, 
+			       hd->part[minor].start_sect + hd->part[minor].nr_sects - 1);
+			if ((current_minor & 0x3f) >= 60)
+				continue;
+			if (p->sys_ind == EXTENDED_PARTITION) {
+				extended_partition(hd, (hd->major << 8) | minor);
+			}
+		}
+		/*
+		 * check for Disk Manager partition table
+		 */
+		if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
+			p = 0x1BE + (void *)bh->b_data;
+			for (i = 4 ; i < 16 ; i++, current_minor++) {
+				p--;
+				if ((current_minor & 0x3f) >= 60)
+					break;
+				if (!(p->start_sect && p->nr_sects))
+					continue;
+				hd->part[current_minor].start_sect = p->start_sect;
+				hd->part[current_minor].nr_sects = p->nr_sects;
+				printk(" DM part %d start %d size %d end %d\n\r",
+				       current_minor,
+				       hd->part[current_minor].start_sect, 
+				       hd->part[current_minor].nr_sects,
+				       hd->part[current_minor].start_sect + 
+				       hd->part[current_minor].nr_sects - 1);
+			}
+		}
+	} else
+		printk("Bad partition table on dev %04x\n",dev);
+	brelse(bh);
+}
+
+static void setup_dev(struct gendisk *dev)
+{
+	int i;
+	int j = dev->max_nr * dev->max_p;
+	int major = dev->major << 8;
+	int drive;
+	
+
+	for (i = 0 ; i < j; i++)  {
+		dev->part[i].start_sect = 0;
+		dev->part[i].nr_sects = 0;
+	}
+	dev->init();	
+	for (drive=0 ; drive<dev->nr_real ; drive++) {
+		current_minor = 1+(drive<<dev->minor_shift);
+		check_partition(dev, major+(drive<<dev->minor_shift));
+	}
+	for (i=0 ; i < j ; i++)
+		dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
+	blk_size[dev->major] = dev->sizes;
+}
+	
+/* This may be used only once, enforced by 'static int callable' */
+int sys_setup(void * BIOS)
+{
+	static int callable = 1;
+	struct gendisk *p;
+	int nr=0;
+
+	if (!callable)
+		return -1;
+	callable = 0;
+
+	for (p = gendisk_head ; p ; p=p->next) {
+		setup_dev(p);
+		nr += p->nr_real;
+	}
+		
+	if (nr)
+		printk("Partition table%s ok.\n\r",(nr>1)?"s":"");
+
+#ifdef RAMDISK
+	rd_load();
+#endif
+	mount_root();
+	return (0);
+}
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index 8ff900d..b1620d2 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/hd.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -16,17 +16,19 @@
  *  in the early extended-partition checks and added DM partitions
  */
 
+#include <linux/config.h>
+#ifdef CONFIG_BLK_DEV_HD
+
 #define HD_IRQ 14
 
-#include <errno.h>
-#include <signal.h>
-
-#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/hdreg.h>
+#include <linux/genhd.h>
 
 #define REALLY_SLOW_IO
 #include <asm/system.h>
@@ -72,11 +74,7 @@
 static int NR_HD = 0;
 #endif
 
-static struct hd_struct {
-	long start_sect;
-	long nr_sects;
-} hd[MAX_HD<<6]={{0,0},};
-
+static struct hd_struct hd[MAX_HD<<6]={{0,0},};
 static int hd_sizes[MAX_HD<<6] = {0, };
 
 #define port_read(port,buf,nr) \
@@ -85,209 +83,6 @@
 #define port_write(port,buf,nr) \
 __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
 
-extern void rd_load(void);
-
-static unsigned int current_minor;
-
-/*
- * Create devices for each logical partition in an extended partition.
- * The logical partitions form a linked list, with each entry being
- * a partition table with two entries.  The first entry
- * is the real data partition (with a start relative to the partition
- * table start).  The second is a pointer to the next logical partition
- * (with a start relative to the entire extended partition).
- * We do not create a Linux partition for the partition tables, but
- * only for the actual data partitions.
- */
-static void extended_partition(unsigned int dev)
-{
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned long first_sector, this_sector;
-
-	first_sector = hd[MINOR(dev)].start_sect;
-	this_sector = first_sector;
-
-	while (1) {
-		if ((current_minor & 0x3f) >= 60)
-			return;
-		if (!(bh = bread(dev,0))) {
-			printk("Unable to read partition table of device %04x\n",dev);
-			return;
-		}
-	  /*
-	   * This block is from a device that we're about to stomp on.
-	   * So make sure nobody thinks this block is usable.
-	   */
-		bh->b_dirt=0;
-		bh->b_uptodate=0;
-		if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
-			p = 0x1BE + (void *)bh->b_data;
-		/*
-		 * Process the first entry, which should be the real
-		 * data partition.
-		 */
-			if (p->sys_ind == EXTENDED_PARTITION ||
-			    !(hd[current_minor].nr_sects = p->nr_sects))
-				goto done;  /* shouldn't happen */
-			hd[current_minor].start_sect = this_sector + p->start_sect;
-			printk("  Logical part %d start %d size %d end %d\n\r", 
-			       current_minor, hd[current_minor].start_sect, 
-			       hd[current_minor].nr_sects,
-			       hd[current_minor].start_sect + 
-			       hd[current_minor].nr_sects - 1);
-			current_minor++;
-			p++;
-		/*
-		 * Process the second entry, which should be a link
-		 * to the next logical partition.  Create a minor
-		 * for this just long enough to get the next partition
-		 * table.  The minor will be reused for the real
-		 * data partition.
-		 */
-			if (p->sys_ind != EXTENDED_PARTITION ||
-			    !(hd[current_minor].nr_sects = p->nr_sects))
-				goto done;  /* no more logicals in this partition */
-			hd[current_minor].start_sect = first_sector + p->start_sect;
-			this_sector = first_sector + p->start_sect;
-			dev = 0x0300 | current_minor;
-			brelse(bh);
-		} else
-			goto done;
-	}
-done:
-	brelse(bh);
-}
-
-static void check_partition(unsigned int dev)
-{
-	int i, minor = current_minor;
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned long first_sector;
-
-	first_sector = hd[MINOR(dev)].start_sect;
-	if (!(bh = bread(dev,0))) {
-		printk("Unable to read partition table of device %04x\n",dev);
-		return;
-	}
-	printk("Drive %d:\n\r",minor >> 6);
-	current_minor += 4;  /* first "extra" minor */
-	if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
-		p = 0x1BE + (void *)bh->b_data;
-		for (i=1 ; i<=4 ; minor++,i++,p++) {
-			if (!(hd[minor].nr_sects = p->nr_sects))
-				continue;
-			hd[minor].start_sect = first_sector + p->start_sect;
-			printk(" part %d start %d size %d end %d \n\r", i, 
-			       hd[minor].start_sect, hd[minor].nr_sects, 
-			       hd[minor].start_sect + hd[minor].nr_sects - 1);
-			if ((current_minor & 0x3f) >= 60)
-				continue;
-			if (p->sys_ind == EXTENDED_PARTITION) {
-				extended_partition(0x0300 | minor);
-			}
-		}
-		/*
-		 * check for Disk Manager partition table
-		 */
-		if (*(unsigned short *) (bh->b_data+0xfc) == 0x55AA) {
-			p = 0x1BE + (void *)bh->b_data;
-			for (i = 4 ; i < 16 ; i++, current_minor++) {
-				p--;
-				if ((current_minor & 0x3f) >= 60)
-					break;
-				if (!(p->start_sect && p->nr_sects))
-					continue;
-				hd[current_minor].start_sect = p->start_sect;
-				hd[current_minor].nr_sects = p->nr_sects;
-				printk(" DM part %d start %d size %d end %d\n\r",
-				       current_minor,
-				       hd[current_minor].start_sect, 
-				       hd[current_minor].nr_sects,
-				       hd[current_minor].start_sect + 
-				       hd[current_minor].nr_sects - 1);
-			}
-		}
-	} else
-		printk("Bad partition table on dev %04x\n",dev);
-	brelse(bh);
-}
-
-/* This may be used only once, enforced by 'static int callable' */
-int sys_setup(void * BIOS)
-{
-	static int callable = 1;
-	int i,drive;
-	unsigned char cmos_disks;
-
-	if (!callable)
-		return -1;
-	callable = 0;
-#ifndef HD_TYPE
-	for (drive=0 ; drive<2 ; drive++) {
-		hd_info[drive].cyl = *(unsigned short *) BIOS;
-		hd_info[drive].head = *(unsigned char *) (2+BIOS);
-		hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
-		hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
-		hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
-		hd_info[drive].sect = *(unsigned char *) (14+BIOS);
-		BIOS += 16;
-	}
-
-	/*
-		We querry CMOS about hard disks : it could be that 
-		we have a SCSI/ESDI/etc controller that is BIOS
-		compatable with ST-506, and thus showing up in our
-		BIOS table, but not register compatable, and therefore
-		not present in CMOS.
-
-		Furthurmore, we will assume that our ST-506 drives
-		<if any> are the primary drives in the system, and 
-		the ones reflected as drive 1 or 2.
-
-		The first drive is stored in the high nibble of CMOS
-		byte 0x12, the second in the low nibble.  This will be
-		either a 4 bit drive type or 0xf indicating use byte 0x19 
-		for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
-
-		Needless to say, a non-zero value means we have 
-		an AT controller hard disk for that drive.
-
-		
-	*/
-
-	if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
-		if (cmos_disks & 0x0f)
-			NR_HD = 2;
-		else
-			NR_HD = 1;
-	else
-		NR_HD = 0;
-#endif
-	for (i = 0 ; i < (MAX_HD<<6) ; i++) {
-		hd[i].start_sect = 0;
-		hd[i].nr_sects = 0;
-	}
-	for (i = 0 ; i < NR_HD ; i++)
-		hd[i<<6].nr_sects = hd_info[i].head*
-				hd_info[i].sect*hd_info[i].cyl;
-	for (drive=0 ; drive<NR_HD ; drive++) {
-		current_minor = 1+(drive<<6);
-		check_partition(0x0300+(drive<<6));
-	}
-	for (i=0 ; i<(MAX_HD<<6) ; i++)
-		hd_sizes[i] = hd[i].nr_sects>>1 ;
-	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);
-}
-
 #if (HD_DELAY > 0)
 unsigned long read_timer(void)
 {
@@ -322,10 +117,13 @@
 
 	if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
 		== (READY_STAT | SEEK_STAT))
-		return(0); /* ok */
-	if (i&1)
+		return 0; /* ok */
+	printk("HD: win_result: status = 0x%02x\n",i);
+	if (i&1) {
 		i=inb(HD_ERROR);
-	return (1);
+		printk("HD: win_result: error = 0x%02x\n",i);
+	}	
+	return 1;
 }
 
 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
@@ -367,7 +165,7 @@
 		if (c == (READY_STAT | SEEK_STAT))
 			return 0;
 	}
-	printk("HD controller times out, c=%02x\n\r",c);
+	printk("HD controller times out, status = 0x%02x\n\r",c);
 	return(1);
 }
 
@@ -416,12 +214,9 @@
  */
 void unexpected_hd_interrupt(void)
 {
+	sti();
 	printk("Unexpected HD interrupt\n\r");
 	SET_TIMER;
-#if 0
-	reset = 1;
-	do_hd_request();
-#endif
 }
 
 static void bad_rw_intr(void)
@@ -436,6 +231,16 @@
 		recalibrate = 1;
 }
 
+static inline int wait_DRQ(void)
+{
+	int retries = 100000;
+
+	while (--retries > 0)
+		if (inb_p(HD_STATUS) & DRQ_STAT)
+			return 0;
+	return -1;
+}
+
 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
 #define STAT_OK (READY_STAT | SEEK_STAT)
 
@@ -444,23 +249,36 @@
 	int i;
 
 	i = (unsigned) inb_p(HD_STATUS);
-	if (!(i & DRQ_STAT))
+	if ((i & STAT_MASK) != STAT_OK) {
+		printk("HD: read_intr: status = 0x%02x\n",i);
 		goto bad_read;
-	if ((i & STAT_MASK) != STAT_OK)
+	}
+	if (wait_DRQ()) {
+		printk("HD: read_intr: no DRQ\n");
 		goto bad_read;
+	}
 	port_read(HD_DATA,CURRENT->buffer,256);
 	i = (unsigned) inb_p(HD_STATUS);
 	if (!(i & BUSY_STAT))
-		if ((i & STAT_MASK) != STAT_OK)
+		if ((i & STAT_MASK) != STAT_OK) {
+			printk("HD: read_intr: second status = 0x%02x\n",i);
 			goto bad_read;
+		}
 	CURRENT->errors = 0;
 	CURRENT->buffer += 512;
 	CURRENT->sector++;
 	i = --CURRENT->nr_sectors;
-	if (!i || (CURRENT->bh && !(i&1)))
+	--CURRENT->current_nr_sectors;
+#ifdef DEBUG
+	printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
+		MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT-> 
+		buffer);
+#endif
+	if (!i || (CURRENT->bh && !SUBSECTOR(i)))
 		end_request(1);
 	if (i > 0) {
 		SET_INTR(&read_intr);
+		sti();
 		return;
 	}
 #if (HD_DELAY > 0)
@@ -469,8 +287,10 @@
 	do_hd_request();
 	return;
 bad_read:
-	if (i & ERR_STAT)
+	if (i & ERR_STAT) {
 		i = (unsigned) inb(HD_ERROR);
+		printk("HD: read_intr: error = 0x%02x\n",i);
+	}
 	bad_rw_intr();
 	do_hd_request();
 	return;
@@ -481,18 +301,24 @@
 	int i;
 
 	i = (unsigned) inb_p(HD_STATUS);
-	if ((i & STAT_MASK) != STAT_OK)
+	if ((i & STAT_MASK) != STAT_OK) {
+		printk("HD: write_intr: status = 0x%02x\n",i);
 		goto bad_write;
-	if (CURRENT->nr_sectors > 1 && !(i & DRQ_STAT))
+	}
+	if (CURRENT->nr_sectors > 1 && wait_DRQ()) {
+		printk("HD: write_intr: no DRQ\n");
 		goto bad_write;
+	}
 	CURRENT->sector++;
 	i = --CURRENT->nr_sectors;
+	--CURRENT->current_nr_sectors;
 	CURRENT->buffer += 512;
-	if (!i || (CURRENT->bh && !(i & 1)))
+	if (!i || (CURRENT->bh && !SUBSECTOR(i)))
 		end_request(1);
 	if (i > 0) {
 		SET_INTR(&write_intr);
 		port_write(HD_DATA,CURRENT->buffer,256);
+		sti();
 	} else {
 #if (HD_DELAY > 0)
 		last_req = read_timer();
@@ -501,9 +327,13 @@
 	}
 	return;
 bad_write:
-	if (i & ERR_STAT)
+	sti();
+	if (i & ERR_STAT) {
 		i = (unsigned) inb(HD_ERROR);
+		printk("HD: write_intr: error = 0x%02x\n",i);
+	}
 	bad_rw_intr();
+	cli();
 	do_hd_request();
 	return;
 }
@@ -520,30 +350,50 @@
  * best idea seems to just set reset, and start all over again.
  */
 static void hd_times_out(void)
-{	
+{
+	sti();
 	DEVICE_INTR = NULL;
 	reset = 1;
 	if (!CURRENT)
 		return;
 	printk("HD timeout\n\r");
 	cli();
-	if (++CURRENT->errors >= MAX_ERRORS)
+	if (++CURRENT->errors >= MAX_ERRORS) {
+#ifdef DEBUG
+		printk("hd : too many errors.\n");
+#endif
 		end_request(0);
+	}
+
 	do_hd_request();
 }
 
+/*
+ * The driver has been modified to enable interrupts a bit more: in order to
+ * do this we first (a) disable the timeout-interrupt and (b) clear the
+ * device-interrupt. This way the interrupts won't mess with out code (the
+ * worst that can happen is that an unexpected HD-interrupt comes in and
+ * sets the "reset" variable and starts the timer)
+ */
 static void do_hd_request(void)
 {
-	int i,r;
 	unsigned int block,dev;
 	unsigned int sec,head,cyl;
 	unsigned int nsect;
 
+repeat:
+	DEVICE_INTR = NULL;
+	timer_active &= ~(1<<HD_TIMER);
+	sti();
 	INIT_REQUEST;
 	dev = MINOR(CURRENT->dev);
 	block = CURRENT->sector;
 	nsect = CURRENT->nr_sectors;
 	if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
+#ifdef DEBUG
+		printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
+		   	block, hd[dev].nr_sects);
+#endif
 		end_request(0);
 		goto repeat;
 	}
@@ -554,9 +404,15 @@
 	head = block % hd_info[dev].head;
 	cyl = block / hd_info[dev].head;
 	sec++;
+#ifdef DEBUG
+	printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
+		dev, cyl, head, sec, CURRENT->buffer);
+#endif
+	cli();
 	if (reset) {
 		recalibrate = 1;
 		reset_hd();
+		sti();
 		return;
 	}
 	if (recalibrate) {
@@ -564,23 +420,25 @@
 		hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
 		if (reset)
 			goto repeat;
+		sti();
 		return;
 	}	
 	if (CURRENT->cmd == WRITE) {
 		hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 		if (reset)
 			goto repeat;
-		for(i=0 ; i<10000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
-			/* nothing */ ;
-		if (!r) {
+		if (wait_DRQ()) {
+			printk("HD: do_hd_request: no DRQ\n");
 			bad_rw_intr();
 			goto repeat;
 		}
 		port_write(HD_DATA,CURRENT->buffer,256);
+		sti();
 	} else if (CURRENT->cmd == READ) {
 		hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
 		if (reset)
 			goto repeat;
+		sti();
 	} else
 		panic("unknown hd-command");
 }
@@ -623,6 +481,79 @@
 	sync_dev(inode->i_rdev);
 }
 
+
+static void hd_geninit();
+
+static struct gendisk hd_gendisk = {
+	MAJOR_NR,	/* Major number */	
+	"hd",		/* Major name */
+	6,		/* Bits to shift to get real from partition */
+	1 << 6,		/* Number of partitions per real */
+	MAX_HD,		/* maximum number of real */
+	hd_geninit,	/* init function */
+	hd,		/* hd struct */
+	hd_sizes,	/* block sizes */
+	0,		/* number */
+	(void *) hd_info,	/* internal */
+	NULL		/* next */
+};
+	
+static void hd_geninit(void)
+{
+	int drive;
+#ifndef HD_TYPE
+	extern struct drive_info drive_info;
+	void *BIOS = (void *) &drive_info;
+	int cmos_disks, i;
+	   
+	for (drive=0 ; drive<2 ; drive++) {
+		hd_info[drive].cyl = *(unsigned short *) BIOS;
+		hd_info[drive].head = *(unsigned char *) (2+BIOS);
+		hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
+		hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
+		hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
+		hd_info[drive].sect = *(unsigned char *) (14+BIOS);
+		BIOS += 16;
+	}
+
+	/*
+		We querry CMOS about hard disks : it could be that 
+		we have a SCSI/ESDI/etc controller that is BIOS
+		compatable with ST-506, and thus showing up in our
+		BIOS table, but not register compatable, and therefore
+		not present in CMOS.
+
+		Furthurmore, we will assume that our ST-506 drives
+		<if any> are the primary drives in the system, and 
+		the ones reflected as drive 1 or 2.
+
+		The first drive is stored in the high nibble of CMOS
+		byte 0x12, the second in the low nibble.  This will be
+		either a 4 bit drive type or 0xf indicating use byte 0x19 
+		for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
+
+		Needless to say, a non-zero value means we have 
+		an AT controller hard disk for that drive.
+
+		
+	*/
+
+	if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
+		if (cmos_disks & 0x0f)
+			NR_HD = 2;
+		else
+			NR_HD = 1;
+	else
+		NR_HD = 0;
+#endif
+
+	for (i = 0 ; i < NR_HD ; i++)
+		hd[i<<6].nr_sects = hd_info[i].head*
+				hd_info[i].sect*hd_info[i].cyl;
+
+	hd_gendisk.nr_real = NR_HD;
+}
+
 static struct file_operations hd_fops = {
 	NULL,			/* lseek - default */
 	block_read,		/* read - general block-dev read */
@@ -634,7 +565,7 @@
 	hd_release		/* release */
 };
 
-static void hd_interrupt(int cpl)
+static void hd_interrupt(int unused)
 {
 	void (*handler)(void) = DEVICE_INTR;
 
@@ -643,6 +574,7 @@
 	if (!handler)
 		handler = unexpected_hd_interrupt;
 	handler();
+	sti();
 }
 
 /*
@@ -650,6 +582,9 @@
  * 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...
+ *
+ * We enable interrupts in some of the routines after making sure it's
+ * safe.
  */
 static struct sigaction hd_sigaction = {
 	hd_interrupt,
@@ -662,7 +597,11 @@
 {
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 	blkdev_fops[MAJOR_NR] = &hd_fops;
+	hd_gendisk.next = gendisk_head;
+	gendisk_head = &hd_gendisk;
 	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;
 }
+
+#endif
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index 0ef93b6..0a7005b 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -1,16 +1,17 @@
 /*
  *  linux/kernel/blk_dev/ll_rw.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
  * 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 <linux/errno.h>
+#include <linux/string.h>
+
 #include <asm/system.h>
 
 #include "blk.h"
@@ -136,6 +137,7 @@
 
 static void make_request(int major,int rw, struct buffer_head * bh)
 {
+	unsigned int sector, count;
 	struct request * req;
 	int rw_ahead;
 
@@ -153,8 +155,10 @@
 		printk("Bad block dev command, must be R/W/RA/WA\n");
 		return;
 	}
+	count = bh->b_size >> 9;
+	sector = bh->b_blocknr * count;
 	if (blk_size[major])
-		if (blk_size[major][MINOR(bh->b_dev)] <= bh->b_blocknr) {
+		if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) {
 			bh->b_dirt = bh->b_uptodate = 0;
 			return;
 		}
@@ -165,16 +169,16 @@
 	}
 repeat:
 	cli();
-	if (major == 3 && (req = blk_dev[major].current_request)) {
+	if ((major == 3 ||  major == 8 )&& (req = blk_dev[major].current_request)) {
 		while (req = req->next) {
 			if (req->dev == bh->b_dev &&
 			    !req->waiting &&
 			    req->cmd == rw &&
-			    req->sector + req->nr_sectors == bh->b_blocknr << 1 &&
+			    req->sector + req->nr_sectors == sector &&
 			    req->nr_sectors < 254) {
 				req->bhtail->b_reqnext = bh;
 				req->bhtail = bh;
-				req->nr_sectors += 2;
+				req->nr_sectors += count;
 				bh->b_dirt = 0;
 				sti();
 				return;
@@ -208,8 +212,9 @@
 	req->dev = bh->b_dev;
 	req->cmd = rw;
 	req->errors = 0;
-	req->sector = bh->b_blocknr<<1;
-	req->nr_sectors = 2;
+	req->sector = sector;
+	req->nr_sectors = count;
+	req->current_nr_sectors = count;
 	req->buffer = bh->b_data;
 	req->waiting = NULL;
 	req->bh = bh;
@@ -224,7 +229,7 @@
 	unsigned int major = MAJOR(dev);
 
 	if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
-		printk("Trying to read nonexistent block-device\n\r");
+		printk("Trying to read nonexistent block-device %04x (%d)\n",dev,page*8);
 		return;
 	}
 	if (rw!=READ && rw!=WRITE)
@@ -250,6 +255,7 @@
 	req->errors = 0;
 	req->sector = page<<3;
 	req->nr_sectors = 8;
+	req->current_nr_sectors = 8;
 	req->buffer = buffer;
 	req->waiting = &current->wait;
 	req->bh = NULL;
@@ -265,9 +271,14 @@
 
 	if (!bh)
 		return;
+	if (bh->b_size != 1024) {
+		printk("ll_rw_block: only 1024-char blocks implemented (%d)\n",bh->b_size);
+		bh->b_dirt = bh->b_uptodate = 0;
+		return;
+	}
 	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");
+		printk("ll_rw_block: Trying to read nonexistent block-device %04x (%d)\n",bh->b_dev,bh->b_blocknr);
 		bh->b_dirt = bh->b_uptodate = 0;
 		return;
 	}
@@ -331,6 +342,7 @@
 		req->errors = 0;
 		req->sector = b[i] << 1;
 		req->nr_sectors = 2;
+		req->current_nr_sectors = 2;
 		req->buffer = buf;
 		req->waiting = &current->wait;
 		req->bh = NULL;
diff --git a/kernel/blk_drv/ramdisk.c b/kernel/blk_drv/ramdisk.c
index 833322f..195146d 100644
--- a/kernel/blk_drv/ramdisk.c
+++ b/kernel/blk_drv/ramdisk.c
@@ -4,9 +4,10 @@
  *  Written by Theodore Ts'o, 12/2/91
  */
 
-#include <linux/string.h>
 
 #include <linux/config.h>
+#ifdef RAMDISK
+#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/fs.h>
@@ -21,11 +22,12 @@
 char	*rd_start;
 int	rd_length = 0;
 
-void do_rd_request(void)
+static void do_rd_request(void)
 {
 	int	len;
 	char	*addr;
 
+repeat:
 	INIT_REQUEST;
 	addr = rd_start + (CURRENT->sector << 9);
 	len = CURRENT->nr_sectors << 9;
@@ -119,7 +121,7 @@
 		if (nblocks > 2) 
 			bh = breada(ROOT_DEV, block, block+1, block+2, -1);
 		else
-			bh = bread(ROOT_DEV, block);
+			bh = bread(ROOT_DEV, block, BLOCK_SIZE);
 		if (!bh) {
 			printk("I/O error on block %d, aborting load\n", 
 				block);
@@ -136,3 +138,4 @@
 	printk("\ndone\n");
 	ROOT_DEV=0x0101;
 }
+#endif
diff --git a/kernel/blk_drv/scsi/7000fasst.c b/kernel/blk_drv/scsi/7000fasst.c
new file mode 100644
index 0000000..8a72be4
--- /dev/null
+++ b/kernel/blk_drv/scsi/7000fasst.c
@@ -0,0 +1,465 @@
+/* $Id: 7000fasst.c,v 1.1 1992/07/24 06:27:38 root Exp root $
+ *  linux/kernel/7000fasst.c
+ *
+ *  Copyright (C) 1992  Thomas Wuensche
+ *	closely related to the aha1542 driver from Tommy Thorn
+ *	( as close as different hardware allows on a lowlevel-driver :-) )
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "scsi.h"
+#include "hosts.h"
+
+struct mailbox{
+	unchar status;
+	unchar scbptr[3];
+};
+
+/* #define DEBUG */
+
+#include "7000fasst.h"
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+/*static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/7000fasst.c,v 1.1 1992/07/24 06:27:38 root Exp root $";*/
+
+static struct scb scbs[OGMB_CNT];
+
+long wd7000fasst_WAITnexttimeout = 3000000;
+
+void (*wd7000fasst_do_done)() = NULL;
+extern void wd7000fasst_interrupt();
+void wd7000fasst_call_buh();
+
+static unchar controlstat = 0;
+static unchar wd7000fasst_hostno;
+
+#define wd7000fasst_intr_reset()  outb(0,INTR_ACK)
+#define PC_IMR	0x21
+#define AT_IMR	0xa1
+
+#define wd7000fasst_enable_intr(){\
+	controlstat |= INT_EN;\
+	outb(controlstat,CONTROL);\
+	outb((inb((intr_chan<=7)?PC_IMR:AT_IMR))& ~0xff,(intr_chan<=7)?PC_IMR:AT_IMR);}
+
+#define wd7000fasst_disable_intr() outb(controlstat |= INT_EN, CONTROL)
+#define wd7000fasst_enable_dma() {\
+	controlstat |= DMA_EN;\
+	outb(controlstat,CONTROL);\
+	outb((DMA_CH|CASCADE),DMA_MODE_REG);\
+	outb(DMA_CH,DMA_MASK_REG);}
+
+#define wd7000fasst_disable_dma() {\
+	outb(DMA_CH|S_DMA_MASK,DMA_MASK_REG);\
+	controlstat &= ~DMA_EN;\
+	outb(controlstat,CONTROL);}
+
+#define WAIT(port, mask, allof, noneof)					\
+ { register WAITbits;							\
+   register WAITtimeout = wd7000fasst_WAITnexttimeout;				\
+   while (1) {								\
+     WAITbits = inb(port) & (mask);					\
+     if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
+       break;                                                         	\
+     if (--WAITtimeout == 0) goto fail;					\
+   }									\
+ }
+
+static void wd7000fasst_stat(void)
+{
+/*    int s = inb(ASC_STAT), i = inb(INTR_STAT);*/
+/*    printk("status = %x, intrflags = %x served %d last %x\n", s, i, intr_flag, intr_last); 
+    printk("status=%x intrflags=%x\n", s, i);
+*/}
+
+static int wd7000fasst_out(unchar *cmdp, int len)
+{
+    while (len--)
+      {
+	  WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
+	  outb(*cmdp++, COMMAND);
+      }
+    return 0;
+  fail:
+    printk("wd7000fasst_out failed(%d): ", len+1); wd7000fasst_stat();
+    return 1;
+}
+
+int wd7000fasst_make_error_code(unsigned hosterr, unsigned scsierr)
+{   
+#ifdef DEBUG
+    int in_error=hosterr;
+#endif
+    switch ((hosterr&0xff00)>>8){
+	case 0:	/* It is reserved, should never happen */
+		hosterr=DID_ERROR;
+		break;
+	case 1:	hosterr=DID_OK;
+		break;
+	case 2: /* Command complete with logged error */
+		/* My actual copies of the manual pages are unreadable
+		 * For now we simply tell there is an error */
+		DEB(printk("Hosterror: VUE = %x\n",hosterr&0xff);)
+		switch (hosterr&0xff) {
+		    default:	DEB(printk("wd7000fasst_make_error_code: unknown hoststatus %x\n", hosterr);)
+				hosterr=DID_ERROR;
+		    		break;
+	    	}
+	    	break;
+	case 4:	hosterr=DID_BAD_TARGET;	/* Command failed to complete without SCSI status */
+		break;
+	case 5: hosterr=DID_RESET;	/* Cmd terminated; Bus reset by external device */
+		break;
+	case 6:	hosterr=DID_ERROR;/* Hardware Failure, requires host reset */
+		break;
+	case 7: hosterr=DID_RESET;
+		break;
+	case 8:	hosterr=DID_OK;
+		printk("wd7000fasst: Linked command not implemented\n");
+		break;
+	}
+#ifdef DEBUG
+    if (scsierr||hosterr) printk("SCSI-Command error: SCSI %x HOST %x RETURN %x\n",scsierr,in_error,hosterr);
+#endif
+    return scsierr|(hosterr << 16);
+}
+
+/* The following is space for the Mailboxes */
+struct{ struct mailbox ombox[OGMB_CNT]; 
+	struct mailbox imbox[ICMB_CNT]; } mbstruct;
+
+int wd7000fasst_init(void)
+{   int i;
+    volatile int debug = 0;
+    /* Page 47 */
+    unchar init_block[]={ 1, 7, 0x18, 0x18, 0, 0, 0, 0, OGMB_CNT, ICMB_CNT };
+    /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
+    
+    DEB(printk("wd7000fasst_init called \n")); 
+    
+    outb(SCSI_RES|ASC_RES, CONTROL);
+    /* Wait at least 25 us */
+    for (i=0; i< 1000; i++) inb(ASC_STAT);
+    /* Now reset the reset */
+    outb(0,CONTROL);
+    debug = 1;
+    /* Expect Command Port Ready */
+    WAIT(ASC_STAT, STATMASK, CMD_RDY, 0);
+    DEB(printk("wd7000fasst_init: Power on Diagnostics finished\n"));
+    if ((i=inb(INTR_STAT))!=1) 
+	printk("Power on Diagnostics error %x\n",i); 
+    
+    debug = 2;
+    /* Clear mbstruct */
+    memset(&mbstruct,0,sizeof (mbstruct));
+    /* Set up init block */
+    any2scsi(init_block+5,&mbstruct);
+    /* Execute init command */
+    wd7000fasst_out(init_block,sizeof(init_block));
+    DEB(printk("Init-Block :");
+    for (i=0;i<sizeof(init_block);i++) printk(" %x",init_block[i]);
+    printk("\n");)
+    /* Wait until init finished */
+    WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
+    outb(2,COMMAND);
+    WAIT(ASC_STAT, STATMASK, CMD_RDY | ASC_INI, 0);
+    /* Enable Interrupt and DMA */
+    wd7000fasst_enable_dma();
+    wd7000fasst_call_buh();
+    DEB(printk("wd7000fasst_detect: enable interrupt channel %d\n", intr_chan));
+    wd7000fasst_enable_intr(); 
+    printk("wd7000fasst_init: Controller initialized\n");
+    return 1;
+  fail:
+    return 0;					/* 0 = not ok */
+}
+
+/* What's this little function for? */
+char *wd7000fasst_info(void)
+{
+    static char buffer[] = "Western Digital 7000-FASST";
+    return buffer;
+}
+
+/* A "high" level interrupt handler */
+void wd7000fasst_intr_handle(void)
+{   struct scb * scbptr;
+    DEB(int len=sizeof (struct scb);)
+    DEB(int k;)
+    unsigned host_error,scsi_error;
+    int flag = inb(INTR_STAT);
+    void (*my_done)() = wd7000fasst_do_done;
+    int errstatus;
+    DEB(printk("WD Interrupt aufgetreten\n"));
+    if (!(inb(ASC_STAT)&0x80)){ 
+	printk("Interrupt without Interrupt\n"); 
+	wd7000fasst_intr_reset();
+	return; 
+    }
+    wd7000fasst_do_done = NULL;
+    if (!my_done) {
+	printk("wd7000fasst_intr_handle: Unexpected interrupt\n");
+	wd7000fasst_intr_reset();
+	return;
+    }
+
+    /* is there mail for me :-) */
+    if ((flag&0xc0)==0xc0){
+	/* Ok, the interrupt is for an incoming mailbox */
+	/* We make the content available for the starter  of the command */
+	DEB(if ((flag&0xc0)==0xc0) printk("INTR_STAT: %x mbstat: %x\n",flag,mbstruct.imbox[flag&0x3f].status));
+	if (mbstruct.imbox[flag&0x3f].status==0){
+	    /* Something strange happened */
+	    wd7000fasst_intr_reset();
+	    return;
+	    ;
+	}
+	scbptr=(struct scb *)scsi2int(mbstruct.imbox[flag&0x3f].scbptr);
+	DEB(printk("Datenbereiche aus %x ein %x \n",scbptr,&(scbs[flag&0x3f]));
+	printk("SCB after return:\n");
+	k=0;
+	while (len-- >0){
+	    printk("%x ",*((unchar *)scbptr));
+	    ((unchar *)scbptr)++;
+	    if (++k==16){ printk("\n"); k=0; }
+	});
+    }
+    else { printk("Error in interrupt\n"); return; }
+    /* more error checking left out here */
+
+    scbptr=(struct scb *)scsi2int(mbstruct.imbox[flag&0x3f].scbptr);
+    host_error=scbptr->vue |  mbstruct.imbox[flag&0x3f].status<<8;
+    scsi_error=scbptr->sretstat;
+    errstatus=wd7000fasst_make_error_code(host_error,scsi_error);    
+    DEB(if (errstatus) printk("Target was %x\n",scbptr->idlun>>5);)
+    DEB(if (errstatus) printk("wd7000fasst_intr_handle: returning %6x\n", errstatus));
+    DEB(printk("wd7000fasst_intr_handle: Status of the finished command: %x\n",mbstruct.imbox[flag&0x3f].status));
+    /* I make a SCSI reset */
+    /* Left out */
+    my_done(wd7000fasst_hostno,errstatus);
+    wd7000fasst_intr_reset();
+    return;
+}
+
+volatile static int internal_done_flag = 0;
+volatile static int internal_done_errcode = 0;
+
+/* The following code queues a SCSI command */
+int wd7000fasst_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, 
+		void (*done)(int, int))
+{
+    int i;
+#ifdef DEBUG
+    int j;
+#endif
+    unchar *cmd = (unchar *) cmnd;
+/* We first look for a free outgoing mailbox */
+    for (i=0;i<OGMB_CNT;i++){
+	if (mbstruct.ombox[i].status==0){
+	    /* We found one, now set up the scb */
+	    DEB(printk("Found outgoing mbox %x\n",i));
+	    memset(&scbs[i], 0, sizeof(struct scb));
+	    /* scbs[i].cdblen = (*cmd<=0x1f)?6:10; */	/* SCSI Command Descriptor Block Length */
+	    memcpy(scbs[i].scbdata, cmd, (*cmd<=0x1f)?6:10);
+	    scbs[i].op = 0;				/* SCSI Initiator Command */
+	    scbs[i].idlun = (target<<5)&0xe0;		/* SCSI Target Id Bit 7-5 Target Id*/
+	    any2scsi(scbs[i].dataptr,buff);
+	    any2scsi(scbs[i].maxdata,bufflen);
+	    scbs[i].direc=0x40;		/* Disable direction check */
+	    DEB(printk("Kommando fuer target %x ist: ",target);
+	    	for (j=0;j<12;j++) printk(" %x",scbs[i].scbdata[j]);
+	    	printk("\n"));
+	    /* Now we set up the pointer to scb, then the status of the mbox */
+	    any2scsi((mbstruct.ombox[i].scbptr),&(scbs[i]));
+	    mbstruct.ombox[i].status=1;
+	    /* Everything set up, start the command */
+	    break;
+	}
+    }
+    if (i==OGMB_CNT){
+	/* No free mbox, send command "Interrupt on free OGMB" */
+	DEB(printk("No free Mailbox\n"));
+	return 0;
+    }
+    {	int len,k;
+	struct scb * scbptr;
+	    DEB(printk("Found outgoing mbox %x\n",i));
+	scbptr=&(scbs[i]);
+	len=sizeof(struct scb);
+	k=0;
+	DEB(printk("SCB before execute:\n");
+	    while (len-- >0){
+	    	printk("%x ",*((unchar *)scbptr));
+	    	((unchar *)scbptr)++;
+	    	if (++k==16){ printk("\n"); k=0; }
+	    };)
+    }
+    /* Set up the "done" response function */
+    if (done) {
+	DEB(printk("wd7000fasst_queuecommand: now waiting for interrupt "); 
+	    wd7000fasst_stat());
+	if (wd7000fasst_do_done)
+	    printk("wd7000fasst_queuecommand: Two concurrent queuecommand?\n");
+	else
+	    wd7000fasst_do_done = done;
+	DEB(wd7000fasst_stat());
+	wd7000fasst_enable_intr(); 
+    }
+    else{
+	printk("wd7000fasst_queuecommand: done can't be NULL\n");
+	return 0;
+    }
+    /* Now we initialize execution */
+retry:	WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
+	outb(0x80+i,COMMAND);
+	WAIT(ASC_STAT,STATMASK,CMD_RDY,0);
+	if (inb(ASC_STAT)&CMD_REJ) goto retry;
+	return 1;
+    /* Wait until done */
+
+fail:
+    return 0;
+}
+
+/* We use this function for queueing a command from wd7000fasst_command */ 
+static void internal_done(int host, int errcode)
+{
+    internal_done_errcode = errcode;
+    ++internal_done_flag;
+}
+
+int wd7000fasst_command(unchar target, const void *cmnd, void *buff, int bufflen)
+{
+#ifdef DEBUG
+    int k;
+#endif
+    wd7000fasst_queuecommand(target, cmnd, buff, bufflen, internal_done);
+
+    while (!internal_done_flag);
+    internal_done_flag = 0;
+    DEB(printk("wd7000fasst_command finished: ..leaving with errcode %x\n",
+	internal_done_errcode));
+    DEB(for (k=0;k<5000000;k++) inb(INTR_STAT));
+    return internal_done_errcode;
+}
+
+/* a hack to avoid a strange compilation error */
+
+void wd7000fasst_call_buh()
+{
+    set_intr_gate((intr_chan<=7)?intr_chan+8:intr_chan+0x20,&wd7000fasst_interrupt);
+}
+
+/* return non-zero on detection */
+static const char *wd_bases[] = {(char *)0xce000};
+typedef struct {char * signature;
+		unsigned offset;
+		unsigned length;
+	       }Signature;
+
+static const Signature signatures[] =
+	      {{"SSTBIOS",0xd,0x7}};
+
+#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
+
+int wd7000fasst_detect(int hostnum) /* hostnum ignored for now */
+{
+    int i,j;
+    char const * base_address = 0;
+    /* Store our host number */
+    wd7000fasst_hostno=hostnum;
+    DEB(printk("wd7000fasst_detect: \n"));
+
+    for(i=0;i<(sizeof(wd_bases)/sizeof(char *));i++){
+	for(j=0;j<NUM_SIGNATURES;j++){
+	    if(!memcmp((void *)(wd_bases[i] + signatures[j].offset),
+		(void *) signatures[j].signature,signatures[j].length)){
+		    base_address=wd_bases[i];
+		    printk("WD 7000-FASST detected\n");
+	    }	
+	}
+    }
+    if (!base_address) return 0;
+    wd7000fasst_init();    
+
+    /* Set the Bus on/off-times as not to ruin floppy performens */
+
+    wd7000fasst_stat();
+
+    printk(" *** READ CAPACITY ***\n");
+
+    {   unchar rstat;
+	unchar buf[8];
+	static unchar cmd[] = {	READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	int i;
+	
+	for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
+	for (i = 0; i < 3; ++i){
+	  rstat=0;
+	  while (rstat<2){
+	    if (wd7000fasst_command(i, cmd, buf, sizeof(buf))) rstat++;
+	    else break;
+	  }
+	  if (rstat<2)
+	      printk("wd7000fasst_detect: LU %d sector_size 0x%x device_size 0x%x capacity %d\n",
+		i, xscsi2int(buf+4), xscsi2int(buf), xscsi2int(buf+4)*xscsi2int(buf));
+	}
+    }
+
+    return 1;
+}
+
+int wd7000fasst_abort(int i)
+{
+    printk("wd7000fasst_abort\n");
+    return 0;
+}
+
+int wd7000fasst_reset(void)
+{
+    printk("wd7000fasst_reset called\n");
+    return 0;
+}
+
+__asm__("
+_wd7000fasst_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
+# Please, someone, change this to use the timer
+#	andl $0xfffeffff,_timer_active
+	movl $_wd7000fasst_intr_handle,%edx
+	call *%edx		# ``interesting'' way of handling intr.
+# Free the interrupt only after resetting the host interrupt
+	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
+	pop %fs
+	pop %es
+	pop %ds
+	popl %edx
+	popl %ecx
+	popl %eax
+	iret
+");
diff --git a/kernel/blk_drv/scsi/7000fasst.h b/kernel/blk_drv/scsi/7000fasst.h
new file mode 100644
index 0000000..7411950
--- /dev/null
+++ b/kernel/blk_drv/scsi/7000fasst.h
@@ -0,0 +1,137 @@
+#ifndef _WD7000FASST_H
+
+/* $Id: 7000fasst.h,v 1.1 1992/07/24 06:27:38 root Exp root $
+ *
+ * Header file for the WD 7000-FASST driver for Linux
+ *
+ * $Log: 7000fasst.h,v $
+ * Revision 1.1  1992/07/24  06:27:38  root
+ * Initial revision
+ *
+ * Revision 1.1  1992/07/05  08:32:32  root
+ * Initial revision
+ *
+ * Revision 1.1  1992/05/15  18:38:05  root
+ * Initial revision
+ *
+ * Revision 1.1  1992/04/02  03:23:13  drew
+ * Initial revision
+ *
+ * Revision 1.3  1992/01/27  14:46:29  tthorn
+ * *** empty log message ***
+ *
+ */
+
+#include <linux/types.h>
+
+#undef STATMASK
+#undef CONTROL
+
+#define io_base		0x350
+#define intr_chan	15
+#define dma_chan	6
+#define OGMB_CNT	8
+#define ICMB_CNT	8
+
+/* I/O Port interface 4.2 */
+/* READ */
+#define ASC_STAT io_base
+#define INT_IM	0x80		/* Interrupt Image Flag */
+#define CMD_RDY	0x40		/* Command Port Ready */
+#define CMD_REJ	0x20		/* Command Port Byte Rejected */
+#define ASC_INI	0x10		/* ASC Initialized Flag */
+#define STATMASK 0xf0		/* The lower 4 Bytes are reserved */
+
+/* This register saves two purposes
+ * Diagnostics error
+ * Interrupt Status
+ */
+#define INTR_STAT ASC_STAT+1
+#define ANYINTR	0x80		/* Mailbox Service possible/required */
+#define IMB	0x40		/* 1 Incoming / 0 Outgoing */
+#define MBMASK 0x3f
+/* if MSB is zero, the content of the lower ones keeps Diagnostic State *
+ * 00	Power-on, no diagnostics executed
+ * 01	No diagnostic Error Occured
+ * 02	RAM Failed
+ * 03	FIFO R/W Failed
+ * ...
+*/
+
+/* WRITE */
+#define COMMAND ASC_STAT
+
+#define INTR_ACK ASC_STAT+1
+
+
+#define CONTROL ASC_STAT+2
+#define INT_EN	0x08		/* Interrupt Enable	*/
+#define DMA_EN	0x04		/* DMA Enable		*/
+#define SCSI_RES	0x02	/* SCSI Reset		*/
+#define ASC_RES	0x01		/* ASC Reset		*/
+
+/* The DMA-Controller */
+#define DMA_MODE_REG	0xd6
+#define DMA_MASK_REG	0xd4
+#define S_DMA_MSK	0x04
+#define DMA_CH		0x02
+#define	CASCADE		0xc0
+
+/* Mailbox Definition 5.3 */
+
+/* These belong in scsi.h also */
+#undef any2scsi
+#define any2scsi(up, p)			\
+(up)[0] = (((long)(p)) >> 16);	\
+(up)[1] = ((long)(p)) >> 8;		\
+(up)[2] = ((long)(p));
+
+#define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
+
+#define xany2scsi(up, p)	\
+(up)[0] = ((long)(p)) >> 24;	\
+(up)[1] = ((long)(p)) >> 16;	\
+(up)[2] = ((long)(p)) >> 8;	\
+(up)[3] = ((long)(p));
+
+#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
+		      + (((long)(up)[2]) <<  8) +  ((long)(up)[3]) )
+
+#define MAX_CDB 12
+#define MAX_SENSE 14
+
+struct scb {			/* Command Control Block 5.4.1 */
+  unchar op;			/* Command Control Block Operation Code */
+  unchar idlun;			/* op=0,2:Target Id, op=1:Initiator Id */
+				/* Outbound data transfer, length is checked*/
+				/* Inbound data transfer, length is checked */
+				/* Logical Unit Number */
+  unchar scbdata[12];		/* SCSI Command Block */
+  unchar sretstat;		/* SCSI Return Status */
+  unchar vue;			/* Vendor Unique Error Code */
+  unchar maxdata[3];		/* Maximum Data Transfer Length */
+  unchar dataptr[3];		/* SCSI Data Block Pointer */
+  unchar linkptr[3];		/* Next Command Link Pointer */
+  unchar direc;			/* Transfer Direction */
+  unchar reserved2[6];		/* SCSI Command Descriptor Block */
+				/* REQUEST SENSE */
+};
+
+int wd7000fasst_detect(int);
+int wd7000fasst_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
+int wd7000fasst_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int,int));
+int wd7000fasst_abort(int);
+char *wd7000fasst_info(void);
+int wd7000fasst_reset(void);
+
+#ifndef NULL
+	#define NULL 0
+#endif
+
+#define WD7000FASST {"Western Digital 7000FASST", wd7000fasst_detect,	\
+		wd7000fasst_info, wd7000fasst_command,		\
+		wd7000fasst_queuecommand,		\
+		wd7000fasst_abort,				\
+		wd7000fasst_reset,				\
+		1, 7, 0}
+#endif
diff --git a/kernel/blk_drv/scsi/Makefile b/kernel/blk_drv/scsi/Makefile
index fd978dd..f9d8e57 100644
--- a/kernel/blk_drv/scsi/Makefile
+++ b/kernel/blk_drv/scsi/Makefile
@@ -10,30 +10,28 @@
 
 .c.s:
 	$(CC) $(CFLAGS) $(DEBUG) -S $<
+
 .s.o:
 	$(AS) -c -o $*.o $<
+
 .c.o:
 	$(CC) $(CFLAGS) $(DEBUG) -c $<
 
-LOWLEVELCSRC = aha1542.c seagate.c ultrastor.c 
-LOWLEVELHSRC = aha1542.c seagate.h ultrastor.h
+
+LOWLEVELSSRC = seagate2.s
+LOWLEVELCSRC = aha1542.c fdomain.c seagate.c ultrastor.c 7000fasst.c
+LOWLEVELHSRC = aha1542.h fdomain.h seagate.h ultrastor.h 7000fasst.o
  
-CSRC = hosts.c sd.c st.c scsi.c $(LOWLEVELCSRC)
-HSRC = hosts.h sd.h st.h scsi.h $(LOWLEVELHSRC)
+CSRC = hosts.c sd.c sd_ioctl.c st.c st_ioctl.c scsi.c scsi_ioctl.c $(LOWLEVELCSRC)
+HSRC = hosts.h sd.h st.h scsi.h scsi_ioctl.h $(LOWLEVELHSRC)
 
 OBJS =	scsi.o hosts.o scsi_ioctl.o sd.o sd_ioctl.o st.o st_ioctl.o \
-	aha1542.o seagate.o ultrastor.o
+	aha1542.o fdomain.o seagate.o seagate2.o ultrastor.o 7000fasst.o
 
 all: scsi.a
 
-config.out : config.in $(KERNELHDRS)/linux/config.h
-	rm -f  foo.c
-	ln -s config.in foo.c	
-	$(CPP) foo.c | grep '\.o' > config.out 
-	rm foo.c
-
-figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c config.out
-	$(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
+figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c 
+	$(HOSTCC) -N -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure
 
 max_hosts.h : figure
 	(echo "#ifndef _MAX_HOSTS_H"; \
@@ -46,93 +44,124 @@
 	$(AR) rcs scsi.a $(OBJS)
 	sync
 
-scsi.shar: Makefile scsi.doc $(CSRC) $(HSRC) ../ll_rw_blk.c ../blk.h all.diff
-	(cd ..; shar scsi/scsi.doc scsi/Makefile scsi/*.{c,h} scsi/all.diff blk.h ll_rw_blk.c) > scsi.shar;
-
 clean:
-	rm -f core *.o *.a tmp_make tmp_max figure config.out Makefile.tag max_hosts.h
+	rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h
 
-seagate.s seagate.o : seagate.c ../../../include/linux/config.h \
-  ../../../include/linux/config.dist.h ../../../include/linux/sched.h \
-  ../../../include/linux/head.h ../../../include/linux/fs.h \
-  ../../../include/sys/types.h ../../../include/linux/mm.h \
-  ../../../include/linux/kernel.h ../../../include/signal.h \
-  ../../../include/sys/param.h ../../../include/sys/time.h \
-  ../../../include/time.h ../../../include/sys/resource.h \
-  ../../../include/linux/string.h seagate.h scsi.h hosts.h max_hosts.h 
-	$(CC) -Wall -c seagate.c $(DEBUG) 
+seagate2.o : seagate2.s
+
+seagate.o: seagate.c
+	$(CC) -Wall -c seagate.c 
 
 dep:
+	touch max_hosts.h
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
-	for i in *.c ;do $(CPP) -M $$i;done >> tmp_make
+	for i in *.c;do $(CPP) -M $$i;done >> tmp_make
+	rm max_hosts.h
 	cp tmp_make Makefile
 
 ### Dependencies:
-aha1542.s aha1542.o : aha1542.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
-  ../../../include/linux/head.h ../../../include/linux/string.h ../../../include/asm/system.h \
-  ../../../include/asm/io.h scsi.h hosts.h max_hosts.h aha1542.h 
-hosts.s hosts.o : hosts.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
-  scsi.h hosts.h max_hosts.h aha1542.h seagate.h ultrastor.h 
-scsi.s scsi.o : scsi.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/asm/system.h \
-  ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
-  ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
-  ../../../include/linux/mm.h ../../../include/linux/kernel.h ../../../include/signal.h \
-  ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
-  ../../../include/sys/resource.h ../../../include/linux/timer.h ../../../include/linux/string.h \
-  scsi.h hosts.h max_hosts.h sd.h st.h 
-scsi_ioctl.s scsi_ioctl.o : scsi_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/errno.h \
-  ../../../include/asm/io.h ../../../include/asm/segment.h ../../../include/asm/system.h \
-  ../../../include/linux/kernel.h ../../../include/linux/sched.h ../../../include/linux/head.h \
-  ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
-  ../../../include/limits.h ../../../include/linux/mm.h ../../../include/signal.h \
-  ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
-  ../../../include/sys/resource.h ../../../include/linux/string.h scsi.h hosts.h \
-  max_hosts.h scsi_ioctl.h 
-sd.s sd.o : sd.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/string.h \
-  ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
-  ../../../include/limits.h ../../../include/linux/kernel.h ../../../include/linux/sched.h \
-  ../../../include/linux/head.h ../../../include/linux/mm.h ../../../include/signal.h \
-  ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
-  ../../../include/sys/resource.h scsi.h sd.h ../blk.h 
-sd_ioctl.s sd_ioctl.o : sd_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
-  ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
-  ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
-  ../../../include/linux/mm.h ../../../include/signal.h ../../../include/sys/param.h \
-  ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
-  scsi.h sd.h 
-seagate.s seagate.o : seagate.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/sched.h \
-  ../../../include/linux/head.h ../../../include/linux/fs.h ../../../include/sys/types.h \
-  ../../../include/sys/dirent.h ../../../include/limits.h ../../../include/linux/mm.h \
-  ../../../include/linux/kernel.h ../../../include/signal.h ../../../include/sys/param.h \
-  ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
+7000fasst.o : 7000fasst.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
+  scsi.h hosts.h max_hosts.h 7000fasst.h 
+aha1542.o : aha1542.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
+  scsi.h hosts.h max_hosts.h aha1542.h 
+fdomain.o : fdomain.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/asm/io.h fdomain.h scsi.h hosts.h max_hosts.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/errno.h 
+hosts.o : hosts.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/kernel.h scsi.h hosts.h max_hosts.h aha1542.h /usr/src/linux/include/linux/types.h \
+  fdomain.h seagate.h ultrastor.h 7000fasst.h 
+scsi.o : scsi.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/asm/system.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/string.h scsi.h \
+  hosts.h max_hosts.h sd.h /usr/src/linux/include/linux/genhd.h st.h 
+scsi_ioctl.o : scsi_ioctl.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/kernel.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h scsi.h hosts.h max_hosts.h scsi_ioctl.h 
+sd.o : sd.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/kernel.h \
+  /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h /usr/src/linux/include/linux/string.h \
+  scsi.h sd.h /usr/src/linux/include/linux/genhd.h ../blk.h 
+sd_ioctl.o : sd_ioctl.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/kernel.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h scsi.h sd.h /usr/src/linux/include/linux/genhd.h 
+seagate.o : seagate.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/system.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
   seagate.h scsi.h hosts.h max_hosts.h 
-st.s st.o : st.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h scsi.h \
-  st.h ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
-  ../../../include/limits.h ../../../include/linux/kernel.h ../../../include/linux/sched.h \
-  ../../../include/linux/head.h ../../../include/linux/mm.h ../../../include/signal.h \
-  ../../../include/sys/param.h ../../../include/sys/time.h ../../../include/time.h \
-  ../../../include/sys/resource.h ../blk.h 
-st_ioctl.s st_ioctl.o : st_ioctl.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/linux/kernel.h \
-  ../../../include/linux/sched.h ../../../include/linux/head.h ../../../include/linux/fs.h \
-  ../../../include/sys/types.h ../../../include/sys/dirent.h ../../../include/limits.h \
-  ../../../include/linux/mm.h ../../../include/signal.h ../../../include/sys/param.h \
-  ../../../include/sys/time.h ../../../include/time.h ../../../include/sys/resource.h \
-  st.h scsi.h 
-ultrastor.s ultrastor.o : ultrastor.c ../../../include/linux/config.h ../../../include/linux/config_rel.h \
-  ../../../include/linux/config_ver.h ../../../include/linux/config.dist.h ../../../include/stddef.h \
-  ../../../include/linux/string.h ../../../include/linux/sched.h ../../../include/linux/head.h \
-  ../../../include/linux/fs.h ../../../include/sys/types.h ../../../include/sys/dirent.h \
-  ../../../include/limits.h ../../../include/linux/mm.h ../../../include/linux/kernel.h \
-  ../../../include/signal.h ../../../include/sys/param.h ../../../include/sys/time.h \
-  ../../../include/time.h ../../../include/sys/resource.h ../../../include/linux/hdreg.h \
-  ../../../include/asm/system.h ../../../include/asm/io.h ../../../include/asm/segment.h \
-  ultrastor.h scsi.h hosts.h max_hosts.h 
+st.o : st.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  scsi.h st.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  ../blk.h 
+st_ioctl.o : st_ioctl.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/kernel.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h st.h scsi.h 
+ultrastor.o : ultrastor.c /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/stddef.h /usr/src/linux/include/linux/string.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/system.h ultrastor.h \
+  scsi.h hosts.h max_hosts.h 
diff --git a/kernel/blk_drv/scsi/aha1542.c b/kernel/blk_drv/scsi/aha1542.c
index f09a2f2..a616675 100644
--- a/kernel/blk_drv/scsi/aha1542.c
+++ b/kernel/blk_drv/scsi/aha1542.c
@@ -1,17 +1,17 @@
-/* $Id: aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $
+/* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $
  *  linux/kernel/aha1542.c
  *
- *  (C) 1992  Tommy Thorn
+ *  Copyright (C) 1992  Tommy Thorn
  */
 
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/head.h>
+#include <linux/types.h>
 #include <linux/string.h>
-#include <linux/sched.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
-#include <sys/types.h>
 #include "scsi.h"
 #include "hosts.h"
 
@@ -23,7 +23,7 @@
 #endif
 
 /*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
 */
 
 #define base 0x330
@@ -34,7 +34,9 @@
 
 long WAITtimeout, WAITnexttimeout = 3000000;
 
-void (*do_done)() = NULL;
+void (*do_done)(int, int) = NULL;
+int aha1542_host = 0;
+extern void aha1542_interrupt();
 
 #define aha1542_intr_reset()  outb(IRST, CONTROL)
 #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
@@ -53,9 +55,8 @@
 
 static void aha1542_stat(void)
 {
-    int s = inb(STATUS), i = inb(INTRFLAGS);
-/*  printk("status = %x, intrflags = %x served %d last %x timeout %d\n", s, i, intr_flag, intr_last, WAITtimeout); */
-    printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout);
+/*    int s = inb(STATUS), i = inb(INTRFLAGS);
+  printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
 }
 
 static int aha1542_out(unchar *cmdp, int len)
@@ -192,15 +193,14 @@
 }
 
 /* A "high" level interrupt handler */
-static void aha1542_interrupt(int cpl)
+void aha1542_intr_handle(void)
 {
-    int flag = inb(INTRFLAGS);
-    void (*my_done)() = do_done;
+    void (*my_done)(int, int) = do_done;
     int errstatus;
 
     do_done = NULL;
 #ifdef DEBUG
-    printk("aha1542_interrupt: ");
+    printk("aha1542_intr_handle: ");
     if (!(flag&ANYINTR)) printk("no interrupt?");
     if (flag&MBIF) printk("MBIF ");
     if (flag&MBOA) printk("MBOF ");
@@ -212,15 +212,15 @@
 #endif
     aha1542_intr_reset();
     if (!my_done) {
-	printk("aha1542_interrupt: Unexpected interrupt\n");
+	printk("aha1542_intr_handle: Unexpected interrupt\n");
 	return;
     }
 
     /* is there mail :-) */
 	
     if (!mb[1].status) {
-	DEB(printk("aha1542_interrupt: strange: mbif but no mail!\n"));
-	my_done(DID_TIME_OUT << 16);
+	DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
+	my_done(aha1542_host, DID_TIME_OUT << 16);
 	return;
     }
 
@@ -235,29 +235,29 @@
 
     if (ccb.tarstat == 2) {
 	int i;
-	DEB(printk("aha1542_interrupt: sense:"));
+	DEB(printk("aha1542_intr_handle: sense:"));
 	for (i = 0; i < 12; i++)
 	  printk("%02x ", ccb.cdb[ccb.cdblen+i]);
 	printk("\n");
 /*
-	DEB(printk("aha1542_interrupt: buf:"));
+	DEB(printk("aha1542_intr_handle: 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);
+    DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
+    my_done(aha1542_host, errstatus);
     return;
 }
 
-int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int))
+int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
 {
     unchar ahacmd = CMD_START_SCSI;
-    int i;
     unchar *cmd = (unchar *) cmnd;
+    DEB(int i);
 
-    DEB(if (target > 1) {done(DID_TIME_OUT << 16); return 0;});
+    DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
     
 #ifdef DEBUG
     if (*cmd == READ_10 || *cmd == WRITE_10)
@@ -317,7 +317,7 @@
 
 volatile static int internal_done_flag = 0;
 volatile static int internal_done_errcode = 0;
-static void internal_done(int errcode)
+static void internal_done(int host, int errcode)
 {
     internal_done_errcode = errcode;
     ++internal_done_flag;
@@ -355,18 +355,11 @@
 
 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);
+    set_intr_gate(0x2b,&aha1542_interrupt);
 }
 
 /* return non-zero on detection */
-int aha1542_detect(int hostnum) /* hostnum ignored for now */
+int aha1542_detect(int hostnum)
 {
     int i;
 
@@ -441,6 +434,7 @@
 	  aha1542_command(0, cmd, buffer, 512);
       }
 #endif
+    aha1542_host = hostnum;
     return 1;
 }
 
@@ -455,3 +449,35 @@
     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
+");
diff --git a/kernel/blk_drv/scsi/aha1542.h b/kernel/blk_drv/scsi/aha1542.h
index 47848d8..5d3640f 100644
--- a/kernel/blk_drv/scsi/aha1542.h
+++ b/kernel/blk_drv/scsi/aha1542.h
@@ -1,10 +1,25 @@
 #ifndef _AHA1542_H
 
-/* $Id: aha1542.h,v 1.1 1992/04/24 18:01:50 root Exp root $
+/* $Id: aha1542.h,v 1.1 1992/07/24 06:27:38 root Exp root $
  *
  * Header file for the adaptec 1542 driver for Linux
  *
  * $Log: aha1542.h,v $
+ * Revision 1.1  1992/07/24  06:27:38  root
+ * Initial revision
+ *
+ * Revision 1.2  1992/07/04  18:41:49  root
+ * Replaced distribution with current drivers
+ *
+ * Revision 1.3  1992/06/23  23:58:20  root
+ * Fixes.
+ *
+ * Revision 1.2  1992/05/26  22:13:23  root
+ * Changed bug that prevented DMA above first 2 mbytes.
+ *
+ * Revision 1.1  1992/05/22  21:00:29  root
+ * Initial revision
+ *
  * Revision 1.1  1992/04/24  18:01:50  root
  * Initial revision
  *
@@ -16,6 +31,8 @@
  *
  */
 
+#include <linux/types.h>
+
 /* I/O Port interface 4.2 */
 /* READ */
 #define STATUS base
@@ -64,10 +81,10 @@
 };
 
 /* These belong in scsi.h also */
-#define any2scsi(up, p)			\
-(up)[0] = (((long)(p)) >> 16) & 0xff;	\
-(up)[1] = ((long)(p)) >> 8;		\
-(up)[2] = ((long)(p));
+#define any2scsi(up, p)				\
+(up)[0] = (((unsigned long)(p)) >> 16)  ;	\
+(up)[1] = (((unsigned long)(p)) >> 8);		\
+(up)[2] = ((unsigned long)(p));
 
 #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
 
@@ -104,7 +121,7 @@
 
 int aha1542_detect(int);
 int aha1542_command(unsigned char target, const void *cmnd, void *buff, int bufflen);
-/*int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int));*/
+int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int));
 int aha1542_abort(int);
 char *aha1542_info(void);
 int aha1542_reset(void);
@@ -115,8 +132,8 @@
 
 #define AHA1542 {"Adaptec 1542", aha1542_detect,	\
 		aha1542_info, aha1542_command,		\
-		/*aha1542_queuecommand*/ NULL,		\
+		aha1542_queuecommand,			\
 		aha1542_abort,				\
 		aha1542_reset,				\
-		0, 7, 0}
+		1, 7, 0}
 #endif
diff --git a/kernel/blk_drv/scsi/config.out b/kernel/blk_drv/scsi/config.out
new file mode 100644
index 0000000..83ce57d
--- /dev/null
+++ b/kernel/blk_drv/scsi/config.out
@@ -0,0 +1,10 @@
+scsi.o
+hosts.o
+scsi_ioctl.o
+sd.o
+sd_ioctl.o
+st.o
+st_ioctl.o
+aha1542.o
+seagate.o
+ultrastor.o
diff --git a/kernel/blk_drv/scsi/fdomain.c b/kernel/blk_drv/scsi/fdomain.c
new file mode 100644
index 0000000..ae05651
--- /dev/null
+++ b/kernel/blk_drv/scsi/fdomain.c
@@ -0,0 +1,1234 @@
+/* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver
+ * Created: Sun May  3 18:53:19 1992
+ * Revised: Tue Jul 28 19:45:25 1992 by root
+ * Author: Rickard E. Faith, faith@cs.unc.edu
+ * Copyright 1992 Rickard E. Faith
+ *
+ * $Log$
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+
+ * WARNING: THIS IS A BETA VERSION!
+ *          USE AT YOUR OWN RISK!
+ *          BACKUP YOUR SYSTEM BEFORE USING!
+
+ * I would like to thank Maxtor, whose *free* 206 page manual on the LXT
+ * drives was very helpful: "LXT SCSI Products: Specifications and OEM
+ * Technical Manual (Revision B/September 1991)"
+
+ * I wish that I could thank Future Domain for the necessary documentation,
+ * but I can't.  I used the $25 "TMC-1800 SCSI Chip Specification" document
+ * (FDC-1800T), which documents the *chip* and not the board.  Without it,
+ * I would have been totally lost, but it would have been nice to have some
+ * example source.  (The DOS BIOS source cost $250 and the UN*X driver
+ * source was $750 [both required a non-disclosure agreement].  Ever wonder
+ * why there are no freely available Future Domain drivers?)
+
+ * Thanks to Todd Carrico (todd@wutc.wustl.edu), Dan Poirier
+ * (poirier@cs.unc.edu ), Ken Corey (kenc@sol.acs.unt.edu), and C. de Bruin
+ * (bruin@dutiba.tudelft.nl) for alpha testing.  Also thanks to Drew
+ * Eckhardt (drew@cs.colorado.edu) for answering questions. */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SCSI_FUTURE_DOMAIN
+
+#include <linux/sched.h>
+#include <asm/io.h>
+#include "fdomain.h"
+#include "scsi.h"
+#include "hosts.h"
+#if QUEUE
+#include <asm/system.h>
+#include <linux/errno.h>
+#endif
+
+#define VERSION          "1.9"	/* Change with each revision */
+#define DEBUG            1	/* Enable debugging output */
+#define SEND_IDENTIFY    0	/* Send IDENTIFY message -- DOESN'T WORK! */
+#define USE_FIFO         1	/* Use the FIFO buffer for I/O */
+#define FAST_SYNCH       1	/* Enable Fast Synchronous */
+#define ALLOW_ALL_IRQ    0	/* Allow all IRQ's -- NOT RECOMMENDED */
+#define NEW_IRQ          1	/* Enable new IRQ handling */
+#define DECREASE_IL      1	/* Try to decrease interrupt latency */
+
+#if DEBUG
+#define EVERY_ACCESS     0	/* Write a line on every scsi access */
+#define ERRORS_ONLY      1	/* Only write a line if there is an error */
+#define DEBUG_DETECT     0	/* Debug fdomain_16x0_detect() */
+#else
+#define EVERY_ACCESS     0	/* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
+#define ERRORS_ONLY      0
+#define DEBUG_DETECT     0
+#endif
+
+/* Errors are reported on the line, so we don't need to report them again */
+#if EVERY_ACCESS
+#undef ERRORS_ONLY
+#define ERRORS_ONLY      0
+#endif
+
+static int               port_base = 0;
+static void              *bios_base = NULL;
+static int               interrupt_level = 0;
+static volatile int      aborted = 0;
+
+static int               Data_Mode_Cntl_port;
+static int               FIFO_Data_Count_port;
+static int               Interrupt_Cntl_port;
+static int               Read_FIFO_port;
+static int               Read_SCSI_Data_port;
+static int               SCSI_Cntl_port;
+static int               SCSI_Status_port;
+static int               TMC_Cntl_port;
+static int               TMC_Status_port;
+static int               Write_FIFO_port;
+static int               Write_SCSI_Data_port;
+
+#if QUEUE
+static unsigned char     current_target = 0;
+static unsigned char     current_cmnd[10] = { 0, };
+static void              *current_buff = NULL;
+static int               current_bufflen = 0;
+static void              (*current_done)(int,int) = NULL;
+
+volatile static int      in_command = 0;
+volatile static int      current_phase;
+static int               this_host = 0;
+
+enum { in_arbitration, in_selection, in_other };
+
+#if NEW_IRQ
+extern void              fdomain_16x0_intr( int unused );
+#else
+extern void              fdomain_16x0_interrupt();
+#endif
+
+static const char        *cmd_pt;
+static const char        *the_command;
+static unsigned char     *out_buf_pt;
+static unsigned char     *in_buf_pt;
+volatile static int      Status;
+volatile static int      Message;
+volatile static unsigned data_sent;
+volatile static int      have_data_in;
+
+volatile static int      in_interrupt_code = 0;
+
+#endif
+
+
+enum in_port_type { Read_SCSI_Data = 0, SCSI_Status = 1, TMC_Status = 2,
+			  LSB_ID_Code = 5, MSB_ID_Code = 6, Read_Loopback = 7,
+			  SCSI_Data_NoACK = 8, Option_Select = 10,
+			  Read_FIFO = 12, FIFO_Data_Count = 14 };
+
+enum out_port_type { Write_SCSI_Data = 0, SCSI_Cntl = 1, Interrupt_Cntl = 2,
+			   Data_Mode_Cntl = 3, TMC_Cntl = 4, Write_Loopback = 7,
+			   Write_FIFO = 12 };
+
+static void *addresses[] = {
+   (void *)0xc8000,
+   (void *)0xca000,
+   (void *)0xce000,
+   (void *)0xde000 };
+#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
+		       
+static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
+#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
+
+static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
+
+/*
+
+  READ THIS BEFORE YOU ADD A SIGNATURE!
+
+  READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME!
+
+  READ EVERY WORD, ESPECIALLY THE WORD *NOT*
+
+  This driver works *ONLY* for Future Domain cards using the
+  TMC-1600 chip.  This includes models TMC-1660 and TMC-1680
+  *ONLY*.
+
+  The following is a BIOS signature for a TMC-950 board, which
+  looks like it is a 16 bit board (based on card edge), but
+  which only uses the extra lines for IRQ's (not for data):
+
+  FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
+
+  THIS WILL *NOT* WORK WITH THIS DRIVER!
+
+  Here is another BIOS signature for yet another Future
+  Domain board WHICH WILL *NOT* WORK WITH THIS DRIVER:
+
+  FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
+
+  Here is another BIOS signature for the TMC-88x series:
+
+  FUTURE DOMAIN COPR. (C) 1986-1989 V6.0A7/28/90
+
+  THIS WILL *NOT* WORK WITH THIS DRIVER, but it *WILL*
+  work with the *SEAGATE* ST-01/ST-02 driver.
+
+  */
+
+struct signature {
+   char *signature;
+   int  sig_offset;
+   int  sig_length;
+} signatures[] = {
+   { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0 7/28/89", 5, 50 },
+   { "FUTURE DOMAIN CORP. (C) 1986-1990 1800", 5, 37 },
+   /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGANTURE */
+};
+
+#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+
+
+/* These functions are based on include/asm/io.h */
+
+#if 1
+static unsigned short inline inw( unsigned short port )
+{
+   unsigned short _v;
+   
+   __asm__ volatile ("inw %1,%0"
+		     :"=a" (_v):"d" ((unsigned short) port));
+   return _v;
+}
+
+static void inline outw( unsigned short value, unsigned short port )
+{
+   __asm__ volatile ("outw %0,%1"
+		     ::"a" ((unsigned short) value),
+		     "d" ((unsigned short) port));
+}
+#else
+
+#define inw( port ) \
+      ({ unsigned short _v; \
+	       __asm__ volatile ("inw %1,%0" \
+				: "=a" (_v) : "d" ((unsigned short) port)); \
+				      _v; })
+
+#define outw( value ) \
+      __asm__ volatile \
+      ("outw %0,%1" : : "a" ((unsigned short) value), \
+       "d" ((unsigned short) port))
+#endif
+
+
+/* These defines are copied from kernel/blk_drv/hd.c */
+
+#define insw( buf, count, port ) \
+      __asm__ volatile \
+      ( "cld;rep;insw"::"d" (port),"D" (buf),"c" (count):"cx","di" )
+
+#define outsw( buf, count, port) \
+      __asm__ volatile \
+      ("cld;rep;outsw"::"d" (port),"S" (buf),"c" (count):"cx","si")
+
+
+static void do_pause( unsigned amount )	/* Pause for amount*10 milliseconds */
+{
+   unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
+
+   while (jiffies < the_time);
+}
+
+static void inline fdomain_make_bus_idle( void )
+{
+   outb( 0, SCSI_Cntl_port );
+   outb( 0, Data_Mode_Cntl_port );
+   outb( 1, TMC_Cntl_port );
+}
+
+static int fdomain_is_valid_port( int port )
+{
+   int options;
+
+#if DEBUG_DETECT 
+   printk( " (%x%x),",
+	  inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
+#endif
+
+   /* The MCA ID is a unique id for each MCA compatible board.  We
+      are using ISA boards, but Future Domain provides the MCA ID
+      anyway.  We can use this ID to ensure that this is a Future
+      Domain TMC-1660/TMC-1680.
+    */
+
+   if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
+      if (inb( port + LSB_ID_Code ) != 0x27) return 0;
+      if (inb( port + MSB_ID_Code ) != 0x61) return 0;
+   } else {			            /* test for 0xe960 id */
+      if (inb( port + MSB_ID_Code ) != 0x60) return 0;
+   }
+
+   /* We have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board.
+      Now, check to be sure the bios_base matches these ports.
+      If someone was unlucky enough to have purchased more than one
+      Future Domain board, then they will have to modify this code, as
+      we only detect one board here.  [The one with the lowest bios_base].
+    */
+
+   options = inb( port + Option_Select );
+
+#if DEBUG_DETECT
+   printk( " Options = %x,", options );
+#endif
+
+   if (addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
+   interrupt_level = ints[ (options & 0x0e) >> 1 ];
+
+   return 1;
+}
+
+static int fdomain_test_loopback( void )
+{
+   int i;
+   int result;
+
+   for (i = 0; i < 255; i++) {
+      outb( i, port_base + Write_Loopback );
+      result = inb( port_base + Read_Loopback );
+      if (i != result) return 1;
+   }
+   return 0;
+}
+
+#if !NEW_IRQ
+static void fdomain_enable_interrupt( void )
+{
+   if (!interrupt_level) return;
+
+#if ALLOW_ALL_IRQ
+   if (interrupt_level < 8) {
+      outb( inb_p( 0x21 ) & ~(1 << interrupt_level), 0x21 );
+   } else
+#endif
+	 {
+	    outb( inb_p( 0xa1 ) & ~(1 << (interrupt_level - 8)), 0xa1 );
+	 }
+}
+
+static void fdomain_disable_interrupt( void )
+{
+   if (!interrupt_level) return;
+
+#if ALLOW_ALL_IRQ
+   if (interrupt_level < 8) {
+      outb( inb_p( 0x21 ) | (1 << interrupt_level), 0x21 );
+   } else
+#endif
+	 {
+	    outb( inb_p( 0xa1 ) | (1 << (interrupt_level - 8)), 0xa1 );
+	 }
+}
+#endif
+
+int fdomain_16x0_detect( int hostnum )
+{
+   int           i, j;
+   int           flag;
+   unsigned char do_inquiry[] =       { 0x12, 0, 0, 0, 255, 0 };
+   unsigned char do_request_sense[] = { 0x03, 0, 0, 0, 255, 0 };
+   unsigned char do_read_capacity[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+   unsigned char buf[256];
+   unsigned      retcode;
+
+#if DEBUG_DETECT
+   printk( "SCSI: fdomain_16x0_detect()," );
+#endif
+
+   for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
+#if DEBUG_DETECT
+      printk( " %x(%x),", (unsigned)addresses[i], (unsigned)bios_base );
+#endif
+      for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
+	 if (!memcmp( ((char *)addresses[i] + signatures[j].sig_offset),
+		    signatures[j].signature, signatures[j].sig_length )) {
+	    bios_base = addresses[i];
+	 }
+      }
+   }
+
+   if (!bios_base) {
+#if DEBUG_DETECT
+      printk( " FAILED: NO BIOS\n" );
+#endif
+      return 0;
+   }
+
+   /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
+      Assuming the ROM is enabled (otherwise we wouldn't have been
+      able to read the ROM signature :-), then the ROM set up the
+      RAM area with some magic numbers, such as a list of port
+      base addresses and a list of the disk "geometry" reported to
+      DOS (this geometry has nothing to do with physical geometry).
+    */
+
+   port_base = *((char *)bios_base + 0x1fcc)
+	 + (*((char *)bios_base + 0x1fcd) << 8);
+   
+#if DEBUG_DETECT
+   printk( " %x,", port_base );
+#endif
+
+   for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
+      if (port_base == ports[i]) ++flag;
+   }
+
+   if (flag) flag = fdomain_is_valid_port( port_base );
+
+   if (!flag) {			/* Cannot get port base from BIOS RAM */
+      
+      /* This is a bad sign.  It usually means that someone patched the
+	 BIOS signature list (the signatures variable) to contain a BIOS
+	 signature for a board *OTHER THAN* the TMC-1660/TMC-1680.
+       */
+      
+#if DEBUG_DETECT
+      printk( " RAM FAILED, " );
+#endif
+      /* Anyway, the alternative to finding the address in the RAM is
+	 to just search through every possible port address for one
+	 that is attached to the Future Domain card.  Don't panic,
+	 though, about reading all these random port addresses--there
+	 are rumors that the Future Domain BIOS does something very
+	 similar.
+       */
+
+      for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
+	 port_base = ports[i];
+#if DEBUG_DETECT
+	 printk( " %x,", port_base );
+#endif
+	 flag = fdomain_is_valid_port( port_base );
+      }
+   }
+
+   if (!flag) {
+#if DEBUG_DETECT
+      printk( " FAILED: NO PORT\n" );
+#endif
+      return 0;		/* Cannot find valid set of ports */
+   }
+
+#if DEBUG_DETECT
+   printk( "\n" );
+   printk( "SCSI: bios_base = %x, port_base = %x, interrupt_level = %d\n",
+	  (unsigned)bios_base, port_base, interrupt_level );
+#endif
+
+   if (interrupt_level) {
+      printk( "Future Domain BIOS at %x; port base at %x; using IRQ %d\n",
+	     (unsigned)bios_base, port_base, interrupt_level );
+   } else {
+      printk( "Future Domain BIOS at %x; port base at %x; *NO* IRQ\n",
+	     (unsigned)bios_base, port_base );
+   }
+   
+   Data_Mode_Cntl_port  = port_base + Data_Mode_Cntl;
+   FIFO_Data_Count_port = port_base + FIFO_Data_Count;
+   Interrupt_Cntl_port  = port_base + Interrupt_Cntl;
+   Read_FIFO_port       = port_base + Read_FIFO;
+   Read_SCSI_Data_port  = port_base + Read_SCSI_Data;
+   SCSI_Cntl_port       = port_base + SCSI_Cntl;
+   SCSI_Status_port     = port_base + SCSI_Status;
+   TMC_Cntl_port        = port_base + TMC_Cntl;
+   TMC_Status_port      = port_base + TMC_Status;
+   Write_FIFO_port      = port_base + Write_FIFO;
+   Write_SCSI_Data_port = port_base + Write_SCSI_Data;
+
+   fdomain_16x0_reset();
+
+   if (fdomain_test_loopback()) {
+#if DEBUG_DETECT
+      printk( "SCSI: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
+#endif
+      return 0;
+   }
+
+   /* These routines are here because of the way the SCSI bus behaves
+      after a reset.  This appropriate behavior was not handled correctly
+      by the higher level SCSI routines when I first wrote this driver.
+    */
+   
+   printk( "Future Domain detection routine scanning for devices:\n" );
+   for (i = 0; i < 8; i++) {
+      if (i == 6) continue;	/* The host adapter is at SCSI ID 6 */
+      retcode = fdomain_16x0_command( i, do_request_sense, buf, 255 );
+      if (!retcode) {
+	 retcode = fdomain_16x0_command( i, do_inquiry, buf, 255 );
+	 if (!retcode) {
+	    printk( "     SCSI ID %d: ", i );
+	    for (j = 8; j < 32; j++) printk( "%c", buf[j] );
+	    retcode = fdomain_16x0_command( i, do_read_capacity, buf, 255 );
+	    if (!retcode) {
+	       unsigned long blocks, size, capacity;
+	       
+	       blocks = (buf[0] << 24) | (buf[1] << 16)
+		     | (buf[2] << 8) | buf[3];
+	       size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+	       capacity = +(blocks * size * 10) / +(1024L * 1024L);
+
+	       printk( "%lu MB (%lu byte blocks)",
+		      ((capacity + 5L) / 10L), size );
+	    }
+	    printk ("\n" );
+	 }
+      }
+   }
+
+#if QUEUE
+#if !ALLOW_ALL_IRQ
+   if (interrupt_level < 8) {
+      printk( "Future Domain: WILL NOT USE IRQ LESS THAN 8 FOR QUEUEING!\n" );
+      scsi_hosts[hostnum].can_queue = 0;
+   } else
+#endif
+#if NEW_IRQ
+	 {
+	    int              retcode;
+	    struct sigaction sa;
+
+	    this_host      = hostnum;
+
+	    sa.sa_handler  = fdomain_16x0_intr;
+	    sa.sa_flags    = SA_INTERRUPT;
+	    sa.sa_mask     = 0;
+	    sa.sa_restorer = NULL;
+
+	    retcode = irqaction( interrupt_level, &sa );
+
+	    if (retcode < 0) {
+	       if (retcode == -EINVAL) {
+		  printk( "Future Domain: IRQ %d is bad!\n", interrupt_level );
+		  printk( "       This shouldn't happen: REPORT TO RIK!\n" );
+	       } else if (retcode == -EBUSY) {
+		  printk( "Future Domain: IRQ %d is already in use!\n",
+			 interrupt_level );
+		  printk( "       Please use another IRQ for the FD card!\n" );
+	       } else {
+		  printk( "Future Domain: Error getting IRQ %d\n",
+			 interrupt_level );
+		  printk( "       This shouldn't happen: REPORT TO RIK!\n" );
+	       }
+	       printk( "       IRQs WILL NOT BE USED!\n" );
+	       
+	       scsi_hosts[this_host].can_queue = 0;
+	    } else {
+	       printk( "Future Domain: IRQ %d selected with retcode = %d\n",
+		       interrupt_level, retcode );
+	    }
+	 }
+#else
+	 {
+	    this_host = hostnum;
+	    set_intr_gate( 0x20 + interrupt_level, &fdomain_16x0_interrupt );
+	    fdomain_enable_interrupt();
+	 }
+#endif
+#endif
+
+   return 1;
+}
+
+char *fdomain_16x0_info(void)
+{
+   static char buffer[] =
+	 "Future Domain TMC-1660/TMC-1680 SCSI driver version "
+	       VERSION
+		     "\n";
+   return buffer;
+}
+
+static int fdomain_arbitrate( void )
+{
+   int           status = 0;
+   unsigned long timeout;
+
+#if VERBOSE
+   printk( "SCSI: fdomain_arbitrate()\n" );
+#endif
+   
+   outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
+   outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
+   outb( 0x04, TMC_Cntl_port );	              /* Start arbitration */
+
+   timeout = jiffies + 50;	              /* 500 mS */
+   while (jiffies < timeout) {
+      status = inb( TMC_Status_port );        /* Read adapter status */
+      if (status & 0x02) return 0;            /* Arbitration complete */
+   }
+
+   /* Make bus idle */
+   fdomain_make_bus_idle();
+
+#if EVERY_ACCESS
+   printk( "Arbitration failed, status = %x\n", status );
+#endif
+#if ERRORS_ONLY
+   printk( "SCSI: Arbitration failed, status = %x", status );
+#endif
+   return 1;
+}
+
+static int fdomain_select( int target )
+{
+   int           status;
+   unsigned long timeout;
+
+   outb( 0x80, SCSI_Cntl_port );	/* Bus Enable */
+   outb( 0x8a, SCSI_Cntl_port );	/* Bus Enable + Attention + Select */
+
+   /* Send our address OR'd with target address */
+#if SEND_IDENTIFY
+   outb( 0x40 | (1 << target), port_base + SCSI_Data_NoACK );
+#else
+   outb( (1 << target), port_base + SCSI_Data_NoACK );
+#endif
+
+    /* Stop arbitration (also set FIFO for output and enable parity) */
+   outb( 0xc8, TMC_Cntl_port ); 
+
+   timeout = jiffies + 25;	        /* 250mS */
+   while (jiffies < timeout) {
+      status = inb( SCSI_Status_port ); /* Read adapter status */
+      if (status & 1) {		        /* Busy asserted */
+	 /* Enable SCSI Bus (on error, should make bus idle with 0) */
+#if SEND_IDENTIFY
+	 /* Also, set ATN so that the drive will make a MESSAGE OUT phase */
+	 outb( 0x88, SCSI_Cntl_port );
+#else
+	 outb( 0x80, SCSI_Cntl_port );
+#endif
+	 return 0;
+      }
+   }
+   /* Make bus idle */
+   fdomain_make_bus_idle();
+#if EVERY_ACCESS
+   if (!target) printk( "Select failed\n" );
+#endif
+#if ERRORS_ONLY
+   if (!target) printk( "SCSI: Select failed" );
+#endif
+   return 1;
+}
+
+#if QUEUE
+
+#if !USE_FIFO
+#pragma error QUEUE requires USE_FIFO
+#endif
+
+void my_done( int error )
+{
+   if (in_command) {
+      in_command = 0;
+      in_interrupt_code = 0;
+      outb( 0x00, Interrupt_Cntl_port );
+      fdomain_make_bus_idle();
+      if (current_done) current_done( this_host, error );
+      else panic( "SCSI (Future Domain): current_done() == NULL" );
+   } else {
+      panic( "SCSI (Future Domain): my_done() called outside of command\n" );
+   }
+}
+
+#if NEW_IRQ
+void fdomain_16x0_intr( int unused )
+#else
+void fdomain_16x0_intr( void )
+#endif
+{
+   int      status;
+   int      done = 0;
+   unsigned data_count;
+
+#if NEW_IRQ
+   sti();
+#endif
+
+   if (in_interrupt_code)
+	 panic( "SCSI (Future Domain): fdomain_16x0_intr() NOT REENTRANT!\n" );
+   else
+	 ++in_interrupt_code;
+   
+   outb( 0x00, Interrupt_Cntl_port );
+
+#if EVERY_ACCESS
+   printk( "aborted = %d, ", aborted );
+#endif
+
+   if (aborted) {
+      /* Force retry for timeouts after selection complete */
+      if (current_phase == in_other)
+	    my_done( DID_BUS_BUSY << 16 );
+      else
+	    my_done( aborted << 16 );
+#if NEW_IRQ && !DECREASE_IL
+      cli();
+#endif
+      return;
+   }
+
+   /* We usually have one spurious interrupt after each command.  Ignore it. */
+   if (!in_command) {		/* Spurious interrupt */
+      in_interrupt_code = 0;
+#if NEW_IRQ && !DECREASE_IL
+      cli();
+#endif
+      return;
+   }
+   
+   if (current_phase == in_arbitration) {
+      status = inb( TMC_Status_port );        /* Read adapter status */
+      if (!(status & 0x02)) {
+#if EVERY_ACCESS
+	 printk( " AFAIL " );
+#endif
+	 my_done( DID_TIME_OUT << 16 );
+#if NEW_IRQ && !DECREASE_IL
+	 cli();
+#endif
+	 return;
+      }
+      current_phase = in_selection;
+
+      outb( 0x80, SCSI_Cntl_port );	/* Bus Enable */
+      outb( 0x8a, SCSI_Cntl_port );	/* Bus Enable + Attention + Select */
+      
+      outb( (1 << current_target), port_base + SCSI_Data_NoACK );
+
+      outb( 0x40, Interrupt_Cntl_port );
+      /* Stop arbitration (also set FIFO for output and enable parity) */
+      in_interrupt_code = 0;
+      outb( 0xd8, TMC_Cntl_port );
+#if NEW_IRQ && !DECREASE_IL
+      cli();
+#endif
+      return;
+   } else if (current_phase == in_selection) {
+      status = inb( SCSI_Status_port );
+      if (!(status & 0x01)) {
+#if EVERY_ACCESS
+	 printk( " SFAIL " );
+#endif
+	 my_done( DID_NO_CONNECT << 16 );
+#if NEW_IRQ && !DECREASE_IL
+	 cli();
+#endif
+	 return;
+      }
+      current_phase = in_other;
+#if FAST_SYNCH
+      outb( 0xc0, Data_Mode_Cntl_port );
+#endif
+      in_interrupt_code = 0;
+      outb( 0x90, Interrupt_Cntl_port );
+      outb( 0x80, SCSI_Cntl_port );
+#if NEW_IRQ && !DECREASE_IL
+      cli();
+#endif
+      return;
+   }
+
+   /* current_phase == in_other: this is the body of the routine */
+
+   switch ((unsigned char)*the_command) {
+   case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
+   case 0x2e: case 0x3b: case 0xea: case 0x3f:
+      data_count = 0x2000 - inw( FIFO_Data_Count_port );
+      if (current_bufflen - data_sent < data_count)
+	    data_count = current_bufflen - data_sent;
+      if (data_count > 0) {
+/* 	 if (data_count > 512) data_count = 512; */
+#if EVERY_ACCESS
+	 printk( "%d OUT, ", data_count );
+#endif
+	 if (data_count == 1) {
+	    outb( *out_buf_pt++, Write_FIFO_port );
+	    ++data_sent;
+	 } else {
+	    data_count >>= 1;
+	    outsw( out_buf_pt, data_count, Write_FIFO_port );
+	    out_buf_pt += 2 * data_count;
+	    data_sent += 2 * data_count;
+	 }
+      }
+      break;
+   default:
+      if (!have_data_in) {
+	 outb( 0x98, TMC_Cntl_port );
+	 ++have_data_in;
+      } else {
+	 data_count = inw( FIFO_Data_Count_port );
+/* 	 if (data_count > 512) data_count = 512; */
+	 if (data_count) {
+#if EVERY_ACCESS
+	    printk( "%d IN, ", data_count );
+#endif
+	    if (data_count == 1) {
+	       *in_buf_pt++ = inb( Read_FIFO_port );
+	    } else {
+	       data_count >>= 1; /* Number of words */
+	       insw( in_buf_pt, data_count, Read_FIFO_port );
+	       in_buf_pt += 2 * data_count;
+	    }
+	 }
+      }
+      break;
+   }
+
+   status = inb( SCSI_Status_port );
+
+   if (status & 0x10) {	/* REQ */
+      
+      switch (status & 0x0e) {
+      case 0x08:		/* COMMAND OUT */
+	 outb( *cmd_pt++, Write_SCSI_Data_port );
+#if EVERY_ACCESS
+	 printk( "CMD = %x,", (unsigned char)cmd_pt[-1] );
+#endif
+	 break;
+      case 0x0c:		/* STATUS IN */
+	 Status = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+	 printk( "Status = %x, ", Status );
+#endif
+#if ERRORS_ONLY
+	 if (Status) {
+	    printk( "SCSI: target = %d, command = %x, Status = %x\n",
+		   current_target, (unsigned char)*the_command, Status );
+	 }
+#endif
+	 break;
+      case 0x0a:		/* MESSAGE OUT */
+#if SEND_IDENTIFY
+	 /* On the first request, send an Identify message */
+	 if (!sent_identify) {
+	    outb( 0x80, SCSI_Cntl_port );          /* Lower ATN */
+	    outb( 0x80, Write_SCSI_Data_port );    /* Identify */
+	    ++sent_identify;
+	 } else
+#else
+	       outb( 0x07, Write_SCSI_Data_port ); /* Reject */
+#endif
+	 break;
+      case 0x0e:		/* MESSAGE IN */
+	 Message = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+	 printk( "Message = %x, ", Message );
+#endif
+	 if (!Message) ++done;
+	 break;
+      }
+   }
+
+   if (done) {
+#if EVERY_ACCESS
+      printk( " ** IN DONE ** " );
+#endif
+
+      if (have_data_in) {
+	 while (data_count = inw( FIFO_Data_Count_port )) {
+	    if (data_count == 1) {
+	       *in_buf_pt++ = inb( Read_FIFO_port );
+	    } else {
+	       data_count >>= 1; /* Number of words */
+	       insw( in_buf_pt, data_count, Read_FIFO_port );
+	       in_buf_pt += 2 * data_count;
+	    }
+	 }
+      }
+#if EVERY_ACCESS
+      printk( "AFTER DATA GET\n" );
+#endif
+      
+#if ERRORS_ONLY
+      if (*the_command == REQUEST_SENSE && !Status) {
+	 if ((unsigned char)(*((char *)current_buff + 2)) & 0x0f) {
+	    printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
+		   (unsigned char)(*((char *)current_buff + 2)) & 0x0f,
+		   (unsigned char)(*((char *)current_buff + 12)) );
+	 }
+      }
+#endif
+#if EVERY_ACCESS
+      printk( "BEFORE MY_DONE\n" );
+#endif
+      my_done( (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );
+   } else {
+      in_interrupt_code = 0;
+      outb( 0x90, Interrupt_Cntl_port );
+   }
+
+#if NEW_IRQ && !DECREASE_IL
+   cli();
+#endif
+   return;
+}
+
+int fdomain_16x0_queue( unsigned char target, const void *cmnd,
+			 void *buff, int bufflen, void (*done)(int,int) )
+{
+   if (in_command) {
+      panic( "SCSI (Future Domain): fdomain_16x0_queue() NOT REENTRANT!\n" );
+   }
+#if EVERY_ACCESS
+   printk( "queue %d %x\n", target, *(unsigned char *)cmnd );
+#endif
+
+   fdomain_make_bus_idle();
+
+   aborted         = 0;
+   current_target  = target;
+   memcpy( current_cmnd, cmnd, ((*(unsigned char *)cmnd) <= 0x1f ? 6 : 10 ) );
+   current_buff    = buff;
+   current_bufflen = bufflen;
+   current_done    = done;
+
+   /* Initialize static data */
+   cmd_pt          = current_cmnd;
+   the_command     = current_cmnd;
+   out_buf_pt      = current_buff;
+   in_buf_pt       = current_buff;
+   
+   Status          = 0;
+   Message         = 0;
+   data_sent       = 0;
+   have_data_in    = 0;
+
+   /* Start arbitration */
+   current_phase = in_arbitration;
+   outb( 0x00, Interrupt_Cntl_port );
+   outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */
+   outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */
+   ++in_command;
+   outb( 0x20, Interrupt_Cntl_port );
+   outb( 0x1c, TMC_Cntl_port );	              /* Start arbitration */
+
+   return 0;
+}
+#endif
+
+int fdomain_16x0_command( unsigned char target, const void *cmnd,
+			 void *buff, int bufflen )
+{
+   const char     *cmd_pt = cmnd;
+   const char     *the_command = cmnd;
+   unsigned char  *out_buf_pt = buff;
+   unsigned char  *in_buf_pt = buff;
+   int            Status = 0;
+   int            Message = 0;
+   int            status;
+   int            done = 0;
+   unsigned long  timeout;
+   unsigned       data_sent = 0;
+   unsigned       data_count;
+#if USE_FIFO
+   int            have_data_in = 0;
+#endif
+#if SEND_IDENTITY
+   int            sent_identify = 0;
+#endif
+
+#if EVERY_ACCESS
+   printk( "fdomain_command(%d, %x): ", target, (unsigned char)*the_command );
+#endif
+
+   if (fdomain_arbitrate()) {
+#if ERRORS_ONLY
+      printk( ", target = %d, command = %x\n",
+	     target, (unsigned char)*the_command );
+#endif
+      return DID_TIME_OUT << 16;
+   }
+
+   if (fdomain_select( target )) {
+#if ERRORS_ONLY
+      if (!target) printk( ", target = %d, command = %x\n",
+			 target, (unsigned char)*the_command );
+#endif
+      return DID_NO_CONNECT << 16;
+   }
+
+   timeout = jiffies + 500;	/* 5000 mS -- For Maxtor after a RST */
+   aborted = 0;			/* How is this supposed to get reset??? */
+
+#if FAST_SYNCH
+   outb( 0xc0, Data_Mode_Cntl_port );
+#endif
+
+#if USE_FIFO
+   switch ((unsigned char)*the_command) {
+   case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:
+   case 0x2e: case 0x3b: case 0xea: case 0x3f:
+      data_count = 0x2000 - inw( FIFO_Data_Count_port );
+      if (bufflen - data_sent < data_count)
+	    data_count = bufflen - data_sent;
+      if (data_count == 1) {
+	 outb( *out_buf_pt++, Write_FIFO_port );
+	 ++data_sent;
+      } else {
+	 data_count >>= 1;
+	 outsw( out_buf_pt, data_count, Write_FIFO_port );
+	 out_buf_pt += 2 * data_count;
+	 data_sent += 2 * data_count;
+      }
+      break;
+   default:
+      outb( 0x88, TMC_Cntl_port );
+      ++have_data_in;
+      break;
+   }
+#endif
+   
+   while (((status = inb( SCSI_Status_port )) & 1)
+	  && !done && !aborted && jiffies < timeout) {
+      
+      if (status & 0x10) {	/* REQ */
+
+	 switch (status & 0x0e) {
+	 case 0x00:		/* DATA OUT */
+#if USE_FIFO
+	    data_count = 0x2000 - inw( FIFO_Data_Count_port );
+	    if (bufflen - data_sent < data_count)
+		  data_count = bufflen - data_sent;
+	    if (data_count == 1) {
+	       outb( *out_buf_pt++, Write_FIFO_port );
+	       ++data_sent;
+	    } else {
+	       data_count >>= 1;
+	       outsw( out_buf_pt, data_count, Write_FIFO_port );
+	       out_buf_pt += 2 * data_count;
+	       data_sent += 2 * data_count;
+	    }
+#else
+	    outb( *out_buf_pt++, Write_SCSI_Data_port );
+#endif
+	    break;
+	 case 0x04:		/* DATA IN */
+#if USE_FIFO
+	    if (!have_data_in) {
+	       outb( 0x88, TMC_Cntl_port );
+	       ++have_data_in;
+	    }
+	    data_count = inw( FIFO_Data_Count_port );
+	    if (data_count == 1) {
+	       *in_buf_pt++ = inb( Read_FIFO_port );
+	    } else {
+	       data_count >>= 1; /* Number of words */
+	       insw( in_buf_pt, data_count, Read_FIFO_port );
+	       in_buf_pt += 2 * data_count;
+	    }
+#else
+	    *in_buf_pt++ = inb( Read_SCSI_Data_port );
+#endif
+	    break;
+	 case 0x08:		/* COMMAND OUT */
+	    outb( *cmd_pt++, Write_SCSI_Data_port );
+#if EVERY_ACCESS
+	    printk( "%x,", (unsigned char)cmd_pt[-1] );
+#endif
+	    break;
+	 case 0x0c:		/* STATUS IN */
+	    Status = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+	    printk( "Status = %x, ", Status );
+#endif
+#if ERRORS_ONLY
+	    if (Status) {
+	       printk( "SCSI: target = %d, command = %x, Status = %x\n",
+		      target, (unsigned char)*the_command, Status );
+	    }
+#endif
+	    break;
+	 case 0x0a:		/* MESSAGE OUT */
+#if SEND_IDENTIFY
+	    /* On the first request, send an Identify message */
+	    if (!sent_identify) {
+	       outb( 0x80, SCSI_Cntl_port );          /* Lower ATN */
+	       outb( 0x80, Write_SCSI_Data_port );    /* Identify */
+	       ++sent_identify;
+	    } else
+#else
+		  outb( 0x07, Write_SCSI_Data_port ); /* Reject */
+#endif
+	    break;
+	 case 0x0e:		/* MESSAGE IN */
+	    Message = inb( Read_SCSI_Data_port );
+#if EVERY_ACCESS
+	    printk( "Message = %x, ", Message );
+#endif
+	    if (!Message) ++done;
+	    break;
+	 }
+      }
+   }
+
+   if (jiffies >= timeout) {
+#if EVERY_ACCESS
+      printk( "Time out, status = %x\n", status );
+#endif
+#if ERRORS_ONLY
+      printk( "SCSI: Time out, status = %x (target = %d, command = %x)\n",
+	     status, target, (unsigned char)*the_command );
+#endif
+      fdomain_make_bus_idle();
+      return DID_BUS_BUSY << 16;
+   }
+
+   if (aborted) {
+#if EVERY_ACCESS
+      printk( "Aborted\n" );
+#endif
+#if ONLY_ERRORS
+      printk( "SCSI: Aborted (command = %x)\n", (unsigned char)*the_command );
+#endif
+      fdomain_16x0_reset();
+      return DID_ABORT << 16;
+   }
+   
+#if USE_FIFO
+   if (have_data_in) {
+      while (data_count = inw( FIFO_Data_Count_port )) {
+	 if (data_count == 1) {
+	    *in_buf_pt++ = inb( Read_FIFO_port );
+	 } else {
+	    data_count >>= 1; /* Number of words */
+	    insw( in_buf_pt, data_count, Read_FIFO_port );
+	    in_buf_pt += 2 * data_count;
+	 }
+      }
+   }
+#endif
+
+   fdomain_make_bus_idle();
+
+#if EVERY_ACCESS
+   printk( "Retcode = %x\n",
+	  (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );
+#endif
+#if ERRORS_ONLY
+   if (*the_command == REQUEST_SENSE && !Status) {
+      if ((unsigned char)(*((char *)buff + 2)) & 0x0f) {
+	 printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",
+		(unsigned char)(*((char *)buff + 2)) & 0x0f,
+		(unsigned char)(*((char *)buff + 12)) );
+      }
+   }
+#endif
+
+   return (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16);
+}
+
+int fdomain_16x0_abort( int code )
+{
+
+#if EVERY_ACCESS
+   printk( " ABORT " );
+#endif
+
+#if QUEUE
+   cli();
+   if (!in_command) {
+      sti();
+      return 0;
+   }
+
+   aborted = code ? code : DID_ABORT;
+
+   sti();
+   fdomain_make_bus_idle();
+#else
+   aborted = code ? code : DID_ABORT;
+#endif
+
+   return 0;
+}
+
+int fdomain_16x0_reset( void )
+{
+   outb( 1, SCSI_Cntl_port );
+   do_pause( 2 );
+   outb( 0, SCSI_Cntl_port );
+   do_pause( 115 );
+   outb( 0, Data_Mode_Cntl_port );
+   outb( 0, TMC_Cntl_port );
+
+   aborted = DID_RESET;
+
+   return 0;
+}
+
+#if QUEUE && !NEW_IRQ
+
+/* This is copied from kernel/sys_calls.s
+   and from kernel/blk_drv/scsi/aha1542.c */
+
+__asm__("
+_fdomain_16x0_interrupt:
+	cld
+	push %gs
+	push %fs
+	push %es
+	push %ds
+	pushl %eax
+	pushl %ebp
+	pushl %edi
+	pushl %esi
+	pushl %edx
+	pushl %ecx
+	pushl %ebx
+	movl $0x10,%edx
+	mov %dx,%ds
+	mov %dx,%es
+	movl $0x17,%edx
+	mov %dx,%fs
+
+	movl $_fdomain_disable_interrupt,%edx
+	call *%edx
+
+	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
+
+	sti
+	movl $_fdomain_16x0_intr,%edx
+	call *%edx		# ``interesting'' way of handling intr.
+	cli
+
+	movl $_fdomain_enable_interrupt,%edx
+	call *%edx
+
+	popl %ebx
+	popl %ecx
+	popl %edx
+	popl %esi
+	popl %edi
+	popl %ebp
+	popl %eax
+	pop %ds
+	pop %es
+	pop %fs
+	pop %gs
+	iret
+");
+#endif
+
+#endif
diff --git a/kernel/blk_drv/scsi/fdomain.h b/kernel/blk_drv/scsi/fdomain.h
new file mode 100644
index 0000000..78f2b09
--- /dev/null
+++ b/kernel/blk_drv/scsi/fdomain.h
@@ -0,0 +1,45 @@
+/* fdomain.h -- Header for Future Domain TMC-1660/TMC-1680 driver
+ * Created: Sun May  3 18:47:33 1992
+ * Revised: Sat May 23 22:42:55 1992 by root
+ * Author: Rickard E. Faith, faith@cs.unc.edu
+ * Copyright 1992 Rickard E. Faith
+ * This program comes with ABSOLUTELY NO WARRANTY.
+ *
+ * $Log$
+ */
+
+#ifndef _FDOMAIN_H
+#define _FDOMAIN_H
+
+#define QUEUE         1		/* Enable command queueing */
+
+int  fdomain_16x0_detect( int );
+int  fdomain_16x0_command( unsigned char target, const void *cmnd,
+	 		   void *buff, int bufflen);
+int  fdomain_16x0_abort( int );
+char *fdomain_16x0_info( void );
+int  fdomain_16x0_reset( void ); 
+
+#if QUEUE
+int  fdomain_16x0_queue( unsigned char target, const void *cmnd,
+			 void *buff, int bufflen, void (*done)(int,int) );
+
+#define FDOMAIN_16X0  { "Future Domain TMC-1660/TMC-1680", \
+			 fdomain_16x0_detect,              \
+			 fdomain_16x0_info,                \
+			 fdomain_16x0_command,             \
+			 fdomain_16x0_queue,               \
+		         fdomain_16x0_abort,               \
+			 fdomain_16x0_reset,               \
+			 1, 6, 0 }
+#else
+#define FDOMAIN_16X0  { "Future Domain TMC-1660/TMC-1680", \
+			 fdomain_16x0_detect,              \
+			 fdomain_16x0_info,                \
+			 fdomain_16x0_command,             \
+			 NULL,                             \
+		         fdomain_16x0_abort,               \
+			 fdomain_16x0_reset,               \
+			 0, 6, 0 }
+#endif
+#endif
diff --git a/kernel/blk_drv/scsi/hosts.c b/kernel/blk_drv/scsi/hosts.c
index 268bc71..b4f227c 100644
--- a/kernel/blk_drv/scsi/hosts.c
+++ b/kernel/blk_drv/scsi/hosts.c
@@ -8,10 +8,10 @@
 
 
 /*
-	This file contains the medium level SCSI
-	host interface initialization, as well as the scsi_hosts array of SCSI
-	hosts currently present in the system. 
-*/
+ *	This file contains the medium level SCSI
+ *	host interface initialization, as well as the scsi_hosts array of SCSI
+ *	hosts currently present in the system. 
+ */
 
 #include <linux/config.h>
 
@@ -30,10 +30,13 @@
 #include "hosts.h"
 
 #ifdef CONFIG_SCSI_AHA1542
-#include <sys/types.h>
 #include "aha1542.h"
 #endif
 
+#ifdef CONFIG_SCSI_FUTURE_DOMAIN
+#include "fdomain.h"
+#endif
+
 #ifdef CONFIG_SCSI_SEAGATE
 #include "seagate.h"
 #endif
@@ -42,27 +45,31 @@
 #include "ultrastor.h"
 #endif
 
+#ifdef CONFIG_SCSI_7000FASST
+#include "7000fasst.h"
+#endif
+
 /*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
 */
 
 /*
-	The scsi host entries should be in the order you wish the 
-	cards to be detected.  A driver may appear more than once IFF
-	it can deal with being detected (and therefore initialized) 
-	with more than one simulatenous host number, can handle being
-	rentrant, etc.
-
-	They may appear in any order, as each SCSI host  is told which host number it is
-	during detection.
-*/
+ *	The scsi host entries should be in the order you wish the 
+ *	cards to be detected.  A driver may appear more than once IFF
+ *	it can deal with being detected (and therefore initialized) 
+ *	with more than one simulatenous host number, can handle being
+ *	rentrant, etc.
+ *
+ *	They may appear in any order, as each SCSI host  is told which host number it is
+ *	during detection.
+ */
 
 /*
-	When figure is run, we don't want to link to any object code.  Since 
-	the macro for each host will contain function pointers, we cannot 
-	use it and instead must use a "blank" that does no such 
-	idiocy.
-*/
+ *	When figure is run, we don't want to link to any object code.  Since 
+ *	the macro for each host will contain function pointers, we cannot 
+ *	use it and instead must use a "blank" that does no such 
+ *	idiocy.
+ */
 
 #ifdef FIGURE_MAX_SCSI_HOSTS
 	#define BLANKIFY(what) BLANK_HOST
@@ -76,12 +83,19 @@
 	BLANKIFY(AHA1542),
 #endif
 
+#ifdef CONFIG_SCSI_FUTURE_DOMAIN
+	BLANKIFY(FDOMAIN_16X0),
+#endif
+
 #ifdef CONFIG_SCSI_SEAGATE
 	BLANKIFY(SEAGATE_ST0X),
 #endif
 #ifdef CONFIG_SCSI_ULTRASTOR
 	BLANKIFY(ULTRASTOR_14F),
 #endif
+#ifdef CONFIG_SCSI_7000FASST
+	BLANKIFY(WD7000FASST),
+#endif
 	};
 
 #ifdef FIGURE_MAX_SCSI_HOSTS
@@ -92,20 +106,17 @@
 #ifdef FIGURE_MAX_SCSI_HOSTS
 #include <stdio.h>
 void main (void)
-{
+{	
 	printf("%d", MAX_SCSI_HOSTS);
 }
 #else
 /*
-	Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here. 
-*/
+ *	Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here. 
+ */
 
 volatile unsigned char host_busy[MAX_SCSI_HOSTS];
 volatile int host_timeout[MAX_SCSI_HOSTS];
 volatile Scsi_Cmnd *host_queue[MAX_SCSI_HOSTS]; 
-/*
-	scsi_init initializes the scsi hosts. 
-*/
 
 void scsi_init(void)
 	{
@@ -116,28 +127,31 @@
 		called = 1;	
 		for (count = i = 0; i < MAX_SCSI_HOSTS; ++i)
 			{
-			/*
-				Initialize our semaphores.  -1 is interpreted to mean 
-				"inactive" - where as 0 will indicate a time out condition.
-			*/ 
+/*
+ * Initialize our semaphores.  -1 is interpreted to mean 
+ * "inactive" - where as 0 will indicate a time out condition.
+ */ 
 
 			host_busy[i] = 0;
 			host_timeout[i] = 0;
 			host_queue[i] = NULL;	
 			
 			if ((scsi_hosts[i].detect) &&  (scsi_hosts[i].present = scsi_hosts[i].detect(i)))
-					{		
-					printk ("Host %d is detected as a(n) %s.\n\r",
-						count, scsi_hosts[i].name);
-					printk ("%s", scsi_hosts[i].info());
-					++count;
-					}
+				{		
+				printk ("scsi%d : %s.\n\r",
+				         count, scsi_hosts[i].name);
+				printk ("%s", scsi_hosts[i].info());
+				++count;
+				}
 			}
-		printk ("%d host adapters detected. \n\r", count);
+		printk ("scsi : %d hosts. \n\r", count);
 		}
 
 	}
 
 #endif
-
+#else
+void main(void) {
+	printf("0\n");
+	}
 #endif	
diff --git a/kernel/blk_drv/scsi/hosts.h b/kernel/blk_drv/scsi/hosts.h
index 468a044..f5504d6 100644
--- a/kernel/blk_drv/scsi/hosts.h
+++ b/kernel/blk_drv/scsi/hosts.h
@@ -14,7 +14,7 @@
 #endif
 
 /*
-	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.h,v 1.1 1992/04/24 18:01:50 root Exp root $
+	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hosts.h,v 1.1 1992/07/24 06:27:38 root Exp root $
 */
 
 /*
diff --git a/kernel/blk_drv/scsi/scsi.c b/kernel/blk_drv/scsi/scsi.c
index 22f3402..1469ce2 100644
--- a/kernel/blk_drv/scsi/scsi.c
+++ b/kernel/blk_drv/scsi/scsi.c
@@ -4,7 +4,13 @@
  *		Drew Eckhardt 
  *
  *	<drew@colorado.edu>
+ *
+ *	Bug correction thanks go to : 
+ *		Rik Faith <faith@cs.unc.edu>
+ *		Tommy Thorn <tthorn>
+ *		Thomas Wuensche <tw@fgb1.fgb.mw.tu-meunchen.de>
  */
+
 #include <linux/config.h>
 
 #ifdef CONFIG_SCSI
@@ -25,7 +31,7 @@
 #endif
 
 /*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
 */
 
 #define INTERNAL_ERROR (printk ("Internal error in file %s, line %s.\n", __FILE__, __LINE__), panic(""))
@@ -48,10 +54,10 @@
 
 #define SENSE_LENGTH 255
 /*
-	As the scsi do command functions are inteligent, and may need to 
-	redo a command, we need to keep track of the last command 
-	executed on each one.
-*/
+ *	As the scsi do command functions are inteligent, and may need to 
+ *	redo a command, we need to keep track of the last command 
+ *	executed on each one.
+ */
 
 #define WAS_RESET 	0x01
 #define WAS_TIMEDOUT 	0x02
@@ -62,66 +68,70 @@
 static int last_reset[MAX_SCSI_HOSTS];
 
 /*
-	This is the number  of clock ticks we should wait before we time out 
-	and abort the command.  This is for  where the scsi.c module generates 
-	the command, not where it originates from a higher level, in which
-	case the timeout is specified there.
-	
+ *	This is the number  of clock ticks we should wait before we time out 
+ *	and abort the command.  This is for  where the scsi.c module generates 
+ *	the command, not where it originates from a higher level, in which
+ *	case the timeout is specified there.
+ *
+ *	ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT
+ *	respectively.
+ */
 
-	ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT
-	respectively.
-*/
 #ifdef DEBUG
 	#define SCSI_TIMEOUT 500
 #else
 	#define SCSI_TIMEOUT 100
 #endif
+
 #ifdef DEBUG
 	#define SENSE_TIMEOUT SCSI_TIMEOUT
 	#define ABORT_TIMEOUT SCSI_TIMEOUT
 	#define RESET_TIMEOUT SCSI_TIMEOUT
 #else
-
 	#define SENSE_TIMEOUT 50
 	#define RESET_TIMEOUT 50
 	#define ABORT_TIMEOUT 50
 	#define MIN_RESET_DELAY 25
-
 #endif
-/*
-	As the actual SCSI command runs in the background, we must set up a 
-	flag that tells scan_scsis() when the result it has is valid.  
-	scan_scsis can set the_result to -1, and watch for it to become the 
-	actual return code for that call.  the scan_scsis_done function() is 
-	our user specified completion function that is passed on to the  
-	scsi_do_cmd() function.
-*/
 
+/*
+ *	As the actual SCSI command runs in the background, we must set up a 
+ *	flag that tells scan_scsis() when the result it has is valid.  
+ *	scan_scsis can set the_result to -1, and watch for it to become the 
+ *	actual return code for that call.  the scan_scsis_done function() is 
+ *	our user specified completion function that is passed on to the  
+ *	scsi_do_cmd() function.
+ */
+
+volatile static int in_scan = 0;
 static int the_result;
 static unsigned char sense_buffer[SENSE_LENGTH];
 static void scan_scsis_done (int host, int result)
 	{
 	
 #ifdef DEBUG
-	printk ("scan_scsis_done(%d, %06x\n\r", host, result);
+	printk ("scan_scsis_done(%d, %06x)\n\r", host, result);
 #endif	
 	the_result = result;
 	}
 /*
-	Detecting SCSI devices :	
-	We scan all present host adapter's busses,  from ID 0 to ID 6.  
-	We use the INQUIRY command, determine device type, and pass the ID / 
-	lun address of all sequential devices to the tape driver, all random 
-	devices to the disk driver.
-*/
+ *	Detecting SCSI devices :	
+ *	We scan all present host adapter's busses,  from ID 0 to ID 6.  
+ *	We use the INQUIRY command, determine device type, and pass the ID / 
+ *	lun address of all sequential devices to the tape driver, all random 
+ *	devices to the disk driver.
+ */
 
 static void scan_scsis (void)
 	{
-        int host_nr , dev, lun, type, maxed;
+        int host_nr , dev, lun, type, maxed, slave;
 	static unsigned char scsi_cmd [12];
 	static unsigned char scsi_result [256];
 
-        for (host_nr = 0; host_nr < MAX_SCSI_HOSTS; ++host_nr)
+	++in_scan;
+
+        for (slave = host_nr = 0; host_nr < MAX_SCSI_HOSTS; ++host_nr, 
+	     slave = 0)
                 if (scsi_hosts[host_nr].present)
 			{
 			for (dev = 0; dev < 7; ++dev)
@@ -133,7 +143,9 @@
 					{
 					lun = 0;
 				#endif
-					/* Build an INQUIRY command block.  */
+/*
+ * Build an INQUIRY command block.  
+ */
 
 					scsi_cmd[0] = INQUIRY;
 					scsi_cmd[1] = (lun << 5) & 0xe0;
@@ -143,16 +155,17 @@
 					scsi_cmd[5] = 0;
 					the_result = -1;	
 #ifdef DEBUG
-	memset ((void *) scsi_result , 0, 255);
+					memset ((void *) scsi_result , 0, 255);
 #endif 
 					scsi_do_cmd (host_nr, dev, (void *)  scsi_cmd, (void *) 							    
 						 scsi_result, 256,  scan_scsis_done, 
 						 SCSI_TIMEOUT, sense_buffer, 3);
 					
-					/* Wait for valid result */
+/*
+ * 	Wait for valid result 
+ */
 
 					while (the_result < 0);
-	
 
                                         if (!the_result)
 						{
@@ -165,113 +178,143 @@
                                                 scsi_devices[NR_SCSI_DEVICES].
 							removable = (0x80 & 
 							scsi_result[1]) >> 7;
-
-
-
 /* 
-	Currently, all sequential devices are assumed to be tapes,
-	all random devices disk, with the appropriate read only 
-	flags set for ROM / WORM treated as RO.
-*/ 
+ *	Currently, all sequential devices are assumed to be tapes,
+ *	all random devices disk, with the appropriate read only 
+ *	flags set for ROM / WORM treated as RO.
+ */ 
 
                                                 switch (type = scsi_result[0])
-                                                	{
-                                                        case TYPE_TAPE:
-                                                        case TYPE_DISK:
-                                                        	scsi_devices[NR_SCSI_DEVICES].writeable = 1;
-                                                                break;
-                                                        case TYPE_WORM:
-                                                        case TYPE_ROM:
-                                                        	scsi_devices[NR_SCSI_DEVICES].writeable = 0;
-                                                                break;
-                                                        default:
-                                                                type = -1;
-                                                        }
+                                                {
+                                                case TYPE_TAPE :
+                                                case TYPE_DISK :
+                                                	scsi_devices[NR_SCSI_DEVICES].writeable = 1;
+                                                     	break;
+                                                case TYPE_WORM :
+                                                case TYPE_ROM :
+                                                	scsi_devices[NR_SCSI_DEVICES].writeable = 0;
+                                                	break;
+                                                default :
+                                                	type = -1;
+                                                }
 
                                                 scsi_devices[NR_SCSI_DEVICES].random = (type == TYPE_TAPE) ? 0 : 1;
 
                                                 maxed = 0;
                                                 switch (type)
-							{
-                                                        case -1:
-                                                        	break;
-                                                        case TYPE_TAPE:
-								printk("Detected scsi tape at host %d, ID  %d, lun %d \n", host_nr, dev, lun);
-#ifdef CONFIG_BLK_DEV_ST
-                                                                if (!(maxed = (NR_ST == MAX_ST)))
-                                                                                scsi_tapes[NR_ST].device = &scsi_devices[NR_SCSI_DEVICES];
+						{
+                                                case -1 :
+                                                	break;
+                                                case TYPE_TAPE :
+#ifdef DEBUG
+							printk("Detected scsi tape at host %d, ID  %d, lun %d \n", host_nr, dev, lun);
 #endif
-                                                        default:
-								printk("Detected scsi disk at host %d, ID  %d, lun %d \n", host_nr, dev, lun);
+#ifdef CONFIG_BLK_DEV_ST
+                                                        if (!(maxed = (NR_ST == MAX_ST)))
+                                                        	scsi_tapes[NR_ST].device = &scsi_devices[NR_SCSI_DEVICES];
+#endif
+							break;
+                                                default :
+#ifdef DEBUG
+							printk("Detected scsi disk at host %d, ID  %d, lun %d \n", host_nr, dev, lun);
+#endif
 #ifdef CONFIG_BLK_DEV_SD
-                                                               	if (!(maxed = (NR_SD >= MAX_SD)))
-										rscsi_disks[NR_SD].device = &scsi_devices[NR_SCSI_DEVICES];
+                                                        if (!(maxed = (NR_SD >= MAX_SD)))
+								rscsi_disks[NR_SD].device = &scsi_devices[NR_SCSI_DEVICES];
 #endif
-                                                                }
+						}
 
-                                                        if (maxed)
-                                                                {
-                                                                printk ("Already have detected maximum number of SCSI %ss Unable to \n"
-                                                                        "add drive at SCSI host %s, ID %d, LUN %d\n\r", (type == TYPE_TAPE) ?
-                                                                        "tape" : "disk", scsi_hosts[host_nr].name,
-                                                                        dev, lun);
-                                                                type = -1;
-                                                                break;
-                                                                }
+                                                if (maxed)
+                                                	{
+                                                	printk ("scsi : already have detected maximum number of SCSI %ss Unable to \n"
+                                                                "add drive at SCSI host %s, ID %d, LUN %d\n\r", (type == TYPE_TAPE) ?
+                                                                "tape" : "disk", scsi_hosts[host_nr].name,
+                                                                dev, lun);
+                                                        type = -1;
+                                                        break;
+                                                        }
 
-                                                        else if (type != -1)
-                                                                {
-                                                                if (type == TYPE_TAPE)
+                                                 else if (type != -1)
+                                                        {
+							char *p;
+							char str[25]; 
+memcpy((void *) str, (void *) &scsi_result[8], 8);
+for (p = str; (p < (str  + 8)) && (*p != ' '); ++p);
+*p++ = ' ';
+memcpy((void *) p, (void *) &scsi_result[16], 16);
+for (; *p != ' '; ++p);
+*p = 0;
+
+printk("s%c%d at scsi%d, id %d, lun %d : %s\n",
+	(type == TYPE_TAPE) ? 't' : 'd',
+	(type == TYPE_TAPE) ? 
 #ifdef CONFIG_BLK_DEV_ST
-                                                                	++NR_ST;
+	NR_ST  
+#else 
+	-1
+#endif
+	: 
+#ifdef CONFIG_BLK_DEV_SD
+	NR_SD
+#else
+	-1	
+#endif
+	,host_nr , dev, lun, p); 
+                                                        if (type == TYPE_TAPE)
+#ifdef CONFIG_BLK_DEV_ST
+                                                        	++NR_ST;
 #else
 ;
 #endif
 
-                                                                else
+							else
 #ifdef CONFIG_BLK_DEV_SD
-                                                                        ++NR_SD;
+                                                        	++NR_SD;
 #else
 ;
 #endif
                                                                 }
+							++slave;
 							++NR_SCSI_DEVICES;
                                                         }       /* if result == DID_OK ends */
                                         }       /* for lun ends */
                         }      	/* if present */  
 
-	printk("Detected "
+	printk("scsi : detected "
 #ifdef CONFIG_BLK_DEV_SD
-"%d disk%s "
+	"%d SCSI disk%s "
 #endif
 
 #ifdef CONFIG_BLK_DEV_ST
-"%d tape%s "
+	"%d tape%s "
 #endif
 
-"total.\n",  
+	"total.\n",  
 
 #ifdef CONFIG_BLK_DEV_SD
-NR_SD, (NR_SD != 1) ? "s" : ""
+	NR_SD, (NR_SD != 1) ? "s" : ""
 #ifdef CONFIG_BLK_DEV_ST 
-,
+	,
 #endif
 #endif
 
 #ifdef CONFIG_BLK_DEV_ST
-NR_ST, (NR_ST != 1) ? "s" : ""
+	NR_ST, (NR_ST != 1) ? "s" : ""
 #endif
-);
+	);
+	in_scan = 0;
         }       /* scan_scsis  ends */
 
 /*
-	We handle the timeout differently if it happens when a reset, 
-	abort, etc are in process. 
-*/
+ *	We handle the timeout differently if it happens when a reset, 
+ *	abort, etc are in process. 
+ */
 
 static unsigned char internal_timeout[MAX_SCSI_HOSTS];
 
-/* Flag bits for the internal_timeout array */
+/*
+ *	Flag bits for the internal_timeout array 
+ */
 
 #define NORMAL_TIMEOUT 0
 #define IN_ABORT 1
@@ -288,7 +331,8 @@
  	switch (internal_timeout[host] & (IN_ABORT | IN_RESET))
 		{
 		case NORMAL_TIMEOUT:
-			printk("SCSI host %d timed out - aborting command \r\n",
+			if (!in_scan)
+			      printk("SCSI host %d timed out - aborting command \r\n",
 				host);
 			
 			if (!scsi_abort	(host, DID_TIME_OUT))
@@ -439,11 +483,11 @@
 			{
 			sti();
 #ifdef DEBUG
-			printk("Host %d is busy.\n"	);
+			printk("Host %d is busy.\n", host);
 #endif
 			while (host_busy[host]);
 #ifdef DEBUG
-			printk("Host %d is no longer busy.");
+			printk("Host %d is no longer busy.\n", host);
 #endif
 			}
 		else
@@ -784,8 +828,8 @@
 		#ifdef DEBUG
 			printk("Calling done function - at address %08x\n", last_cmnd[host].done);
 		#endif
-		last_cmnd[host].done (host, (result | ((exit & 0xff) << 24)));
 		host_busy[host] = 0;
+		last_cmnd[host].done (host, (result | ((exit & 0xff) << 24)));
 		}
 
 
@@ -825,11 +869,11 @@
 			}
 		else
 			{	
+			oldto = host_timeout[host];
 			internal_timeout[host] |= IN_ABORT;
 			host_timeout[host] = ABORT_TIMEOUT;	
 			update_timeout();
 
-			oldto = host_timeout[host];
 			
 			sti();
 			if (!host_busy[host] || !scsi_hosts[host].abort(why))
@@ -937,7 +981,7 @@
 	
 static void update_timeout(void)
 	{
-	int i, least, used;
+	unsigned int i, least, used;
 
 	cli();
 
@@ -992,9 +1036,9 @@
 	timer_table[SCSI_TIMER].expires = 0;
 
 	scsi_init();            /* initialize all hosts */
-	/*
-		Set up sense command in each host structure.
-	*/
+/*
+ *	Set up sense command in each host structure.
+ */
 
 	for (i = 0; i < MAX_SCSI_HOSTS; ++i)
 		{
diff --git a/kernel/blk_drv/scsi/scsi.h b/kernel/blk_drv/scsi/scsi.h
index 1a949ab..60ca176 100644
--- a/kernel/blk_drv/scsi/scsi.h
+++ b/kernel/blk_drv/scsi/scsi.h
@@ -9,7 +9,7 @@
 #ifndef _SCSI_H
 	#define _SCSI_H
 /*
-	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.h,v 1.1 1992/04/24 18:01:50 root Exp root $
+	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.h,v 1.1 1992/07/24 06:27:38 root Exp root $
 
 	For documentation on the OPCODES, MESSAGES, and SENSE values,
 	please consult the SCSI standard.
@@ -71,7 +71,12 @@
 #define LINKED_CMD_COMPLETE	0x0a
 #define LINKED_FLG_CMD_COMPLETE	0x0b
 #define BUS_DEVICE_RESET	0x0c
-#define IDENTIFY		0x80
+#define IDENTIFY_BASE		0x80
+#define IDENTIFY(can_disconnect, lun)   (IDENTIFY_BASE |\
+					 ((can_disconnect) ?  0x40 : 0) |\
+					 ((lun) & 0x07)) 
+
+				 
 /*
 	Status codes
 */
@@ -129,6 +134,10 @@
 	Reset by somebody.
 */
 #define DID_RESET 		0x08
+/*
+	Got an interrupt we weren't expecting.
+*/
+#define	DID_BAD_INTR		0x09
 
 /*
 	Driver status
@@ -226,7 +235,7 @@
 	These are the SCSI devices available on the system.
 */
 
-#define MAX_SCSI_DEVICE 2
+#define MAX_SCSI_DEVICE 4
 extern int NR_SCSI_DEVICES;
 extern Scsi_Device scsi_devices[MAX_SCSI_DEVICE];
 /*
@@ -253,5 +262,5 @@
                   void *buffer, unsigned bufflen, void (*done)(int,int),
                   int timeout, unsigned  char *sense_buffer, int retries);
 
-int scsi_reset (int host);
+extern int scsi_reset (int host);
 #endif
diff --git a/kernel/blk_drv/scsi/scsi_ioctl.c b/kernel/blk_drv/scsi/scsi_ioctl.c
index b373c3b..8a700b1 100644
--- a/kernel/blk_drv/scsi/scsi_ioctl.c
+++ b/kernel/blk_drv/scsi/scsi_ioctl.c
@@ -1,11 +1,11 @@
 #include <linux/config.h>
 #ifdef CONFIG_SCSI 
 
-#include <errno.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 
+#include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -16,7 +16,7 @@
 
 #define MAX_RETRIES 5	
 #define MAX_TIMEOUT 200
-#define MAX_BUF 1024  	
+#define MAX_BUF 8192  	
 
 #define max(a,b) (((a) > (b)) ? (a) : (b))
 
@@ -44,21 +44,23 @@
  * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
  * The MAX_TIMEOUT and MAX_RETRIES  variables are used.  
  * 
- * dev is the SCSI device number, *(int *) arg the length of the input
- * data, *((int *)arg + 1) the output buffer.
+ * dev is the SCSI device struct ptr, *(int *) arg is the length of the
+ * input data, if any, not including the command string & counts, 
+ * *((int *)arg + 1) is the output buffer size in bytes.
  * 
- * *(char *) ((int *) arg)[1] the actual command.   
+ * *(char *) ((int *) arg)[2] the actual command byte.   
  * 
- * Note that no more than MAX_BUF bytes will be transfered.  Since
+ * Note that no more than MAX_BUF data bytes will be transfered.  Since
  * SCSI block device size is 512 bytes, I figured 1K was good.
+ * but (WDE) changed it to 8192 to handle large bad track buffers.
  * 
- * This size * does  * include  the initial lengths that were passed.
+ * This size *does not* include the initial lengths that were passed.
  * 
- * The SCSI command is read from  the memory location immediately after the
- * length words, and the out data after the command.  The SCSI routines know the
- * command size based on the length byte.  
+ * The SCSI command is read from the memory location immediately after the
+ * length words, and the input data is right after the command.  The SCSI
+ * routines know the command size based on the opcode decode.  
  * 
- * The area is then filled in from the byte at offset 0. 
+ * The output area is then filled in starting from the command byte. 
  */
 
 static int the_result[MAX_SCSI_HOSTS];
@@ -80,13 +82,13 @@
 		return -EINVAL;
 	
 	inlen = get_fs_long((int *) buffer);
-	outlen = get_fs_long(((int *) buffer) + 1);
+	outlen = get_fs_long( ((int *) buffer) + 1);
 
 	cmd_in = (char *) ( ((int *)buffer) + 2);
 	opcode = get_fs_byte(cmd_in); 
 
-	memcpy_fromfs ((void *) cmd,  cmd_in, cmdlen = COMMAND_SIZE (opcode));
-	memcpy_fromfs ((void *) buf,  (void *) (cmd_in + cmdlen), inlen);
+	memcpy_fromfs ((void *) cmd,  cmd_in,  cmdlen = COMMAND_SIZE (opcode));
+	memcpy_fromfs ((void *) buf,  (void *) (cmd_in + cmdlen),  inlen);
 	host = dev->host_no;
 
 #ifndef DEBUG_NO_CMD
@@ -103,26 +105,29 @@
 		}
 	} while (1);
 	
-	scsi_do_cmd(host,  dev->id, cmd, buf, ((outlen > MAX_BUF) ? 
-			MAX_BUF : outlen),  scsi_ioctl_done, MAX_TIMEOUT, 
-			buf, MAX_RETRIES);
+	scsi_do_cmd(host,  dev->id,  cmd,  buf,  ((outlen > MAX_BUF) ? 
+			MAX_BUF : outlen),  scsi_ioctl_done,  MAX_TIMEOUT, 
+			buf,  MAX_RETRIES);
 
 	while (the_result[host] == -1)
 		/* nothing */;
 	temp = the_result[host];
-	the_result[host]=0;
-	memcpy_tofs (buffer, buf, (outlen > MAX_BUF) ? MAX_BUF  : outlen);
+	the_result[host] = 0;
+	memcpy_tofs ((void *) cmd_in,  buf,  (outlen > MAX_BUF) ? MAX_BUF  : outlen);
 	return temp;
 #else
 	{
 	int i;
-	printk("scsi_ioctl : device %d.  command = ", dev);
+	printk("scsi_ioctl : device %d.  command = ", dev->id);
 	for (i = 0; i < 10; ++i)
 		printk("%02x ", cmd[i]);
 	printk("\r\nbuffer =");
 	for (i = 0; i < 20; ++i)
 		printk("%02x ", buf[i]);
 	printk("\r\n");
+	printk("inlen = %d, outlen = %d, cmdlen = %d\n",
+		inlen, outlen, cmdlen);
+	printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
 	}
 	return 0;
 #endif
@@ -132,18 +137,18 @@
 /*
 	the scsi_ioctl() function differs from most ioctls in that it does
 	not take a major/minor number as the dev filed.  Rather, it takes
-	an index in scsi_devices[] 
+	a pointer to a scsi_devices[] element, a structure. 
 */
-int scsi_ioctl (int dev, int cmd, void *arg)
+int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
 {
-	if ((cmd != 0 && dev > NR_SCSI_DEVICES) || dev < 0)
+	if ((cmd != 0 && dev->id > NR_SCSI_DEVICES))
 		return -ENODEV;
-	if ((cmd == 0 && dev > MAX_SCSI_HOSTS))
+	if ((cmd == 0 && dev->host_no > MAX_SCSI_HOSTS))
 		return -ENODEV;
 	
 	switch (cmd) {
 		case SCSI_IOCTL_PROBE_HOST:
-			return ioctl_probe(dev, arg);
+			return ioctl_probe(dev->host_no, arg);
 		case SCSI_IOCTL_SEND_COMMAND:
 			return ioctl_command((Scsi_Device *) dev, arg);
 		default :			
diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c
index 0ad47d3..5e034cc 100644
--- a/kernel/blk_drv/scsi/sd.c
+++ b/kernel/blk_drv/scsi/sd.c
@@ -9,16 +9,18 @@
 #include <linux/config.h>
 
 #ifdef CONFIG_BLK_DEV_SD
-#include <linux/string.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/string.h>
+
 #include "scsi.h"
 #include "sd.h"
 
 #define MAJOR_NR 8
 
 #include "../blk.h"
+#include <linux/genhd.h>
 
 /*
 static const char RCSid[] = "$Header:";
@@ -30,15 +32,18 @@
  *	Time out in seconds
  */
 
-#define SD_TIMEOUT 100
+#define SD_TIMEOUT 200
 
-Partition scsi_disks[MAX_SD << 4];
+struct hd_struct sd[MAX_SD << 4];
+				
 int NR_SD=0;
 Scsi_Disk rscsi_disks[MAX_SD];
 static int sd_sizes[MAX_SD << 4];
 static int this_count;
 static int the_result;
 
+static char sense_buffer[255];
+
 extern int sd_ioctl(struct inode *, struct file *, unsigned long, unsigned long);
 
 static void sd_release(struct inode * inode, struct file * file)
@@ -46,6 +51,17 @@
 	sync_dev(inode->i_rdev);
 }
 
+static struct gendisk sd_gendisk;
+
+static void sd_geninit (void) {
+	int i;
+	for (i = 0; i < NR_SD; ++i)
+		sd_sizes[i << 4] = 
+		(sd[i << 4].nr_sects = rscsi_disks[i].capacity) >>
+		(BLOCK_SIZE_BITS - 9);
+	sd_gendisk.nr_real = NR_SD;
+}
+
 static struct file_operations sd_fops = {
 	NULL,			/* lseek - default */
 	block_read,		/* read - general block-dev read */
@@ -57,12 +73,19 @@
 	sd_release		/* release */
 };
 
-/*
-	The sense_buffer is where we put data for all mode sense commands 
-	performed.
-*/
-
-static unsigned char sense_buffer[255];
+static struct gendisk sd_gendisk = {
+	MAJOR_NR,		/* Major number */	
+	"sd",		/* Major name */
+	4,		/* Bits to shift to get real from partition */
+	1 << 4,		/* Number of partitions per real */
+	MAX_SD,		/* maximum number of real */
+	sd_geninit,	/* init function */
+	sd,		/* hd struct */
+	sd_sizes,	/* block sizes */
+	0,		/* number */
+	(void *) rscsi_disks,	/* internal */
+	NULL		/* next */
+};
 
 /*
 	rw_intr is the interrupt routine for the device driver.  It will
@@ -75,30 +98,66 @@
 	if (HOST != host)
 		panic ("sd.o : rw_intr() recieving interrupt for different host.");
 
+#ifdef DEBUG
+	printk("sd%d : rw_intr(%d, %x)\n", MINOR(CURRENT->dev), host, result);
+#endif
+
 /*
 	First case : we assume that the command succeeded.  One of two things will
 	happen here.  Either we will be finished, or there will be more 
 	sectors that we were unable to read last time.
 */
 
-	if (!result)
-		if (!(CURRENT->nr_sectors -= this_count)) {
-			end_request(1);
-			do_sd_request();
-		} else {			
-			CURRENT->nr_sectors -= this_count;
+	if (!result) {
+		CURRENT->nr_sectors -= this_count;
+
+#ifdef DEBUG
+		printk("sd%d : %d sectors remain.\n", MINOR(CURRENT->dev), CURRENT->nr_sectors);
+#endif
+
+/*
+ * 	If multiple sectors are requested in one buffer, then
+ *	they will have been finished off by the first command.  If
+ *	not, then we have a multi-buffer command.
+ */
+		if (CURRENT->nr_sectors)
+			{
+			CURRENT->sector += this_count;
+			CURRENT->errors = 0;
+
+			if (!CURRENT->bh)
+				{
+#ifdef DEBUG
+				printk("sd%d : handling page request, no buffer\n", 
+					MINOR(CURRENT->dev));
+#endif
+
 /*
 	The CURRENT->nr_sectors field is always done in 512 byte sectors,
 	even if this really isn't the case.
 */
-	
-			(char *) CURRENT->buffer += this_count << 9;
-			CURRENT->sector += this_count;
-			CURRENT->errors = 0;
-			do_sd_request();			 
+				(char *) CURRENT->buffer += this_count << 9;
+				}
+			else
+				{
+#ifdef DEBUG
+				printk("sd%d :  handling linked buffer request\n", MINOR(CURRENT->dev));
+#endif
+				end_request(1);
+				}
+			}
+		else
+			end_request(1);
+		do_sd_request();			 
 		}
 
 /*
+ *	Of course, the error handling code is a little Fubar down in scsi.c.  
+ *	Version 2 of the drivers will fix that, and we will *really* recover 
+ *	from errors.
+ */
+
+/*
 	Now, if we were good little boys and girls, Santa left us a request 
 	sense buffer.  We can extract information from this, so we 
 	can choose a block to remap, etc.
@@ -148,7 +207,7 @@
 				sense_class(sense_buffer[0]), 
 				sense_error(sense_buffer[0]),
 				sense_buffer[2] & 0xf);
-	
+
 		end_request(0);
 	}
 }
@@ -159,11 +218,12 @@
 	them to SCSI commands.
 */
 	
-void do_sd_request (void)
+static void do_sd_request (void)
 {
 	int dev, block;
 	unsigned char cmd[10];
 
+repeat:
 	INIT_REQUEST;
 	dev =  MINOR(CURRENT->dev);
 	block = CURRENT->sector;
@@ -172,27 +232,31 @@
 	printk("Doing sd request, dev = %d, block = %d\n", dev, block);
 #endif
 
-	if (dev >= (NR_SD << 4) || block + 2 > scsi_disks[dev].nr_sects || 
-		(dev % 16) > 5)
+	if (dev >= (NR_SD << 4) || block + CURRENT->nr_sectors > sd[dev].nr_sects) 
 		{
 		end_request(0);	
 		goto repeat;
 		}
 	
-	block += scsi_disks[dev].start_sect;
+	block += sd[dev].start_sect;
 	dev = DEVICE_NR(dev);
 
 #ifdef DEBUG
-	printk("Real dev = %d, block = %d\n", dev, block);
+	printk("sd%d : real dev = /dev/sd%d, block = %d\n", MINOR(CURRENT->dev), dev, block);
 #endif
 
-	if (!rscsi_disks[dev].use)
-		{
-		end_request(0);
-		goto repeat;
-		}
+
+	if (!CURRENT->bh)  	
+		this_count = CURRENT->nr_sectors;
+	else
+		this_count = (BLOCK_SIZE / 512);
+
+#ifdef DEBUG
+	printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(CURRENT->dev), 
+		(CURRENT->cmd == WRITE) ? "writing" : "reading",
+		this_count, CURRENT->nr_sectors);
+#endif
 	
-	this_count = CURRENT->nr_sectors;
 	switch (CURRENT->cmd)
 		{
 		case WRITE : 
@@ -210,7 +274,7 @@
 			printk ("Unknown sd command %d\r\n", CURRENT->cmd);
 			panic("");
 		}
-	
+
 	cmd[1] = (LUN << 5) & 0xe0;
 
 	if (((this_count > 0xff) ||  (block > 0x1fffff)) && rscsi_disks[dev].ten) 
@@ -255,23 +319,31 @@
 
 void sd_init(void)
 {
-	int i,j,k;
+	int i,j;
 	unsigned char cmd[10];
 	unsigned char buffer[513];
-
-	Partition *p;
+	int try_again;
 
 	
 	for (i = 0; i < NR_SD; ++i)
 		{
+		try_again=2;
 		cmd[0] = READ_CAPACITY;
-		rscsi_disks[i].use = 1;
 		cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
-		memset ((void *) &cmd[2], 0, 8);
+		memset ((void *) &cmd[2], 0, 8);	
+
+/*
+ *	Super Kludge - since the midlevel error handling code doesn't work
+ *	Version 2 will - it's under development 8^) 
+ * 
+ *	We manually retry
+ */
+	
+
+		do {
 	 	the_result = -1;
 #ifdef DEBUG
-	printk("Read capacity, disk %d at host = %d, id = %d\n", i, 
-		rscsi_disks[i].device->host_no, rscsi_disks[i].device->id);
+	printk("sd%d : READ CAPACITY\n ", i); 
 #endif
 		scsi_do_cmd (rscsi_disks[i].device->host_no , 
 				rscsi_disks[i].device->id, 
@@ -280,24 +352,25 @@
 				 MAX_RETRIES);
 
 		while(the_result < 0);
+		} while (try_again  && the_result);
 /*
-	The SCSI standard says "READ CAPACITY is necessary for self confuring software"
-	While not mandatory, support of READ CAPACITY is strongly encouraged.
-
-	We used to die if we couldn't successfully do a READ CAPACITY.  
-	But, now we go on about our way.  The side effects of this are
-
-	1.  We can't know block size with certainty.  I have said "512 bytes is it"
-	  	as this is most common.
-
-	2.  Recovery from when some one attempts to read past the end of the raw device will
-	    be slower.  
-*/
-
+ *	The SCSI standard says "READ CAPACITY is necessary for self confuring software"
+ *	While not mandatory, support of READ CAPACITY is strongly encouraged.
+ *	We used to die if we couldn't successfully do a READ CAPACITY.  
+ *	But, now we go on about our way.  The side effects of this are
+ *
+ *	1.  We can't know block size with certainty.  I have said "512 bytes is it"
+ *	   	as this is most common.
+ *
+ *	2.  Recovery from when some one attempts to read past the end of the raw device will
+ *	    be slower.  
+ */
+	
 		if (the_result)
 			{
-			printk ("Warning : SCSI device at host %d, id %d, lun %d failed READ CAPACITY.\n"
-				"status = %x, message = %02x, host = %02x, driver = %02x \n",
+			printk ("sd%d : READ CAPACITY failed.\n" 
+				"sd%d : status = %x, message = %02x, host = %02x, driver = %02x \n",
+				i,i,
 				rscsi_disks[i].device->host_no, rscsi_disks[i].device->id,
 				rscsi_disks[i].device->lun,
 			        status_byte(the_result),
@@ -306,11 +379,11 @@
 			        driver_byte(the_result)
 			        );
 			if (driver_byte(the_result)  & DRIVER_SENSE)  
-				printk("Extended sense code = %1x \n", sense_buffer[2] & 0xf);
+				printk("sd%d : extended sense code = %1x \n", i, sense_buffer[2] & 0xf);
 			else
-				printk("Sense not available. \n");
+				printk("sd%d : sense not available. \n", i);
 
-			printk("Block size assumed to be 512 bytes, disk size 1GB.  \n");
+			printk("sd%d : block size assumed to be 512 bytes, disk size 1GB.  \n", i);
 			rscsi_disks[i].capacity = 0x1fffff;
 			rscsi_disks[i].sector_size = 512;
 			}
@@ -326,55 +399,24 @@
 						     (buffer[6] << 8) | 
 						     buffer[7]) != 512)
 				{
-				printk ("Unsupported sector size %d for sd %d",
-					 rscsi_disks[i].sector_size, i);
-				rscsi_disks[i].use = 0;
+				printk ("sd%d : unsupported sector size %d.\n", 
+					i, rscsi_disks[i].sector_size);
+				printk ("scsi : deleting disk entry.\n");
+				for  (j=i;  j < NR_SD;)
+					rscsi_disks[j] = rscsi_disks[++j];
+				--i;
+				continue;
 				}
 			}
 
-		if (rscsi_disks[i].use)
-			{
-			scsi_disks[j = (i << 4)].start_sect = 0;
-
-			sd_sizes[j]=(scsi_disks[j].nr_sects =  rscsi_disks[i].capacity)>>1;
-#ifdef DEBUG
-			printk("/dev/sd%1d size = %d\n", j, sd_sizes[j]);
-#endif
-			cmd[0] = READ_6;
-			cmd[2] = cmd[3] = cmd[5] = 0; 
-			cmd[4] = 1;
- 			the_result = -1;
-	
-			scsi_do_cmd (rscsi_disks[i].device->host_no ,  rscsi_disks[i].device->id, 
-			     	(void *) cmd, (void *) buffer, 512, sd_init_done,  SD_TIMEOUT, 
-			     	sense_buffer, MAX_RETRIES);
-					
-			while (the_result < 0);
-
-
-			if (the_result || (0xaa55 != *(unsigned short *)(buffer + 510)))
-					{
-					printk ("Cannot read partition table for sd %d"
-						"\n\r",i);
-					rscsi_disks[i].use = 0;					
-					}
-			else
-				for (++j, k=j+4, p=(Partition *) (buffer + 0x1be); j < k; ++j, ++p)
-					{
-					memcpy ((void *) &scsi_disks[j], (void *) p, sizeof(Partition));	
-					sd_sizes[j]=(scsi_disks[j].nr_sects)>>1;
-#ifdef DEBUG
-	printk("/dev/sd%1d size = %d (%d blocks), offset = %d\n", j, scsi_disks[j].nr_sects, sd_sizes[j], scsi_disks[j].start_sect);
-#endif
-					}
-		
-			rscsi_disks[i].ten = 1;
-			rscsi_disks[i].remap = 1;
-			}
+		rscsi_disks[i].ten = 1;
+		rscsi_disks[i].remap = 1;
 		}
+
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 	blk_size[MAJOR_NR] = sd_sizes;	
 	blkdev_fops[MAJOR_NR] = &sd_fops; 
+	sd_gendisk.next = gendisk_head;
+	gendisk_head = &sd_gendisk;
 }	
 #endif
-
diff --git a/kernel/blk_drv/scsi/sd.h b/kernel/blk_drv/scsi/sd.h
index e4c4613..aacb01f 100644
--- a/kernel/blk_drv/scsi/sd.h
+++ b/kernel/blk_drv/scsi/sd.h
@@ -8,32 +8,27 @@
 #ifndef _SD_H
 	#define _SD_H
 /*
-	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/04/24 18:01:50 root Exp root $
+	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $
 */
 
 #ifndef _SCSI_H
 #include "scsi.h"
 #endif
 
-#define MAX_SD 2
+#ifndef _GENDISK_H
+#include <linux/genhd.h>
+#endif
 
-typedef struct partition {
-	unsigned char boot_ind;		/* 0x80 - active (unused) */
-	unsigned char head;		/* ? */
-	unsigned char sector;		/* ? */
-	unsigned char cyl;		/* ? */
-	unsigned char sys_ind;		/* ? */
-	unsigned char end_head;		/* ? */
-	unsigned char end_sector;	/* ? */
-	unsigned char end_cyl;		/* ? */
-	unsigned int start_sect;	/* starting sector counting from 0 */
-	unsigned int nr_sects;		/* nr of sectors in partition */
-} Partition;
+/*
+	This is an arbitrary constant, and may be changed to whatever
+	suits your purposes.  Note that smaller will get you a few bytes
+	more in kernel space if that is your thing.
+*/
 
+#define MAX_SD 4
 extern int NR_SD;
 
-extern Partition scsi_disks[MAX_SD << 4] ;
-
+extern struct hd_struct sd[MAX_SD << 4];
 
 typedef struct {
 		unsigned capacity;		/* size in blocks */
@@ -42,9 +37,7 @@
 		unsigned char sector_bit_size;	/* sector_size = 2 to the  bit size power */
 		unsigned char sector_bit_shift;	/* power of 2 sectors per FS block */
 		unsigned ten:1;			/* support ten byte read / write */
-		unsigned remap:1;		/* support remapping */
-		unsigned use:1;			/* after the initial inquiry, is 
-						   the device still supported ? */
+		unsigned remap:1;		/* support remapping  */
 		} Scsi_Disk;
 	
 extern Scsi_Disk rscsi_disks[MAX_SD];
diff --git a/kernel/blk_drv/scsi/sd_ioctl.c b/kernel/blk_drv/scsi/sd_ioctl.c
index 5c55e16..d2f18d2 100644
--- a/kernel/blk_drv/scsi/sd_ioctl.c
+++ b/kernel/blk_drv/scsi/sd_ioctl.c
@@ -3,22 +3,18 @@
 #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"
 
-extern int scsi_ioctl (int dev, int cmd, void *arg);
+extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 
 int sd_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
 {
 	int dev = inode->i_rdev;
 	
 	switch (cmd) {
-		RO_IOCTLS(dev,arg);
 		default:
-			return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device,cmd,(void *) arg);
+			return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device, cmd, (void *) arg);
 	}
 }
 #endif
diff --git a/kernel/blk_drv/scsi/seagate.c b/kernel/blk_drv/scsi/seagate.c
index 28df162..e36dbec 100644
--- a/kernel/blk_drv/scsi/seagate.c
+++ b/kernel/blk_drv/scsi/seagate.c
@@ -8,13 +8,19 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_SCSI_SEAGATE
+#if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x) 
+#include <asm/io.h>
+#include <asm/system.h>
 #include <linux/sched.h>
-
 #include "seagate.h"
 #include "scsi.h"
 #include "hosts.h"
 
+extern void seagate_intr(void);
+static int internal_command(unsigned char target, const void *cmnd,
+			 void *buff, int bufflen, int reselect);
+void (*do_seagate)(void) = NULL;
+
 static int incommand;			/*
 						set if arbitration has finished and we are 
 						in some command phase.
@@ -27,7 +33,7 @@
 					*/
 static volatile int abort_confirm = 0;
 
-volatile void *st0x_cr_sr;       /*
+static volatile void *st0x_cr_sr;       /*
 						control register write,
 						status register read.
 						256 bytes in length.
@@ -71,9 +77,33 @@
 	} Signature;
 	
 static const Signature signatures[] = {
+#ifdef CONFIG_SCSI_SEAGATE
 {"SCSI BIOS 2.00  (C) Copyright 1987 Seagate", 15, 40},
+
+/*
+	The following two lines are NOT mistakes.  One detects 
+ 	ROM revision 3.0.0, the other 3.2.  Since seagate
+	has only one type of SCSI adapter, and this is not 
+	going to change, the "SEAGATE" and "SCSI" together
+	are probably "good enough"
+*/
+
 {"SEAGATE SCSI BIOS ",16, 17},
-{"SEAGATE SCSI BIOS ",17, 17}};
+{"SEAGATE SCSI BIOS ",17, 17},
+#endif
+
+/*
+	This is for the Future Domain 88x series.  I've been told that
+	the Seagate controllers are just repackages of these, and seeing
+	early seagate BIOS bearing the Future Domain copyright,
+	I believe it.
+*/
+
+#ifdef CONFIG_SCSI_FD_88x
+{"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
+#endif
+}
+;
 /*
 	Note that the last signature handles BIOS revisions 3.0.0 and 
 	3.2 - the real ID's are 
@@ -86,31 +116,44 @@
 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
 #endif
 
+/*
+ * hostno stores the hostnumber, as told to us by the init routine.
+ */
+
+static int hostno = -1;
+
 int seagate_st0x_detect (int hostnum)
 	{
-	#ifndef OVERRIDE
-		int i,j;
-	#endif
+#ifndef OVERRIDE
+	int i,j;
+#endif
 
-	/*
-		First, we try for the manual override.
-	*/
-	#ifdef DEBUG 
-		printk("Autodetecting seagate ST0x\n");
-	#endif
+/*
+ *	First, we try for the manual override.
+ */
+#ifdef DEBUG 
+	printk("Autodetecting seagate ST0x\n");
+#endif
+	
+	if (hostno != -1)
+		{
+		printk ("ERROR : seagate_st0x_detect() called twice.\n");
+		return 0;
+		}
 	
 	base_address = NULL;
-	#ifdef OVERRIDE
-		base_address = (void *) OVERRIDE;	
-		#ifdef DEBUG
-			printk("Base address overridden to %x\n", base_address);
-		#endif
-	#else	
-	/*
-		To detect this card, we simply look for the SEAGATE SCSI
-		from the BIOS version notice in all the possible locations
-		of the ROM's.
-	*/
+#ifdef OVERRIDE
+	base_address = (void *) OVERRIDE;	
+#ifdef DEBUG
+	printk("Base address overridden to %x\n", base_address);
+#endif
+#else	
+/*
+ *	To detect this card, we simply look for the signature
+ *	from the BIOS version notice in all the possible locations
+ *	of the ROM's.  This has a nice sideeffect of not trashing
+ * 	any register locations that might be used by something else.
+ */
 
 	for (i = 0; i < (sizeof (seagate_bases) / sizeof (char  * )); ++i)
 		for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
@@ -118,75 +161,182 @@
 		    signatures[j].offset), (void *) signatures[j].signature,
 		    signatures[j].length))
 			base_address = (void *) seagate_bases[i];
-       	#endif
+ #endif
  
 	if (base_address)
 		{
 		st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00); 
 		st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
-		#ifdef DEBUG
-			printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
-		#endif
+#ifdef DEBUG
+		printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
+#endif
+		hostno = hostnum;
+
+/*
+ *	At all times, we will use IRQ 5.  
+ */
+		
+#if 1
+		set_intr_gate (0x25, seagate_intr);
+		__asm__("
+		inb	$0x21, %%al
+		andb	$0xdf, %%al
+		outb	%%al, $0x21"::);
+#endif
 		return -1;
 		}
 	else
 		{
-		#ifdef DEBUG
-			printk("ST0x not detected.\n");
-		#endif
+#ifdef DEBUG
+		printk("ST0x not detected.\n");
+#endif
 		return 0;
 		}
 	}
 	 
-	
-
 char *seagate_st0x_info(void)
 {
 	static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
-"$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/04/24 18:01:50 root Exp root $\n";
+"$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
 	return buffer;
 }
 
+/*
+ * These are our saved pointers for the outstanding command that is 
+ * waiting for a reconnect
+ */
 
+static unsigned char current_target;
+static unsigned char *current_cmnd, *current_data;
+static int current_bufflen;
+static void (*done_fn)(int, int) = NULL;
 
-int seagate_st0x_command(unsigned char target, const void *cmnd,
-			 void *buff, int bufflen)
+/*
+ * These control weather or not disconnect / reconnect will be attempted,
+ * or are being attempted.
+ */
+
+#define NO_RECONNECT 	0
+#define RECONNECT_NOW 	1
+#define CAN_RECONNECT	2
+
+/*
+ * This determines if we are expecting to reconnect or not.
+ */
+
+static int should_reconnect = 0;
+
+void seagate_unexpected_intr (void)
+	{
+	printk("scsi%d: unexpected interrupt.\n", hostno);
+	}	
+	
+/*
+ * The seagate_reconnect_intr routine is called when a target reselects the 
+ * host adapter.  This occurs on the interrupt triggered by the target 
+ * asserting SEL.
+ */
+
+void seagate_reconnect_intr (void)
+	{
+	int temp;
+	
+#if (DEBUG & PHASE_RESELECT)
+	printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
+#endif
+
+	if (!should_reconnect)
+		seagate_unexpected_intr();
+	else
+		{
+		should_reconnect = 0;
+
+#if (DEBUG & PHASE_RESELECT)
+		printk("scsi%d : internal_command("
+		       "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, 
+			current_target, current_data, current_bufflen);
+#endif
+	
+		temp =  internal_command (current_target, 
+			current_cmnd, current_data, current_bufflen,
+			RECONNECT_NOW);
+
+		if (msg_byte(temp) != DISCONNECT)
+			{
+			if (done_fn)
+				{
+#if (DEBUG & PHASE_RESELECT)
+				printk("scsi%d : done_fn(%d,%08x)", hostno, 
+				hostno, temp);
+#endif
+				done_fn (hostno, temp);
+				}
+			else
+				printk("done_fn() not defined.\n");
+			}
+		}
+	} 
+
+/* 
+ * The seagate_st0x_queue_command() function provides a queued interface
+ * to the seagate SCSI driver.  Basically, it just passes control onto the
+ * seagate_command() function, after fixing it so that the done_fn()
+ * is set to the one passed to the function.
+ */
+
+int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
+				void *buff, int bufflen, void (*fn)(int, 
+				 int))
+	{
+	int result;
+
+	done_fn = fn;
+	current_target = target;
+	(const void *) current_cmnd = cmnd;
+	current_data = buff;
+	current_bufflen = bufflen;
+
+	result = internal_command (target, cmnd, buff, bufflen, 
+				   CAN_RECONNECT);
+	if (msg_byte(result) == DISCONNECT)
+		return 0;
+	else 
+		{
+		done_fn (hostno, result); 
+		return 1; 
+		}
+	}
+
+int seagate_st0x_command (unsigned char target, const void *cmnd, 
+			void *buff, int bufflen)
+	{
+	return internal_command (target, cmnd, buff, bufflen, 
+				 (int) NO_RECONNECT);
+	}
+	
+static int internal_command(unsigned char target, const void *cmnd,
+			 void *buff, int bufflen, int reselect)
 	{
 	int len;			
 	unsigned char *data;	
+	int clock;			
+	int temp;
 
-	int clock;			/*
-						We use clock for timeouts, etc.   This replaces the 
-						seagate_st0x_timeout that we had been using.
-					*/
-	#if (DEBUG & PHASE_SELECTION)
-		int temp;
-	#endif
 
-	#if (DEBUG & PHASE_EXIT)
-		 void *retaddr, *realretaddr;
-	#endif
+#if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))	
+	int i;
+#endif
 
-	#if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))	
-		int i;
-	#endif
-
-	#if (DEBUG & PHASE_ETC)
-		int phase=0, newphase;
-	#endif
+#if (DEBUG & PHASE_ETC)
+	int phase=0, newphase;
+#endif
 
 	int done = 0;
 	unsigned char status = 0;	
 	unsigned char message = 0;
 	register unsigned char status_read;
 
-	#if (DEBUG & PHASE_EXIT)
-		 __asm__("
-movl 4(%%ebp), %%eax 
-":"=a" (realretaddr):);
-		printk("return address = %08x\n", realretaddr);
-	#endif
-
+	do_seagate = seagate_unexpected_intr;
 
 	len=bufflen;
 	data=(unsigned char *) buff;
@@ -194,73 +344,201 @@
 	incommand = 0;
 	st0x_aborted = 0;
 
-	#if (DEBUG & PRINT_COMMAND)
-		printk ("seagate_st0x_command, target = %d, command = ", target);
-		for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
-			printk("%02x ",  ((unsigned char *) cmnd)[i]);
-		printk("\n");
-	#endif
+#if (DEBUG & PRINT_COMMAND)
+	printk ("scsi%d : target = %d, command = ", hostno, target);
+	for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
+		printk("%02x ",  ((unsigned char *) cmnd)[i]);
+	printk("\n");
+#endif
+
+#if (DEBUG & PHASE_RESELECT)
+	switch (reselect)
+	{
+	case RECONNECT_NOW :
+		printk("scsi%d : reconnecting\n", hostno);
+		break;
+	case CAN_RECONNECT :
+		printk("scsi%d : allowed to reconnect\n", hostno);
+		break;
+	default :
+		printk("scsi%d : not allowed to reconnect\n", hostno);
+	}
+#endif
 	
+
 	if (target > 6)
+		{
+		if (reselect == RECONNECT_NOW)
+			eoi();
 		return DID_BAD_TARGET;
+		}
 
-	
-	#if (DEBUG & PHASE_BUS_FREE)
-		printk ("SCSI PHASE = BUS FREE \n");
-	#endif
+/*
+ *	We work it differently depending on if this is is "the first time,"
+ *	or a reconnect.  If this is a reselct phase, then SEL will 
+ *	be asserted, and we must skip selection / arbitration phases.
+ */
 
-	/*
+	if (reselect == RECONNECT_NOW) 
+		{
+#if (DEBUG & PHASE_RESELECT)
+		printk("scsi%d : phase RESELECT \n", hostno);
+#endif
 
-		BUS FREE PHASE
+/*
+ *	At this point, we should find the logical or of our ID and the original
+ *	target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
+ *
+ *	After ARBITRATION phase is completed, only SEL, BSY, and the 
+ *	target ID are asserted.  A valid initator ID is not on the bus
+ *	until IO is asserted, so we must wait for that.
+ */
+		
+		for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
+		     !(STATUS & STAT_IO););
+		
+		if (jiffies >= clock)
+			{
+#if (DEBUG & PHASE_RESELECT)
+			printk("scsi%d : RESELECT timed out while waiting for IO .\n",
+				hostno);
+#endif
+			eoi();
+			return (DID_BAD_INTR << 16);
+			}
 
-		On entry, we make sure that the BUS is in a BUS FREE
-		phase, by insuring that both BSY and SEL are low for
-		at least one bus settle delay.  The standard requires a
-		minimum of 400 ns, which is 16 clock cycles on a
-		386-40  .
+/* 
+ * 	After I/O is asserted by the target, we can read our ID and its
+ *	ID off of the BUS.
+ */
+ 
+		if (!((temp = DATA) & 0x80))
+			{
+#if (DEBUG & PHASE_RESELECT)
+			printk("scsi%d : detected reconnect request to different target.\n" 
+			       "\tData bus = %d\n", hostno, temp);
+#endif
+			eoi();
+			return (DID_BAD_INTR << 16);
+			}
 
-		This doesn't give us much time - so we'll do two several
-		reads to be sure be sure.
-	*/
+		if (!(temp & (1 << current_target)))
+			{
+			printk("scsi%d : Unexpected reselect interrupt.  Data bus = %d\n",
+				hostno, temp);
+			eoi();
+			return (DID_BAD_INTR << 16);
+			}
+                data=current_data;      /* WDE add */
+                cmnd=current_cmnd;      /* WDE add */
+                len=current_bufflen;    /* WDE add */
 
-	clock = jiffies + ST0X_BUS_FREE_DELAY;	
+/*
+ * 	We have determined that we have been selected.  At this point, 
+ *	we must respond to the reselection by asserting BSY ourselves
+ */
 
-	while (((STATUS |  STATUS | STATUS) & 
-	         (STAT_BSY | STAT_SEL)) && 
-		 (!st0x_aborted) && (jiffies < clock));
+		CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
 
-	if (jiffies > clock)
-		return retcode(DID_BUS_BUSY);
-	else if (st0x_aborted)
-		return retcode(st0x_aborted);
+/*
+ *	The target will drop SEL, and raise BSY, at which time we must drop
+ *	BSY.
+ */
 
-	/*
-		Bus free has been detected, within BUS settle.  I used to support an arbitration
-		phase - however, on the seagate, this degraded performance by a factor > 10 - so
-	        it is no more.
-	*/
+		for (clock = jiffies + 10; (jiffies < clock) &&  (STATUS & STAT_SEL););
 
-	/*
-		SELECTION PHASE
+		if (jiffies >= clock)
+			{ 
+			CONTROL = (BASE_CMD | CMD_INTR);
+#if (DEBUG & PHASE_RESELECT)
+			printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
+				hostno);
+#endif
+			eoi();
+			return (DID_BAD_INTR << 16);				 
+			}
 
-		Now, we select the disk, giving it the SCSI ID at data
-		and a command of PARITY if necessary, plus driver enable,
-		plus raise select signal.
-	*/
+		CONTROL = BASE_CMD;
 
-	#if (DEBUG & PHASE_SELECTION)
-		printk("SCSI PHASE = SELECTION\n");
-	#endif
+/*
+ *	At this point, we have connected with the target and can get 
+ *	on with our lives.
+ */	 
+		eoi();
+		}  	
+	else
+ 		{	
+#if (DEBUG & PHASE_BUS_FREE)
+		printk ("scsi%d : phase = BUS FREE \n", hostno);
+#endif
 
-	clock = jiffies + ST0X_SELECTION_DELAY;
-	DATA = (unsigned char) (1 << target);
+/*
+ *	BUS FREE PHASE
+ *
+ * 	On entry, we make sure that the BUS is in a BUS FREE
+ *	phase, by insuring that both BSY and SEL are low for
+ *	at least one bus settle delay.  Several reads help
+ *	eliminate wire glitch.
+ */
 
-	CONTROL =  BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL;
+		clock = jiffies + ST0X_BUS_FREE_DELAY;	
 
-	/*
-		When the SCSI device decides that we're gawking at it, it will respond by asserting BUSY on the bus.
-	*/
-	while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock) && !st0x_aborted)
+		while (((STATUS |  STATUS | STATUS) & 
+		         (STAT_BSY | STAT_SEL)) && 
+			 (!st0x_aborted) && (jiffies < clock));
+
+		if (jiffies > clock)
+			return retcode(DID_BUS_BUSY);
+		else if (st0x_aborted)
+			return retcode(st0x_aborted);
+
+/*
+ *	Bus free has been detected, within BUS settle.  I used to 
+ *	support an arbitration phase - however, on the Seagate, this 
+ *	degraded performance by a factor > 10 - so it is no more.
+ */
+
+/*
+ *	SELECTION PHASE
+ *
+ *	Now, we select the disk, giving it the SCSI ID at data
+ *	and a command of PARITY if necessary, and we raise SEL.
+ */
+
+#if (DEBUG & PHASE_SELECTION)
+		printk("scsi%d : phase = SELECTION\n", hostno);
+#endif
+
+		clock = jiffies + ST0X_SELECTION_DELAY;
+
+/*
+ *	If we wish to disconnect, we should request a MESSAGE OUT
+ *	at this point.  Technically, ATTN should be raised before 
+ *	SEL = true and BSY = false (from arbitration), but I think this 
+ *	should do.
+ */
+		if (reselect)
+			CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
+				CMD_ATTN;
+		
+/*
+ *	We must assert both our ID and our target's ID on the bus.
+ */
+		DATA = (unsigned char) ((1 << target) | 0x80);
+
+/*
+ *	If we are allowing ourselves to reconnect, then I will keep 
+ *	ATTN raised so we get MSG OUT. 
+ */ 
+		CONTROL =  BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | 
+			(reselect ? CMD_ATTN : 0);
+
+/*
+ *	When the SCSI device decides that we're gawking at it, it will 
+ *	respond by asserting BUSY on the bus.
+ */
+		while (!((status_read = STATUS) & STAT_BSY) && 
+			(jiffies < clock) && !st0x_aborted)
 
 #if (DEBUG & PHASE_SELECTION)
 		{
@@ -271,110 +549,128 @@
 	
 		}
 		printk("Done.                                             \n\r");
-		printk("Status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", status_read, temp,
-			st0x_aborted);
+		printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", 
+			hostno, status_read, temp, st0x_aborted);
 #else
 		;
 #endif
 	
 
-	if ((jiffies > clock)  || (!st0x_aborted & !(status_read & STAT_BSY)))
-		{
-		#if (DEBUG & PHASE_SELECT)
-			printk ("NO CONNECT with target %d, status = %x \n", target, STATUS);
-		#endif
-		return retcode(DID_NO_CONNECT);
+		if ((jiffies > clock)  || (!st0x_aborted && 
+			!(status_read & STAT_BSY)))
+			{
+#if (DEBUG & PHASE_SELECT)
+			printk ("scsi%d : NO CONNECT with target %d, status = %x \n", 
+				hostno, target, STATUS);
+#endif
+			return retcode(DID_NO_CONNECT);
+			}
+
+/*
+ *	If we have been aborted, and we have a command in progress, IE the 
+ *	target still has BSY asserted, then we will reset the bus, and 
+ * 	notify the midlevel driver to expect sense.
+ */
+
+		if (st0x_aborted)
+			{
+			CONTROL = BASE_CMD;
+			if (STATUS & STAT_BSY)
+				{
+				seagate_st0x_reset();
+				return retcode(DID_RESET);
+				}
+			return retcode(st0x_aborted);
+			}	
 		}
 
-	/*
-		If we have been aborted, and we have a command in progress, IE the target still has
-		BSY asserted, then we will reset the bus, and notify the midlevel driver to
-		expect sense.
-	*/
-
-	if (st0x_aborted)
-		{
-		CONTROL = BASE_CMD;
-		if (STATUS & STAT_BSY)
-			{
-			seagate_st0x_reset();
-			return retcode(DID_RESET);
-			}
-		
-		return retcode(st0x_aborted);
-		}	
+	CONTROL = BASE_CMD | CMD_DRVR_ENABLE | 
+		((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
 	
-	/*
-		COMMAND PHASE
-		The device has responded with a BSY, so we may now enter
-		the information transfer phase, where we will send / recieve
-		data and command as directed by the target.
+/*
+ * 	INFORMATION TRANSFER PHASE
+ *
+ *	The nasty looking read / write inline assembler loops we use for 
+ *	DATAIN and DATAOUT phases are approximately 4-5 times as fast as 
+ *	the 'C' versions - since we're moving 1024 bytes of data, this
+ *	really adds up.
+ */
 
-
-		The nasty looking read / write inline assembler loops we use for 
-		DATAIN and DATAOUT phases are approximately 4-5 times as fast as 
-		the 'C' versions - since we're moving 1024 bytes of data, this
-		really adds up.
-	*/
-
-	#if (DEBUG & PHASE_ETC)
-		printk("PHASE = information transfer\n");
-	#endif  
+#if (DEBUG & PHASE_ETC)
+	printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
+#endif  
 
 	incommand = 1;
 
-	/*
-		Enable command
-	*/
 
-	CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
-
-	/*
-		Now, we poll the device for status information,
-		and handle any requests it makes.  Note that since we are unsure of 
-		how much data will be flowing across the system, etc and cannot 
-		make reasonable timeouts, that we will instead have the midlevel
-		driver handle any timeouts that occur in this phase.
-	*/
+/*
+ * 	Now, we poll the device for status information,
+ *	and handle any requests it makes.  Note that since we are unsure of 
+ *	how much data will be flowing across the system, etc and cannot 
+ *	make reasonable timeouts, that we will instead have the midlevel
+ * 	driver handle any timeouts that occur in this phase.
+ */
 
 	while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) 
+		{
+#ifdef PARITY
+		if (status_read & STAT_PARITY)
 			{
-			#ifdef PARITY
-				if (status_read & STAT_PARITY)
-					{
-					done = 1;
-					st0x_aborted = DID_PARITY;
-					}	
-			#endif
+			done = 1;
+			st0x_aborted = DID_PARITY;
+			}	
+#endif
 
-			if (status_read & STAT_REQ)
+		if (status_read & STAT_REQ)
+			{
+#if (DEBUG & PHASE_ETC)
+			if ((newphase = (status_read & REQ_MASK)) != phase)
 				{
-				#if (DEBUG & PHASE_ETC)
-					if ((newphase = (status_read & REQ_MASK)) != phase)
-						{
-						phase = newphase;
-						switch (phase)
-							{
-							case REQ_DATAOUT : printk("SCSI PHASE = DATA OUT\n"); break;
-							case REQ_DATAIN : printk("SCSI PHASE = DATA IN\n"); break;
-							case REQ_CMDOUT : printk("SCSI PHASE = COMMAND OUT\n"); break;
-							case REQ_STATIN : printk("SCSI PHASE = STATUS IN\n"); break;
-							case REQ_MSGOUT : printk("SCSI PHASE = MESSAGE OUT\n"); break;
-							case REQ_MSGIN : printk("SCSI PHASE = MESSAGE IN\n"); break;
-							default : printk("UNKNOWN PHASE"); st0x_aborted = 1; done = 1;
-							}	
-						}
-				#endif
+				phase = newphase;
+				switch (phase)
+				{
+				case REQ_DATAOUT: 
+					printk("scsi%d : phase = DATA OUT\n",
+						hostno); 
+					break;
+				case REQ_DATAIN : 
+					printk("scsi%d : phase = DATA IN\n",
+						hostno); 
+					break;
+				case REQ_CMDOUT : 
+					printk("scsi%d : phase = COMMAND OUT\n",
+						hostno); 
+					break;
+				case REQ_STATIN :
+					 printk("scsi%d : phase = STATUS IN\n",
+						hostno); 
+					break;
+				case REQ_MSGOUT :
+					printk("scsi%d : phase = MESSAGE OUT\n",
+						hostno); 
+					break;
+				case REQ_MSGIN :
+					printk("scsi%d : phase = MESSAGE IN\n",
+						hostno);
+					break;
+				default : 
+					printk("scsi%d : phase = UNKNOWN\n",
+						hostno); 
+					st0x_aborted = 1; 
+					done = 1;
+				}	
+				}
+#endif
 
-				switch (status_read & REQ_MASK)
-					{			
-					case REQ_DATAOUT : 
+		switch (status_read & REQ_MASK)
+		{			
+		case REQ_DATAOUT : 
 
-	/*
-		We loop as long as we are in a data out phase, there is data to send, and BSY is still
-		active
-	*/
-							__asm__ ("
+/*
+ * 	We loop as long as we are in a data out phase, there is data to send, 
+ *	and BSY is still active.
+ */
+		__asm__ ("
 
 /*
 	Local variables : 
@@ -428,15 +724,15 @@
 /* clobbered */
 "ebx", "ecx", "edi", "esi"); 
 
-							break;
+			break;
 
-      					case REQ_DATAIN : 
-	/*
-		We loop as long as we are in a data out phase, there is room to read, and BSY is still
-		active
-	*/
+		case REQ_DATAIN : 
+/*
+ * 	We loop as long as we are in a data in phase, there is room to read, 
+ * 	and BSY is still active
+ */
  
-							__asm__ ("
+			__asm__ ("
 /*
 	Local variables : 
 	ecx = len
@@ -491,71 +787,153 @@
 "0" (data), "1" (len) :
 /* clobbered */
 "ebx", "ecx", "edi", "esi"); 
-							break;
+			break;
 
-					case REQ_CMDOUT : 
-							while (((status_read = STATUS) & STAT_BSY) && ((status_read & REQ_MASK) ==
-								REQ_CMDOUT))
-								DATA = *(unsigned char *) cmnd ++;
-						break;
+		case REQ_CMDOUT : 
+			while (((status_read = STATUS) & STAT_BSY) && 
+			       ((status_read & REQ_MASK) == REQ_CMDOUT))
+				if (status_read & STAT_REQ)
+					DATA = *(unsigned char *) cmnd ++;
+			break;
 	
-					case REQ_STATIN : 
-						status = DATA;
-						break;
+		case REQ_STATIN : 
+			status = DATA;
+			break;
 				
-					case REQ_MSGOUT : 
-						DATA = MESSAGE_REJECT;
-						break;
-					
-					case REQ_MSGIN : 
-						if ((message = DATA) == COMMAND_COMPLETE)
-							done=1;
-						
-						break;
+		case REQ_MSGOUT : 
+/*
+ *	We can only have sent a MSG OUT if we requested to do this 
+ *	by raising ATTN.  So, we must drop ATTN.
+ */
 
-					default : printk("UNKNOWN PHASE"); st0x_aborted = DID_ERROR; 
-					}	
+			CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
+/*
+ * 	If we are reconecting, then we must send an IDENTIFY message in 
+ *	 response  to MSGOUT.
+ */
+			if (reselect)
+				{
+				DATA = IDENTIFY(1,0);
+#if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) 
+				printk("scsi%d : sent IDENTIFY message.\n", hostno);
+#endif
 				}
+			else  
+				{
+				DATA = MESSAGE_REJECT;
+				
+#if (DEBUG & PHASE_MSGOUT)
+				printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
+#endif
+				}
+			break;
+					
+		case REQ_MSGIN : 
+			switch (message = DATA)
+			{
+			case DISCONNECT :
+				should_reconnect = 1;
+                                current_data = data;    /* WDE add */
+                                current_bufflen = len;  /* WDE add */
+#if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
+				printk("scsi%d : disconnected.\n", hostno);
+				done=1;
+				break;
+#endif
+			case COMMAND_COMPLETE :
+#if (DEBUG & PHASE_MSGIN)	
+				printk("scsi%d : command complete.\n", hostno);
+				done=1;
+				break;
+#endif
+			case ABORT :
+#if (DEBUG & PHASE_MSGIN)
+				printk("scsi%d : abort message.\n", hostno);
+#endif
+				done=1;
+				break;
+			case SAVE_POINTERS :
+				current_data = data;	/* WDE mod */
+                                current_bufflen = len;  /* WDE add */
+#if (DEBUG & PHASE_MSGIN)
+				printk("scsi%d : pointers saved.\n", hostno);
+#endif 
+				break;
+			case RESTORE_POINTERS:
+				data=current_data;	/* WDE mod */
+				cmnd=current_cmnd;
+#if (DEBUG & PHASE_MSGIN)
+				printk("scsi%d : pointers restored.\n", hostno);
+#endif
+				break;
+			default:
 
-		}
+/*
+ * 	IDENTIFY distinguishes itself from the other messages by setting the
+ *	high byte.
+ */
+
+				if (message & 0x80)
+					{
+#if (DEBUG & PHASE_MSGIN)
+					printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
+						hostno, target, message & 7);
+#endif
+					}	
+				else
+					{
+			
+#if (DEBUG & PHASE_MSGIN)
+					printk("scsi%d : unknown message %d from target %d.\n",
+						hostno,  message,   target);
+#endif	
+					}
+			}
+			break;
+
+		default : 
+			printk("scsi%d : unknown phase.\n", hostno); 
+			st0x_aborted = DID_ERROR; 
+		}	
+		} /* while ends */
+		} /* if ends */
 
 #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
 	printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
 #endif
 
 #if (DEBUG & PHASE_EXIT)
-		printk("Buffer : \n");
-		for (i = 0; i < 20; ++i) 
-			printk ("%02x  ", ((unsigned char *) buff)[i]);
-		printk("\n");
-		printk("Status = %02x, message = %02x\n", status, message);
+	printk("Buffer : \n");
+	for (i = 0; i < 20; ++i) 
+		printk ("%02x  ", ((unsigned char *) data)[i]);	/* WDE mod */
+	printk("\n");
+	printk("Status = %02x, message = %02x\n", status, message);
 #endif
 
 	
-		if (st0x_aborted)
+	if (st0x_aborted)
+		{
+		if (STATUS & STAT_BSY)
 			{
-			if (STATUS & STAT_BSY)
-				{
-				seagate_st0x_reset();
-				st0x_aborted = DID_RESET;
-				}
-			abort_confirm = 1;
-			}	
-			
+			seagate_st0x_reset();
+			st0x_aborted = DID_RESET;
+			}
+		abort_confirm = 1;
+		}		
+
+	if (should_reconnect)
+		{
+#if (DEBUG & PHASE_RESELECT)
+		printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
+			hostno);
+#endif
+		do_seagate = seagate_reconnect_intr;
+		CONTROL = BASE_CMD | CMD_INTR ;
+		}
+	else
 		CONTROL = BASE_CMD;
 
-#if (DEBUG & PHASE_EXIT)
-	__asm__("
-mov 4(%%ebp), %%eax
-":"=a" (retaddr):);
-
-	printk("Exiting seagate_st0x_command() - return address is %08x \n", retaddr);
-	if (retaddr != realretaddr)
-		panic ("Corrupted stack : return address on entry != return address on exit.\n");
-	
-#endif
-
-		return retcode (st0x_aborted);
+	return retcode (st0x_aborted);
 	}
 
 int seagate_st0x_abort (int code)
@@ -604,4 +982,6 @@
 #endif
 	return 0;
 	}
+
 #endif	
+
diff --git a/kernel/blk_drv/scsi/seagate.h b/kernel/blk_drv/scsi/seagate.h
index d625446..0eb3b30 100644
--- a/kernel/blk_drv/scsi/seagate.h
+++ b/kernel/blk_drv/scsi/seagate.h
@@ -13,7 +13,11 @@
 */
 #ifndef ASM
 int seagate_st0x_detect(int);
-int seagate_st0x_command(unsigned char target, const void *cmnd,  void *buff, int bufflen);
+int seagate_st0x_command(unsigned char target, const void *cmnd,  void *buff, 
+	int bufflen);
+int seagate_st0x_queue_command(unsigned char target, const void *cmnd,  
+	void *buff,  int bufflen, void (*done)(int, int));
+
 int seagate_st0x_abort(int);
 char *seagate_st0x_info(void);
 int seagate_st0x_reset(void); 
@@ -24,8 +28,8 @@
 
 #define SEAGATE_ST0X  {"Seagate ST-01/ST-02", seagate_st0x_detect, 	\
 			 seagate_st0x_info, seagate_st0x_command,  	\
-			 NULL, seagate_st0x_abort, seagate_st0x_reset,	\
-			 0, 7, 0}
+			 seagate_st0x_queue_command, seagate_st0x_abort, \
+			 seagate_st0x_reset, 1, 7, 0}
 #endif
 
 
@@ -111,13 +115,17 @@
 #define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
 #define PRINT_COMMAND 0x200
 #define PHASE_EXIT 0x400
+#define PHASE_RESELECT 0x800
 
 /* 
-	Control options - these are timeouts specified in .01 seconds.
-*/
+ *	Control options - these are timeouts specified in .01 seconds.
+ */
 
 #define ST0X_BUS_FREE_DELAY 25
-#define ST0X_SELECTION_DELAY 25
+#define ST0X_SELECTION_DELAY 3
+
+#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::)
+	
 
 #endif
 
diff --git a/kernel/blk_drv/scsi/seagate2.s b/kernel/blk_drv/scsi/seagate2.s
new file mode 100644
index 0000000..9b1b6a2
--- /dev/null
+++ b/kernel/blk_drv/scsi/seagate2.s
@@ -0,0 +1,36 @@
+/*
+ *	seagate2.S
+ *	low level scsi driver for ST01/ST02 by
+ *		Drew Eckhardt 
+ *
+ *	<drew@colorado.edu>
+ */
+.text
+.globl _seagate_intr
+_seagate_intr:
+	cld			# GCC thing
+
+	pushal 
+	push %ds
+	push %es
+	
+	mov $0x10, %ax		# switch to kernel space
+	mov %ax, %ds
+	mov %ax, %es
+	
+
+
+	xor %eax, %eax 
+	xchg _do_seagate, %eax
+	test %eax, %eax
+	jnz 1f
+	mov $_seagate_unexpected_intr, %eax	
+1:	call *%eax
+
+	mov $0x20, %al		# non-specific EOI
+	out %al, $0x20
+
+	pop %es
+	pop %ds
+	popal
+	iret
diff --git a/kernel/blk_drv/scsi/st.c b/kernel/blk_drv/scsi/st.c
index bef3ae8..1f81217 100644
--- a/kernel/blk_drv/scsi/st.c
+++ b/kernel/blk_drv/scsi/st.c
@@ -15,10 +15,6 @@
 #include <linux/sched.h>
 #include "../blk.h" 
 
-/*
-static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.c,v 1.1 1992/04/24 18:01:50 root Exp root $";
-*/
-
 Scsi_Tape scsi_tapes[MAX_ST];
 static int st_sizes[MAX_ST];
 int NR_ST=0;
diff --git a/kernel/blk_drv/scsi/st.h b/kernel/blk_drv/scsi/st.h
index 1a7c044..9ae0795 100644
--- a/kernel/blk_drv/scsi/st.h
+++ b/kernel/blk_drv/scsi/st.h
@@ -2,7 +2,7 @@
 #ifndef _ST_H
 	#define _ST_H
 /*
-	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/04/24 18:01:50 root Exp root $
+	$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/st.h,v 1.1 1992/07/24 06:27:38 root Exp root $
 */
 
 #ifndef _SCSI_H
diff --git a/kernel/blk_drv/scsi/st_ioctl.c b/kernel/blk_drv/scsi/st_ioctl.c
index 4bc7a39..4780989 100644
--- a/kernel/blk_drv/scsi/st_ioctl.c
+++ b/kernel/blk_drv/scsi/st_ioctl.c
@@ -5,15 +5,15 @@
 #include <linux/fs.h>
 #include "st.h"
 
-extern int scsi_ioctl(int dev, int cmd, void *arg);
+extern int scsi_ioctl(Scsi_Device *dev, int cmd, void *arg);
 
-int st_ioctl(struct inode * inode,struct file * file, unsigned long cmd, unsigned long arg)
+int st_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
 {
 	int dev = inode->i_rdev;
 
 	switch (cmd) {
 		default:
-			return scsi_ioctl(scsi_tapes[MINOR(dev)].device,cmd,(void *) arg);
+			return scsi_ioctl(scsi_tapes[MINOR(dev)].device, cmd, (void *) arg);
 	}
 }
 #endif
diff --git a/kernel/blk_drv/scsi/ultrastor.c b/kernel/blk_drv/scsi/ultrastor.c
index ba30f21..279448f 100644
--- a/kernel/blk_drv/scsi/ultrastor.c
+++ b/kernel/blk_drv/scsi/ultrastor.c
@@ -1,5 +1,5 @@
 /*
- *	ultrastor.c	(C) 1991 David B. Gentzel
+ *	ultrastor.c	Copyright (C) 1991, 1992 David B. Gentzel
  *	Low-level SCSI driver for UltraStor 14F
  *	by David B. Gentzel, Whitfield Software Services, Carnegie, PA
  *	    (gentzel@nova.enet.dec.com)
@@ -28,22 +28,21 @@
  *    commands to complete.  I hope to go back and beat it into shape, but
  *    PLEASE, anyone else who would like to, please make improvements!
  *
- *    By defining USE_QUEUECOMMAND as TRUE in ultrastor.h, you enable the
- *    queueing feature of the mid-level SCSI driver.  This should improve
- *    performance somewhat.  However, it does not seem to work.  I believe
- *    this is due to a bug in the mid-level driver, but I haven't looked
- *    too closely.
+ *    By defining NO_QUEUEING in ultrastor.h, you disable the queueing feature
+ *    of the mid-level SCSI driver.  Once I'm satisfied that the queueing
+ *    version is as stable as the non-queueing version, I'll eliminate this
+ *    option.
  */
 
 #include <linux/config.h>
 
 #ifdef CONFIG_SCSI_ULTRASTOR
 
-#include <stddef.h>
-
+#include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -156,7 +155,7 @@
 };
 #endif
 
-void ultrastor_interrupt(int cpl);
+void ultrastor_interrupt(void);
 
 static void (*ultrastor_done)(int, int) = 0;
 
@@ -195,7 +194,7 @@
 # ifdef PORT_OVERRIDE
 	    printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
 # else
-	    printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
+	    printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
 # endif
 #endif
 #ifdef PORT_OVERRIDE
@@ -211,7 +210,7 @@
 # ifdef PORT_OVERRIDE
 	    printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
 # else
-	    printk("US14F: detect: no adapter at port %03X", PORT_ADDRESS);
+	    printk("US14F: detect: no adapter at port %03X\n", PORT_ADDRESS);
 # endif
 #endif
 #ifdef PORT_OVERRIDE
@@ -292,18 +291,12 @@
 #endif
     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;
-   	}
-    }
+#ifndef NO_QUEUEING
+    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;
 }
@@ -341,9 +334,13 @@
     do
 	in_byte = inb_p(LCL_DOORBELL_INTR(PORT_ADDRESS));
     while (!aborted && (in_byte & 1));
-    if (aborted)
+    if (aborted) {
+#if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
+	printk("US14F: queuecommand: aborted\n");
+#endif
 	/* ??? is this right? */
 	return (aborted << 16);
+    }
 
     /* Store pointer in OGM address bytes */
     outb_p(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
@@ -363,7 +360,7 @@
     return 0;
 }
 
-#if !USE_QUEUECOMMAND
+#ifdef NO_QUEUEING
 int ultrastor_14f_command(unsigned char target, const void *cmnd,
 			  void *buff, int bufflen)
 {
@@ -379,9 +376,13 @@
     do
 	in_byte = inb_p(SYS_DOORBELL_INTR(PORT_ADDRESS));
     while (!aborted && !(in_byte & 1));
-    if (aborted)
+    if (aborted) {
+#if (ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT))
+	printk("US14F: command: aborted\n");
+#endif
 	/* ??? is this right? */
 	return (aborted << 16);
+    }
 
     /* Clean ICM slot (set ICMINT bit to 0) */
     outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
@@ -398,7 +399,16 @@
 
 int ultrastor_14f_abort(int code)
 {
+#if (ULTRASTOR_DEBUG & UD_ABORT)
+    printk("US14F: abort: called\n");
+#endif
+
     aborted = (code ? code : DID_ABORT);
+
+#if (ULTRASTOR_DEBUG & UD_ABORT)
+    printk("US14F: abort: returning\n");
+#endif
+
     return 0;
 }
 
@@ -426,20 +436,68 @@
     return 0;
 }
 
-#if USE_QUEUECOMMAND
-void ultrastor_interrupt(int cpl)
+#ifndef NO_QUEUEING
+void ultrastor_interrupt_service(void)
 {
-    if (ultrastor_done == 0) {
-	printk("US14F: unexpected ultrastor interrupt\n\r");
-	/* ??? Anything else we should do here?  Reset? */
-	return;
-    }
-    printk("US14F: got an ultrastor interrupt: %u\n\r",
+#if (ULTRASTOR_DEBUG & UD_INTERRUPT)
+    printk("US14F: interrupt_service: called: status = %08X\n",
 	   (mscp.adapter_status << 16) | mscp.target_status);
-    ultrastor_done(host_number,
-		   (mscp.adapter_status << 16) | mscp.target_status);
-    ultrastor_done = 0;
+#endif
+
+    if (ultrastor_done == 0)
+	panic("US14F: interrupt_service: unexpected interrupt!\n");
+    else {
+	void (*done)(int, int);
+
+	/* Save ultrastor_done locally and zero before calling.  This is needed
+	   as once we call done, we may get another command queued before this
+	   interrupt service routine can return. */
+	done = ultrastor_done;
+	ultrastor_done = 0;
+
+	/* Clean ICM slot (set ICMINT bit to 0) */
+	outb_p(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
+
+	/* Let the higher levels know that we're done */
+	/* ??? status is wrong here... */
+	done(host_number, (mscp.adapter_status << 16) | mscp.target_status);
+    }
+
+#if (ULTRASTOR_DEBUG & UD_INTERRUPT)
+    printk("US14F: interrupt_service: returning\n");
+#endif
 }
+
+__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
diff --git a/kernel/blk_drv/scsi/ultrastor.h b/kernel/blk_drv/scsi/ultrastor.h
index dfe34ee..b881419 100644
--- a/kernel/blk_drv/scsi/ultrastor.h
+++ b/kernel/blk_drv/scsi/ultrastor.h
@@ -17,36 +17,40 @@
 # define FALSE 0
 #endif
 
-/* ??? This should go eventually, once the queueing bug is fixed */
-#define USE_QUEUECOMMAND FALSE
+/* ??? This should go eventually, once I'm convinced the queueing stuff is
+   stable enough... */
+/* #define NO_QUEUEING */
 
 int ultrastor_14f_detect(int);
 const char *ultrastor_14f_info(void);
 int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
 			       void *buff, int bufflen,
 			       void (*done)(int, int));
-#if !USE_QUEUECOMMAND
+#ifdef NO_QUEUEING
 int ultrastor_14f_command(unsigned char target, const void *cmnd,
 			  void *buff, int bufflen);
 #endif
 int ultrastor_14f_abort(int);
 int ultrastor_14f_reset(void);
 
-#if !USE_QUEUECOMMAND
-#define ULTRASTOR_14F \
-    { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
-      ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
-      FALSE, 0, 0 }
-#else
+#ifndef NO_QUEUEING
 #define ULTRASTOR_14F \
     { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
       ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
-      TRUE, 0, 0 }
+      1, 0, 0 }
+    /* ??? What should can_queue be set to?  Currently 1... */
+#else
+#define ULTRASTOR_14F \
+    { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
+      ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
+      0, 0, 0 }
 #endif
 
-#define UD_DETECT 0x1
-#define UD_COMMAND 0x2
-#define UD_RESET 0x4
+#define UD_ABORT 0x0001
+#define UD_COMMAND 0x0002
+#define UD_DETECT 0x0004
+#define UD_INTERRUPT 0x0008
+#define UD_RESET 0x0010
 
 #ifdef ULTRASTOR_PRIVATE
 
diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile
index 83fffae..db51601 100644
--- a/kernel/chr_drv/Makefile
+++ b/kernel/chr_drv/Makefile
@@ -37,77 +37,98 @@
 
 ### Dependencies:
 console.o : console.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 \
-  /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/linux/timer.h /usr/src/linux/include/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/config.h \
-  /usr/src/linux/include/linux/config_rel.h /usr/src/linux/include/linux/config_ver.h \
-  /usr/src/linux/include/linux/config.dist.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/kd.h \
-  vt_kern.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/config.h /usr/src/linux/include/linux/config_rel.h \
+  /usr/src/linux/include/linux/config_ver.h /usr/src/linux/include/linux/config.dist.h \
+  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/io.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/kd.h vt_kern.h 
 keyboard.o : keyboard.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 \
-  /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/linux/ctype.h /usr/src/linux/include/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/asm/io.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/ctype.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/ptrace.h /usr/src/linux/include/asm/io.h 
 lp.o : lp.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 \
-  /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/linux/lp.h /usr/src/linux/include/errno.h \
-  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h 
-mem.o : mem.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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/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/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/asm/io.h 
-pty.o : pty.c /usr/src/linux/include/errno.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/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 /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/linux/tty.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h /usr/src/linux/include/linux/fcntl.h \
-  /usr/src/linux/include/asm/io.h 
-serial.o : serial.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/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/linux/timer.h \
-  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h 
-tty_io.o : tty_io.c /usr/src/linux/include/errno.h /usr/src/linux/include/signal.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/fcntl.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/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/ctype.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/sys/kd.h vt_kern.h 
-tty_ioctl.o : tty_ioctl.c /usr/src/linux/include/errno.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.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/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/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h \
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/lp.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/io.h \
   /usr/src/linux/include/asm/segment.h 
-vt.o : vt.c /usr/src/linux/include/errno.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/sys/kd.h /usr/src/linux/include/sys/vt.h \
-  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.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/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/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/termios.h \
-  /usr/src/linux/include/linux/timer.h vt_kern.h 
+mem.o : mem.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/mouse.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/io.h 
+mouse.o : mouse.c /usr/src/linux/include/linux/kernel.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/mouse.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/io.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/irq.h 
+pty.o : pty.c /usr/src/linux/include/linux/errno.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/asm/io.h 
+serial.o : serial.c /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/signal.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h 
+tty_io.o : tty_io.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/errno.h \
+  /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/fcntl.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/mm.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h \
+  /usr/src/linux/include/linux/resource.h /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/ctype.h /usr/src/linux/include/asm/io.h \
+  /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/kd.h vt_kern.h 
+tty_ioctl.o : tty_ioctl.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/termios.h \
+  /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h 
+vt.o : vt.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/errno.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/tty.h /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/linux/timer.h /usr/src/linux/include/asm/io.h /usr/src/linux/include/asm/segment.h \
+  vt_kern.h /usr/src/linux/include/sys/kd.h /usr/src/linux/include/sys/vt.h 
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index c440e7a..cff8124 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/console.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -37,40 +37,20 @@
 #include <linux/tty.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 
-#include <linux/string.h>
-#include <errno.h>
-
 #include <sys/kd.h>
 #include "vt_kern.h"
 
-/*
- * These are set up by the setup-routine at boot-time:
- */
-
-#define ORIG_X			(*(unsigned char *)0x90000)
-#define ORIG_Y			(*(unsigned char *)0x90001)
-#define ORIG_VIDEO_PAGE		(*(unsigned short *)0x90004)
-#define ORIG_VIDEO_MODE		((*(unsigned short *)0x90006) & 0xff)
-#define ORIG_VIDEO_COLS 	(((*(unsigned short *)0x90006) & 0xff00) >> 8)
-#define ORIG_VIDEO_LINES	((*(unsigned short *)0x9000e) & 0xff)
-#define ORIG_VIDEO_EGA_AX	(*(unsigned short *)0x90008)
-#define ORIG_VIDEO_EGA_BX	(*(unsigned short *)0x9000a)
-#define ORIG_VIDEO_EGA_CX	(*(unsigned short *)0x9000c)
-
-#define VIDEO_TYPE_MDA		0x10	/* Monochrome Text Display	*/
-#define VIDEO_TYPE_CGA		0x11	/* CGA Display 			*/
-#define VIDEO_TYPE_EGAM		0x20	/* EGA/VGA in Monochrome Mode	*/
-#define VIDEO_TYPE_EGAC		0x21	/* EGA/VGA in Color Mode	*/
-
 #define NPAR 16
 
 extern void vt_init(void);
-extern void keyboard_interrupt(int cpl);
+extern void keyboard_interrupt(int pt_regs);
 extern void set_leds(void);
 extern unsigned char kapplic;
 extern unsigned char ckmode;
@@ -1489,11 +1469,11 @@
 		currcons = 0;
 	while (c = *(b++)) {
 		if (c == 10 || c == 13 || need_wrap) {
-			cr(currcons);
-			if (c == 10 || need_wrap)
+			if (c != 13)
 				lf(currcons);
-			need_wrap = 0;
-			continue;
+			cr(currcons);
+			if (c == 10 || c == 13)
+				continue;
 		}
 		*(char *) pos = c;
 		*(char *) (pos+1) = attr;
diff --git a/kernel/chr_drv/keyboard.c b/kernel/chr_drv/keyboard.c
index bd437f1..8e4e521 100644
--- a/kernel/chr_drv/keyboard.c
+++ b/kernel/chr_drv/keyboard.c
@@ -11,6 +11,8 @@
 #include <linux/ctype.h>
 #include <linux/tty.h>
 #include <linux/mm.h>
+#include <linux/ptrace.h>
+
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -58,12 +60,15 @@
 static void kb_wait(void), kb_ack(void);
 static unsigned int handle_diacr(unsigned int);
 
-void keyboard_interrupt(int cpl)
+static struct pt_regs * pt_regs;
+
+void keyboard_interrupt(int int_pt_regs)
 {
 	static unsigned char rep = 0xff, repke0 = 0;
 	unsigned char scancode, x;
 	struct tty_struct * tty = TTY_TABLE(0);
 
+	pt_regs = (struct pt_regs *) int_pt_regs;
 	scancode=inb_p(0x60);
 	x=inb_p(0x61);
 	outb_p(x|0x80, 0x61);
@@ -229,11 +234,28 @@
 	kmode &= ~CAPSDOWN;
 }
 
+static void show_ptregs(void)
+{
+	printk("\nEIP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
+	if (pt_regs->cs & 3)
+		printk(" ESP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
+	printk(" EFLAGS: %08x",pt_regs->eflags);
+	printk("\nEAX: %08x EBX: %08x ECX: %08x EDX: %08x",
+		pt_regs->orig_eax,pt_regs->ebx,pt_regs->ecx,pt_regs->edx);
+	printk("\nESI: %08x EDI: %08x EBP: %08x",
+		pt_regs->esi, pt_regs->edi, pt_regs->ebp);
+	printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
+		0xffff & pt_regs->ds,0xffff & pt_regs->es,
+		0xffff & pt_regs->fs,0xffff & pt_regs->gs);
+}
+
 static void scroll(int sc)
 {
 	if (kmode & (LSHIFT | RSHIFT))
 		show_mem();
-	else
+	else if (kmode & (ALT | ALTGR))
+		show_ptregs();
+	else if (kmode & (LCTRL | RCTRL))
 		show_state();
 	kleds ^= SCRLED;
 	set_leds();
@@ -776,6 +798,7 @@
           0 };
 
 #elif defined KBD_SG
+
 static unsigned char key_map[] = {
           0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
         '7',  '8',  '9',  '0', '\'',  '^',  127,    9,
@@ -790,6 +813,7 @@
           0,    0,    0,    0,    0,    0,  '<',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
 static unsigned char shift_map[] = {
           0,   27,  '+',  '"',  '*',    0,  '%',  '&',
         '/',  '(',  ')',  '=',  '?',  '`',  127,    9,
@@ -804,6 +828,7 @@
           0,    0,    0,    0,    0,    0,  '>',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
 static unsigned char alt_map[] = {
           0,    0,    0,  '@',  '#',    0,    0,    0,
         '|',    0,    0,    0, '\'',  '~',    0,    0,
@@ -818,7 +843,9 @@
           0,    0,    0,    0,    0,    0, '\\',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
 #elif defined KBD_SG_LATIN1
+
 static unsigned char key_map[] = {
           0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
         '7',  '8',  '9',  '0', '\'',  '^',  127,    9,
@@ -833,6 +860,7 @@
           0,    0,    0,    0,    0,    0,  '<',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
 static unsigned char shift_map[] = {
           0,   27,  '+',  '"',  '*',  231,  '%',  '&',
         '/',  '(',  ')',  '=',  '?',  '`',  127,    9,
@@ -847,6 +875,7 @@
           0,    0,    0,    0,    0,    0,  '>',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
 static unsigned char alt_map[] = {
           0,    0,    0,  '@',  '#',    0,    0,  172,
         '|',  162,    0,    0, '\'',  '~',    0,    0,
@@ -861,6 +890,54 @@
           0,    0,    0,    0,    0,    0, '\\',    0,
           0,    0,    0,    0,    0,    0,    0,    0,
           0 };
+
+#elif defined KBD_NO
+
+static unsigned char key_map[] = {
+	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
+	'7',  '8',  '9',  '0',  '+', '\\',  127,    9,
+	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
+	'o',  'p',  '}',  '~',   13,    0,  'a',  's',
+	'd',  'f',  'g',  'h',  'j',  'k',  'l',  '|',
+        '{',  '|',    0, '\'',  'z',  'x',  'c',  'v',
+	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
+	  0,   32,    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,    0,    0,
+          0 };
+
+static unsigned char shift_map[] = {
+	  0,   27,  '!', '\"',  '#',  '$',  '%',  '&',
+	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
+	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
+	'O',  'P',  ']',  '^',   13,    0,  'A',  'S',
+	'D',  'F',  'G',  'H',  'J',  'K',  'L', '\\',
+	'[',    0,    0,  '*',  'Z',  'X',  'C',  'V',
+        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
+	  0,   32,    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,    0,    0,
+	  0 };
+
+static unsigned char alt_map[] = {
+	  0,    0,    0,  '@',    0,  '$',    0,    0,
+        '{',   '[',  ']', '}',    0, '\'',    0,    0,
+          0,    0,    0,    0,    0,    0,    0,    0,
+          0,    0,    0,  '~',   13,    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,    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,    0,
+          0 };
+
 #else
 #error "KBD-type not defined"
 #endif
diff --git a/kernel/chr_drv/lp.c b/kernel/chr_drv/lp.c
index 4643c27..4270b2d 100644
--- a/kernel/chr_drv/lp.c
+++ b/kernel/chr_drv/lp.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/sched.h>
-#define __LP_C__
 #include <linux/lp.h>
 
 static int lp_reset(int minor)
diff --git a/kernel/chr_drv/mem.c b/kernel/chr_drv/mem.c
index 64d8365..1496239 100644
--- a/kernel/chr_drv/mem.c
+++ b/kernel/chr_drv/mem.c
@@ -1,15 +1,15 @@
 /*
  *  linux/kernel/chr_drv/mem.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-#include <sys/types.h>
-
+#include <linux/types.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/mouse.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -36,17 +36,17 @@
 	addr = file->f_pos;
 	tmp = buf;
 	while (count > 0) {
+		if (current->signal & ~current->blocked)
+			break;
 		pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
-		if (!((pte = *((unsigned long *) pde)) & 1))
+		pte = *(unsigned long *) pde;
+		if (!(pte & PAGE_PRESENT))
 			break;
 		pte &= 0xfffff000;
 		pte += (addr >> 10) & 0xffc;
-		if (((page = *((unsigned long *) pte)) & 1) == 0)
+		page = *(unsigned long *) pte;
+		if (!(page & 1))
 			break;
-/*
-		if ((page & 2) == 0)
-			un_wp_page((unsigned long *) pte);
-*/
 		page &= 0xfffff000;
 		page += addr & 0xfff;
 		i = 4096-(addr & 0xfff);
@@ -73,15 +73,21 @@
 	addr = file->f_pos;
 	tmp = buf;
 	while (count > 0) {
+		if (current->signal & ~current->blocked)
+			break;
 		pde = (unsigned long) pg_dir + (addr >> 20 & 0xffc);
-		if (!((pte = *((unsigned long *) pde)) & 1))
+		pte = *(unsigned long *) pde;
+		if (!(pte & PAGE_PRESENT))
 			break;
 		pte &= 0xfffff000;
 		pte += (addr >> 10) & 0xffc;
-		if (((page = *((unsigned long *) pte)) & 1) == 0)
+		page = *(unsigned long *) pte;
+		if (!(page & PAGE_PRESENT))
 			break;
-		if ((page & 2) == 0)
-			un_wp_page((unsigned long *) pte);
+		if (!(page & 2)) {
+			do_wp_page(0,addr,current,0);
+			continue;
+		}
 		page &= 0xfffff000;
 		page += addr & 0xfff;
 		i = 4096-(addr & 0xfff);
@@ -93,7 +99,11 @@
 		count -= i;
 	}
 	file->f_pos = addr;
-	return tmp-buf;
+	if (tmp != buf)
+		return tmp-buf;
+	if (current->signal & ~current->blocked)
+		return -ERESTARTSYS;
+	return 0;
 }
 
 static int read_kmem(struct inode * inode, struct file * file,char * buf, int count)
@@ -102,10 +112,10 @@
 
 	if (count < 0)
 		return -EINVAL;
-	if (p >= HIGH_MEMORY)
+	if (p >= high_memory)
 		return 0;
-	if (count > HIGH_MEMORY - p)
-		count = HIGH_MEMORY - p;
+	if (count > high_memory - p)
+		count = high_memory - p;
 	memcpy_tofs(buf,(void *) p,count);
 	file->f_pos += count;
 	return count;
@@ -117,10 +127,10 @@
 
 	if (count < 0)
 		return -EINVAL;
-	if (p >= HIGH_MEMORY)
+	if (p >= high_memory)
 		return 0;
-	if (count > HIGH_MEMORY - p)
-		count = HIGH_MEMORY - p;
+	if (count > high_memory - p)
+		count = high_memory - p;
 	memcpy_fromfs((void *) p,buf,count);
 	file->f_pos += count;
 	return count;
diff --git a/kernel/chr_drv/mouse.c b/kernel/chr_drv/mouse.c
index 66f0ccc..396e6c2 100644
--- a/kernel/chr_drv/mouse.c
+++ b/kernel/chr_drv/mouse.c
@@ -20,17 +20,17 @@
 #include	<linux/sched.h>
 #include	<linux/mouse.h>
 #include	<linux/tty.h>
+#include	<linux/signal.h>
+#include	<linux/errno.h>
+
 #include	<asm/io.h>
 #include	<asm/segment.h>
 #include	<asm/system.h>
 #include	<asm/irq.h>
-#include	<signal.h>
-#include	<errno.h>
-#include	<signal.h>
 
 static struct mouse_status mouse;
 
-static void mouse_interrupt(int cpl)
+static void mouse_interrupt(int unused)
 {
 	char dx, dy, buttons;
 
@@ -77,8 +77,6 @@
 		return -EBUSY;
 	if (!mouse.present)
 		return -EINVAL;
-	if (request_irq(MOUSE_IRQ, mouse_interrupt))
-		return -EBUSY;
 	mouse.active = 1;
 	mouse.ready = 0;
 	mouse.inode = inode;
@@ -86,6 +84,13 @@
 	mouse.dy = 0;	
 	mouse.buttons = mouse.latch_buttons = 0x80;
 	MSE_INT_ON();	
+	if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
+		MSE_INT_OFF();
+		mouse.active = 0;
+		mouse.ready = 0;
+		mouse.inode = NULL;
+		return -EBUSY;
+	}
 	return 0;
 }
 
diff --git a/kernel/chr_drv/pty.c b/kernel/chr_drv/pty.c
index 729be84..76a8915 100644
--- a/kernel/chr_drv/pty.c
+++ b/kernel/chr_drv/pty.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/chr_drv/pty.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -12,8 +12,7 @@
  *	void spty_write(struct tty_struct * queue);
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/fcntl.h>
diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c
index 284f0b6..13e15b8 100644
--- a/kernel/chr_drv/serial.c
+++ b/kernel/chr_drv/serial.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/serial.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -13,9 +13,8 @@
  * and all interrupts pertaining to serial IO.
  */
 
-#include <signal.h>
-#include <errno.h>
-
+#include <linux/errno.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/tty.h>
@@ -33,24 +32,6 @@
 	{ PORT_UNKNOWN, 3, 0x2E8, 3, NULL},
 };
 
-static void send_intr(struct serial_struct * info);
-
-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 (info->tty->termios.c_cflag & CRTSCTS)
-			info->tty->stopped = !(status & 0x10);
-
-		if (!info->tty->stopped)
-			send_intr(info);
-	}
-}
-
 void send_break(unsigned int line)
 {
 	unsigned short port;
@@ -131,6 +112,22 @@
 /*	printk("line status: %02x\n",status); */
 }
 
+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 (info->tty->termios.c_cflag & CRTSCTS)
+			info->tty->stopped = !(status & 0x10);
+
+		if (!info->tty->stopped)
+			send_intr(info);
+	}
+}
+
 static void (*jmp_table[4])(struct serial_struct *) = {
 	modem_status_intr,
 	send_intr,
@@ -173,22 +170,22 @@
 /*
  * IRQ routines: one per line
  */
-static void com1_IRQ(int cpl)
+static void com1_IRQ(int unused)
 {
 	check_tty(serial_table+0);
 }
 
-static void com2_IRQ(int cpl)
+static void com2_IRQ(int unused)
 {
 	check_tty(serial_table+1);
 }
 
-static void com3_IRQ(int cpl)
+static void com3_IRQ(int unused)
 {
 	check_tty(serial_table+2);
 }
 
-static void com4_IRQ(int cpl)
+static void com4_IRQ(int unused)
 {
 	check_tty(serial_table+3);
 }
@@ -304,16 +301,20 @@
 
 static void startup(unsigned short port)
 {
+	int i;
+
 	outb_p(0x03,port+3);	/* reset DLAB */
-	outb_p(0x0f,port+4);	/* set DTR,RTS, OUT_2 */
+	outb_p(0x0b,port+4);	/* set DTR,RTS, OUT_2 */
 	outb_p(0x0f,port+1);	/* enable all intrs */
 	inb_p(port+2);
 	inb_p(port+6);
 	inb_p(port+2);
 	inb_p(port+5);
-	do {		/* drain all of the stuck characters out of the port */
+	for (i = 0; i < 16 ; i++) {
 		inb_p(port+0);
-	} while (inb_p(port+5) & 1 == 1);
+		if (!(inb_p(port+5) & 1))
+			break;
+	}
 	inb_p(port+2);
 	inb_p(port+5);
 }
@@ -368,8 +369,12 @@
 	struct serial_struct * info;
 	int irq,retval;
 	unsigned short port;
-	void (*handler)(int) = serial_handler[line];
+	struct sigaction sa;
 
+	sa.sa_handler = serial_handler[line];
+	sa.sa_flags = SA_INTERRUPT;
+	sa.sa_mask = 0;
+	sa.sa_restorer = NULL;
 	if (line >= NR_SERIALS)
 		return -ENODEV;
 	info = serial_table + line;
@@ -378,7 +383,7 @@
 	irq = info->irq;
 	if (irq == 2)
 		irq = 9;
-	if (retval = request_irq(irq,handler))
+	if (retval = irqaction(irq,&sa))
 		return retval;
 	startup(port);
 	return 0;
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index f50227c..67d4153 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/tty_io.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -11,16 +11,14 @@
  * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
  */
 
-#include <errno.h>
-#include <signal.h>
-
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
 #include <linux/fcntl.h>
-
-#define ALRMMASK (1<<(SIGALRM-1))
-
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/ctype.h>
+
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -28,10 +26,6 @@
 #include <sys/kd.h>
 #include "vt_kern.h"
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define QUEUES	(3*(NR_CONSOLES+NR_SERIALS+2*NR_PTYS))
 static struct tty_queue * tty_queues;
 struct tty_struct tty_table[256];
@@ -60,7 +54,7 @@
  */
 struct tty_queue * table_list[] = { NULL, NULL };
 
-void put_tty_queue(char c, struct tty_queue * queue)
+void inline put_tty_queue(char c, struct tty_queue * queue)
 {
 	int head;
 	unsigned long flags;
@@ -74,7 +68,7 @@
 	__asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 }
 
-int get_tty_queue(struct tty_queue * queue)
+int inline get_tty_queue(struct tty_queue * queue)
 {
 	int result = -1;
 	unsigned long flags;
@@ -88,7 +82,7 @@
 	return result;
 }
 
-void tty_write_flush(struct tty_struct * tty)
+void inline tty_write_flush(struct tty_struct * tty)
 {
 	if (EMPTY(tty->write_q))
 		return;
@@ -132,6 +126,7 @@
 void wait_for_keypress(void)
 {
 	sleep_if_empty(tty_table[fg_console].secondary);
+	flush_input(&tty_table[fg_console]);
 }
 
 void copy_to_cooked(struct tty_struct * tty)
@@ -177,7 +172,6 @@
 						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);
 				}
@@ -199,7 +193,6 @@
 					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);
 				continue;
@@ -214,7 +207,6 @@
 			if ((START_CHAR(tty) != __DISABLED_CHAR) &&
 			    (c==START_CHAR(tty))) {
 				tty->stopped=0;
-				TTY_WRITE_FLUSH(tty);
 				continue;
 			}
 		}
@@ -241,7 +233,7 @@
 		if (c==10 || (EOF_CHAR(tty) != __DISABLED_CHAR &&
 		    c==EOF_CHAR(tty)))
 			tty->secondary->data++;
-		if ((L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty))) && (c==10)) {
+		if ((c==10) && (L_ECHO(tty) || (L_CANON(tty) && L_ECHONL(tty)))) {
 			put_tty_queue(10,tty->write_q);
 			put_tty_queue(13,tty->write_q);
 		} else if (L_ECHO(tty)) {
@@ -252,12 +244,11 @@
 				put_tty_queue(c,tty->write_q);
 		}
 		put_tty_queue(c,tty->secondary);
-		TTY_WRITE_FLUSH(tty);
 	}
 	TTY_WRITE_FLUSH(tty);
 	if (!EMPTY(tty->secondary))
 		wake_up(&tty->secondary->proc_list);
-	if (LEFT(tty->write_q) > TTY_BUF_SIZE/2)
+	if (tty->write_q->proc_list && LEFT(tty->write_q) > TTY_BUF_SIZE/2)
 		wake_up(&tty->write_q->proc_list);
 }
 
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index d508807..eb213ac 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -1,16 +1,16 @@
 /*
  *  linux/kernel/chr_drv/tty_ioctl.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-#include <termios.h>
-#include <sys/types.h>
-
+#include <linux/types.h>
+#include <linux/termios.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/fcntl.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -391,6 +391,23 @@
 			if (!IS_A_SERIAL(dev))
 				return -EINVAL;
 			return set_serial_info(dev-64,(struct serial_struct *) arg);
+		case FIONBIO:
+			if (arg)
+				file->f_flags |= O_NONBLOCK;
+			else
+				file->f_flags &= ~O_NONBLOCK;
+			return 0;
+		case TIOCNOTTY:
+			if (MINOR(file->f_rdev) != current->tty)
+				return -EINVAL;
+			current->tty = -1;
+			if (current->leader) {
+				if (tty->pgrp > 0)
+					kill_pg(tty->pgrp, SIGHUP, 0);
+				tty->pgrp = -1;
+				tty->session = 0;
+			}
+			return 0;
 		default:
 			return vt_ioctl(tty, dev, cmd, arg);
 	}
diff --git a/kernel/chr_drv/vt.c b/kernel/chr_drv/vt.c
index 407f09b..580e6b5 100644
--- a/kernel/chr_drv/vt.c
+++ b/kernel/chr_drv/vt.c
@@ -1,24 +1,22 @@
 /*
  *  kernel/chr_drv/vt.c
  *
- *  (C) 1992 obz under the linux copyright
+ *  Copyright (C) 1992 obz under the linux copyright
  */
 
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/kd.h>
-#include <sys/vt.h>
-
-#include <asm/io.h>
-#include <asm/segment.h>
-
+#include <linux/types.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
 
+#include <asm/io.h>
+#include <asm/segment.h>
+
 #include "vt_kern.h"
+#include <sys/kd.h>
+#include <sys/vt.h>
 
 /*
  * console (vt and kd) routines, as defined by usl svr4 manual
diff --git a/kernel/exit.c b/kernel/exit.c
index 221d142..b31e90e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1,19 +1,19 @@
 /*
  *  linux/kernel/exit.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define DEBUG_PROC_TREE
 
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
+
 #include <asm/segment.h>
 
 int sys_close(int fd);
diff --git a/kernel/fork.c b/kernel/fork.c
index ca15238..e80abe8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/fork.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -10,15 +10,18 @@
  * Fork is rather simple, once you get the hang of it, but the memory
  * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  */
-#include <errno.h>
-#include <stddef.h>
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/stddef.h>
+
 #include <asm/segment.h>
 #include <asm/system.h>
 
+#define MAX_TASKS_PER_USER ((NR_TASKS/4)*3)
+
 long last_pid=0;
 
 void verify_area(void * addr,int size)
@@ -41,8 +44,8 @@
 	unsigned long old_data_base,new_data_base,data_limit;
 	unsigned long old_code_base,new_code_base,code_limit;
 
-	code_limit=get_limit(0x0f);
-	data_limit=get_limit(0x17);
+	code_limit = get_limit(0x0f);
+	data_limit = get_limit(0x17);
 	old_code_base = get_base(current->ldt[1]);
 	old_data_base = get_base(current->ldt[2]);
 	if (old_data_base != old_code_base) {
@@ -67,14 +70,21 @@
 static int find_empty_process(void)
 {
 	int i, task_nr;
+	int this_user_tasks = 0;
 
-	repeat:
-		if ((++last_pid) & 0xffff0000)
-			last_pid=1;
-		for(i=0 ; i<NR_TASKS ; i++)
-			if (task[i] && ((task[i]->pid == last_pid) ||
-				        (task[i]->pgrp == last_pid)))
-				goto repeat;
+repeat:
+	if ((++last_pid) & 0xffff0000)
+		last_pid=1;
+	for(i=0 ; i < NR_TASKS ; i++) {
+		if (!task[i])
+			continue;
+		if (task[i]->uid == current->uid)
+			this_user_tasks++;
+		if (task[i]->pid == last_pid || task[i]->pgrp == last_pid)
+			goto repeat;
+	}
+	if (this_user_tasks > MAX_TASKS_PER_USER && !suser())
+		return -EAGAIN;
 /* Only the super-user can fill the last available slot */
 	task_nr = 0;
 	for(i=1 ; i<NR_TASKS ; i++)
@@ -102,7 +112,7 @@
 	int i,nr;
 	struct file *f;
 
-	p = (struct task_struct *) get_free_page();
+	p = (struct task_struct *) get_free_page(GFP_KERNEL);
 	if (!p)
 		return -EAGAIN;
 	nr = find_empty_process();
@@ -117,6 +127,8 @@
 	p->state = TASK_UNINTERRUPTIBLE;
 	p->flags &= ~PF_PTRACED;
 	p->pid = last_pid;
+	if (p->pid > 1)
+		p->swappable = 1;
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
 	SET_LINKS(p);
diff --git a/kernel/ioport.c b/kernel/ioport.c
index 70a77dd..0fde696 100644
--- a/kernel/ioport.c
+++ b/kernel/ioport.c
@@ -7,9 +7,8 @@
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
-
-#include <sys/types.h>
-#include <errno.h>
+#include <linux/errno.h>
+#include <linux/types.h>
 
 #define _IODEBUG
 
diff --git a/kernel/irq.c b/kernel/irq.c
index 8b6cd69..438fb68 100644
--- a/kernel/irq.c
+++ b/kernel/irq.c
@@ -1,7 +1,7 @@
 /*
  *	linux/kernel/irq.c
  *
- *	(C) 1992 Linus Torvalds
+ *	Copyright (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
@@ -22,20 +22,15 @@
  * sa_restorer is the unused
  */
 
-#include <signal.h>
-#include <errno.h>
-
-#include <sys/ptrace.h>
-
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/signal.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 },
-};
-
 void irq13(void);
 
 /*
@@ -45,6 +40,13 @@
  * the operations that are needed to keep the AT interrupt-controller
  * happy. They are also written to be fast - and to disable interrupts
  * as little as humanly possible.
+ *
+ * NOTE! These macros expand to three different handlers for each line: one
+ * complete handler that does all the fancy stuff (including signal handling),
+ * and one fast handler that is meant for simple IRQ's that want to be
+ * atomic. The specific handler is chosen depending on the SA_INTERRUPT
+ * flag when installing a handler. Finally, one "bad interrupt" handler, that
+ * is used when no handler is present.
  */
 BUILD_IRQ(FIRST,0,0x01)
 BUILD_IRQ(FIRST,1,0x02)
@@ -64,39 +66,77 @@
 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). If no handler exists, we return
- * an error value, telling the low-level IRQ routines not to
- * re-enable this IRQ line.
- *
- * 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.
+ * Pointers to the low-level handlers: first the general ones, then the
+ * fast ones, then the bad ones.
+ */
+static void (*interrupt[16])(void) = {
+	IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
+	IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
+	IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
+	IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
+};
+
+static void (*fast_interrupt[16])(void) = {
+	fast_IRQ0_interrupt, fast_IRQ1_interrupt,
+	fast_IRQ2_interrupt, fast_IRQ3_interrupt,
+	fast_IRQ4_interrupt, fast_IRQ5_interrupt,
+	fast_IRQ6_interrupt, fast_IRQ7_interrupt,
+	fast_IRQ8_interrupt, fast_IRQ9_interrupt,
+	fast_IRQ10_interrupt, fast_IRQ11_interrupt,
+	fast_IRQ12_interrupt, fast_IRQ13_interrupt,
+	fast_IRQ14_interrupt, fast_IRQ15_interrupt
+};
+
+static void (*bad_interrupt[16])(void) = {
+	bad_IRQ0_interrupt, bad_IRQ1_interrupt,
+	bad_IRQ2_interrupt, bad_IRQ3_interrupt,
+	bad_IRQ4_interrupt, bad_IRQ5_interrupt,
+	bad_IRQ6_interrupt, bad_IRQ7_interrupt,
+	bad_IRQ8_interrupt, bad_IRQ9_interrupt,
+	bad_IRQ10_interrupt, bad_IRQ11_interrupt,
+	bad_IRQ12_interrupt, bad_IRQ13_interrupt,
+	bad_IRQ14_interrupt, bad_IRQ15_interrupt
+};
+
+/*
+ * Initial irq handlers.
+ */
+static struct sigaction irq_sigaction[16] = {
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
+	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+};
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts disabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
  */
 int do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct sigaction * sa = irq + irq_sigaction;
-	void (*handler)(int);
-	unsigned int esp;
 
-	if (!(handler = sa->sa_handler))
-		return -1;	/* the irq isn't re-enabled */
-	__asm__ __volatile__("movl %%esp,%0":"=r" (esp));
-	if (esp < 200+(unsigned long)(current+1)) {
-		printk("Stack overflow on IRQ%d: shutting down\n",irq);
-		return -1;
-	}
-	if (sa->sa_flags & SA_INTERRUPT)
-		cli();
-	handler(regs->cs & 3);
-	sti();
+	sa->sa_handler((int) regs);
+	return 0;		/* re-enable the irq when returning */
+}
+
+/*
+ * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
+ * stuff - the handler is also running with interrupts disabled unless
+ * it explicitly enables them later.
+ */
+int do_fast_IRQ(int irq)
+{
+	struct sigaction * sa = irq + irq_sigaction;
+
+	sa->sa_handler(0);
 	return 0;		/* re-enable the irq when returning */
 }
 
@@ -107,18 +147,24 @@
 
 	if (irq > 15)
 		return -EINVAL;
-	if (irq == 2)
-		irq = 9;
 	sa = irq + irq_sigaction;
 	if (sa->sa_mask)
 		return -EBUSY;
+	if (!new->sa_handler)
+		return -EINVAL;
 	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=r" (flags));
 	*sa = *new;
 	sa->sa_mask = 1;
+	if (sa->sa_flags & SA_INTERRUPT)
+		set_intr_gate(0x20+irq,fast_interrupt[irq]);
+	else
+		set_intr_gate(0x20+irq,interrupt[irq]);
 	if (irq < 8)
 		outb(inb_p(0x21) & ~(1<<irq),0x21);
-	else
+	else {
+		outb(inb_p(0x21) & ~(1<<2),0x21);
 		outb(inb_p(0xA1) & ~(1<<(irq-8)),0xA1);
+	}
 	__asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 	return 0;
 }
@@ -152,6 +198,7 @@
 		outb(inb_p(0x21) | (1<<irq),0x21);
 	else
 		outb(inb_p(0xA1) | (1<<(irq-8)),0xA1);
+	set_intr_gate(0x20+irq,bad_interrupt[irq]);
 	sa->sa_handler = NULL;
 	sa->sa_flags = 0;
 	sa->sa_mask = 0;
@@ -159,32 +206,31 @@
 	__asm__ __volatile__("pushl %0 ; popfl"::"r" (flags));
 }
 
-extern void math_error(void);
+extern void do_coprocessor_error(long,long);
 
 static void math_error_irq(int cpl)
 {
 	outb(0,0xF0);
-	math_error();
+	do_coprocessor_error(0,0);
 }
 
+static void no_action(int cpl) { }
+
+static struct sigaction ignore_IRQ = {
+	no_action,
+	0,
+	SA_INTERRUPT,
+	NULL
+};
+
 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,IRQ9_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);
+	int i;
+
+	for (i = 0; i < 16 ; i++)
+		set_intr_gate(0x20+i,bad_interrupt[i]);
+	if (irqaction(2,&ignore_IRQ))
+		printk("Unable to get IRQ2 for cascade\n");
 	if (request_irq(13,math_error_irq))
 		printk("Unable to get IRQ13 for math-error handler\n");
 }
diff --git a/kernel/itimer.c b/kernel/itimer.c
index d04e2e7..b69e1da 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -1,18 +1,18 @@
 /*
  * linux/kernel/itimer.c
  *
- * (C) 1992 Darren Senn
+ * Copyright (C) 1992 Darren Senn
  */
 
 /* These are all the functions necessary to implement itimers */
 
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <asm/segment.h>
+#include <linux/errno.h>
+#include <linux/time.h>
 
-#include <signal.h>
-#include <sys/time.h>
-#include <errno.h>
+#include <asm/segment.h>
 
 static unsigned long tvtojiffies(struct timeval *value)
 {
diff --git a/kernel/math/Makefile b/kernel/math/Makefile
index 67828ab..5b2a163 100644
--- a/kernel/math/Makefile
+++ b/kernel/math/Makefile
@@ -13,7 +13,7 @@
 .c.o:
 	$(CC) $(CFLAGS) $(MATH_EMULATION) -c $<
 
-OBJS  = emulate.o error.o convert.o ea.o get_put.o \
+OBJS  = emulate.o convert.o ea.o get_put.o \
 	add.o mul.o div.o compare.o sqrt.o
 
 math.a: $(OBJS)
@@ -31,62 +31,67 @@
 
 ### Dependencies:
 add.o : add.c /usr/src/linux/include/linux/math_emu.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/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 /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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
 compare.o : compare.c /usr/src/linux/include/linux/math_emu.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/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 /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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
 convert.o : convert.c /usr/src/linux/include/linux/math_emu.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/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 /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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
 div.o : div.c /usr/src/linux/include/linux/math_emu.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/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 /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 
-ea.o : ea.c /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/math_emu.h \
+  /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
+ea.o : ea.c /usr/src/linux/include/linux/stddef.h /usr/src/linux/include/linux/math_emu.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/types.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/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/asm/segment.h 
-emulate.o : emulate.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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 
-error.o : error.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.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 
-get_put.o : get_put.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/linux/math_emu.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/segment.h 
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/asm/segment.h 
+emulate.o : emulate.c /usr/src/linux/include/linux/signal.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
+get_put.o : get_put.c /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/math_emu.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/asm/segment.h 
 mul.o : mul.c /usr/src/linux/include/linux/math_emu.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/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 /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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
 sqrt.o : sqrt.c /usr/src/linux/include/linux/math_emu.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/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 /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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h 
diff --git a/kernel/math/add.c b/kernel/math/add.c
index 5cf84ef..563ec69 100644
--- a/kernel/math/add.c
+++ b/kernel/math/add.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/add.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
diff --git a/kernel/math/compare.c b/kernel/math/compare.c
index 4f1dfac..e3d676c 100644
--- a/kernel/math/compare.c
+++ b/kernel/math/compare.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/compare.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
diff --git a/kernel/math/convert.c b/kernel/math/convert.c
index e938324..3f5bbdf 100644
--- a/kernel/math/convert.c
+++ b/kernel/math/convert.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/convert.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 #include <linux/math_emu.h>
diff --git a/kernel/math/div.c b/kernel/math/div.c
index e485fd9..55ee711 100644
--- a/kernel/math/div.c
+++ b/kernel/math/div.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/div.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
diff --git a/kernel/math/ea.c b/kernel/math/ea.c
index 571dc1e..dba41ff 100644
--- a/kernel/math/ea.c
+++ b/kernel/math/ea.c
@@ -1,16 +1,16 @@
 /*
  * linux/kernel/math/ea.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
  * Calculate the effective address.
  */
 
-#include <stddef.h>
-
+#include <linux/stddef.h>
 #include <linux/math_emu.h>
+
 #include <asm/segment.h>
 
 static int __regoffset[] = {
diff --git a/kernel/math/emulate.c b/kernel/math/emulate.c
index f3a6829..1df0691 100644
--- a/kernel/math/emulate.c
+++ b/kernel/math/emulate.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/emulate.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
@@ -32,7 +32,7 @@
 
 #ifdef KERNEL_MATH_EMULATION
 
-#include <signal.h>
+#include <linux/signal.h>
 
 #define __ALIGNED_TEMP_REAL 1
 #include <linux/math_emu.h>
@@ -537,7 +537,7 @@
 
 #else /* no math emulation */
 
-#include <signal.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
 
 void math_emulate(long ___false)
diff --git a/kernel/math/error.c b/kernel/math/error.c
deleted file mode 100644
index a4218a2..0000000
--- a/kernel/math/error.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/kernel/math/error.c
- *
- * (C) 1991 Linus Torvalds
- */
-
-#include <signal.h>
-
-#include <linux/sched.h>
-
-void math_error(void)
-{
-	if (last_task_used_math)
-		send_sig(SIGFPE,last_task_used_math,1);
-	__asm__("fnclex");
-}
diff --git a/kernel/math/get_put.c b/kernel/math/get_put.c
index 39063fe..bb603cb 100644
--- a/kernel/math/get_put.c
+++ b/kernel/math/get_put.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/get_put.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
@@ -9,8 +9,7 @@
  * ints/reals/BCD etc. This is the only part that concerns itself with
  * other than temporary real format. All other cals are strictly temp_real.
  */
-#include <signal.h>
-
+#include <linux/signal.h>
 #include <linux/math_emu.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
diff --git a/kernel/math/mul.c b/kernel/math/mul.c
index ae85e70..506f418 100644
--- a/kernel/math/mul.c
+++ b/kernel/math/mul.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/mul.c
  *
- * (C) 1991 Linus Torvalds
+ * Copyright (C) 1991, 1992 Linus Torvalds
  */
 
 /*
diff --git a/kernel/math/sqrt.c b/kernel/math/sqrt.c
index 8982d75..8522224 100644
--- a/kernel/math/sqrt.c
+++ b/kernel/math/sqrt.c
@@ -1,7 +1,7 @@
 /*
  * linux/kernel/math/sqrt.c
  *
- * (C) 1991 Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
diff --git a/kernel/mktime.c b/kernel/mktime.c
index a67db96..5de9c67 100644
--- a/kernel/mktime.c
+++ b/kernel/mktime.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/mktime.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <time.h>
diff --git a/kernel/panic.c b/kernel/panic.c
index 7d8a06b..2459e76 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/panic.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
diff --git a/kernel/printk.c b/kernel/printk.c
index 1d5ef8d..2e0a7a1 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1,16 +1,15 @@
 /*
  *  linux/kernel/printk.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <stdarg.h>
-#include <stddef.h>
-#include <errno.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
@@ -39,7 +38,7 @@
 			wake_up(&log_wait);
 			return 0;
 		case 1:
-			i = get_free_page();
+			i = get_free_page(GFP_KERNEL);
 			if (log_page) {
 				free_page(i);
 				return 0;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4cfc7c8..07f3a8d 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -6,13 +6,12 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 
-#include <errno.h>
-#include <sys/ptrace.h>
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -31,9 +30,6 @@
  */
 #define MAGICNUMBER 68
 
-void do_no_page(unsigned long, unsigned long, struct task_struct *, unsigned long);
-void write_verify(unsigned long);
-
 /* change a pid into a task struct. */
 static inline struct task_struct * get_task(int pid)
 {
@@ -135,7 +131,7 @@
 		goto repeat;
 	}
 	if (!(page & PAGE_RW)) {
-		write_verify(addr);
+		do_wp_page(0,addr,tsk,0);
 		goto repeat;
 	}
 	page &= 0xfffff000;
diff --git a/kernel/sched.c b/kernel/sched.c
index f8ad4ad..208aefb 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/sched.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -13,18 +13,19 @@
 
 #define TIMER_IRQ 0
 
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
 #include <linux/sys.h>
 #include <linux/fdreg.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/ptrace.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/segment.h>
-#include <sys/time.h>
-
-#include <signal.h>
-#include <errno.h>
 
 int need_resched = 0;
 
@@ -381,7 +382,13 @@
 unsigned long timer_active = 0;
 struct timer_struct timer_table[32];
 
-static void do_timer(int cpl)
+/*
+ * The int argument is really a (struct pt_regs *), in case the
+ * interrupt wants to know from where it was called. The timer
+ * irq uses this to decide if it should update the user or system
+ * times.
+ */
+static void do_timer(int regs)
 {
 	unsigned long mask;
 	struct timer_struct *tp = timer_table+0;
@@ -389,10 +396,16 @@
 	static int avg_cnt = 0;
 
 	jiffies++;
-	if (!cpl)
-		current->stime++;
-	else
+	if (3 & ((struct pt_regs *) regs)->cs)
 		current->utime++;
+	else {
+		current->stime++;
+		/* 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);
+		}
+	}
 	if (--avg_cnt < 0) {
 		avg_cnt = 500;
 		update_avg();
@@ -414,11 +427,6 @@
 		current->it_prof_value = current->it_prof_incr;
 		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;
diff --git a/kernel/signal.c b/kernel/signal.c
index ea33ca1..ca850fa 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1,17 +1,17 @@
 /*
  *  linux/kernel/signal.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <asm/segment.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
 
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/ptrace.h>
-#include <errno.h>
+#include <asm/segment.h>
 
 extern int core_dump(long signr,struct pt_regs * regs);
 
@@ -122,6 +122,11 @@
 
 extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
 
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
 int do_signal(long signr,struct pt_regs * regs)
 {
 	unsigned long sa_handler;
@@ -154,6 +159,8 @@
 		return(1);   /* Ignore, see if there are more signals... */
 	}
 	if (!sa_handler) {
+		if (current->pid == 1)
+			return 1;
 		switch (signr) {
 		case SIGCONT:
 		case SIGCHLD:
diff --git a/kernel/sys.c b/kernel/sys.c
index 013b6d4..94a8de5 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1,22 +1,22 @@
 /*
  *  linux/kernel/sys.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <errno.h>
-
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
-#include <asm/segment.h>
-#include <sys/times.h>
+#include <linux/times.h>
 #include <linux/utsname.h>
-#include <sys/param.h>
-#include <sys/resource.h>
+#include <linux/param.h>
+#include <linux/resource.h>
 #include <linux/string.h>
 
+#include <asm/segment.h>
+
 /*
  * this indicates wether you can reboot with ctrl-alt-del: the deault is yes
  */
@@ -165,8 +165,7 @@
 	if (C_A_D)
 		hard_reset_now();
 	else
-		if (task[1])
-			send_sig(SIGINT,task[1],1);
+		send_sig(SIGINT,task[1],1);
 }
 	
 
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
index 410f3fe..735a795 100644
--- a/kernel/sys_call.S
+++ b/kernel/sys_call.S
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/sys_call.S
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -168,27 +168,6 @@
 	iret
 
 .align 2
-_coprocessor_error:
-	pushl $-1		# mark this as an int. 
-	SAVE_ALL
-	pushl $ret_from_sys_call
-	jmp _math_error
-
-.align 2
-_device_not_available:
-	pushl $-1		# mark this as an int
-	SAVE_ALL
-	pushl $ret_from_sys_call
-	clts				# clear TS so that we can use math
-	movl %cr0,%eax
-	testl $0x4,%eax			# EM (math emulation bit)
-	je _math_state_restore
-	pushl $0		# temporary storage for ORIG_EIP
-	call _math_emulate
-	addl $4,%esp
-	ret
-
-.align 2
 _sys_execve:
 	lea (EIP+4)(%esp),%eax  # don't forget about the return address.
 	pushl %eax
@@ -228,9 +207,29 @@
 	addl $8,%esp
 	jmp ret_from_sys_call
 
+.align 2
+_coprocessor_error:
+	pushl $0
+	pushl $_do_coprocessor_error
+	jmp error_code
+
+.align 2
+_device_not_available:
+	pushl $-1		# mark this as an int
+	SAVE_ALL
+	pushl $ret_from_sys_call
+	clts				# clear TS so that we can use math
+	movl %cr0,%eax
+	testl $0x4,%eax			# EM (math emulation bit)
+	je _math_state_restore
+	pushl $0		# temporary storage for ORIG_EIP
+	call _math_emulate
+	addl $4,%esp
+	ret
+
 _debug:
 	pushl $0
-	pushl $_do_int3		# _do_debug
+	pushl $_do_debug
 	jmp error_code
 
 _nmi:
diff --git a/kernel/traps.c b/kernel/traps.c
index 9931015..8d7d039 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/traps.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -10,16 +10,15 @@
  * to mainly kill the offending process (probably by giving it a signal,
  * but possibly by killing it outright if necessary).
  */
-#include <linux/string.h>
-
 #include <linux/head.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
-#include <errno.h>
-
 
 #define get_seg_byte(seg,addr) ({ \
 register char __res; \
@@ -59,57 +58,53 @@
 void reserved(void);
 void alignment_check(void);
 
-static void die(char * str,long esp_ptr,long nr)
+static void die_if_kernel(char * str,long esp_ptr,long nr)
 {
 	long * esp = (long *) esp_ptr;
 	int i;
 
+	if ((0xffff & esp[1]) == 0xf)
+		return;
 	printk("%s: %04x\n\r",str,nr&0xffff);
 	printk("EIP:    %04x:%p\nEFLAGS: %p\n", 0xffff & esp[1],esp[0],esp[2]);
-	if ((0xffff & esp[1]) == 0xf)
-		printk("ESP:    %04x:%p\n",0xffff & esp[4],esp[3]);
 	printk("fs: %04x\n",_fs());
 	printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
-	if ((0xffff & esp[1]) == 0xf) {
-		printk("Stack: ");
-		for (i=0;i<4;i++)
-			printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
-		printk("\n");
-	}
 	str(i);
 	printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i);
 	for(i=0;i<10;i++)
 		printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
 	printk("\n\r");
-	if ((0xffff & esp[1]) == 0xf)
-		send_sig(SIGSEGV, current, 0);
-	else
-		do_exit(SIGSEGV);
+	do_exit(SIGSEGV);
 }
 
 void do_double_fault(long esp, long error_code)
 {
-	die("double fault",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("double fault",esp,error_code);
 }
 
 void do_general_protection(long esp, long error_code)
 {
-	die("general protection",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("general protection",esp,error_code);
 }
 
 void do_alignment_check(long esp, long error_code)
 {
-	die("alignment check",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("alignment check",esp,error_code);
 }
 
 void do_divide_error(long esp, long error_code)
 {
-	die("divide error",esp,error_code);
+	send_sig(SIGFPE, current, 1);
+	die_if_kernel("divide error",esp,error_code);
 }
 
 void do_int3(long esp, long error_code)
 {
-	send_sig(SIGTRAP, current, 0);
+	send_sig(SIGTRAP, current, 1);
+	die_if_kernel("int3",esp,error_code);
 }
 
 void do_nmi(long esp, long error_code)
@@ -119,59 +114,68 @@
 
 void do_debug(long esp, long error_code)
 {
-	send_sig(SIGTRAP, current, 0);
+	send_sig(SIGTRAP, current, 1);
+	die_if_kernel("debug",esp,error_code);
 }
 
 void do_overflow(long esp, long error_code)
 {
-	die("overflow",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("overflow",esp,error_code);
 }
 
 void do_bounds(long esp, long error_code)
 {
-	die("bounds",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("bounds",esp,error_code);
 }
 
 void do_invalid_op(long esp, long error_code)
 {
-	die("invalid operand",esp,error_code);
+	send_sig(SIGILL, current, 1);
+	die_if_kernel("invalid operand",esp,error_code);
 }
 
 void do_device_not_available(long esp, long error_code)
 {
-	die("device not available",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("device not available",esp,error_code);
 }
 
 void do_coprocessor_segment_overrun(long esp, long error_code)
 {
-	die("coprocessor segment overrun",esp,error_code);
+	send_sig(SIGFPE, last_task_used_math, 1);
+	die_if_kernel("coprocessor segment overrun",esp,error_code);
 }
 
 void do_invalid_TSS(long esp,long error_code)
 {
-	die("invalid TSS",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("invalid TSS",esp,error_code);
 }
 
 void do_segment_not_present(long esp,long error_code)
 {
-	die("segment not present",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("segment not present",esp,error_code);
 }
 
 void do_stack_segment(long esp,long error_code)
 {
-	die("stack segment",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("stack segment",esp,error_code);
 }
 
 void do_coprocessor_error(long esp, long error_code)
 {
-	if (last_task_used_math != current)
-		return;
-	die("coprocessor error",esp,error_code);
+	send_sig(SIGFPE, last_task_used_math, 1);
+	__asm__("fnclex");
 }
 
 void do_reserved(long esp, long error_code)
 {
-	die("reserved (15,17-47) error",esp,error_code);
+	send_sig(SIGSEGV, current, 1);
+	die_if_kernel("reserved (15,17-47) error",esp,error_code);
 }
 
 void trap_init(void)
diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c
index 8ce9873..3613e38 100644
--- a/kernel/vsprintf.c
+++ b/kernel/vsprintf.c
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/vsprintf.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
@@ -10,6 +10,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/types.h>
 #include <linux/string.h>
 
 /* we use this so that we can do without the ctype library */
diff --git a/lib/Makefile b/lib/Makefile
index 698c50d..b86a6d4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -37,15 +37,13 @@
 errno.o : errno.c 
 execve.o : execve.c /usr/src/linux/include/linux/unistd.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 \
-  /usr/src/linux/include/signal.h /usr/src/linux/include/asm/system.h 
+  /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h \
+  /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h \
+  /usr/src/linux/include/linux/minix_fs_sb.h /usr/src/linux/include/linux/ext_fs_sb.h \
+  /usr/src/linux/include/linux/msdos_fs_sb.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/asm/system.h 
 open.o : open.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/stdarg.h 
-setsid.o : setsid.c /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h \
-  /usr/src/linux/include/linux/unistd.h 
-string.o : string.c /usr/src/linux/include/linux/string.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h 
-wait.o : wait.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/sys/wait.h \
-  /usr/src/linux/include/sys/types.h /usr/src/linux/include/stddef.h 
-write.o : write.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h 
+setsid.o : setsid.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/unistd.h 
+string.o : string.c /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/string.h 
+wait.o : wait.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/linux/types.h 
+write.o : write.c /usr/src/linux/include/linux/unistd.h /usr/src/linux/include/linux/types.h 
diff --git a/lib/_exit.c b/lib/_exit.c
index a1630f4..b0b77e7 100644
--- a/lib/_exit.c
+++ b/lib/_exit.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/_exit.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
diff --git a/lib/close.c b/lib/close.c
index 31bb780..2c3f436 100644
--- a/lib/close.c
+++ b/lib/close.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/close.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
diff --git a/lib/ctype.c b/lib/ctype.c
index f1103a9..d3613be 100644
--- a/lib/ctype.c
+++ b/lib/ctype.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/ctype.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #include <linux/ctype.h>
diff --git a/lib/dup.c b/lib/dup.c
index fddb3c3..6d5ed11 100644
--- a/lib/dup.c
+++ b/lib/dup.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/dup.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
diff --git a/lib/errno.c b/lib/errno.c
index 50aca2e..41cb9d7 100644
--- a/lib/errno.c
+++ b/lib/errno.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/errno.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 int errno;
diff --git a/lib/execve.c b/lib/execve.c
index 996b0ea..32a93f0 100644
--- a/lib/execve.c
+++ b/lib/execve.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/execve.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
diff --git a/lib/itimer.c b/lib/itimer.c
deleted file mode 100644
index 69cf1eb..0000000
--- a/lib/itimer.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- *  linux/lib/itimer.c
- *
- *  (C) 1992  Darren Senn
- */
-
-#define __LIBRARY__
-#include <linux/unistd.h>
-#include <sys/time.h>
-
-_syscall2(int,getitimer,int,which,struct itimerval *,value)
-_syscall3(int,setitimer,int,which,struct itimerval *,value,struct itimerval *,ovalue)
diff --git a/lib/malloc.c b/lib/malloc.c
index 42723a7..e841689 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -99,7 +99,7 @@
 	struct bucket_desc *bdesc, *first;
 	int	i;
 	
-	first = bdesc = (struct bucket_desc *) get_free_page();
+	first = bdesc = (struct bucket_desc *) get_free_page(GFP_KERNEL);
 	if (!bdesc)
 		panic("Out of memory in init_bucket_desc()");
 	for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
@@ -153,7 +153,7 @@
 		free_bucket_desc = bdesc->next;
 		bdesc->refcnt = 0;
 		bdesc->bucket_size = bdir->size;
-		bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
+		bdesc->page = bdesc->freeptr = (void *) cp = get_free_page(GFP_KERNEL);
 		if (!cp)
 			panic("Out of memory in kernel malloc()");
 		/* Set up the chain of free objects */
diff --git a/lib/open.c b/lib/open.c
index 55c82ec..b69d2b5 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -1,7 +1,7 @@
 /*
  *  linux/lib/open.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
diff --git a/lib/setsid.c b/lib/setsid.c
index f9f056f..c157b71 100644
--- a/lib/setsid.c
+++ b/lib/setsid.c
@@ -1,11 +1,11 @@
 /*
  *  linux/lib/setsid.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
-#include <sys/types.h>
+#include <linux/types.h>
 #include <linux/unistd.h>
 
 _syscall0(pid_t,setsid)
diff --git a/lib/string.c b/lib/string.c
index ebbdfff..4f4722f 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -1,13 +1,15 @@
 /*
  *  linux/lib/string.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #ifndef __GNUC__
 #error I want gcc!
 #endif
 
+#include <linux/types.h>
+
 #define extern
 #define inline
 #define __LIBRARY__
diff --git a/lib/wait.c b/lib/wait.c
index 114ef33..727a271 100644
--- a/lib/wait.c
+++ b/lib/wait.c
@@ -1,12 +1,12 @@
 /*
  *  linux/lib/wait.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
 #include <linux/unistd.h>
-#include <sys/wait.h>
+#include <linux/types.h>
 
 _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
diff --git a/lib/write.c b/lib/write.c
index 5269cc6..9336ed9 100644
--- a/lib/write.c
+++ b/lib/write.c
@@ -1,12 +1,12 @@
 /*
  *  linux/lib/write.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 #define __LIBRARY__
 #include <linux/unistd.h>
-#include <sys/types.h>
+#include <linux/types.h>
 
 _syscall3(int,write,int,fd,const char *,buf,off_t,count)
 
diff --git a/mm/Makefile b/mm/Makefile
index c5ad9d3..9523711 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -29,23 +29,28 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-memory.o : memory.c /usr/src/linux/include/signal.h /usr/src/linux/include/sys/types.h \
-  /usr/src/linux/include/stddef.h /usr/src/linux/include/asm/system.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 
+memory.o : memory.c /usr/src/linux/include/asm/system.h /usr/src/linux/include/linux/signal.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/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/string.h 
 mmap.o : mmap.c /usr/src/linux/include/linux/stat.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/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 /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/asm/segment.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/errno.h /usr/src/linux/include/sys/mman.h 
-swap.o : swap.c /usr/src/linux/include/errno.h /usr/src/linux/include/linux/stat.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 /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/signal.h \
-  /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.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/linux/head.h /usr/src/linux/include/linux/fs.h /usr/src/linux/include/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/time.h /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/asm/system.h \
+  /usr/src/linux/include/sys/mman.h 
+swap.o : swap.c /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/fs.h \
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/signal.h \
+  /usr/src/linux/include/linux/sched.h /usr/src/linux/include/linux/head.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h 
diff --git a/mm/memory.c b/mm/memory.c
index 6fea346..209641e 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1,7 +1,7 @@
 /*
  *  linux/mm/memory.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -28,43 +28,59 @@
  * 20.12.91  -  Ok, making the swap-device changeable like the root.
  */
 
-#include <signal.h>
-
 #include <asm/system.h>
 
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/head.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
 current->start_code + current->end_code)
 
-unsigned long HIGH_MEMORY = 0;
+unsigned long low_memory = 0;
+unsigned long high_memory = 0;
+unsigned long paging_pages = 0;
 
 #define copy_page(from,to) \
 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
 
-#define CHECK_LAST_NR	16
+unsigned char * mem_map = NULL;
 
-static unsigned long last_pages[CHECK_LAST_NR] = { 0, };
+/*
+ * oom() prints a message (so that the user knows why the process died),
+ * and gives the process an untrappable SIGSEGV.
+ */
+void oom(struct task_struct * task)
+{
+	printk("\nout of memory\n");
+	task->sigaction[SIGSEGV-1].sa_handler = NULL;
+	task->blocked &= ~(1<<(SIGSEGV-1));
+	send_sig(SIGSEGV,task,1);
+}
 
-unsigned char mem_map [ PAGING_PAGES ] = {0,};
-
+int nr_free_pages = 0;
 /*
  * Free a page of memory at physical address 'addr'. Used by
  * 'free_page_tables()'
  */
 void free_page(unsigned long addr)
 {
-	if (addr < LOW_MEM) return;
-	if (addr < HIGH_MEMORY) {
-		addr -= LOW_MEM;
-		addr >>= 12;
-		if (mem_map[addr]--)
+	unsigned long i;
+
+	if (addr < low_memory)
+		return;
+	if (addr < high_memory) {
+		i = addr - low_memory;
+		i >>= 12;
+		if (mem_map[i] == 1)
+			++nr_free_pages;
+		if (mem_map[i]--)
 			return;
-		mem_map[addr]=0;
+		mem_map[i] = 0;
 	}
-	printk("trying to free free page: memory probably corrupted");
+	printk("trying to free free page (%08x): memory probably corrupted\n",addr);
 }
 
 /*
@@ -105,8 +121,6 @@
 		free_page(0xfffff000 & page_dir);
 	}
 	invalidate();
-	for (page = 0; page < CHECK_LAST_NR ; page++)
-		last_pages[page] = 0;
 	return 0;
 }
 
@@ -154,30 +168,36 @@
 			continue;
 		}
 		from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
-		if (!(to_page_table = (unsigned long *) get_free_page()))
+		if (!(to_page_table = (unsigned long *) get_free_page(GFP_KERNEL)))
 			return -1;	/* Out of memory, see freeing */
 		*to_dir = ((unsigned long) to_page_table) | 7;
 		nr = (from==0)?0xA0:1024;
 		for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
+repeat:
 			this_page = *from_page_table;
 			if (!this_page)
 				continue;
 			if (!(1 & this_page)) {
-				if (!(new_page = get_free_page()))
+				if (!(new_page = get_free_page(GFP_KERNEL)))
 					return -1;
 				++current->rss;
 				read_swap_page(this_page>>1, (char *) new_page);
+				if (*from_page_table != this_page) {
+					free_page(new_page);
+					goto repeat;
+				}
 				*to_page_table = this_page;
 				*from_page_table = new_page | (PAGE_DIRTY | 7);
 				continue;
 			}
 			this_page &= ~2;
 			*to_page_table = this_page;
-			if (this_page > LOW_MEM) {
+			if (this_page > low_memory) {
 				*from_page_table = this_page;
-				this_page -= LOW_MEM;
+				this_page -= low_memory;
 				this_page >>= 12;
-				mem_map[this_page]++;
+				if (!mem_map[this_page]++)
+					--nr_free_pages;
 			}
 		}
 	}
@@ -236,8 +256,6 @@
 		}
 	}
 	invalidate();
-	for (page = 0; page < CHECK_LAST_NR ; page++)
-		last_pages[page] = 0;
 	return 0;
 }
 
@@ -260,6 +278,7 @@
 {
 	unsigned long *page_table, *dir;
 	unsigned long poff, pcnt;
+	unsigned long page;
 
 	if ((from & 0xfff) || (to & 0xfff))
 		panic("remap_page_range called with wrong alignment");
@@ -271,7 +290,7 @@
 
 	while (size > 0) {
 		if (!(1 & *dir)) {
-			if (!(page_table = (unsigned long *)get_free_page())) {
+			if (!(page_table = (unsigned long *)get_free_page(GFP_KERNEL))) {
 				invalidate();
 				return -1;
 			}
@@ -299,12 +318,13 @@
 			if (permiss & 4)
 				mask |= 1;
 
-			if (*page_table) {
+			if (page = *page_table) {
+				*page_table = 0;
 				--current->rss;
-				if (1 & *page_table)
-					free_page(0xfffff000 & *page_table);
+				if (1 & page)
+					free_page(0xfffff000 & page);
 				else
-					swap_free(*page_table >> 1);
+					swap_free(page >> 1);
 			}
 
 			/*
@@ -314,16 +334,17 @@
 			 * when the page is referenced. current assumptions
 			 * cause it to be treated as demand allocation.
 			 */
-			if (mask == 4 || to >= HIGH_MEMORY)
+			if (mask == 4 || to >= high_memory)
 				*page_table++ = 0;	/* not present */
 			else {
 				++current->rss;
 				*page_table++ = (to | mask);
-				if (to > LOW_MEM) {
+				if (to > low_memory) {
 					unsigned long frame;
-					frame = to - LOW_MEM;
+					frame = to - low_memory;
 					frame >>= 12;
-					mem_map[frame]++;
+					if (!mem_map[frame]++)
+						--nr_free_pages;
 				}
 			}
 			to += PAGE_SIZE;
@@ -331,8 +352,6 @@
 		pcnt = (size > 1024 ? 1024 : size);
 	}
 	invalidate();
-	for (to = 0; to < CHECK_LAST_NR ; to++)
-		last_pages[to] = 0;
 	return 0;
 }
 
@@ -348,11 +367,11 @@
 
 /* NOTE !!! This uses the fact that _pg_dir=0 */
 
-	if (page < LOW_MEM || page >= HIGH_MEMORY) {
+	if (page >= high_memory) {
 		printk("put_page: trying to put page %p at %p\n",page,address);
 		return 0;
 	}
-	if (mem_map[(page-LOW_MEM)>>12] != 1) {
+	if (page >= low_memory && mem_map[(page-low_memory)>>12] != 1) {
 		printk("put_page: mem_map disagrees with %p at %p\n",page,address);
 		return 0;
 	}
@@ -360,10 +379,13 @@
 	if ((*page_table)&1)
 		page_table = (unsigned long *) (0xfffff000 & *page_table);
 	else {
-		if (!(tmp=get_free_page()))
-			return 0;
+		tmp = get_free_page(GFP_KERNEL);
+		if (!tmp) {
+			oom(current);
+			tmp = BAD_PAGETABLE;
+		}
 		*page_table = tmp | 7;
-		page_table = (unsigned long *) tmp;
+		return 0;
 	}
 	page_table += (address>>12) & 0x3ff;
 	if (*page_table) {
@@ -388,15 +410,15 @@
 
 /* NOTE !!! This uses the fact that _pg_dir=0 */
 
-	if (page < LOW_MEM || page >= HIGH_MEMORY)
+	if (page < low_memory || page >= high_memory)
 		printk("put_dirty_page: trying to put page %p at %p\n",page,address);
-	if (mem_map[(page-LOW_MEM)>>12] != 1)
+	if (mem_map[(page-low_memory)>>12] != 1)
 		printk("mem_map disagrees with %p at %p\n",page,address);
 	page_table = (unsigned long *) ((address>>20) & 0xffc);
 	if ((*page_table)&1)
 		page_table = (unsigned long *) (0xfffff000 & *page_table);
 	else {
-		if (!(tmp=get_free_page()))
+		if (!(tmp=get_free_page(GFP_KERNEL)))
 			return 0;
 		*page_table = tmp|7;
 		page_table = (unsigned long *) tmp;
@@ -412,7 +434,7 @@
 	return page;
 }
 
-void un_wp_page(unsigned long * table_entry)
+static void un_wp_page(unsigned long * table_entry, struct task_struct * task)
 {
 	unsigned long old_page;
 	unsigned long new_page = 0;
@@ -420,32 +442,36 @@
 
 repeat:
 	old_page = *table_entry;
-	dirty = old_page & PAGE_DIRTY;
 	if (!(old_page & 1)) {
 		if (new_page)
 			free_page(new_page);
 		return;
 	}
+	dirty = old_page & PAGE_DIRTY;
 	old_page &= 0xfffff000;
-	if (old_page >= HIGH_MEMORY) {
+	if (old_page >= high_memory) {
 		if (new_page)
 			free_page(new_page);
 		printk("bad page address\n\r");
-		do_exit(SIGSEGV);
+		send_sig(SIGSEGV, task, 1);
+		*table_entry = BAD_PAGE | 7;
+		return;
 	}
-	if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
+	if (old_page >= low_memory && mem_map[MAP_NR(old_page)]==1) {
 		*table_entry |= 2;
 		invalidate();
 		if (new_page)
 			free_page(new_page);
 		return;
 	}
-	if (!new_page) {
-		if (!(new_page=get_free_page()))
-			oom();
+	if (!new_page && (new_page=get_free_page(GFP_KERNEL)))
 		goto repeat;
+	if (new_page)
+		copy_page(old_page,new_page);
+	else {
+		new_page = BAD_PAGE;
+		send_sig(SIGSEGV,task,1);
 	}
-	copy_page(old_page,new_page);
 	*table_entry = new_page | dirty | 7;
 	free_page(old_page);
 	invalidate();
@@ -458,32 +484,49 @@
  *
  * If it's in code space we exit with a segment error.
  */
-void do_wp_page(unsigned long error_code,unsigned long address)
+void do_wp_page(unsigned long error_code, unsigned long address,
+	struct task_struct * tsk, unsigned long user_esp)
 {
-	if (address < TASK_SIZE) {
-		printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
-		do_exit(SIGSEGV);
+	unsigned long pde, pte, page;
+
+	pde = (address>>20) & 0xffc;
+	pte = *(unsigned long *) pde;
+	if ((pte & 3) != 3) {
+		printk("do_wp_page: bogus page-table at address %08x (%08x)\n",address,pte);
+		*(unsigned long *) pde = BAD_PAGETABLE | 7;
+		send_sig(SIGSEGV, tsk, 1);
+		return;
 	}
-	if (address - current->start_code >= TASK_SIZE) {
-		printk("Bad things happen: page error in do_wp_page\n\r");
-		do_exit(SIGSEGV);
+	if (address < TASK_SIZE) {
+		printk("do_wp_page: kernel WP error at address %08x (%08x)\n",address,pte);
+		*(unsigned long *) pde = BAD_PAGETABLE | 7;
+		send_sig(SIGSEGV, tsk, 1);
+		return;
+	}
+	pte &= 0xfffff000;
+	pte += (address>>10) & 0xffc;
+	page = *(unsigned long *) pte;
+	if ((page & 3) != 1) {
+		printk("do_wp_page: bogus page at address %08x (%08x)\n",address,page);
+		*(unsigned long *) pte = BAD_PAGE | 7;
+		send_sig(SIGSEGV, tsk, 1);
+		return;
 	}
 	++current->min_flt;
-	un_wp_page((unsigned long *)
-		(((address>>10) & 0xffc) + (0xfffff000 &
-		*((unsigned long *) ((address>>20) &0xffc)))));
+	un_wp_page((unsigned long *) pte, tsk);
 }
 
 void write_verify(unsigned long address)
 {
 	unsigned long page;
 
-	if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))
+	page = *(unsigned long *) ((address>>20) & 0xffc);
+	if (!(page & PAGE_PRESENT))
 		return;
 	page &= 0xfffff000;
 	page += ((address>>10) & 0xffc);
 	if ((3 & *(unsigned long *) page) == 1)  /* non-writeable, present */
-		un_wp_page((unsigned long *) page);
+		un_wp_page((unsigned long *) page, current);
 	return;
 }
 
@@ -491,10 +534,13 @@
 {
 	unsigned long tmp;
 
-	if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
-		free_page(tmp);		/* 0 is ok - ignored */
-		oom();
+	tmp = get_free_page(GFP_KERNEL);
+	if (!tmp) {
+		oom(current);
+		tmp = BAD_PAGE;
 	}
+	if (!put_page(tmp,address))
+		free_page(tmp);
 }
 
 /*
@@ -527,14 +573,14 @@
 	if ((phys_addr & 0x41) != 0x01)
 		return 0;
 	phys_addr &= 0xfffff000;
-	if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)
+	if (phys_addr >= high_memory || phys_addr < low_memory)
 		return 0;
 	to = *(unsigned long *) to_page;
 	if (!(to & 1)) {
-		if (to = get_free_page())
-			*(unsigned long *) to_page = to | 7;
-		else
-			oom();
+		to = get_free_page(GFP_KERNEL);
+		if (!to)
+			return 0;
+		*(unsigned long *) to_page = to | 7;
 	}
 	to &= 0xfffff000;
 	to_page = to + ((address>>10) & 0xffc);
@@ -544,9 +590,10 @@
 	*(unsigned long *) from_page &= ~2;
 	*(unsigned long *) to_page = *(unsigned long *) from_page;
 	invalidate();
-	phys_addr -= LOW_MEM;
+	phys_addr -= low_memory;
 	phys_addr >>= 12;
-	mem_map[phys_addr]++;
+	if (!mem_map[phys_addr]++)
+		--nr_free_pages;
 	return 1;
 }
 
@@ -587,9 +634,9 @@
 }
 
 /*
- * fill in an empty page or directory if none exists
+ * fill in an empty page-table if none exists
  */
-static unsigned long get_empty(unsigned long * p)
+static unsigned long get_empty_pgtable(unsigned long * p)
 {
 	unsigned long page = 0;
 
@@ -599,38 +646,29 @@
 		return *p;
 	}
 	if (*p) {
-		printk("get_empty: bad page entry \n");
+		printk("get_empty_pgtable: bad page-directory entry \n");
 		*p = 0;
 	}
 	if (page) {
 		*p = page | 7;
 		return *p;
 	}
-	if (!(page = get_free_page()))
-		oom();
-	goto repeat;
+	if (page = get_free_page(GFP_KERNEL))
+		goto repeat;
+	oom(current);
+	*p = BAD_PAGETABLE | 7;
+	return 0;
 }
 
 void do_no_page(unsigned long error_code, unsigned long address,
 	struct task_struct *tsk, unsigned long user_esp)
 {
-	static unsigned int last_checked = 0;
 	int nr[4];
 	unsigned long tmp;
 	unsigned long page;
 	unsigned int block,i;
 	struct inode * inode;
 
-	/* Thrashing ? Make it interruptible, but don't penalize otherwise */
-	for (i = 0; i < CHECK_LAST_NR; i++)
-		if ((address & 0xfffff000) == last_pages[i]) {
-			current->counter = 0;
-			schedule();
-		}
-	last_checked++;
-	if (last_checked >= CHECK_LAST_NR)
-		last_checked = 0;
-	last_pages[last_checked] = address & 0xfffff000;
 	if (address < TASK_SIZE) {
 		printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
 		do_exit(SIGSEGV);
@@ -639,7 +677,9 @@
 		printk("Bad things happen: nonexistent page error in do_no_page\n\r");
 		do_exit(SIGSEGV);
 	}
-	page = get_empty((unsigned long *) ((address >> 20) & 0xffc));
+	page = get_empty_pgtable((unsigned long *) ((address >> 20) & 0xffc));
+	if (!page)
+		return;
 	page &= 0xfffff000;
 	page += (address >> 10) & 0xffc;
 	tmp = *(unsigned long *) page;
@@ -691,8 +731,12 @@
 			return;
 		}
 	++tsk->maj_flt;
-	if (!(page = get_free_page()))
-		oom();
+	page = get_free_page(GFP_KERNEL);
+	if (!page) {
+		oom(current);
+		put_page(BAD_PAGE,address);
+		return;
+	}
 	for (i=0 ; i<4 ; block++,i++)
 		nr[i] = bmap(inode,block);
 	bread_page(page,inode->i_dev,nr);
@@ -707,26 +751,7 @@
 	if (put_page(page,address))
 		return;
 	free_page(page);
-	oom();
-}
-
-void mem_init(long start_mem, long end_mem)
-{
-	int i;
-
-	end_mem &= 0xfffff000;
-	start_mem += 0xfff;
-	start_mem &= 0xfffff000;
-	swap_device = 0;
-	swap_file = NULL;
-	HIGH_MEMORY = end_mem;
-	for (i=0 ; i<PAGING_PAGES ; i++)
-		mem_map[i] = USED;
-	i = MAP_NR(start_mem);
-	end_mem -= start_mem;
-	end_mem >>= 12;
-	while (end_mem-->0)
-		mem_map[i++]=0;
+	oom(current);
 }
 
 void show_mem(void)
@@ -736,9 +761,10 @@
 	unsigned long * pg_tbl;
 
 	printk("Mem-info:\n\r");
-	for(i=0 ; i<PAGING_PAGES ; i++) {
-		if (mem_map[i] == USED)
-			continue;
+	printk("Free pages:    %6d\n",nr_free_pages);
+	printk("Buffer heads:  %6d\n",nr_buffer_heads);
+	printk("Buffer blocks: %6d\n",nr_buffers);
+	for (i = 0 ; i < paging_pages ; i++) {
 		total++;
 		if (!mem_map[i])
 			free++;
@@ -747,21 +773,22 @@
 	}
 	printk("%d free pages of %d\n\r",free,total);
 	printk("%d pages shared\n\r",shared);
+	printk("%d free pages via nr_free_pages\n\r", nr_free_pages);
 	k = 0;
 	for(i=4 ; i<1024 ;) {
 		if (1&pg_dir[i]) {
-			if (pg_dir[i]>HIGH_MEMORY) {
+			if (pg_dir[i]>high_memory) {
 				printk("page directory[%d]: %08X\n\r",
 					i,pg_dir[i]);
 				i++;
 				continue;
 			}
-			if (pg_dir[i]>LOW_MEM)
+			if (pg_dir[i]>low_memory)
 				free++,k++;
 			pg_tbl=(unsigned long *) (0xfffff000 & pg_dir[i]);
 			for(j=0 ; j<1024 ; j++)
-				if ((pg_tbl[j]&1) && pg_tbl[j]>LOW_MEM)
-					if (pg_tbl[j]>HIGH_MEMORY)
+				if ((pg_tbl[j]&1) && pg_tbl[j]>low_memory)
+					if (pg_tbl[j]>high_memory)
 						printk("page_dir[%d][%d]: %08X\n\r",
 							i,j, pg_tbl[j]);
 					else
@@ -796,7 +823,25 @@
 		do_no_page(error_code, address, current, user_esp);
 		return;
 	} else {
-		do_wp_page(error_code, address);
+		do_wp_page(error_code, address, current, user_esp);
 		return;
 	}
 }
+
+unsigned long mem_init(unsigned long start_mem, unsigned long end_mem)
+{
+	end_mem &= 0xfffff000;
+	high_memory = end_mem;
+	mem_map = (char *) start_mem;
+	paging_pages = (end_mem - start_mem) >> 12;
+	start_mem += paging_pages;
+	start_mem += 0xfff;
+	start_mem &= 0xfffff000;
+	low_memory = start_mem;
+	paging_pages = (high_memory - low_memory) >> 12;
+	swap_device = 0;
+	swap_file = NULL;
+	memset(mem_map,0,paging_pages);
+	nr_free_pages = paging_pages;
+	return start_mem;
+}
diff --git a/mm/mmap.c b/mm/mmap.c
index 281da97..38dc07d 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -7,9 +7,11 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/errno.h>
+
 #include <asm/segment.h>
 #include <asm/system.h>
-#include <errno.h>
+
 #include <sys/mman.h>
 
 /*
@@ -57,7 +59,7 @@
 		return (caddr_t)-ENODEV;
 
 	/*
-	 * we only allow mappings from address 0 to HIGH_MEMORY, since thats
+	 * we only allow mappings from address 0 to high_memory, since thats
 	 * the range of our memory [actually this is a lie. the buffer cache
 	 * and ramdisk occupy higher memory, but the paging stuff won't
 	 * let us map to it anyway, so we break it here].
@@ -71,7 +73,7 @@
 	 * truly useful.
 	 */
 
-	if (len > HIGH_MEMORY || off > HIGH_MEMORY - len) /* avoid overflow */
+	if (len > high_memory || off > high_memory - len) /* avoid overflow */
 		return (caddr_t)-ENXIO;
 
 	if (remap_page_range(addr, off, len, PERMISS(flags, prot)))
diff --git a/mm/swap.c b/mm/swap.c
index f968e05..b582eb4 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -1,7 +1,7 @@
 /*
  *  linux/mm/swap.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -9,14 +9,22 @@
  * Started 18.12.91
  */
 
-#include <errno.h>
-
-#include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/head.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+
+static int lowest_bit = 0;
+static int highest_bit = 0;
+
+/*
+ * The following are used to make sure we don't thrash too much...
+ */
+#define NR_LAST_FREE_PAGES 32
+static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,};
 
 #define SWAP_BITS (4096<<3)
 
@@ -35,98 +43,118 @@
 bitop(clrbit,"r")
 
 static char * swap_bitmap = NULL;
+static char * swap_lockmap = NULL;
 unsigned int swap_device = 0;
 struct inode * swap_file = NULL;
 
 void rw_swap_page(int rw, unsigned int nr, char * buf)
 {
-	unsigned int zones[4];
-	int i;
+	static struct wait_queue * lock_queue = NULL;
 
-	if (swap_device) {
-		ll_rw_page(rw,swap_device,nr,buf);
+	if (!swap_lockmap) {
+		printk("No swap lock-map\n");
 		return;
 	}
-	if (swap_file) {
-		nr <<= 2;
+	while (setbit(swap_lockmap,nr))
+		sleep_on(&lock_queue);
+	if (swap_device) {
+		ll_rw_page(rw,swap_device,nr,buf);
+	} else if (swap_file) {
+		unsigned int zones[4];
+		unsigned int block = nr << 2;
+		int i;
+
 		for (i = 0; i < 4; i++)
-			if (!(zones[i] = bmap(swap_file,nr++))) {
+			if (!(zones[i] = bmap(swap_file,block++))) {
 				printk("rw_swap_page: bad swap file\n");
 				return;
 			}
 		ll_rw_swap_file(rw,swap_file->i_dev, zones,4,buf);
-		return;
-	}
-	printk("ll_swap_page: no swap file or device\n");
+	} else
+		printk("re_swap_page: no swap file or device\n");
+	if (!clrbit(swap_lockmap,nr))
+		printk("rw_swap_page: lock already cleared\n");
+	wake_up(&lock_queue);
 }
 
-/*
- * We never page the pages in task[0] - kernel memory.
- * We page all other pages.
- */
-#define FIRST_VM_PAGE (TASK_SIZE>>12)
-#define LAST_VM_PAGE (1024*1024)
-#define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
-
-static int get_swap_page(void)
+static unsigned int get_swap_page(void)
 {
-	int nr;
+	unsigned int nr;
 
 	if (!swap_bitmap)
 		return 0;
-	for (nr = 1; nr < SWAP_BITS ; nr++)
-		if (clrbit(swap_bitmap,nr))
-			return nr;
+	for (nr = lowest_bit; nr <= highest_bit ; nr++)
+		if (clrbit(swap_bitmap,nr)) {
+			if (nr == highest_bit)
+				highest_bit--;
+			return lowest_bit = nr;
+		}
 	return 0;
 }
 
-void swap_free(int swap_nr)
+void swap_free(unsigned int swap_nr)
 {
 	if (!swap_nr)
 		return;
-	if (swap_bitmap && swap_nr < SWAP_BITS)
+	if (swap_bitmap && swap_nr < SWAP_BITS) {
+		if (swap_nr < lowest_bit)
+			lowest_bit = swap_nr;
+		if (swap_nr > highest_bit)
+			highest_bit = swap_nr;
 		if (!setbit(swap_bitmap,swap_nr))
 			return;
-	printk("swap_free: swap-space bitmap bad\n");
+	}
+	printk("swap_free: swap-space bitmap bad (bit %d)\n",swap_nr);
 	return;
 }
 
 void swap_in(unsigned long *table_ptr)
 {
-	int swap_nr;
+	unsigned long swap_nr;
 	unsigned long page;
 
-	if (!swap_bitmap) {
-		printk("Trying to swap in without swap bit-map");
-		return;
-	}
-	if (1 & *table_ptr) {
+	swap_nr = *table_ptr;
+	if (1 & swap_nr) {
 		printk("trying to swap in present page\n\r");
 		return;
 	}
-	swap_nr = *table_ptr >> 1;
 	if (!swap_nr) {
 		printk("No swap page in swap_in\n\r");
 		return;
 	}
-	if (!(page = get_free_page()))
-		oom();
-	read_swap_page(swap_nr, (char *) page);
-	if (setbit(swap_bitmap,swap_nr))
-		printk("swapping in multiply from same page\n\r");
+	if (!swap_bitmap) {
+		printk("Trying to swap in without swap bit-map");
+		*table_ptr = BAD_PAGE;
+		return;
+	}
+	page = get_free_page(GFP_KERNEL);
+	if (!page) {
+		oom(current);
+		page = BAD_PAGE;
+	} else	
+		read_swap_page(swap_nr>>1, (char *) page);
+	if (*table_ptr != swap_nr) {
+		free_page(page);
+		return;
+	}
+	swap_free(swap_nr>>1);
 	*table_ptr = page | (PAGE_DIRTY | 7);
 }
 
 int try_to_swap_out(unsigned long * table_ptr)
 {
+	int i;
 	unsigned long page;
 	unsigned long swap_nr;
 
 	page = *table_ptr;
 	if (!(PAGE_PRESENT & page))
 		return 0;
-	if (page - LOW_MEM > PAGING_MEMORY)
+	if (page < low_memory || page >= high_memory)
 		return 0;
+	for (i = 0; i < NR_LAST_FREE_PAGES; i++)
+		if (last_free_pages[i] == (page & 0xfffff000))
+			return 0;
 	if (PAGE_DIRTY & page) {
 		page &= 0xfffff000;
 		if (mem_map[MAP_NR(page)] != 1)
@@ -147,14 +175,20 @@
 }
 
 /*
+ * We never page the pages in task[0] - kernel memory.
+ * We page all other pages.
+ */
+#define FIRST_VM_PAGE (TASK_SIZE>>12)
+#define LAST_VM_PAGE (1024*1024)
+#define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
+
+/*
  * Go through the page tables, searching for a user page that
  * we can swap out.
  *
- * Here it's easy to add a check for tasks that may not be swapped out:
- * loadable device drivers or similar. Just add an entry to the task-struct
- * and check it at the same time you check for the existence of the task.
- * The code assumes tasks are page-table aligned, but so do other parts
- * of the memory manager...
+ * We now check that the process is swappable (normally only 'init'
+ * is un-swappable), allowing high-priority processes which cannot be
+ * swapped out (things like user-level device drivers (Not implemented)).
  */
 int swap_out(void)
 {
@@ -195,8 +229,9 @@
 		dir_entry++;
 		goto check_dir;
 	}
-	if (try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
+	if (p->swappable && try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
 		p->rss--;
+		dir_entry++;
 		return 1;
 	}
 	goto check_table;
@@ -209,9 +244,10 @@
  * Get physical address of first (actually last :-) free page, and mark it
  * used. If no free pages left, return 0.
  */
-unsigned long get_free_page(void)
+unsigned long get_free_page(int priority)
 {
 	unsigned long result;
+	static unsigned long index = 0;
 
 repeat:
 	__asm__("std ; repne ; scasb\n\t"
@@ -226,18 +262,39 @@
 		"movl %%edx,%%eax\n"
 		"1:\tcld"
 		:"=a" (result)
-		:"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
-		"D" (mem_map+PAGING_PAGES-1)
+		:"0" (0),"b" (low_memory),"c" (paging_pages),
+		"D" (mem_map+paging_pages-1)
 		:"di","cx","dx");
-	if (result >= HIGH_MEMORY)
+	if (result >= high_memory)
 		goto repeat;
-	if ((result && result < LOW_MEM) || (result & 0xfff)) {
+	if ((result && result < low_memory) || (result & 0xfff)) {
 		printk("weird result: %08x\n",result);
 		result = 0;
 	}
-	if (!result && swap_out())
+	if (result) {
+		--nr_free_pages;
+		if (index >= NR_LAST_FREE_PAGES)
+			index = 0;
+		last_free_pages[index] = result;
+		index++;
+		return result;
+	}
+	if (nr_free_pages) {
+		printk("Damn. mm_free_page count is off by %d\r\n",
+			nr_free_pages);
+		nr_free_pages = 0;
+	}
+	if (priority <= GFP_BUFFER)
+		return 0;
+	if (shrink_buffers()) {
+		schedule();
 		goto repeat;
-	return result;
+	}
+	if (swap_out()) {
+		schedule();
+		goto repeat;
+	}
+	return 0;
 }
 
 /*
@@ -255,7 +312,7 @@
 		return -EPERM;
 	if (!(swap_inode  = namei(specialfile)))
 		return -ENOENT;
-	if (swap_file || swap_device || swap_bitmap) {
+	if (swap_file || swap_device || swap_bitmap || swap_lockmap) {
 		iput(swap_inode);
 		return -EBUSY;
 	}
@@ -268,36 +325,51 @@
 		iput(swap_inode);
 		return -EINVAL;
 	}
-	tmp = (char *) get_free_page();
-	if (!tmp) {
+	tmp = (char *) get_free_page(GFP_USER);
+	swap_lockmap = (char *) get_free_page(GFP_USER);
+	if (!tmp || !swap_lockmap) {
+		printk("Unable to start swapping: out of memory :-)\n");
+		free_page((long) tmp);
+		free_page((long) swap_lockmap);
 		iput(swap_file);
 		swap_device = 0;
 		swap_file = NULL;
-		printk("Unable to start swapping: out of memory :-)\n");
+		swap_bitmap = NULL;
+		swap_lockmap = NULL;
 		return -ENOMEM;
 	}
 	read_swap_page(0,tmp);
 	if (strncmp("SWAP-SPACE",tmp+4086,10)) {
 		printk("Unable to find swap-space signature\n\r");
 		free_page((long) tmp);
+		free_page((long) swap_lockmap);
 		iput(swap_file);
 		swap_device = 0;
 		swap_file = NULL;
 		swap_bitmap = NULL;
+		swap_lockmap = NULL;
 		return -EINVAL;
 	}
 	memset(tmp+4086,0,10);
 	j = 0;
+	lowest_bit = 0;
+	highest_bit = 0;
 	for (i = 1 ; i < SWAP_BITS ; i++)
-		if (bit(tmp,i))
+		if (bit(tmp,i)) {
+			if (!lowest_bit)
+				lowest_bit = i;
+			highest_bit = i;
 			j++;
+		}
 	if (!j) {
 		printk("Empty swap-file\n");
 		free_page((long) tmp);
+		free_page((long) swap_lockmap);
 		iput(swap_file);
 		swap_device = 0;
 		swap_file = NULL;
 		swap_bitmap = NULL;
+		swap_lockmap = NULL;
 		return -EINVAL;
 	}
 	swap_bitmap = tmp;
diff --git a/net/Makefile b/net/Makefile
index 1292340..daada70 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -29,21 +29,24 @@
 	cp tmp_make Makefile
 
 ### Dependencies:
-socket.o : socket.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/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/linux/stat.h \
-  /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h /usr/src/linux/include/sys/socket.h \
-  /usr/src/linux/include/linux/fcntl.h /usr/src/linux/include/termios.h kern_sock.h \
-  socketcall.h 
-unix.o : unix.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/linux/string.h \
+socket.o : socket.c /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/errno.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/linux/stat.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
-  /usr/src/linux/include/sys/socket.h /usr/src/linux/include/sys/un.h /usr/src/linux/include/linux/fcntl.h \
-  /usr/src/linux/include/termios.h kern_sock.h 
+  /usr/src/linux/include/linux/limits.h /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h \
+  /usr/src/linux/include/linux/dirent.h /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/stat.h /usr/src/linux/include/linux/socket.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
+  kern_sock.h socketcall.h 
+unix.o : unix.c /usr/src/linux/include/linux/signal.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/linux/limits.h \
+  /usr/src/linux/include/linux/wait.h /usr/src/linux/include/linux/types.h /usr/src/linux/include/linux/dirent.h \
+  /usr/src/linux/include/linux/vfs.h /usr/src/linux/include/linux/minix_fs_sb.h \
+  /usr/src/linux/include/linux/ext_fs_sb.h /usr/src/linux/include/linux/msdos_fs_sb.h \
+  /usr/src/linux/include/linux/mm.h /usr/src/linux/include/linux/kernel.h /usr/src/linux/include/linux/time.h \
+  /usr/src/linux/include/linux/param.h /usr/src/linux/include/linux/resource.h \
+  /usr/src/linux/include/linux/errno.h /usr/src/linux/include/linux/string.h /usr/src/linux/include/linux/stat.h \
+  /usr/src/linux/include/linux/socket.h /usr/src/linux/include/linux/un.h /usr/src/linux/include/linux/fcntl.h \
+  /usr/src/linux/include/linux/termios.h /usr/src/linux/include/asm/system.h /usr/src/linux/include/asm/segment.h \
+  kern_sock.h 
diff --git a/net/socket.c b/net/socket.c
index ec3cd35..ffea8a2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1,13 +1,15 @@
-#include <signal.h>
-#include <errno.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/fcntl.h>
+#include <linux/termios.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <sys/socket.h>
-#include <linux/fcntl.h>
-#include <termios.h>
+
 #include "kern_sock.h"
 #include "socketcall.h"
 
diff --git a/net/unix.c b/net/unix.c
index 64a5eb6..8e956b5 100644
--- a/net/unix.c
+++ b/net/unix.c
@@ -1,15 +1,17 @@
-#include <signal.h>
-#include <errno.h>
-#include <linux/string.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/un.h>
+#include <linux/fcntl.h>
+#include <linux/termios.h>
+
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <linux/fcntl.h>
-#include <termios.h>
+
 #include "kern_sock.h"
 
 static struct unix_proto_data {
@@ -169,7 +171,7 @@
 		printk("unix_proto_create: can't allocate buffer\n");
 		return -ENOMEM;
 	}
-	if (!(upd->buf = (char *)get_free_page())) {
+	if (!(upd->buf = (char *)get_free_page(GFP_USER))) {
 		printk("unix_proto_create: can't get page!\n");
 		unix_data_deref(upd);
 		return -ENOMEM;
diff --git a/tools/build.c b/tools/build.c
index 24ab216..5169ce3 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1,7 +1,7 @@
 /*
  *  linux/tools/build.c
  *
- *  (C) 1991  Linus Torvalds
+ *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
 /*
@@ -25,7 +25,7 @@
 #include <stdlib.h>	/* contains exit */
 #include <sys/types.h>	/* unistd.h needs this */
 #include <sys/stat.h>
-#include <linux/fs.h>
+#include <sys/sysmacros.h>
 #include <unistd.h>	/* contains read/write */
 #include <fcntl.h>
 
@@ -69,8 +69,8 @@
 				perror(argv[4]);
 				die("Couldn't stat root device.");
 			}
-			major_root = MAJOR(sb.st_rdev);
-			minor_root = MINOR(sb.st_rdev);
+			major_root = major(sb.st_rdev);
+			minor_root = minor(sb.st_rdev);
 		} else {
 			major_root = 0;
 			minor_root = 0;