diff -u --recursive --new-file v1.3.99/linux/CREDITS linux/CREDITS
--- v1.3.99/linux/CREDITS	Tue May  7 16:22:13 1996
+++ linux/CREDITS	Thu May  9 16:38:43 1996
@@ -425,6 +425,13 @@
 S: Poltava 314023
 S: Ukraine
 
+N: John E. Gotts
+E: jgotts@engin.umich.edu
+D: kernel hacker
+S: 8124 Constitution Apt. 7
+S: Sterling Heights, MI  48313
+S: USA
+
 N: Grant Guenther
 E: grant@torque.net
 D: Iomega PPA / ZIP driver
@@ -983,6 +990,14 @@
 S: Tallak 95
 S: 8103 Rein
 S: Austria
+
+N: Stefan Reinauer
+E: stepan@home.culture.mipt.ru
+W: http://home.culture.mipt.ru/~stepan
+D: Modulized affs and ufs. Minor fixes.
+S: Rebmannsweg 34h
+S: 79539 Loerrach
+S: Germany
 
 N: William E. Roadcap
 E: roadcapw@cfw.com
diff -u --recursive --new-file v1.3.99/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.99/linux/Documentation/Configure.help	Tue May  7 16:22:14 1996
+++ linux/Documentation/Configure.help	Fri May 10 07:46:59 1996
@@ -608,6 +608,21 @@
   format. Saying M or N here is dangerous, because some crucial
   programs on your system might be in A.OUT format.
 
+Kernel support for JAVA binaries
+CONFIG_BINFMT_JAVA
+  JAVA binaries are becoming a universal executable format. This
+  option allows Java binaries and Java Applets to be handled invisibly
+  to the OS. As more and more Java programs become available, the use
+  for this will gradually increase. If you want to use this, read the
+  Java on Linux HOWTO, available via ftp (user: anonymous) at
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO. In order to execute Java binaries,
+  you will also need to install the Java Developers Kit. If you disable
+  this option it will reduce your kernel by about one page. This is not
+  much and by itself does not warrant removing support. However its
+  removal is a good idea if you do not have the JDK installed. If you
+  don't know what to answer at this point then answer Y. You may answer
+  M for module support and later load the module when you install the
+  JDK or find a interesting Java program that you can't live without.
 Processor type
 CONFIG_M386
   This is the processor type of your CPU. It is used for optimizing
@@ -1369,18 +1384,15 @@
 ### Dunno
 ###
 
-Always IN2000 SCSI support (test release)
+Always IN2000 SCSI support
 CONFIG_SCSI_IN2000
-  Believe it or not, there is a SCSI host adaptor of that name. It is
-  explained in section 3.6 of the SCSI-HOWTO, available via ftp (user:
-  anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't
-  work out of the box, you may have to change some settings in
-  drivers/scsi/in2000.h.  You may also want to drop in a rewritten,
-  and probably more reliable, driver from John Shifflett, which you
-  can get from ftp://ftp.netcom.com/pub/js/jshiffle/in2000/ .  If you
-  want to compile this as a module ( = code which can be inserted in
-  and removed from the running kernel whenever you want), say M here
-  and read Documentation/modules.txt.
+  This is support for an ISA bus SCSI host adaptor. You'll find
+  more information in drivers/scsi/in2000.readme. If it doesn't
+  work out of the box, you may have to change the jumpers for IRQ
+  or address selection. If you want to compile this as a module 
+  ( = code which can be inserted in and removed from the running
+  kernel whenever you want), say M here and read 
+  Documentation/modules.txt.
 
 PAS16 SCSI support
 CONFIG_SCSI_PAS16
diff -u --recursive --new-file v1.3.99/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v1.3.99/linux/Documentation/devices.tex	Tue May  7 16:22:14 1996
+++ linux/Documentation/devices.tex	Thu May  9 20:31:12 1996
@@ -42,7 +42,7 @@
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: May 5, 1996}
+\date{Last revised: May 9, 1996}
 \maketitle
 %
 \noindent
@@ -167,7 +167,8 @@
 \major{48}{}{char }{SDL RISCom serial card}
 \major{49}{}{char }{SDL RISCom serial card -- alternate devices}
 \major{50}{}{char }{Reserved for GLINT}
-\major{51}{--59}{}{Unallocated}
+\major{51}{}{char }{Baycom radio modem}
+\major{52}{--59}{}{Unallocated}
 \major{60}{--63}{}{Local/experimental use}
 \major{64}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
@@ -1027,7 +1028,18 @@
 \end{devicelist}
 
 \begin{devicelist}
-\major{50}{--59}{}{Unallocated}
+\major{50}{}{char}{Reserved for GLINT}
+\end{devicelist}
+
+\begin{devicelist}
+\major{51}{}{char }{Baycom radio modem}
+	\minor{0}{/dev/bc0}{First Baycom radio modem}
+	\minor{1}{/dev/bc1}{Second Baycom radio modem}
+	\minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{52}{--59}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
diff -u --recursive --new-file v1.3.99/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v1.3.99/linux/Documentation/devices.txt	Tue May  7 16:22:14 1996
+++ linux/Documentation/devices.txt	Thu May  9 20:31:12 1996
@@ -2,7 +2,7 @@
 
 	     Maintained by H. Peter Anvin <hpa@zytor.com>
 
-		      Last revised: May 5, 1996
+		      Last revised: May 9, 1996
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he got busy with other things in 1993.  It
@@ -708,7 +708,14 @@
 		  1 = /dev/cul1		Callout device corresponding to ttyL1
 		      ...
 
- 50-59		UNALLOCATED
+ 50 char	Reserved for GLINT
+
+ 51 char	Baycom radio modem
+		  0 = /dev/bc0		First Baycom radio modem
+		  1 = /dev/bc1		Second Baycom radio modem
+		      ...
+
+ 52-59		UNALLOCATED
 
  60-63		LOCAL/EXPERIMENTAL USE
 		Allocated for local/experimental use.  For devices not
diff -u --recursive --new-file v1.3.99/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt
--- v1.3.99/linux/Documentation/filesystems/affs.txt	Tue May  7 16:22:14 1996
+++ linux/Documentation/filesystems/affs.txt	Wed May  8 07:20:02 1996
@@ -19,7 +19,7 @@
 
 DOS\4		The original filesystem with directory cache. The directory
 		cache speeds up directory accesses on floppies considerably,
-		but slowes down file creation/deletion. Doesn't make much
+		but slows down file creation/deletion. Doesn't make much
 		sense on hard disks. Not supported.
 
 DOS\5		The Fast File System with directory cache. Not supported.
@@ -37,7 +37,7 @@
 
 uid[=uid]	This sets the uid of the root directory (i. e. the mount point
 		to uid or to the uid of the current user, if the =uid is
-		ommitted.
+		omitted.
 
 gid[=gid]	Same as above, but for gid.
 
@@ -49,7 +49,7 @@
 use_mp		The uid and gid are taken from the now covered mount point
 		instead of the current user or value defined.
 
-mode=mode	Sets the mode flags to the given (octal) value, regardles
+mode=mode	Sets the mode flags to the given (octal) value, regardless
 		of the original permissions. Directories will get an x
 		permission, if the corresponding r bit is set.
 		This is useful since most of the plain AmigaOS files
@@ -58,12 +58,12 @@
 reserved=num	Sets the number of reserved blocks at the start of the
 		partition to num. Default is 2.
 
-root=block	Sets the block number of the root block. This schould never
-		be neccessary.
+root=block	Sets the block number of the root block. This should never
+		be necessary.
 
 bs=blksize	Sets the blocksize to blksize. Valid block sizes are 512,
 		1024, 2048 and 4096. Like the root option, this should
-		never be neccessary, as the affs can figure it out itself.
+		never be necessary, as the affs can figure it out itself.
 
 quiet		The file system will not return an error for disallowed
 		mode changes.
diff -u --recursive --new-file v1.3.99/linux/Documentation/java.txt linux/Documentation/java.txt
--- v1.3.99/linux/Documentation/java.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/java.txt	Wed May  8 18:28:01 1996
@@ -0,0 +1,91 @@
+               JAVA Binary Kernel Support for Linux v1.01
+               ------------------------------------------
+
+Linux beats them ALL! While all other OS's are TALKING about direct
+support of Java Binaries in the OS, Linux is doing it!
+
+You execute Java classes as you would any other executable, after a few
+small details:
+
+	1) You MUST FIRST install the Java Developers Kit for Linux.
+	   The Java on Linux HOWTO gives the details on getting and
+	   installing this. This HOWTO can be found at:
+
+		ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
+
+	   If you install the JDK in a location other than the suggested
+	   directory of /usr/local/java, then you will need to edit the
+	   kernel's fs/binfmt_java.c file and make the needed change to the
+	   _PATH_JAVA definition at the top of that file.
+
+	2) You must chmod the '*.class' files you wish to execute with
+	   the execute bit. This is not normally (till now) done with
+	   '.class' files.
+
+	3) You must optionally export a CLASSPATH environment variable,
+	   if you plan to use Java applications installed outside of
+	   /usr/local/java/classes/*.
+
+	4) Either compile your kernel with Java support builtin, or
+	   as a loadable module. If a module, load it with insmod or
+	   kerneld.
+
+
+To test your new setup, enter in the following simple Java app, and name
+it "HelloWorld.java":
+
+	class HelloWorld {
+		public static void main(String args[]) {
+			System.out.println("Hello World!");
+		}
+	}
+
+
+Now compile the application with:
+
+	/usr/local/java/bin/javac HelloWorld.java
+
+Set the executable permissions of the binary file, with:
+
+	chmod 755 HelloWorld.class
+
+And then execute it:
+
+	./HellowWorld.class
+
+
+Yes, it's JUST THAT EASY! ;-)
+
+-----------------------------------------------------------------
+
+Nope, I didn't forget about Java Applets! ;-)
+
+While this may not be the best way to do this, it works!
+
+Take any html file used with the Java appletviewer (like the
+demo/Blink/example1.html file), and:
+
+	1) Insert a new first line of:
+
+		<!--applet-->
+
+	   Make sure the '<' is the first character in the file. This
+	   will be treated as a valid HTML comment outside of this
+	   Java Applet support, so the modified file can still be used
+	   with all known browsers.
+
+	2) If you install the JDK in a location other than the suggested
+	   directory of /usr/local/java, then you will need to edit the
+	   kernel's fs/binfmt_java.c file and make the needed change to the
+	   _PATH_APPLET definition at the top of that file.
+
+	3) You must chmod the '*.html' files you wish to execute with
+	   the execute bit. This is not normally (till now) done with
+	   '.html' files.
+
+	4) And then execute it.
+
+
+
+Brian A. Lantz
+brian@lantz.com
diff -u --recursive --new-file v1.3.99/linux/Documentation/modules.txt linux/Documentation/modules.txt
--- v1.3.99/linux/Documentation/modules.txt	Tue Feb 13 10:30:24 1996
+++ linux/Documentation/modules.txt	Fri May 10 07:48:05 1996
@@ -59,6 +59,7 @@
 	Some misc modules:
 		lp: line printer
 		binfmt_elf: elf loader
+		binfmt_java: java loader
 		isp16: cdrom interface
 
 When you have made the kernel, you create the modules by doing:
diff -u --recursive --new-file v1.3.99/linux/MAINTAINERS linux/MAINTAINERS
--- v1.3.99/linux/MAINTAINERS	Tue May  7 16:22:16 1996
+++ linux/MAINTAINERS	Fri May 10 07:55:36 1996
@@ -287,7 +287,6 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
-
 MOUSE AND MISC DEVICES [GENERAL]
 P:	Alessandro Rubini
 M:	rubini@ipvvis.unipv.it
@@ -304,6 +303,12 @@
 P:	Thomas Bogendoerfer
 M:	tsbogend@bigbug.franken.de
 L:	linux-net@vger.rutgers.edu
+S:	Maintained
+
+ADVANSYS SCSI DRIVER
+P:	Bob Frey
+M:	Bob Frey <bobf@advansys.com>
+W:	http://www.advansys.com/linux
 S:	Maintained
 
 REST:
diff -u --recursive --new-file v1.3.99/linux/Makefile linux/Makefile
--- v1.3.99/linux/Makefile	Tue May  7 16:22:16 1996
+++ linux/Makefile	Wed May  8 10:33:17 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 99
+SUBLEVEL = 100
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.99/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.99/linux/arch/alpha/defconfig	Sun May  5 08:51:58 1996
+++ linux/arch/alpha/defconfig	Fri May 10 11:56:22 1996
@@ -32,7 +32,6 @@
 CONFIG_ALPHA_ALCOR=y
 # CONFIG_SERIAL_ECHO is not set
 # CONFIG_TGA_CONSOLE is not set
-CONFIG_PCI_OPTIMIZE=y
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 CONFIG_BINFMT_AOUT=y
diff -u --recursive --new-file v1.3.99/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.99/linux/arch/i386/config.in	Tue May  7 16:22:17 1996
+++ linux/arch/i386/config.in	Wed May  8 18:28:44 1996
@@ -33,6 +33,7 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
 bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF
 
 choice 'Processor type' \
diff -u --recursive --new-file v1.3.99/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v1.3.99/linux/arch/i386/defconfig	Sun May  5 08:51:58 1996
+++ linux/arch/i386/defconfig	Thu May  9 08:07:45 1996
@@ -21,10 +21,10 @@
 CONFIG_NET=y
 # CONFIG_MAX_16M is not set
 CONFIG_PCI=y
-CONFIG_PCI_OPTIMIZE=y
 CONFIG_SYSVIPC=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_JAVA is not set
 CONFIG_KERNEL_ELF=y
 # CONFIG_M386 is not set
 # CONFIG_M486 is not set
diff -u --recursive --new-file v1.3.99/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v1.3.99/linux/arch/i386/kernel/setup.c	Tue May  7 16:22:17 1996
+++ linux/arch/i386/kernel/setup.c	Wed May  8 07:42:33 1996
@@ -208,7 +208,7 @@
 {
 	static const char *model[] = {
 		"0","DX","SX","DX/2","4","SX/2","6","DX/2-WB","DX/4","DX/4-WB",
-		"10","11","12","13","Am5x85-WT","Am5x86-WB"
+		"10","11","12","13","Am5x86-WT","Am5x86-WB"
 	};
 	if (nr < sizeof(model)/sizeof(char *))
 		return model[nr];
diff -u --recursive --new-file v1.3.99/linux/arch/i386/math-emu/fpu_emu.h linux/arch/i386/math-emu/fpu_emu.h
--- v1.3.99/linux/arch/i386/math-emu/fpu_emu.h	Tue May  7 16:22:18 1996
+++ linux/arch/i386/math-emu/fpu_emu.h	Thu May  9 07:59:33 1996
@@ -58,7 +58,8 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/sigcontext.h>	/* for struct _fpstate */
-#include <linux/math_emu.h>
+#include <asm/math_emu.h>
+
 #include <linux/linkage.h>
 
 /*
diff -u --recursive --new-file v1.3.99/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.99/linux/drivers/block/floppy.c	Sun May  5 08:51:58 1996
+++ linux/drivers/block/floppy.c	Thu May  9 08:33:23 1996
@@ -248,13 +248,7 @@
 #define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
 #define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
 
-#define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive)
-
-#define DPRINT1(x,x1) printk(DEVICE_NAME "%d: " x,current_drive,(x1))
-
-#define DPRINT2(x,x1,x2) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2))
-
-#define DPRINT3(x,x1,x2,x3) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
+#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
 
 #define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
 #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
@@ -487,7 +481,8 @@
 static void floppy_start(void);
 static void process_fd_request(void);
 static void recalibrate_floppy(void);
-static void floppy_shutdown(unsigned long);
+static void floppy_shutdown(void);
+static void unexpected_floppy_interrupt(void);
 
 static int floppy_grab_irq_and_dma(void);
 static void floppy_release_irq_and_dma(void);
@@ -580,7 +575,7 @@
 {
 	/* this routine checks whether the floppy driver is "alive" */
 	if (fdc_busy && command_status < 2 && !fd_timeout.prev){
-		DPRINT1("timeout handler died: %s\n",message);
+		DPRINT("timeout handler died: %s\n",message);
 	}
 }
 #endif
@@ -688,17 +683,17 @@
 	   (FDCS->dor & 3) != UNIT(drive) ||
 	   fdc != FDC(drive)){
 		DPRINT("probing disk change on unselected drive\n");
-		DPRINT3("drive=%d fdc=%d dor=%x\n",drive, FDC(drive),
+		DPRINT("drive=%d fdc=%d dor=%x\n",drive, FDC(drive),
 			FDCS->dor);
 	}
 #endif
 
 #ifdef DCL_DEBUG
 	if (UDP->flags & FD_DEBUG){
-		DPRINT1("checking disk change line for drive %d\n",drive);
-		DPRINT1("jiffies=%ld\n", jiffies);
-		DPRINT1("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
-		DPRINT1("flags=%x\n",UDRS->flags);
+		DPRINT("checking disk change line for drive %d\n",drive);
+		DPRINT("jiffies=%ld\n", jiffies);
+		DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
+		DPRINT("flags=%x\n",UDRS->flags);
 	}
 #endif
 	if (UDP->flags & FD_BROKEN_DCL)
@@ -708,17 +703,18 @@
 		if (UDRS->maxblock){
 			/* mark it changed */
 			USETF(FD_DISK_CHANGED);
+		}
 
-			/* invalidate its geometry */
-			if (UDRS->keep_data >= 0) {
-				if ((UDP->flags & FTD_MSG) &&
-				    current_type[drive] != NULL)
-					DPRINT("Disk type is undefined after "
-					       "disk change\n");
-				current_type[drive] = NULL;
-				floppy_sizes[TOMINOR(current_drive)] = MAX_DISK_SIZE;
-			}
+		/* invalidate its geometry */
+		if (UDRS->keep_data >= 0) {
+			if ((UDP->flags & FTD_MSG) &&
+			    current_type[drive] != NULL)
+				DPRINT("Disk type is undefined after "
+				       "disk change\n");
+			current_type[drive] = NULL;
+			floppy_sizes[TOMINOR(current_drive)] = MAX_DISK_SIZE;
 		}
+
 		/*USETF(FD_DISK_NEWCHANGE);*/
 		return 1;
 	} else {
@@ -850,7 +846,7 @@
 		DPRINT("FDC access conflict!\n");
 
 	if (DEVICE_INTR)
-		DPRINT1("device interrupt still active at FDC release: %p!\n",
+		DPRINT("device interrupt still active at FDC release: %p!\n",
 			DEVICE_INTR);
 	command_status = FD_COMMAND_NONE;
 	del_timer(&fd_timeout);
@@ -928,8 +924,22 @@
 	set_fdc(saved_drive);
 }
 
+static void empty(void)
+{
+}
+
+static struct tq_struct floppy_tq =
+{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
+
 static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
 
+static void cancel_activity(void)
+{
+	CLEAR_INTR;
+	floppy_tq.routine = (void *)(void *) empty;
+	del_timer(&fd_timer);
+}
+
 /* this function makes sure that the disk stays in the drive during the
  * transfer */
 static void fd_watchdog(void)
@@ -942,7 +952,9 @@
 
 	if (disk_change(current_drive)){
 		DPRINT("disk removed during i/o\n");
-		floppy_shutdown(1);
+		cancel_activity();
+		cont->done(0);
+		reset_fdc();
 	} else {
 		del_timer(&fd_timer);
 		fd_timer.function = (timeout_fn) fd_watchdog;
@@ -1063,7 +1075,7 @@
 			return status;
 	}
 	if (!initialising) {
-		DPRINT2("Getstatus times out (%x) on fdc %d\n",
+		DPRINT("Getstatus times out (%x) on fdc %d\n",
 			status, fdc);
 		show_floppy();
 	}
@@ -1090,8 +1102,8 @@
 	}
 	FDCS->reset = 1;
 	if (!initialising) {
-		DPRINT2("Unable to send byte %x to FDC. Status=%x\n",
-			byte, status);
+		DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
+		       byte, fdc, status);
 		show_floppy();
 	}
 	return -1;
@@ -1120,8 +1132,8 @@
 			break;
 	}
 	if(!initialising) {
-		DPRINT2("'get result' error. Last status=%x Read bytes=%d\n",
-			status, i);
+		DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
+		       fdc, status, i);
 		show_floppy();
 	}
 	FDCS->reset = 1;
@@ -1484,7 +1496,7 @@
 #ifdef DCL_DEBUG
 		if (DP->flags & FD_DEBUG){
 			DPRINT("clearing NEWCHANGE flag because of effective seek\n");
-			DPRINT1("jiffies=%ld\n", jiffies);
+			DPRINT("jiffies=%ld\n", jiffies);
 		}
 #endif
 		CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
@@ -1509,7 +1521,7 @@
 #ifdef DCL_DEBUG
 		if (DP->flags & FD_DEBUG){
 			DPRINT("checking whether disk is write protected\n");
-			DPRINT1("wp=%x\n",ST3 & 0x40);
+			DPRINT("wp=%x\n",ST3 & 0x40);
 		}
 #endif
 		if (!(ST3  & 0x40))
@@ -1677,9 +1689,6 @@
 	FDCS->reset = 1;
 }
 
-static struct tq_struct floppy_tq =
-{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
-
 /* interrupt handler */
 void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
@@ -1765,10 +1774,6 @@
 	}
 }
 
-static void empty(void)
-{
-}
-
 void show_floppy(void)
 {
 	int i;
@@ -1815,21 +1820,19 @@
 	printk("\n");
 }
 
-static void floppy_shutdown(unsigned long mode)
+static void floppy_shutdown(void)
 {
-	if (!initialising && !mode)
+	if (!initialising)
 		show_floppy();
-	CLEAR_INTR;
-	floppy_tq.routine = (void *)(void *) empty;
-	del_timer(&fd_timer);
+	cancel_activity();
 	sti();
 
 	floppy_enable_hlt();
 	fd_disable_dma();
 	/* avoid dma going to a random drive after shutdown */
 
-	if (!initialising && !mode)
-		DPRINT("floppy timeout\n");
+	if (!initialising)
+		DPRINT("floppy timeout called\n");
 	FDCS->reset = 1;
 	if (cont){
 		cont->done(0);
@@ -1940,6 +1943,14 @@
 	(done_f)empty
 };
 
+
+static struct cont_t intr_cont={
+	empty,
+	process_fd_request,
+	empty,
+	(done_f) empty
+};
+
 static int wait_til_done(void (*handler)(void), int interruptible)
 {
 	int ret;
@@ -1956,9 +1967,10 @@
 			sleep_on(&command_done);
 	}
 	if (command_status < 2){
-		floppy_shutdown(1);
+		cancel_activity();
+		cont = &intr_cont;
+		reset_fdc();
 		sti();
-		process_fd_request();
 		return -EINTR;
 	}
 	sti();
@@ -2046,8 +2058,8 @@
 }
 
 /*
- * formatting and support.
- * =======================
+ * formatting support.
+ * ===================
  */
 static void format_interrupt(void)
 {
@@ -2077,7 +2089,7 @@
 	raw_cmd->track = track;
 
 	raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-		/*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
+		FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
 	raw_cmd->rate = _floppy->rate & 0x43;
 	raw_cmd->cmd_count = NR_F;
 	COMMAND = FM_MODE(_floppy,FD_FORMAT);
@@ -2252,7 +2264,7 @@
 	if (nr_sectors > current_count_sectors + ssize -
 	     (current_count_sectors + sector_t) % ssize +
 	     sector_t % ssize){
-		DPRINT2("long rw: %x instead of %lx\n",
+		DPRINT("long rw: %x instead of %lx\n",
 			nr_sectors, current_count_sectors);
 		printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
 		printk("rh=%d h=%d\n", R_HEAD, HEAD);
@@ -2287,7 +2299,7 @@
 
 	if (probing) {
 		if (DP->flags & FTD_MSG)
-			DPRINT2("Auto-detected floppy type %s in fd%d\n",
+			DPRINT("Auto-detected floppy type %s in fd%d\n",
 				_floppy->name,current_drive);
 		current_type[current_drive] = _floppy;
 		floppy_sizes[TOMINOR(current_drive)] = _floppy->size >> 1;
@@ -2389,7 +2401,7 @@
 		if (dma_buffer + size >
 		    floppy_track_buffer + (max_buffer_sectors << 10) ||
 		    dma_buffer < floppy_track_buffer){
-			DPRINT1("buffer overrun in copy buffer %d\n",
+			DPRINT("buffer overrun in copy buffer %d\n",
 				(int) ((floppy_track_buffer - dma_buffer) >>9));
 			printk("sector_t=%d buffer_min=%d\n",
 			       sector_t, buffer_min);
@@ -2402,7 +2414,7 @@
 			break;
 		}
 		if (((unsigned long)buffer) % 512)
-			DPRINT1("%p buffer not aligned\n", buffer);
+			DPRINT("%p buffer not aligned\n", buffer);
 #endif
 		if (CT(COMMAND) == FD_READ) {
 			fd_cacheflush(dma_buffer, size);
@@ -2430,7 +2442,7 @@
 	if (remaining){
 		if (remaining > 0)
 			max_sector -= remaining >> 9;
-		DPRINT1("weirdness: remaining %d\n", remaining>>9);
+		DPRINT("weirdness: remaining %d\n", remaining>>9);
 	}
 #endif
 }
@@ -2582,7 +2594,7 @@
 			raw_cmd->length = current_count_sectors << 9;
 			if (raw_cmd->length == 0){
 				DPRINT("zero dma transfer attempted from make_raw_request\n");
-				DPRINT3("indirect=%d direct=%d sector_t=%d",
+				DPRINT("indirect=%d direct=%d sector_t=%d",
 					indirect, direct, sector_t);
 				return 0;
 			}
@@ -2638,7 +2650,7 @@
 	      aligned_sector_t < buffer_min)) ||
 	    raw_cmd->length % (128 << SIZECODE) ||
 	    raw_cmd->length <= 0 || current_count_sectors <= 0){
-		DPRINT2("fractionary current count b=%lx s=%lx\n",
+		DPRINT("fractionary current count b=%lx s=%lx\n",
 			raw_cmd->length, current_count_sectors);
 		if (raw_cmd->kernel_data != CURRENT->buffer)
 			printk("addr=%d, length=%ld\n",
@@ -3176,7 +3188,7 @@
 		if (cmd != FDDEFPRM)
 			/* notice a disk change immediately, else
 			 * we loose our settings immediately*/
-			CALL(poll_drive(1,0));
+			CALL(poll_drive(1, FD_RAW_NEED_DISK));
 		user_params[drive] = *g;
 		if (buffer_drive == drive)
 			SUPBOUND(buffer_max, user_params[drive].sect);
@@ -3362,6 +3374,9 @@
 			return set_geometry(cmd, & inparam.g,
 					    drive, type, device);
 		case FDGETPRM:
+			LOCK_FDC(drive,1);
+			CALL(poll_drive(1,0));
+			process_fd_request();
 			if (type)
 				outparam = (char *) &floppy_type[type];
 			else 
@@ -3876,7 +3891,7 @@
 			default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR;
 		}
 	}
-	DPRINT1("Assuming %s floppy hardware\n", param ? "standard" : "broken");
+	DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
 }
 
 static void set_cmos(int *ints, int dummy)
@@ -3896,11 +3911,11 @@
 		FDC2 = 0x370;
 	if (ints[2] <= 0 || 
 	    (ints[2] >= NUMBER(default_drive_params) && ints[2] != 16)){
-		DPRINT1("bad cmos code %d\n", ints[2]);
+		DPRINT("bad cmos code %d\n", ints[2]);
 		return;
 	}
 	DP->cmos = ints[2];
-	DPRINT1("setting cmos code to %d\n", ints[2]);
+	DPRINT("setting cmos code to %d\n", ints[2]);
 }
 
 static struct param_table {
@@ -3949,14 +3964,14 @@
 				if(config_params[i].fn)
 					config_params[i].fn(ints,param);
 				if(config_params[i].var) {
-					DPRINT2("%s=%d\n", str, param);
+					DPRINT("%s=%d\n", str, param);
 					*config_params[i].var = param;
 				}
 				return;
 			}
 		}
 	if (str) {
-		DPRINT1("unknown floppy option [%s]\n", str);
+		DPRINT("unknown floppy option [%s]\n", str);
 		
 		DPRINT("allowed options are:");
 		for (i=0; i< ARRAY_SIZE(config_params); i++)
@@ -4091,12 +4106,12 @@
 	set_dor(0, ~0, 8);  /* avoid immediate interrupt */
 
 	if (fd_request_irq()) {
-		DPRINT1("Unable to grab IRQ%d for the floppy driver\n",
+		DPRINT("Unable to grab IRQ%d for the floppy driver\n",
 			FLOPPY_IRQ);
 		return -1;
 	}
 	if (fd_request_dma()) {
-		DPRINT1("Unable to grab DMA%d for the floppy driver\n",
+		DPRINT("Unable to grab DMA%d for the floppy driver\n",
 			FLOPPY_DMA);
 		fd_free_irq();
 		return -1;
diff -u --recursive --new-file v1.3.99/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v1.3.99/linux/drivers/block/ide-cd.c	Sun May  5 08:51:58 1996
+++ linux/drivers/block/ide-cd.c	Thu May  9 10:35:12 1996
@@ -94,10 +94,17 @@
  * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
  * 3.11  Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de>
  *                       to remove redundant verify_area calls.
+ * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
+ *                        from Gerhard Zuber <zuber@berlin.snafu.de>.
+ *                       Let open succeed even if there's no loaded disc.
  *
  * NOTE: Direct audio reads will only work on some types of drive.
  * So far, i've received reports of success for Sony and Toshiba drives.
  *
+ * NOTE: The changer functions were tested with the NEC CDR-251 drive.
+ * They may not work with the Sanyo 3-cd changer, which i understand
+ * uses a different protocol.
+ *
  * ATAPI cd-rom driver.  To be used with ide.c.
  *
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
@@ -182,6 +189,8 @@
 #define MODE_SELECT_10          0x55
 #define READ_CD                 0xbe
 
+#define LOAD_UNLOAD             0xa6
+
 
 /* ATAPI sense keys (mostly copied from scsi.h). */
 
@@ -1957,6 +1966,23 @@
 }
 
 
+/* If SLOT<0, unload the current slot.  Otherwise, try to load SLOT. */
+static int
+cdrom_load_unload (ide_drive_t *drive, unsigned long slot,
+		   struct atapi_request_sense *reqbuf)
+{
+	struct packet_command pc;
+
+	memset (&pc, 0, sizeof (pc));
+	pc.sense_data = reqbuf;
+
+	pc.c[0] = LOAD_UNLOAD;
+	pc.c[4] = 2 + (slot >= 0);
+	pc.c[8] = slot;
+	return cdrom_queue_packet_command (drive, &pc);
+}
+
+
 int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
 		     struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -2370,6 +2396,33 @@
 		return stat;
 	}
 
+	case CDROMLOADFROMSLOT: {
+		struct atapi_request_sense my_reqbuf;
+		int stat;
+
+		if (drive->usage > 1)
+			return -EBUSY;
+
+		stat = cdrom_load_unload (drive, -1, NULL);
+		if (stat) return stat;
+
+                cdrom_saw_media_change (drive);
+                if (arg == -1) {
+			(void) cdrom_lockdoor (drive, 0, NULL);
+			return 0;
+		}
+		stat = cdrom_load_unload (drive, arg, NULL);
+		if (stat) return stat;
+
+		stat = cdrom_check_status (drive, &my_reqbuf);
+		if (stat && my_reqbuf.sense_key == NOT_READY) {
+			return -ENOENT;
+		}
+
+		/* And try to read the TOC information now. */
+		return cdrom_read_toc (drive, &my_reqbuf);
+	}
+
 #if 0 /* Doesn't work reliably yet. */
 	case CDROMRESET: {
 		struct request req;
@@ -2471,17 +2524,12 @@
 			stat = cdrom_check_status (drive, &my_reqbuf);
 		}
 
-		/* Return an error if there are still problems. */
-		if (stat && my_reqbuf.sense_key != UNIT_ATTENTION) {
-			--drive->usage;
-			return -ENXIO;
+		/* If things worked ok, lock the door and read the
+		   TOC information. */
+		if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION) {
+			(void) cdrom_lockdoor (drive, 1, &my_reqbuf);
+			(void) cdrom_read_toc (drive, &my_reqbuf);
 		}
-
-		/* Now lock the door. */
-		(void) cdrom_lockdoor (drive, 1, &my_reqbuf);
-
-		/* And try to read the TOC information now. */
-		(void) cdrom_read_toc (drive, &my_reqbuf);
 	}
 
 	return 0;
@@ -2593,7 +2641,7 @@
  *   duplicated functionality between read and ioctl paths?
  *  Establish interfaces for an IDE port driver, and break out the cdrom
  *   code into a loadable module.
- *  Support changers.
+ *  Support changers better.
  *  Write some real documentation.
  */
 
diff -u --recursive --new-file v1.3.99/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.99/linux/drivers/block/ide.c	Sun May  5 08:51:59 1996
+++ linux/drivers/block/ide.c	Fri May 10 08:02:26 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.39  May 3, 1996
+ *  linux/drivers/block/ide.c	Version 5.41  May 9, 1996
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors (see below)
  */
@@ -231,6 +231,10 @@
  *			mask drive irq after use, if sharing with another hwif
  *			add code to help debug weird cmd640 problems
  * Version 5.39		fix horrible error in earlier irq sharing "fix"
+ * Version 5.40		fix serialization -- was broken in 5.39
+ *			help sharing by masking device irq after probing
+ * Version 5.41		more fixes to irq sharing/serialize detection
+ *			disable io_32bit by default on drive reset
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -705,8 +709,10 @@
 	/* For an ATAPI device, first try an ATAPI SRST. */
 	if (drive->media != ide_disk) {
 		if (!do_not_try_atapi) {
-			if (!drive->keep_settings)
+			if (!drive->keep_settings) {
 				drive->unmask = 0;
+				drive->io_32bit = 0;
+			}
 			OUT_BYTE (drive->select.all, IDE_SELECT_REG);
 			udelay (20);
 			OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
@@ -732,6 +738,7 @@
 		if (!rdrive->keep_settings) {
 			rdrive->mult_req = 0;
 			rdrive->unmask = 0;
+			rdrive->io_32bit = 0;
 			if (rdrive->using_dma) {
 				rdrive->using_dma = 0;
 				printk("%s: disabled DMA\n", rdrive->name);
@@ -2376,8 +2383,11 @@
 
 #if CONFIG_BLK_DEV_PROMISE
 	if (IS_PROMISE_DRIVE) {
-		if(promise_cmd(drive,PROMISE_IDENTIFY))
+		if (promise_cmd(drive,PROMISE_IDENTIFY)) {
+			if (irqs)
+				(void) probe_irq_off(irqs);
 			return 1;
+		}
 	} else
 #endif /* CONFIG_BLK_DEV_PROMISE */
 		OUT_BYTE(cmd,IDE_COMMAND_REG);		/* ask drive for ID */
@@ -2385,7 +2395,7 @@
 	timeout += jiffies;
 	do {
 		if (jiffies > timeout) {
-			if (!HWIF(drive)->irq)
+			if (irqs)
 				(void) probe_irq_off(irqs);
 			return 1;	/* drive timed-out */
 		}
@@ -2409,10 +2419,13 @@
 	} else
 		rc = 2;			/* drive refused ID */
 	if (!HWIF(drive)->irq) {
-		irqs = probe_irq_off(irqs);	/* get irq number */
-		if (irqs > 0)
-			HWIF(drive)->irq = irqs;
-		else {				/* Mmmm.. multiple IRQs */
+		irqs = probe_irq_off(irqs);	/* get our irq number */
+		if (irqs > 0) {
+			HWIF(drive)->irq = irqs; /* save it for later */
+			irqs = probe_irq_on();  /* grab irqs, to ignore next edge */
+			OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
+			(void) probe_irq_off(irqs); /* restore irqs again */
+		} else {	/* Mmmm.. multiple IRQs.. don't know which was ours */
 			printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
 #ifdef CONFIG_BLK_DEV_CMD640
 			if (HWIF(drive)->chipset == ide_cmd640) {
@@ -2998,11 +3011,40 @@
 	return 1;
 }
 
+#if MAX_HWIFS > 1
+/*
+ * save_match() is used to simplify logic in init_irq() below.
+ *
+ * A loophole here is that we may not know about a particular
+ * hwif's irq until after that hwif is actually probed/initialized..
+ * This could be a problem for the case where an hwif is on a
+ * dual interface that requires serialization (eg. cmd640) and another
+ * hwif using one of the same irqs is initialized beforehand.
+ *
+ * This routine detects and reports such situations, but does not fix them.
+ */
+static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
+{
+	ide_hwif_t *m = *match;
+
+	if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
+		if (!new->hwgroup)
+			return;
+		printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name);
+	}
+	if (m->irq != hwif->irq) /* don't undo a prior perfect match */
+		*match = new;
+}
+#endif /* MAX_HWIFS > 1 */
 
 /*
  * This routine sets up the irq for an ide interface, and creates a new
  * hwgroup for the irq/hwif if none was previously assigned.
  *
+ * Much of the code is for correctly detecting/handling irq sharing
+ * and irq serialization situations.  This is somewhat complex because
+ * it handles static as well as dynamic (PCMCIA) IDE interfaces.
+ *
  * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with
  * interrupts completely disabled.  This can be bad for interrupt latency,
  * but anything else has led to problems on some machines.  We re-enable
@@ -3011,48 +3053,52 @@
 static int init_irq (ide_hwif_t *hwif)
 {
 	unsigned long flags;
-	ide_hwgroup_t *hwgroup = hwif->hwgroup;
-	ide_hwif_t *mate_hwif;
-	unsigned int index, mate_irq = hwif->irq;
+	unsigned int index;
+	ide_hwgroup_t *hwgroup;
+	ide_hwif_t *match = NULL;
 
 	save_flags(flags);
 	cli();
 
+	hwif->hwgroup = NULL;
+#if MAX_HWIFS > 1
 	/*
-	 * Handle serialization, regardless of init sequence
-	 */
-	mate_hwif = &ide_hwifs[hwif->index ^ 1];
-	if (hwif->serialized && mate_hwif->present)
-		mate_irq = mate_hwif->irq;
-
-	/*
-	 * Group up with any other hwifs that share our irq(s)
+	 * Group up with any other hwifs that share our irq(s).
 	 */
 	for (index = 0; index < MAX_HWIFS; index++) {
-		if (index != hwif->index) {
-			ide_hwif_t *h = &ide_hwifs[index];
-			if (h->irq == hwif->irq || h->irq == mate_irq) {
+		ide_hwif_t *h = &ide_hwifs[index];
+		if (h->hwgroup) {  /* scan only initialized hwif's */
+			if (hwif->irq == h->irq) {
 				hwif->sharing_irq = h->sharing_irq = 1;
-				if (hwgroup && !h->hwgroup)
-					h->hwgroup = hwgroup;
-				else if (!hwgroup)
-					hwgroup = h->hwgroup;
+				save_match(hwif, h, &match);
+			}
+			if (hwif->serialized) {
+				ide_hwif_t *mate = &ide_hwifs[hwif->index^1];
+				if (index == mate->index || h->irq == mate->irq)
+					save_match(hwif, h, &match);
+			}
+			if (h->serialized) {
+				ide_hwif_t *mate = &ide_hwifs[h->index^1];
+				if (hwif->irq == mate->irq)
+					save_match(hwif, h, &match);
 			}
 		}
 	}
-
+#endif /* MAX_HWIFS > 1 */
 	/*
 	 * If we are still without a hwgroup, then form a new one
 	 */
-	if (hwgroup == NULL) {
-		hwgroup = kmalloc (sizeof(ide_hwgroup_t), GFP_KERNEL);
+	if (match) {
+		hwgroup = match->hwgroup;
+	} else {
+		hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL);
 		hwgroup->hwif 	 = hwgroup->next_hwif = hwif->next = hwif;
 		hwgroup->rq      = NULL;
 		hwgroup->handler = NULL;
 		if (hwif->drives[0].present)
-			hwgroup->drive   = &hwif->drives[0];
+			hwgroup->drive = &hwif->drives[0];
 		else
-			hwgroup->drive   = &hwif->drives[1];
+			hwgroup->drive = &hwif->drives[1];
 		hwgroup->poll_timeout = 0;
 		init_timer(&hwgroup->timer);
 		hwgroup->timer.function = &timer_expiry;
@@ -3062,16 +3108,13 @@
 	/*
 	 * Allocate the irq, if not already obtained for another hwif
 	 */
-	if (!hwif->got_irq) {
+	if (!match || match->irq != hwif->irq) {
 		if (request_irq(hwif->irq, ide_intr, SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name, hwgroup)) {
+			if (!match)
+				kfree(hwgroup);
 			restore_flags(flags);
 			return 1;
 		}
-		for (index = 0; index < MAX_HWIFS; index++) {
-			ide_hwif_t *g = &ide_hwifs[index];
-			if (g->irq == hwif->irq)
-				g->got_irq = 1;
-		}
 	}
 
 	/*
@@ -3085,8 +3128,8 @@
 
 	printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
 		hwif->io_base, hwif->io_base+7, hwif->ctl_port, hwif->irq);
-	if (hwgroup->hwif != hwif)
-		printk(" (serialized with %s)", hwgroup->hwif->name);
+	if (match)
+		printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name);
 	printk("\n");
 	return 0;
 }
diff -u --recursive --new-file v1.3.99/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v1.3.99/linux/drivers/block/ide.h	Sun May  5 08:51:59 1996
+++ linux/drivers/block/ide.h	Fri May 10 11:35:00 1996
@@ -419,7 +419,6 @@
 	unsigned	present    : 1;	/* this interface exists */
 	unsigned	serialized : 1;	/* serialized operation with mate hwif */
 	unsigned	no_unmask  : 1;	/* disallow setting unmask bits */
-	unsigned	got_irq    : 1;	/* 1 = already alloc'd our irq */
 	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
 #ifdef CONFIG_BLK_DEV_PROMISE
 	unsigned	is_promise2: 1;	/* 2nd i/f on promise DC4030 */
diff -u --recursive --new-file v1.3.99/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.3.99/linux/drivers/block/ll_rw_blk.c	Tue May  7 16:22:22 1996
+++ linux/drivers/block/ll_rw_blk.c	Fri May 10 08:05:59 1996
@@ -617,6 +617,9 @@
 #ifdef CONFIG_BLK_DEV_LOOP
 	loop_init();
 #endif
+#ifdef CONFIG_CDI_INIT
+	cdi_init();		/* this MUST precede ide_init */
+#endif CONFIG_CDI_INIT
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_init();		/* this MUST precede hd_init */
 #endif
@@ -631,9 +634,6 @@
 #else
 	outb_p(0xc, 0x3f2);
 #endif
-#ifdef CONFIG_CDI_INIT
-	cdi_init();
-#endif CONFIG_CDI_INIT
 #ifdef CONFIG_CDU31A
 	cdu31a_init();
 #endif CONFIG_CDU31A
diff -u --recursive --new-file v1.3.99/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- v1.3.99/linux/drivers/block/umc8672.c	Fri Apr 12 15:51:50 1996
+++ linux/drivers/block/umc8672.c	Fri May 10 08:03:33 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/umc8672.c	Version 0.03  Feb 09, 1996
+ *  linux/drivers/block/umc8672.c	Version 0.04  May 09, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  */
@@ -35,7 +35,7 @@
  * the results from the DOS speed test program supplied from UMC. 11 is the 
  * highest speed (about PIO mode 3)
  */
-#undef REALLY_SLOW_IO		/* most systems can safely undef this */
+#define REALLY_SLOW_IO		/* some systems can safely undef this */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v1.3.99/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.3.99/linux/drivers/char/ChangeLog	Tue May  7 16:22:23 1996
+++ linux/drivers/char/ChangeLog	Wed May  8 10:32:41 1996
@@ -1,3 +1,21 @@
+Tue May  7 22:51:11 1996    <tytso@rsts-11.mit.edu>
+
+	* random.c (add_timer_randomness): Limit the amount randomness
+		that we estimate to 12 bits.  (An arbitrary amount).
+
+		(extract_entropy): To make it harder to analyze the hash
+		function, fold the hash function in half using XOR, and
+		use the folded result as the value to emit to the user.
+		Also, add timer randomness each pass through the
+		exact_entropy call, to increase the amount of unknown
+		values during the extraction process.
+
+		(random_ioctl): Use IOR/IOW definitions to define the
+		ioctl values used by the /dev/random driver.  Allow the
+		old ioctl values to be used for backwards compatibility
+		(for a limited amount of time).
+
+
 Wed Apr 24 14:02:04 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
 	* random.c (add_timer_randomness): Use 2nd derivative as well to
diff -u --recursive --new-file v1.3.99/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v1.3.99/linux/drivers/char/msbusmouse.c	Tue Apr  2 13:32:20 1996
+++ linux/drivers/char/msbusmouse.c	Fri May 10 07:44:05 1996
@@ -47,6 +47,13 @@
 #include <asm/irq.h>
 
 static struct mouse_status mouse;
+static int mouse_irq = MOUSE_IRQ;
+
+void msmouse_setup(char *str, int *ints)
+{
+	if (ints[0] > 0)
+		mouse_irq=ints[1];
+}
 
 static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
@@ -97,7 +104,7 @@
 		return;
 	MS_MSE_INT_OFF();
 	mouse.ready = 0; 
-	free_irq(MOUSE_IRQ, NULL);
+	free_irq(mouse_irq, NULL);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -107,7 +114,7 @@
 		return -EINVAL;
 	if (mouse.active++)
 		return 0;
-	if (request_irq(MOUSE_IRQ, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) {
+	if (request_irq(mouse_irq, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) {
 		mouse.active--;
 		return -EBUSY;
 	}
diff -u --recursive --new-file v1.3.99/linux/drivers/char/random.c linux/drivers/char/random.c
--- v1.3.99/linux/drivers/char/random.c	Tue May  7 16:22:25 1996
+++ linux/drivers/char/random.c	Wed May  8 10:32:41 1996
@@ -1,7 +1,7 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 0.97, last modified 24-Apr-96
+ * Version 0.98, last modified 7-May-96
  * 
  * Copyright Theodore Ts'o, 1994, 1995, 1996.  All rights reserved.
  *
@@ -458,7 +458,6 @@
  * On the i386, this is assumed to be at most 16 bits, and the high bits
  * are used for a high-resolution timer.
  *
- * TODO: Read the time stamp register on the Pentium.
  */
 static void add_timer_randomness(struct random_bucket *r,
 				 struct timer_rand_state *state, unsigned num)
@@ -475,21 +474,6 @@
 		time = (__u32) low;
 		num ^= (__u32) high;
 	} else {
-#if 0
-		/*
-		 * On a 386, read the high resolution timer.  We assume that
-		 * this gives us 2 bits of randomness.
-		 *
-		 * This is turned off for now because of the speed hit
-		 * it entails.
-		 */ 
-		outb_p(0x00, 0x43);	/* latch the count ASAP */
-		num |= inb_p(0x40) << 16;
-		num |= inb(0x40) << 24;
-		if (!state->dont_count_entropy)
-			r->entropy_count += 2;
-#endif
-		
 		time = jiffies;
 	}
 #else
@@ -521,6 +505,13 @@
 		for (nbits = 0; delta; nbits++)
 			delta >>= 1;
 
+		/*
+		 * In no case do we assume we've added more than 12
+		 * bits of randomness.
+		 */
+		if (nbits > 12)
+			nbits = 12;
+
 		r->entropy_count += nbits;
 
 		/* Prevent overflow */
@@ -844,6 +835,7 @@
 {
 	int ret, i;
 	__u32 tmp[HASH_BUFFER_SIZE];
+	char *cp,*dp;
 	
 	add_timer_randomness(r, &extract_timer_state, nbytes);
 	
@@ -885,15 +877,27 @@
 		 * add_entropy_word().
 		 */
 		HASH_TRANSFORM(tmp, r->pool);
+
+		/*
+		 * In case the hash function has some recognizeable
+		 * output pattern, we fold it half.
+		 */
+		cp = (char *) tmp;
+		dp = cp + (HASH_BUFFER_SIZE*sizeof(__u32)) - 1;
+		for (i=0; i <  HASH_BUFFER_SIZE*sizeof(__u32)/2; i++) {
+			*cp ^= *dp;
+			cp++;  dp--;
+		}
 		
 		/* Copy data to destination buffer */
-		i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32));
+		i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
 		if (to_user)
 			memcpy_tofs(buf, (__u8 const *)tmp, i);
 		else
 			memcpy(buf, (__u8 const *)tmp, i);
 		nbytes -= i;
 		buf += i;
+		add_timer_randomness(r, &extract_timer_state, nbytes);
 	}
 
 	/* Wipe data from memory */
@@ -1029,6 +1033,20 @@
 	int *p, size, ent_count;
 	int retval;
 	
+	/*
+	 * Translate old 1.3.XX values.
+	 * Remove this code in 2.1.0.
+	 * <mec@duracef.shout.net>
+	 */
+	switch (cmd) {
+	case 0x01080000: cmd = RNDGETENTCNT;   break;
+	case 0x01080001: cmd = RNDADDTOENTCNT; break;
+	case 0x01080002: cmd = RNDGETPOOL;     break;
+	case 0x01080003: cmd = RNDADDENTROPY;  break;
+	case 0x01080004: cmd = RNDZAPENTCNT;   break;
+	case 0x01080006: cmd = RNDCLEARPOOL;   break;
+	}
+
 	switch (cmd) {
 	case RNDGETENTCNT:
 		retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
diff -u --recursive --new-file v1.3.99/linux/drivers/net/hydra.c linux/drivers/net/hydra.c
--- v1.3.99/linux/drivers/net/hydra.c	Tue May  7 16:22:28 1996
+++ linux/drivers/net/hydra.c	Wed May  8 07:20:02 1996
@@ -382,7 +382,7 @@
             #endif
 	    
 
-	    /* overwrite warning occured, stop NIC & check the BOUNDARY pointer */
+	    /* overwrite warning occurred, stop NIC & check the BOUNDARY pointer */
 	    /* FIXME - real overwrite handling needed !! */
 
 	    printk("hydra_interrupt(): overwrite warning, resetting NIC\n");
diff -u --recursive --new-file v1.3.99/linux/drivers/net/hydra.h linux/drivers/net/hydra.h
--- v1.3.99/linux/drivers/net/hydra.h	Tue May  7 16:22:29 1996
+++ linux/drivers/net/hydra.h	Wed May  8 07:20:02 1996
@@ -117,7 +117,7 @@
 #define ISR_PTX   0x02 /* Packet transmitted without errors */
 #define ISR_RXE   0x04 /* Receive error  */
 #define ISR_TXE   0x08 /* Transmit error */
-#define ISR_OVW   0x10 /* Ring buffer overrrun */
+#define ISR_OVW   0x10 /* Ring buffer overrun */
 #define ISR_CNT   0x20 /* Counter overflow    */
 #define ISR_RDC   0x40 /* Remote DMA compile */
 #define ISR_RST   0x80 /* Reset status      */
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v1.3.99/linux/drivers/scsi/Config.in	Tue May  7 16:22:32 1996
+++ linux/drivers/scsi/Config.in	Thu May  9 16:40:24 1996
@@ -40,7 +40,7 @@
     bool '   allow DISCONNECT' CONFIG_SCSI_NCR53C7xx_DISCONNECT
   fi
 fi
-dep_tristate 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 $CONFIG_SCSI
+dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
 dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
 dep_tristate 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC $CONFIG_SCSI
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v1.3.99/linux/drivers/scsi/advansys.c	Fri Apr 12 15:51:59 1996
+++ linux/drivers/scsi/advansys.c	Fri May 10 07:55:36 1996
@@ -1,4 +1,4 @@
-/* $Id: advansys.c,v 1.12 1996/02/23 20:48:27 bobf Exp bobf $ */
+/* $Id: advansys.c,v 1.14 1996/05/10 00:26:31 bobf Exp bobf $ */
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  * 
@@ -14,8 +14,8 @@
  * bobf@advansys.com (Bob Frey)
  */
 
-/* The driver has been tested with Linux v1.2.1 and v1.3.57 kernels. */
-#define ASC_VERSION "1.3"	/* AdvanSys Driver Version */
+/* The driver has been tested with Linux v1.2.13 and v1.3.57 kernels. */
+#define ASC_VERSION "1.4"	/* AdvanSys Driver Version */
 
 /*
 
@@ -359,6 +359,15 @@
          4. Eliminate 'make dep' warning.
          5. Try to fix problem with handling resets by increasing their
             timeout value.
+
+     5/8/96 1.4:
+         1. Change definitions to eliminate conflicts with other subsystems.
+         2. Add versioning code for the shared interrupt changes.
+         3. Eliminate problem in asc_rmqueue() with iterating after removing
+            a request.
+         4. Remove reset request loop problem from the "Known Problems or
+            Issues" section. This problem was isolated and fixed in the
+            mid-level SCSI driver.
         
   H. Known Problems or Issues
 
@@ -377,10 +386,6 @@
         value is only changed on the first scsi command for each device
         and never thereafter. The same change is made for reset commands.
 
-     3. The driver occasionally enters a loop handling reset requests. It
-        isn't clear yet whether this is a bug in the upper or mid-level
-        scsi modules or in this driver.
-
   I. Credits
 
      Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and
@@ -482,11 +487,6 @@
 #define ASC_LIB_SERIAL_NUMBER  53
 
 typedef unsigned char uchar;
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-
-typedef int         BOOL;
 
 #ifndef NULL
 #define NULL     (0)
@@ -502,33 +502,33 @@
 
 #define  REG     register
 
-#define rchar    REG char
-#define rshort   REG short
-#define rint     REG int
-#define rlong    REG long
-
-#define ruchar   REG uchar
-#define rushort  REG ushort
-#define ruint    REG uint
-#define rulong   REG ulong
+#define rchar    REG __s8
+#define rshort   REG __s16
+#define rint     REG __s32
+#define rlong    REG __s32
+
+#define ruchar   REG __u8
+#define rushort  REG __u16
+#define ruint    REG __u32
+#define rulong   REG __u32
 
 #define NULLPTR   ( void *)0
 #define FNULLPTR  ( void dosfar *)0UL
 #define EOF      (-1)
 #define EOS      '\0'
 #define ERR      (-1)
-#define UB_ERR   (uchar)(0xFF)
-#define UW_ERR   (uint)(0xFFFF)
-#define UL_ERR   (ulong)(0xFFFFFFFFUL)
-
-#define iseven_word( val )  ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 )
-#define isodd_word( val )   ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 )
-#define toeven_word( val )  ( ( ( uint )val ) & ( uint )0xFFFE )
-
-#define biton( val, bits )   ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 )
-#define bitoff( val, bits )  ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 )
-#define lbiton( val, bits )  ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 )
-#define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 )
+#define UB_ERR   (__u8)(0xFF)
+#define UW_ERR   (__u16)(0xFFFF)
+#define UL_ERR   (__u32)(0xFFFFFFFFUL)
+
+#define iseven_word( val )  ( ( ( ( __u16 )val) & ( __u16 )0x0001 ) == 0 )
+#define isodd_word( val )   ( ( ( ( __u16 )val) & ( __u16 )0x0001 ) != 0 )
+#define toeven_word( val )  ( ( ( __u16 )val ) & ( __u16 )0xFFFE )
+
+#define biton( val, bits )   ((( __u16 )( val >> bits ) & (__u16)0x0001 ) != 0 )
+#define bitoff( val, bits )  ((( __u16 )( val >> bits ) & (__u16)0x0001 ) == 0 )
+#define lbiton( val, bits )  ((( __u32 )( val >> bits ) & (__u32)0x00000001UL ) != 0 )
+#define lbitoff( val, bits ) ((( __u32 )( val >> bits ) & (__u32)0x00000001UL ) == 0 )
 
 #define  absh( val )    ( ( val ) < 0 ? -( val ) : ( val ) )
 
@@ -546,25 +546,25 @@
 #define KBYTE       (0x400)
 #endif
 
-#define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) )
-#define LO_BYTE(x) ( *( ( BYTE *)&x ) )
+#define HI_BYTE(x) ( *( ( __u8 *)(&x)+1 ) )
+#define LO_BYTE(x) ( *( ( __u8 *)&x ) )
 
-#define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) )
-#define LO_WORD(x) ( *( ( WORD *)&x ) )
+#define HI_WORD(x) ( *( ( __u16 *)(&x)+1 ) )
+#define LO_WORD(x) ( *( ( __u16 *)&x ) )
 
 #ifndef MAKEWORD
-#define MAKEWORD(lo, hi)    ((WORD) (((WORD) lo) | ((WORD) hi << 8)))
+#define MAKEWORD(lo, hi)    ((__u16) (((__u16) lo) | ((__u16) hi << 8)))
 #endif
 
 #ifndef MAKELONG
-#define MAKELONG(lo, hi)    ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16)))
+#define MAKELONG(lo, hi)    ((__u32) (((__u32) lo) | ((__u32) hi << 16)))
 #endif
 
-#define SwapWords(dWord)        ((DWORD) ((dWord >> 16) | (dWord << 16)))
-#define SwapBytes(word)         ((WORD) ((word >> 8) | (word << 8)))
+#define SwapWords(dWord)        ((__u32) ((dWord >> 16) | (dWord << 16)))
+#define SwapBytes(word)         ((__u16) ((word >> 8) | (word << 8)))
 
 #define BigToLittle(dWord) \
-    ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
+    ((__u32) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
 #define LittleToBig(dWord)      BigToLittle(dWord)
 
 #define Lptr
@@ -2551,7 +2551,11 @@
 #ifdef LINUX_1_3
 STATIC int			asc_proc_copy(off_t, off_t, char *, int , char *, int);
 #endif /* LINUX_1_3 */
+#ifdef LINUX_1_2
+STATIC void 		advansys_interrupt(int, struct pt_regs *);
+#else /* LINUX_1_3 */
 STATIC void 		advansys_interrupt(int, void *, struct pt_regs *);
+#endif /* LINUX_1_3 */
 STATIC void 		advansys_command_done(Scsi_Cmnd *);
 STATIC int 			asc_execute_scsi_cmnd(Scsi_Cmnd *);
 STATIC void 		asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
@@ -3106,8 +3110,13 @@
 
 			/* Register IRQ Number. */
 			ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
+#ifdef LINUX_1_2
+			if ((ret = request_irq(shp->irq, advansys_interrupt,
+								SA_INTERRUPT, "advansys")) != 0) {
+#else /* LINUX_1_3 */
 			if ((ret = request_irq(shp->irq, advansys_interrupt,
 								SA_INTERRUPT, "advansys", NULL)) != 0) {
+#endif /* LINUX_1_3 */
 				ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
 				release_region(shp->io_port, shp->n_io_port);
 				if (shp->dma_channel != NO_ISA_DMA) {
@@ -3130,7 +3139,11 @@
 				if (shp->dma_channel != NO_ISA_DMA) {
 					free_dma(shp->dma_channel);
 				}
+#ifdef LINUX_1_2
+				free_irq(shp->irq);
+#else /* LINUX_1_3 */
 				free_irq(shp->irq, NULL);
+#endif /* LINUX_1_3 */
 				scsi_unregister(shp);
 				asc_board_count--;
 				continue;
@@ -3152,7 +3165,11 @@
 advansys_release(struct Scsi_Host *shp)
 {
 	ASC_DBG(1, "advansys_release: begin\n");
+#ifdef LINUX_1_2
+	free_irq(shp->irq);
+#else /* LINUX_1_3 */
 	free_irq(shp->irq, NULL);
+#endif /* LINUX_1_3 */
 	if (shp->dma_channel != NO_ISA_DMA) {
 		ASC_DBG(1, "advansys_release: free_dma()\n");
 		free_dma(shp->dma_channel);
@@ -3577,7 +3594,11 @@
  * First-level interrupt handler.
  */
 STATIC void
+#ifdef LINUX_1_2
+advansys_interrupt(int irq, struct pt_regs *regs)
+#else /* LINUX_1_3 */
 advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#endif /* LINUX_1_3 */
 {
 	int			i;
 	int			flags;
@@ -4455,6 +4476,7 @@
 			scp->host_scribble = NULL;
 			ASC_STATS(rmqueue);
 			ret = ASC_TRUE;
+			break; /* Note: Don't iterate, *scpp may be NULL. */
 		}
 	}
 	if (ASC_BOARD(shp)->pending[tid] == NULL) {
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v1.3.99/linux/drivers/scsi/aha152x.c	Sun May  5 08:52:00 1996
+++ linux/drivers/scsi/aha152x.c	Thu May  9 07:39:42 1996
@@ -1220,9 +1220,9 @@
     info_array[1]=32;
     info_array[2]=disk->capacity / (64 * 32);
   } else {
-    info_array[0] = 256;
+    info_array[0] = 255;
     info_array[1] = 63;
-    info_array[2] = disk->capacity / (256 * 63);
+    info_array[2] = disk->capacity / (255 * 63);
     if(info_array[2] > 1023)
       info_array[2]=1023;
   }
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v1.3.99/linux/drivers/scsi/eata_dma.c	Tue May  7 16:22:33 1996
+++ linux/drivers/scsi/eata_dma.c	Wed May  8 07:20:02 1996
@@ -1118,7 +1118,7 @@
 
 	/*
 	 * If we are using a ISA board, we can't use extended SG,
-	 * because we would need exessive amounts of memory for
+	 * because we would need excessive amounts of memory for
 	 * bounce buffers.
 	 */
 	if (gc->SG_64K==TRUE && ntohs(gc->SGsiz)==64 && hd->bustype!=IS_ISA){
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v1.3.99/linux/drivers/scsi/in2000.c	Sun May  5 08:52:01 1996
+++ linux/drivers/scsi/in2000.c	Thu May  9 16:40:24 1996
@@ -82,7 +82,7 @@
  *
  *
  * TODO:
- *       proc interface. tagged queuing. multiple cards.
+ *       tagged queuing. multiple cards.
  *
  *
  * NOTE:
@@ -120,32 +120,28 @@
 #include "hosts.h"
 #include "in2000.h"
 
-#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/blk.h>
-#else
-#include "../block/blk.h"
-#endif
+#include <linux/stat.h>
 
 #ifdef MODULE
 #include <linux/module.h>
 #endif
 
 
-#define PROC_INTERFACE     /* add code for /proc/scsi/in2000/xxx interface */
-
-#define FAST_READ_IO       /* No problems with these on my machine */
-#define FAST_WRITE_IO
+#define IN2000_VERSION    "1.28"
+#define IN2000_DATE       "07/May/1996"
 
+#define PROC_INTERFACE     /* add code for /proc/scsi/in2000/xxx interface */
 #define SYNC_DEBUG         /* extra info on sync negotiation printed */
 #define DEBUGGING_ON       /* enable command-line debugging bitmask */
 #define DEBUG_DEFAULTS 0   /* default bitmask - change from command-line */
 
-#define IN2000_VERSION    "1.28"
-#define IN2000_DATE       "27/Apr/1996"
+#define FAST_READ_IO       /* No problems with these on my machine */
+#define FAST_WRITE_IO
 
 #ifdef DEBUGGING_ON
 #define DB(f,a) if (hostdata->args & (f)) a;
-#define CHECK_NULL(p,s) if (!(p)) {printk("\n"); while (1) printk("NP:%s\r",(s));}
+#define CHECK_NULL(p,s) /* if (!(p)) {printk("\n"); while (1) printk("NP:%s\r",(s));} */
 #else
 #define DB(f,a)
 #define CHECK_NULL(p,s)
@@ -851,11 +847,7 @@
  * re-think the multiple card capability....
  */
 
-#if LINUX_VERSION_CODE >= 0x010346   /* 1.3.70 */
 void in2000_intr (int irqnum, void * dev_id, struct pt_regs *ptregs)
-#else
-void in2000_intr (int irqnum, struct pt_regs *ptregs)
-#endif
 {
 struct Scsi_Host *instance;
 struct IN2000_hostdata *hostdata;
@@ -1684,11 +1676,7 @@
 
 
 
-#if LINUX_VERSION_CODE >= 0x010359        /* 1.3.89 */
 int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags)
-#else
-int in2000_reset(Scsi_Cmnd *cmd)
-#endif
 {
 unsigned long flags;
 struct Scsi_Host *instance;
@@ -1930,13 +1918,10 @@
 
 
 
-#if LINUX_VERSION_CODE >= 0x010300
-#include <linux/stat.h>
 struct proc_dir_entry proc_scsi_in2000 = {
    PROC_SCSI_IN2000, 6, "in2000",
    S_IFDIR | S_IRUGO | S_IXUGO, 2
    };
-#endif
 
 
 const unsigned int *bios_tab[] = {
@@ -1995,12 +1980,12 @@
       if (check_setup_strings("ioport",&flags,&val,buf)) {
          base = val;
          switches = ~inb(base + IO_SWITCHES) & 0xff;
-         printk("Forcing detection at IOport 0x%x.\n",base);
+         printk("Forcing IN2000 detection at IOport 0x%x ",base);
          bios = 2;
          }
       else if (*(bios_tab[bios]+0x04) == 0x41564f4e ||
           *(bios_tab[bios]+0x0c) == 0x61776c41) {
-         printk("Found IN2000 BIOS at 0x%x.\n",(unsigned int)bios_tab[bios]);
+         printk("Found IN2000 BIOS at 0x%x ",(unsigned int)bios_tab[bios]);
 
 /* Read the switch image that's mapped into EPROM space */
 
@@ -2015,7 +2000,7 @@
 
          x = ~inb(base + IO_SWITCHES) & 0xff;
          if (x != switches) {
-            printk("Bad IO signature: %02x vs %02x\n",x,switches);
+            printk("Bad IO signature: %02x vs %02x.\n",x,switches);
             continue;
             }
          }
@@ -2054,10 +2039,7 @@
  * initialize it.
  */
 
-#if LINUX_VERSION_CODE >= 0x010300
       tpnt->proc_dir = &proc_scsi_in2000; /* done more than once? harmless. */
-#endif
-
       detect_count++;
       instance  = scsi_register(tpnt, sizeof(struct IN2000_hostdata));
       if (!instance_list)
@@ -2071,12 +2053,7 @@
       write1_io(0,IO_FIFO_READ);             /* start fifo out in read mode */
       write1_io(0,IO_INTR_MASK);    /* allow all ints */
       x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT];
-
-#if LINUX_VERSION_CODE >= 0x010346   /* 1.3.70 */
       if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000", NULL)) {
-#else
-      if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000")) {
-#endif
          printk("in2000_detect: Unable to allocate IRQ.\n");
          detect_count--;
          continue;
@@ -2119,7 +2096,6 @@
       disc_taken_total = 0;
 #endif
 
-
       if (check_setup_strings("nosync",&flags,&val,buf))
          hostdata->sync_off = val;
 
@@ -2139,7 +2115,7 @@
       if (check_setup_strings("debug",&flags,&val,buf))
          hostdata->args = (val & DB_MASK);
 
-      while (check_setup_strings("proc",&flags,&val,buf))
+      if (check_setup_strings("proc",&flags,&val,buf))
          hostdata->proc = val;
 
       x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS);
@@ -2154,27 +2130,26 @@
       else
          hostdata->chip = C_WD33C93;
 
-      printk("in2000-%d: dip_switch=%02x: irq=%d ioport=%02x floppy=%s sync/DOS5=%s\n",
-                  instance->host_no,(switches & 0x7f),
+      printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ",
+                  (switches & 0x7f),
                   instance->irq,hostdata->io_base,
                   (switches & SW_FLOPPY)?"Yes":"No",
                   (switches & SW_SYNC_DOS5)?"Yes":"No");
-      printk("in2000-%d: hardware_ver=%02x chip=%s microcode=%02x\n",
-                  instance->host_no,hrev,
+      printk("hardware_ver=%02x chip=%s microcode=%02x\n",
+                  hrev,
                   (hostdata->chip==C_WD33C93)?"WD33c93":
                   (hostdata->chip==C_WD33C93A)?"WD33c93A":
                   (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
                   hostdata->microcode);
 #ifdef DEBUGGING_ON
-      printk("in2000-%d: setup_strings = ",instance->host_no);
+      printk("setup_strings = ");
       for (x=0; x<8; x++)
          printk("%s,",setup_strings[x]);
       printk("\n");
 #endif
       if (hostdata->sync_off == 0xff)
-         printk("in2000-%d: Sync-transfer DISABLED on all devices: ENABLE from command-line\n",instance->host_no);
-      printk("in2000-%d: driver version %s - %s\n",instance->host_no,
-                        IN2000_VERSION,IN2000_DATE);
+         printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n");
+      printk("IN2000 driver version %s - %s\n",IN2000_VERSION,IN2000_DATE);
       }
 
    return detect_count;
@@ -2186,11 +2161,7 @@
  *       supposed to do...
  */
 
-#if LINUX_VERSION_CODE >= 0x010300
 int in2000_biosparam(Disk *disk, kdev_t dev, int *iinfo)
-#else
-int in2000_biosparam(Disk *disk, int dev, int *iinfo)
-#endif
 {
 int size;
 
@@ -2222,6 +2193,26 @@
       }
     return 0;
 }
+
+
+#ifdef PROC_INTERFACE
+
+/* Certain older compilers (such as a.out 2.5.8) choke and give a
+ * "Too many reloads" error when there are a lot of calls to 'strcat()'
+ * in one function. Modern kernels define 'strcat()' as an inline
+ * function - I _guess_ this is related to the problem. Regardless,
+ * we can make everyone happy by doing some macro fudging to force
+ * gcc to do calls instead of inline expansion.
+ */
+
+char * in2000_strcat(char * dest, const char * src)
+{
+   return strcat(dest,src);
+}
+
+#define strcat(d,s) (in2000_strcat((d),(s)))
+
+#endif
 
 
 int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v1.3.99/linux/drivers/scsi/in2000.h	Mon Apr 29 18:05:18 1996
+++ linux/drivers/scsi/in2000.h	Thu May  9 16:40:24 1996
@@ -2,7 +2,7 @@
  *    in2000.h -  Linux device driver definitions for the
  *                Always IN2000 ISA SCSI card.
  *
- *    IMPORTANT: This file is for version 1.28 - 27/Apr/1996
+ *    IMPORTANT: This file is for version 1.28 - 07/May/1996
  *
  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
  *    john@geolog.com
@@ -25,16 +25,6 @@
 
 #include <asm/io.h>
 
-/* We include version.h to get 'LINUX_VERSION_CODE' - a define used here
- * and there in the source to get around various compatibility problems:
- * -  pre-1.3.xx kernels didn't have 'kdev_t' or proc, and their
- *    <blk.h> was in a different place.
- * -  1.3.70 introduced an additional argument for interrupt functions
- * -  1.3.89 added an argument to in2000_reset(), which we don't really
- *    use at the moment. But for completeness...
- */
-#include <linux/version.h>
-
 
 #define uchar unsigned char
 
@@ -325,17 +315,8 @@
 void in2000_setup(char *, int *);
 int in2000_proc_info(char *, char **, off_t, int, int, int);
 struct proc_dir_entry proc_scsi_in2000;
-
-#if LINUX_VERSION_CODE >= 0x010300
 int in2000_biosparam(struct scsi_disk *, kdev_t, int *);
-#else
-int in2000_biosparam(Disk *, int, int *);
-#endif
-#if LINUX_VERSION_CODE >= 0x010359           /* 1.3.89 */
 int in2000_reset(Scsi_Cmnd *, unsigned int);
-#else
-int in2000_reset(Scsi_Cmnd *);
-#endif
 
 
 #define IN2000_CAN_Q    16
@@ -343,7 +324,6 @@
 #define IN2000_CPL      2
 #define IN2000_HOST_ID  7
 
-#if LINUX_VERSION_CODE >= 0x010300
 #define IN2000 {  NULL,                /* link pointer for modules */ \
                   NULL,                /* usage_count for modules */ \
                   &proc_scsi_in2000,   /* pointer to /proc/scsi directory entry */ \
@@ -366,31 +346,6 @@
                   0,                   /* unchecked dma */ \
                   DISABLE_CLUSTERING \
                }
-
-#else
-#define IN2000 {  NULL,                /* link pointer for modules */ \
-                  NULL,                /* usage_count for modules */ \
-/*                  NULL,*/                /* pointer to /proc/scsi directory entry */ \
-/*                  NULL,*/                /* pointer to proc info function */ \
-                  "Always IN2000",     /* device name */ \
-                  in2000_detect,       /* returns number of in2000's found */ \
-                  NULL,                /* optional unload function for modules */ \
-                  NULL,                /* optional misc info function */ \
-                  NULL,                /* send scsi command, wait for completion */ \
-                  in2000_queuecommand, /* queue scsi command, don't wait */ \
-                  in2000_abort,        /* abort current command */ \
-                  in2000_reset,        /* reset scsi bus */ \
-                  NULL,                /* slave_attach - unused */ \
-                  in2000_biosparam,    /* figures out BIOS parameters for lilo, etc */ \
-                  IN2000_CAN_Q,        /* max commands we can queue up */ \
-                  IN2000_HOST_ID,      /* host-adapter scsi id */ \
-                  IN2000_SG,           /* scatter-gather table size */ \
-                  IN2000_CPL,          /* commands per lun */ \
-                  0,                   /* board counter */ \
-                  0,                   /* unchecked dma */ \
-                  DISABLE_CLUSTERING \
-               }
-#endif
 
 
 #endif /* IN2000_H */
diff -u --recursive --new-file v1.3.99/linux/drivers/scsi/in2000.readme linux/drivers/scsi/in2000.readme
--- v1.3.99/linux/drivers/scsi/in2000.readme	Sun May  5 08:52:01 1996
+++ linux/drivers/scsi/in2000.readme	Thu May  9 16:40:24 1996
@@ -1,5 +1,5 @@
 
-UPDATE NEWS: version 1.28 - 27 Apr 96
+UPDATE NEWS: version 1.28 - 07 May 96
 
    Tightened up the "interrupts enabled/disabled" discipline
    in 'in2000_queuecommand()' and maybe 1 or 2 other places.
@@ -70,51 +70,8 @@
    advantage. In a single device system, or if only 1 device
    is being accessed, transfers usually go faster if disconnects
    are not allowed.
-   Hackers -> the positions of some of the 'setup_default' flags
-              have changed, so check your command-line args if
-              you've been using them with a previous version.
-
-
-Hi everyone:
-
-   A revamped IN2000 SCSI driver is available for download and
-   testing at my ftp site:
-
-            ftp.netcom.com/pub/js/jshiffle
-
-   in the 'in2000' directory. It has what I think are a few
-   improvements over the stock driver, including disconnect/
-   reselect, synchronous transfer, easier debugging, command-
-   line arguments for setting run-time parameters and debug
-   output, and better FIFO handling. Swap partitions work now,
-   as do tape drives and anything else that used to butt heads
-   with the old driver's 2k block size limit. See the top
-   of the 'in2000.c' file for more details.
-
-   This is a rewrite of the in2000.[ch] files for Linux. They
-   are drop-in replacements for the originals in linux/drivers/scsi
-   - just copy them over the old ones. The driver has been tested
-   in 1.2.13 with and without ELF, and in the 1.3 series somewhere
-   up into the 60's. I don't expect any problems with newer kernels.
-   It is "modular-ised" for those who prefer that route.
-
--------  Hackers take note:   ------------------
-Anyone who wants to use LILO to pass a command line to this driver
-will have to make 2 small changes to the file 'init/main.c'. Find
-the area between lines 60-80 where all the 'xxxxx_setup()' extern
-declarations are and insert a new one like the following:
-
-extern void in2000_setup(char *str, int *ints);
-
-Then do a search for "bootsetups" - add a new entry to this array
-(somewhere in the middle) that looks like this:
-
-#ifdef CONFIG_SCSI_IN2000
-   { "in2000=", in2000_setup },
-#endif
 
-[You can skip the above if you're only loading the driver as a module
- or if the driver defaults are OK.]
+
 
 The default arguments (you get these when you don't give an 'in2000'
 command-line argument, or you give a blank argument) will cause
@@ -142,30 +99,15 @@
 
 ------------------------------------------------
 
-   I have run a LOT of tests on this driver, and it seems very solid,
-   including with up to 3 simultaneous large copy or tar commands
-   running between 6 devices at once. Synchronous transfers are
-   working fine for the devices I have to test, although others have
-   reported some failures (CDROM drives, mostly). Tape drives work
-   well (finally!) and so do CD-ROM drives.
-
    I should mention that Drew Eckhardt's 'Generic NCR5380' sources
    were my main inspiration, with lots of reference to the IN2000
    driver currently distributed in the kernel source. I also owe
    much to a driver written by Hamish Macdonald for Linux-m68k(!).
    And to Eric Wright for being an ALPHA guinea pig. And to Bill
    Earnest for 2 tons of great input and information. And to David
-   Willmore for extensive 'bonnie' testing.
+   Willmore for extensive 'bonnie' testing. And to Joe Mack for
+   continual testing and feedback.
 
-   Be forewarned that while I've had good luck with it, this
-   is the first time it's been loose out in the wide world.
-   It wouldn't surprise me if people uncover problems that
-   I haven't caught....
-
-   Please try the driver out. Test it, beat on it. And PLEASE get back
-   to me - I really need to hear about bugs, stupid or bad code,
-   and any ideas for enhancements.
-   Thanks very much...
 
             John Shifflett    jshiffle@netcom.com
 
diff -u --recursive --new-file v1.3.99/linux/fs/Makefile linux/fs/Makefile
--- v1.3.99/linux/fs/Makefile	Sat Apr 27 15:19:57 1996
+++ linux/fs/Makefile	Wed May  8 18:28:01 1996
@@ -173,6 +173,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_BINFMT_JAVA),y)
+BINFMTS += binfmt_java.o
+else
+  ifeq ($(CONFIG_BINFMT_JAVA),m)
+  M_OBJS += binfmt_java.o
+  endif
+endif
+
 # binfmt_script is always there
 BINFMTS += binfmt_script.o
 
diff -u --recursive --new-file v1.3.99/linux/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c
--- v1.3.99/linux/fs/affs/amigaffs.c	Tue May  7 16:22:35 1996
+++ linux/fs/affs/amigaffs.c	Thu May  9 16:37:11 1996
@@ -128,7 +128,7 @@
 	while (1) {
 		if (nextkey == 0)
 			break;
-		pr_debug("AFFS: find_link_pred(): next key=%d\n", nextkey));
+		pr_debug("AFFS: find_link_pred(): next key=%d\n", nextkey);
 		if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
 			break;
 		if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
diff -u --recursive --new-file v1.3.99/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v1.3.99/linux/fs/affs/namei.c	Tue May  7 16:22:36 1996
+++ linux/fs/affs/namei.c	Wed May  8 07:20:01 1996
@@ -603,7 +603,7 @@
 		if (affs_parent_ino(old_inode) != old_dir->i_ino)
 			goto end_rename;
 	}
-	/* Unlink destination if existant */
+	/* Unlink destination if existent */
 	if (new_inode) {
 		if ((retval = affs_fix_hash_pred(new_dir,affs_hash_name(new_name,new_len,
 		                                 AFFS_I2FSTYPE(new_dir),AFFS_I2HSIZE(new_dir)) + 6,
diff -u --recursive --new-file v1.3.99/linux/fs/binfmt_java.c linux/fs/binfmt_java.c
--- v1.3.99/linux/fs/binfmt_java.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/binfmt_java.c	Wed May  8 18:28:01 1996
@@ -0,0 +1,187 @@
+/*
+ *  linux/fs/binfmt_java.c
+ *
+ *  Copyright (C) 1996  Brian A. Lantz
+ *  derived from binfmt_script.c
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/malloc.h>
+#include <linux/binfmts.h>
+#include <paths.h>
+
+#define _PATH_JAVA	"/usr/local/java/bin/java"
+#define _PATH_APPLET	"/usr/local/java/bin/appletviewer"
+#define _PATH_BASH	"/bin/bash"
+
+static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+{
+	char *cp, *interp, *i_name;
+	int retval;
+	unsigned char *ucp = (unsigned char *) bprm->buf;
+	if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe)) 
+		return -ENOEXEC;
+
+	iput(bprm->inode);
+	bprm->dont_iput=1;
+
+	/*
+	 * OK, we've set the interpreter name
+	 * Splice in (1) the interpreter's name for argv[0] (_PATH_BASH)
+	 *           (2) the name of the java wrapper for argv[1] (_PATH_JAVA)
+	 *           (3) filename of Java class (replace argv[0])
+	 *               without leading path or trailing '.class'
+	 *
+	 * This is done in reverse order, because of how the
+	 * user environment and arguments are stored.
+	 */
+	remove_arg_zero(bprm);
+	if ((cp = strstr (bprm->filename, ".class")) != NULL)
+		*cp = 0;
+	if ((i_name = strrchr (bprm->filename, '/')) != NULL)
+		i_name++;
+	else
+		i_name = bprm->filename;
+	bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);
+	bprm->argc++;
+
+	strcpy (bprm->buf, _PATH_JAVA);
+	cp = bprm->buf;
+	bprm->p = copy_strings(1, &cp, bprm->page, bprm->p, 2);
+	bprm->argc++;
+
+	strcpy (bprm->buf, _PATH_BASH);
+	interp = bprm->buf;
+	if ((i_name = strrchr (bprm->buf, '/')) != NULL)
+		i_name++;
+	else
+		i_name = bprm->buf;
+	bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);
+	bprm->argc++;
+	if (!bprm->p) 
+		return -E2BIG;
+	/*
+	 * OK, now restart the process with the interpreter's inode.
+	 * Note that we use open_namei() as the name is now in kernel
+	 * space, and we don't need to copy it.
+	 */
+	retval = open_namei(interp, 0, 0, &bprm->inode, NULL);
+	if (retval)
+		return retval;
+	bprm->dont_iput=0;
+	retval=prepare_binprm(bprm);
+	if(retval<0)
+		return retval;
+
+	return search_binary_handler(bprm,regs);
+}
+
+static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
+{
+	char *cp, *interp, *i_name;
+	int retval;
+	if (strncmp (bprm->buf, "<!--applet", 10))
+		return -ENOEXEC;
+
+	iput(bprm->inode);
+	bprm->dont_iput=1;
+
+	/*
+	 * OK, we've set the interpreter name
+	 * Splice in (1) the interpreter's name for argv[0] (_PATH_BSHELL)
+	 *           (2) the name of the appletviewer wrapper for argv[1] (_PATH_APPLET)
+	 *           (3) filename of html file (replace argv[0])
+	 *
+	 * This is done in reverse order, because of how the
+	 * user environment and arguments are stored.
+	 */
+	remove_arg_zero(bprm);
+	i_name = bprm->filename;
+	bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);
+	bprm->argc++;
+
+	strcpy (bprm->buf, _PATH_APPLET);
+	cp = bprm->buf;
+	bprm->p = copy_strings(1, &cp, bprm->page, bprm->p, 2);
+	bprm->argc++;
+
+	strcpy (bprm->buf, _PATH_BSHELL);
+	interp = bprm->buf;
+	if ((i_name = strrchr (bprm->buf, '/')) != NULL)
+		i_name++;
+	else
+		i_name = bprm->buf;
+	bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);
+	bprm->argc++;
+	if (!bprm->p) 
+		return -E2BIG;
+	/*
+	 * OK, now restart the process with the interpreter's inode.
+	 * Note that we use open_namei() as the name is now in kernel
+	 * space, and we don't need to copy it.
+	 */
+	retval = open_namei(interp, 0, 0, &bprm->inode, NULL);
+	if (retval)
+		return retval;
+	bprm->dont_iput=0;
+	retval=prepare_binprm(bprm);
+	if(retval<0)
+		return retval;
+
+	return search_binary_handler(bprm,regs);
+}
+
+static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+{
+	int retval;
+	MOD_INC_USE_COUNT;
+	retval = do_load_script(bprm,regs);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+struct linux_binfmt java_format = {
+#ifndef MODULE
+	NULL, 0, load_script, NULL, NULL
+#else
+	NULL, &mod_use_count_, load_script, NULL, NULL
+#endif
+};
+
+static int load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
+{
+	int retval;
+	MOD_INC_USE_COUNT;
+	retval = do_load_applet(bprm,regs);
+	MOD_DEC_USE_COUNT;
+	return retval;
+}
+
+struct linux_binfmt applet_format = {
+#ifndef MODULE
+	NULL, 0, load_applet, NULL, NULL
+#else
+	NULL, &mod_use_count_, load_applet, NULL, NULL
+#endif
+};
+
+int init_java_binfmt(void) {
+	printk(KERN_INFO "JAVA Binary support v1.01 for Linux 1.3.98 (C)1996 Brian A. Lantz\n");
+	register_binfmt(&java_format);
+	return register_binfmt(&applet_format);
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return init_java_binfmt();
+}
+
+void cleanup_module( void) {
+	printk(KERN_INFO "Removing JAVA Binary support...\n");
+	unregister_binfmt(&java_format);
+	unregister_binfmt(&applet_format);
+}
+#endif
diff -u --recursive --new-file v1.3.99/linux/fs/exec.c linux/fs/exec.c
--- v1.3.99/linux/fs/exec.c	Sun Apr 21 12:39:02 1996
+++ linux/fs/exec.c	Wed May  8 18:28:01 1996
@@ -70,6 +70,10 @@
 #ifdef CONFIG_BINFMT_AOUT
 	init_aout_binfmt();
 #endif
+
+#ifdef CONFIG_BINFMT_JAVA
+	init_java_binfmt();
+#endif
 	/* This cannot be configured out of the kernel */
 	init_script_binfmt();
 }
diff -u --recursive --new-file v1.3.99/linux/fs/fat/buffer.c linux/fs/fat/buffer.c
--- v1.3.99/linux/fs/fat/buffer.c	Sat Apr 27 15:19:58 1996
+++ linux/fs/fat/buffer.c	Fri May 10 07:54:52 1996
@@ -15,16 +15,19 @@
 	int block)
 {
 	struct buffer_head *ret = NULL;
-	if (sb->s_blocksize == 512){
-/*		ret = bread (sb->s_dev,block,512); */
-		ret = breada (sb->s_dev,block,512,0,18*1024); 
-	}else{
-/*		struct buffer_head *real = bread (sb->s_dev,block>>1,1024); */
-		struct buffer_head *real = breada (sb->s_dev,block>>1,1024,0,18*1024); 
+
+	/* Note that the blocksize is 512 or 1024, but the first read
+	   is always of size 1024. Doing readahead may be counterproductive
+	   or just plain wrong. */
+	if (sb->s_blocksize == 512) {
+		ret = bread (sb->s_dev,block,512);
+	} else {
+		struct buffer_head *real = bread (sb->s_dev,block>>1,1024);
+
 		if (real != NULL){
-			ret = (struct buffer_head *)kmalloc (sizeof(struct buffer_head)
-				,GFP_KERNEL);
-			if (ret != NULL){
+			ret = (struct buffer_head *)
+			  kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
+			if (ret != NULL) {
 				/* #Specification: msdos / strategy / special device / dummy blocks
 					Many special device (Scsi optical disk for one) use
 					larger hardware sector size. This allows for higher
diff -u --recursive --new-file v1.3.99/linux/fs/fat/cache.c linux/fs/fat/cache.c
--- v1.3.99/linux/fs/fat/cache.c	Sat Apr 27 15:19:58 1996
+++ linux/fs/fat/cache.c	Fri May 10 07:54:52 1996
@@ -22,26 +22,27 @@
 {
 	struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
 	unsigned char *p_first,*p_last;
-	int first,last,next,copy;
+	int first,last,next,copy,b;
 
-	if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) return 0;
-	if (MSDOS_SB(sb)->fat_bits == 16) first = last = nr*2;
-	else {
+	if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
+		return 0;
+	if (MSDOS_SB(sb)->fat_bits == 16) {
+		first = last = nr*2;
+	} else {
 		first = nr*3/2;
 		last = first+1;
 	}
-	if (!(bh = breada(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
-	    SECTOR_BITS),SECTOR_SIZE,0,FAT_READAHEAD))) {
-		printk("breada in fat_access failed\n");
+	b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS);
+	if (!(bh = fat_bread(sb, b))) {
+		printk("bread in fat_access failed\n");
 		return 0;
 	}
-	if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS))
+	if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
 		bh2 = bh;
-	else {
-		if (!(bh2 = breada(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
-		    >> SECTOR_BITS),SECTOR_SIZE,0,FAT_READAHEAD))) {
-			brelse(bh);
-			printk("breada in fat_access failed\n");
+	} else {
+		if (!(bh2 = fat_bread(sb, b+1))) {
+			fat_brelse(sb, bh);
+			printk("2nd bread in fat_access failed\n");
 			return 0;
 		}
 	}
@@ -72,31 +73,30 @@
 				*p_first = new_value & 0xff;
 				*p_last = (*p_last & 0xf0) | (new_value >> 8);
 			}
-			mark_buffer_dirty(bh2, 1);
+			fat_mark_buffer_dirty(sb, bh2, 1);
 		}
-		mark_buffer_dirty(bh, 1);
+		fat_mark_buffer_dirty(sb, bh, 1);
 		for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
-			if (!(c_bh = breada(sb->s_dev,MSDOS_SB(sb)->
-			    fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
-			    fat_length*copy,SECTOR_SIZE,0,FAT_READAHEAD))) break;
+			b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS) +
+				MSDOS_SB(sb)->fat_length * copy;
+			if (!(c_bh = fat_bread(sb, b)))
+				break;
 			memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE);
-			mark_buffer_dirty(c_bh, 1);
+			fat_mark_buffer_dirty(sb, c_bh, 1);
 			if (bh != bh2) {
-				if (!(c_bh2 = breada(sb->s_dev,
-				    MSDOS_SB(sb)->fat_start+(first >>
-				    SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy
-				    +1,SECTOR_SIZE,0,FAT_READAHEAD))) {
-					brelse(c_bh);
+				if (!(c_bh2 = fat_bread(sb, b+1))) {
+					fat_brelse(sb, c_bh);
 					break;
 				}
 				memcpy(c_bh2->b_data,bh2->b_data,SECTOR_SIZE);
-				brelse(c_bh2);
+				fat_brelse(sb, c_bh2);
 			}
-			brelse(c_bh);
+			fat_brelse(sb, c_bh);
 		}
 	}
-	brelse(bh);
-	if (bh != bh2) brelse(bh2);
+	fat_brelse(sb, bh);
+	if (bh != bh2)
+		fat_brelse(sb, bh2);
 	return next;
 }
 
diff -u --recursive --new-file v1.3.99/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v1.3.99/linux/fs/fat/dir.c	Tue May  7 16:22:36 1996
+++ linux/fs/fat/dir.c	Fri May 10 07:54:52 1996
@@ -295,7 +295,8 @@
 		}
 		ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);	
 	}
-	if (bh) brelse(bh);
+	if (bh)
+		fat_brelse(sb, bh);
 	if (unicode) {
 		free_page((unsigned long) unicode);
 	}
diff -u --recursive --new-file v1.3.99/linux/fs/fat/file.c linux/fs/fat/file.c
--- v1.3.99/linux/fs/fat/file.c	Sun Feb 25 11:17:58 1996
+++ linux/fs/fat/file.c	Fri May 10 07:54:52 1996
@@ -123,12 +123,12 @@
 static void fat_prefetch (
 	struct inode *inode,
 	struct fat_pre *pre,
-	int nb)		/* How many must be prefetch at once */
+	int nb)		/* How many must we prefetch at once */
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bhreq[MSDOS_PREFETCH];	/* Buffers not */
-												/* already read */
-	int nbreq=0;			/* Number of buffers in bhreq */
+							/* already read */
+	int nbreq = 0;			/* Number of buffers in bhreq */
 	int i;
 	for (i=0; i<nb; i++){
 		int sector = fat_smap(inode,pre->file_sector);
@@ -136,10 +136,11 @@
 			struct buffer_head *bh;
 			PRINTK (("fsector2 %d -> %d\n",pre->file_sector-1,sector));
 			pre->file_sector++;
-			bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
+			bh = fat_getblk(sb, sector);
 			if (bh == NULL)	break;
 			pre->bhlist[pre->nblist++] = bh;
-			if (!fat_is_uptodate(sb,bh)) bhreq[nbreq++] = bh;
+			if (!fat_is_uptodate(sb,bh))
+				bhreq[nbreq++] = bh;
 		}else{
 			break;
 		}
@@ -229,7 +230,7 @@
 		wait_on_buffer(bh);
 		if (!fat_is_uptodate(sb,bh)){
 			/* read error  ? */
-			brelse (bh);
+			fat_brelse (sb, bh);
 			break;
 		}
 		offset = filp->f_pos & (SECTOR_SIZE-1);
@@ -252,12 +253,15 @@
 				}
 			}
 		}
-		brelse(bh);
+		fat_brelse(sb, bh);
 	}
 	PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
-	for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]);
-	if (start == buf) return -EIO;
-	if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
+	for (i=0; i<pre.nblist; i++)
+		fat_brelse (sb, pre.bhlist[i]);
+	if (start == buf)
+		return -EIO;
+	if (!IS_RDONLY(inode))
+		inode->i_atime = CURRENT_TIME;
 	filp->f_reada = 1;	/* Will be reset if a lseek is done */
 	return buf-start;
 }
@@ -288,14 +292,17 @@
 		printk("fat_file_write: mode = %07o\n",inode->i_mode);
 		return -EINVAL;
 	}
-	/* system files are immutable */
-	if (IS_IMMUTABLE(inode)) return -EPERM;
+	/* system files may be immutable */
+	if (IS_IMMUTABLE(inode))
+		return -EPERM;
 /*
  * ok, append may not work when many processes are writing at the same time
  * but so what. That way leads to madness anyway.
  */
-	if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
-	if (count <= 0) return 0;
+	if (filp->f_flags & O_APPEND)
+		filp->f_pos = inode->i_size;
+	if (count <= 0)
+		return 0;
 	error = carry = 0;
 	for (start = buf; count || carry; count -= size) {
 		while (!(sector = fat_smap(inode,filp->f_pos >> SECTOR_BITS)))
@@ -313,19 +320,18 @@
 			/* No need to read the block first since we will */
 			/* completely overwrite it */
 			/* or at least write past the end of file */
-			if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){
+			if (!(bh = fat_getblk(sb,sector))){
 				error = -EIO;
 				break;
 			}
-		}else if (!(bh = bread(inode->i_dev,sector,SECTOR_SIZE))) {
+		} else if (!(bh = fat_bread(sb,sector))) {
 			error = -EIO;
 			break;
 		}
 		if (binary_mode) {
 			memcpy_fromfs(bh->b_data+offset,buf,written = size);
 			buf += size;
-		}
-		else {
+		} else {
 			written = left = SECTOR_SIZE-offset;
 			to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1));
 			if (carry) {
@@ -352,9 +358,9 @@
 			inode->i_size = filp->f_pos;
 			inode->i_dirt = 1;
 		}
-		fat_set_uptodate(sb,bh,1);
-		mark_buffer_dirty(bh, 0);
-		brelse(bh);
+		fat_set_uptodate(sb, bh, 1);
+		fat_mark_buffer_dirty(sb, bh, 0);
+		fat_brelse(sb, bh);
 	}
 	if (start == buf)
 		return error;
@@ -369,7 +375,8 @@
 	int cluster;
 
 	/* Why no return value?  Surely the disk could fail... */
-	if (IS_IMMUTABLE(inode)) return /* -EPERM */;
+	if (IS_IMMUTABLE(inode))
+		return /* -EPERM */;
 	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
diff -u --recursive --new-file v1.3.99/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v1.3.99/linux/fs/fat/inode.c	Sun Apr 21 19:22:11 1996
+++ linux/fs/fat/inode.c	Fri May 10 07:54:52 1996
@@ -213,10 +213,10 @@
 	/* The first read is always 1024 bytes */
 	sb->s_blocksize = 1024;
 	set_blocksize(sb->s_dev, 1024);
-	bh = bread(sb->s_dev, 0, 1024);
+	bh = fat_bread(sb, 0);
 	unlock_super(sb);
 	if (bh == NULL || !fat_is_uptodate(sb,bh)) {
-		brelse (bh);
+		fat_brelse (sb, bh);
 		sb->s_dev = 0;
 		printk("FAT bread failed\n");
 		MOD_DEC_USE_COUNT;
@@ -271,15 +271,15 @@
 		    MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))
 		    || !b->secs_track || !b->heads;
 	}
-	brelse(bh);
+	fat_brelse(sb, bh);
 	/*
 		This must be done after the brelse because the bh is a dummy
 		allocated by fat_bread (see buffer.c)
 	*/
-	sb->s_blocksize = blksize;	/* Using this small block size solve the */
+	sb->s_blocksize = blksize;    /* Using this small block size solves */
 				/* the misfit with buffer cache and cluster */
-				/* because cluster (DOS) are often aligned */
-				/* on odd sector */
+				/* because clusters (DOS) are often aligned */
+				/* on odd sectors. */
 	sb->s_blocksize_bits = blksize == 512 ? 9 : 10;
 	if (error || debug) {
 		/* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
@@ -383,33 +383,31 @@
 	struct msdos_dir_entry *raw_entry;
 	int nr;
 
-/* printk("read inode %d\n",inode->i_ino); */
 	MSDOS_I(inode)->i_busy = 0;
 	MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
 	MSDOS_I(inode)->i_linked = MSDOS_I(inode)->i_oldlink = NULL;
 	MSDOS_I(inode)->i_binary = 1;
-	inode->i_uid = MSDOS_SB(inode->i_sb)->options.fs_uid;
-	inode->i_gid = MSDOS_SB(inode->i_sb)->options.fs_gid;
+	inode->i_uid = MSDOS_SB(sb)->options.fs_uid;
+	inode->i_gid = MSDOS_SB(sb)->options.fs_gid;
 	inode->i_version = ++event;
 	if (inode->i_ino == MSDOS_ROOT_INO) {
-		inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->options.fs_umask) |
+		inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) |
 		    S_IFDIR;
 		inode->i_op = fs_dir_inode_ops;
 		inode->i_nlink = fat_subdirs(inode)+2;
 		    /* subdirs (neither . nor ..) plus . and "self" */
-		inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries*
+		inode->i_size = MSDOS_SB(sb)->dir_entries*
 		    sizeof(struct msdos_dir_entry);
-		inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
+		inode->i_blksize = MSDOS_SB(sb)->cluster_size*
 		    SECTOR_SIZE;
 		inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
-		    inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
+		    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
 		MSDOS_I(inode)->i_start = 0;
 		MSDOS_I(inode)->i_attrs = 0;
 		inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 		return;
 	}
-	if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
-	    SECTOR_SIZE))) {
+	if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
 		printk("dev = %s, ino = %ld\n",
 		       kdevname(inode->i_dev), inode->i_ino);
 		panic("fat_read_inode: unable to read i-node block");
@@ -418,7 +416,7 @@
 	    [inode->i_ino & (MSDOS_DPB-1)];
 	if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
 		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
-		    ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFDIR;
+		    ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR;
 		inode->i_op = fs_dir_inode_ops;
 
 		MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
@@ -435,7 +433,7 @@
 			while (nr != -1) {
 				inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
 				    i_sb)->cluster_size;
-				if (!(nr = fat_access(inode->i_sb,nr,-1))) {
+				if (!(nr = fat_access(sb,nr,-1))) {
 					printk("Directory %ld: bad FAT\n",
 					    inode->i_ino);
 					break;
@@ -444,10 +442,10 @@
 	} else { /* not a directory */
 		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,
 		    ((IS_NOEXEC(inode) || 
-		      (MSDOS_SB(inode->i_sb)->options.showexec &&
+		      (MSDOS_SB(sb)->options.showexec &&
 		       !is_exec(raw_entry->ext)))
 		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)
-		    & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFREG;
+		    & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
 		inode->i_op = (sb->s_blocksize == 1024)
 			? &fat_file_inode_operations_1024
 			: &fat_file_inode_operations;
@@ -456,22 +454,22 @@
 		inode->i_size = CF_LE_L(raw_entry->size);
 	}
 	if(raw_entry->attr & ATTR_SYS)
-		if (MSDOS_SB(inode->i_sb)->options.sys_immutable)
+		if (MSDOS_SB(sb)->options.sys_immutable)
 			inode->i_flags |= S_IMMUTABLE;
-	MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->options.conversion,
+	MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(sb)->options.conversion,
 	    raw_entry->ext);
 	MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
 	/* this is as close to the truth as we can get ... */
-	inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
+	inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
 	inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
-	    inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
+	    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
 	inode->i_mtime = inode->i_atime =
 	    date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
 	inode->i_ctime =
-		MSDOS_SB(inode->i_sb)->options.isvfat
+		MSDOS_SB(sb)->options.isvfat
 		? date_dos2unix(CF_LE_W(raw_entry->ctime),CF_LE_W(raw_entry->cdate))
 		: inode->i_mtime;
-	brelse(bh);
+	fat_brelse(sb, bh);
 }
 
 
@@ -506,8 +504,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,
-	    SECTOR_SIZE))) {
+	if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
 		printk("dev = %s, ino = %ld\n",
 		       kdevname(inode->i_dev), inode->i_ino);
 		panic("msdos_write_inode: unable to read i-node block");
@@ -533,29 +530,30 @@
 		raw_entry->ctime = CT_LE_W(raw_entry->ctime);
 		raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 	}
-	mark_buffer_dirty(bh, 1);
-	brelse(bh);
+	fat_mark_buffer_dirty(sb, bh, 1);
+	fat_brelse(sb, bh);
 }
 
 
 int fat_notify_change(struct inode * inode,struct iattr * attr)
 {
+	struct super_block *sb = inode->i_sb;
 	int error;
 
 	error = inode_change_ok(inode, attr);
 	if (error)
-		return MSDOS_SB(inode->i_sb)->options.quiet ? 0 : error;
+		return MSDOS_SB(sb)->options.quiet ? 0 : error;
 
 	if (((attr->ia_valid & ATTR_UID) && 
-	     (attr->ia_uid != MSDOS_SB(inode->i_sb)->options.fs_uid)) ||
+	     (attr->ia_uid != MSDOS_SB(sb)->options.fs_uid)) ||
 	    ((attr->ia_valid & ATTR_GID) && 
-	     (attr->ia_gid != MSDOS_SB(inode->i_sb)->options.fs_gid)) ||
+	     (attr->ia_gid != MSDOS_SB(sb)->options.fs_gid)) ||
 	    ((attr->ia_valid & ATTR_MODE) &&
 	     (attr->ia_mode & ~MSDOS_VALID_MODE)))
 		error = -EPERM;
 
 	if (error)
-		return MSDOS_SB(inode->i_sb)->options.quiet ? 0 : error;
+		return MSDOS_SB(sb)->options.quiet ? 0 : error;
 
 	inode_setattr(inode, attr);
 
@@ -565,8 +563,8 @@
 		inode->i_mode |= S_IXUGO;
 
 	inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
-	    & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
-	    ~MSDOS_SB(inode->i_sb)->options.fs_umask;
+	    & ~MSDOS_SB(sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
+	    ~MSDOS_SB(sb)->options.fs_umask;
 	return 0;
 }
 
diff -u --recursive --new-file v1.3.99/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v1.3.99/linux/fs/fat/misc.c	Sat Apr 27 15:19:58 1996
+++ linux/fs/fat/misc.c	Fri May 10 07:54:52 1996
@@ -118,35 +118,34 @@
 	struct super_block *sb = inode->i_sb;
 	int count,nr,limit,last,curr,sector,last_sector,file_cluster;
 	struct buffer_head *bh;
-	int cluster_size = MSDOS_SB(inode->i_sb)->cluster_size;
+	int cluster_size = MSDOS_SB(sb)->cluster_size;
 
 	if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
-	if (!MSDOS_SB(inode->i_sb)->free_clusters) return -ENOSPC;
-	lock_fat(inode->i_sb);
-	limit = MSDOS_SB(inode->i_sb)->clusters;
+	if (!MSDOS_SB(sb)->free_clusters) return -ENOSPC;
+	lock_fat(sb);
+	limit = MSDOS_SB(sb)->clusters;
 	nr = limit; /* to keep GCC happy */
 	for (count = 0; count < limit; count++) {
-		nr = ((count+MSDOS_SB(inode->i_sb)->prev_free) % limit)+2;
-		if (fat_access(inode->i_sb,nr,-1) == 0) break;
+		nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2;
+		if (fat_access(sb,nr,-1) == 0) break;
 	}
 	PRINTK (("cnt = %d --",count));
 #ifdef DEBUG
 printk("free cluster: %d\n",nr);
 #endif
-	MSDOS_SB(inode->i_sb)->prev_free = (count+MSDOS_SB(inode->i_sb)->
-	    prev_free+1) % limit;
+	MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit;
 	if (count >= limit) {
-		MSDOS_SB(inode->i_sb)->free_clusters = 0;
-		unlock_fat(inode->i_sb);
+		MSDOS_SB(sb)->free_clusters = 0;
+		unlock_fat(sb);
 		return -ENOSPC;
 	}
-	fat_access(inode->i_sb,nr,MSDOS_SB(inode->i_sb)->fat_bits == 12 ?
+	fat_access(sb,nr,MSDOS_SB(sb)->fat_bits == 12 ?
 	    0xff8 : 0xfff8);
-	if (MSDOS_SB(inode->i_sb)->free_clusters != -1)
-		MSDOS_SB(inode->i_sb)->free_clusters--;
-	unlock_fat(inode->i_sb);
+	if (MSDOS_SB(sb)->free_clusters != -1)
+		MSDOS_SB(sb)->free_clusters--;
+	unlock_fat(sb);
 #ifdef DEBUG
-printk("set to %x\n",fat_access(inode->i_sb,nr,-1));
+printk("set to %x\n",fat_access(sb,nr,-1));
 #endif
 	last = 0;
 	/* We must locate the last cluster of the file to add this
@@ -166,9 +165,9 @@
 		while (curr && curr != -1){
 			PRINTK (("."));
 			file_cluster++;
-			if (!(curr = fat_access(inode->i_sb,
+			if (!(curr = fat_access(sb,
 			    last = curr,-1))) {
-				fat_fs_panic(inode->i_sb,"File without EOF");
+				fat_fs_panic(sb,"File without EOF");
 				return -ENOSPC;
 			}
 		}
@@ -177,27 +176,27 @@
 #ifdef DEBUG
 printk("last = %d\n",last);
 #endif
-	if (last) fat_access(inode->i_sb,last,nr);
+	if (last) fat_access(sb,last,nr);
 	else {
 		MSDOS_I(inode)->i_start = nr;
 		inode->i_dirt = 1;
 	}
 #ifdef DEBUG
-if (last) printk("next set to %d\n",fat_access(inode->i_sb,last,-1));
+if (last) printk("next set to %d\n",fat_access(sb,last,-1));
 #endif
-	sector = MSDOS_SB(inode->i_sb)->data_start+(nr-2)*cluster_size;
+	sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
 	last_sector = sector + cluster_size;
 	for ( ; sector < last_sector; sector++) {
 		#ifdef DEBUG
 			printk("zeroing sector %d\n",sector);
 		#endif
-		if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE)))
+		if (!(bh = fat_getblk(sb, sector)))
 			printk("getblk failed\n");
 		else {
 			memset(bh->b_data,0,SECTOR_SIZE);
-			fat_set_uptodate(sb,bh,1);
-			mark_buffer_dirty(bh, 1);
-			brelse(bh);
+			fat_set_uptodate(sb, bh, 1);
+			fat_mark_buffer_dirty(sb, bh, 1);
+			fat_brelse(sb, bh);
 		}
 	}
 	if (file_cluster != inode->i_blocks/cluster_size){
@@ -209,7 +208,7 @@
 	inode->i_blocks += cluster_size;
 	if (S_ISDIR(inode->i_mode)) {
 		if (inode->i_size & (SECTOR_SIZE-1)) {
-			fat_fs_panic(inode->i_sb,"Odd directory size");
+			fat_fs_panic(sb,"Odd directory size");
 			inode->i_size = (inode->i_size+SECTOR_SIZE) &
 			    ~(SECTOR_SIZE-1);
 		}
@@ -284,7 +283,7 @@
     struct msdos_dir_entry **de)
 {
 	struct super_block *sb = dir->i_sb;
-	int sector,offset;
+	int sector, offset;
 
 	while (1) {
 		offset = *pos;
@@ -296,9 +295,9 @@
 			return -1; /* beyond EOF */
 		*pos += sizeof(struct msdos_dir_entry);
 		if (*bh)
-			brelse(*bh);
+			fat_brelse(sb, *bh);
 		PRINTK (("get_entry sector apres brelse\n"));
-		if (!(*bh = breada(dir->i_dev,sector,SECTOR_SIZE,0,FAT_READAHEAD))) {
+		if (!(*bh = fat_bread(sb, sector))) {
 			printk("Directory sread (sector %d) failed\n",sector);
 			continue;
 		}
@@ -372,7 +371,8 @@
 	struct inode *inode;
 	int entry,start,done;
 
-	if (!(bh = breada(sb->s_dev,sector,SECTOR_SIZE,0,FAT_READAHEAD))) return -EIO;
+	if (!(bh = fat_bread(sb,sector)))
+		return -EIO;
 	data = (struct msdos_dir_entry *) bh->b_data;
 	for (entry = 0; entry < MSDOS_DPS; entry++) {
 /* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
@@ -393,7 +393,8 @@
 		if (done) {
 			if (ino) *ino = sector*MSDOS_DPS+entry;
 			start = CF_LE_W(data[entry].start);
-			if (!res_bh) brelse(bh);
+			if (!res_bh)
+				fat_brelse(sb, bh);
 			else {
 				*res_bh = bh;
 				*res_de = &data[entry];
@@ -401,7 +402,7 @@
 			return start;
 		}
 	}
-	brelse(bh);
+	fat_brelse(sb, bh);
 	return -ENOENT;
 }
 
diff -u --recursive --new-file v1.3.99/linux/fs/fat/msbuffer.h linux/fs/fat/msbuffer.h
--- v1.3.99/linux/fs/fat/msbuffer.h	Tue May  7 16:22:36 1996
+++ linux/fs/fat/msbuffer.h	Fri May 10 07:54:52 1996
@@ -13,24 +13,3 @@
 int fat_is_uptodate (struct super_block *sb, struct buffer_head *bh);
 void fat_ll_rw_block (struct super_block *sb, int opr,
 	int nbreq, struct buffer_head *bh[32]);
-
-/* These macros exist to avoid modifying all the code */
-/* They should be removed one day I guess */
-
-/* The versioning mechanism of the modules system defines those macros */
-/* This removes some warnings */
-#ifdef brelse
-	#undef brelse
-#endif
-#ifdef bread
-	#undef bread
-#endif
-#ifdef getblk
-	#undef getblk
-#endif
-
-#define brelse(b)			fat_brelse(sb,b)
-#define bread(d,b,s)			fat_bread(sb,b)
-#define getblk(d,b,s)			fat_getblk(sb,b)
-#define mark_buffer_dirty(b,v)		fat_mark_buffer_dirty(sb,b,v)
-
diff -u --recursive --new-file v1.3.99/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v1.3.99/linux/fs/msdos/namei.c	Sun Apr 21 19:22:11 1996
+++ linux/fs/msdos/namei.c	Fri May 10 07:54:52 1996
@@ -216,9 +216,9 @@
 		return res;
 	}
 	PRINTK (("msdos_lookup 4\n"));
-	if (bh) brelse(bh);
+	if (bh)
+		fat_brelse(sb, bh);
 	PRINTK (("msdos_lookup 4.5\n"));
-/* printk("lookup: ino=%d\n",ino); */
 	if (!(*result = iget(dir->i_sb,ino))) {
 		iput(dir);
 		return -EACCES;
@@ -279,10 +279,10 @@
 	de->start = 0;
 	fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
 	de->size = 0;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 	if ((*result = iget(dir->i_sb,ino)) != NULL)
 		msdos_read_inode(*result);
-	brelse(bh);
+	fat_brelse(sb, bh);
 	if (!*result) return -EIO;
 	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
 	    CURRENT_TIME;
@@ -316,13 +316,13 @@
 	 */
 	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {
 		fat_unlock_creation();
-		brelse(bh);
+		fat_brelse(sb, bh);
 		iput(dir);
 		return is_hid ? -EEXIST : -EINVAL;
  	}
 	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {
 		fat_unlock_creation();
-		brelse(bh);
+		fat_brelse(sb, bh);
 		iput(dir);
 		return is_hid ? -EINVAL : -EEXIST;
  	}
@@ -370,11 +370,11 @@
 			if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
 			    MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
 			    MSDOS_NAME)) {
-				brelse(bh);
+				fat_brelse(sb, bh);
 				return -ENOTEMPTY;
 			}
 		if (bh)
-			brelse(bh);
+			fat_brelse(sb, bh);
 	}
 	return 0;
 }
@@ -409,10 +409,10 @@
 	dir->i_nlink--;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 	res = 0;
 rmdir_done:
-	brelse(bh);
+	fat_brelse(sb, bh);
 	iput(dir);
 	iput(inode);
 	return res;
@@ -438,7 +438,7 @@
 	fat_lock_creation();
 	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) {
 		fat_unlock_creation();
-		brelse(bh);
+		fat_brelse(sb, bh);
 		iput(dir);
 		return -EEXIST;
  	}
@@ -513,9 +513,9 @@
 	MSDOS_I(inode)->i_busy = 1;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 unlink_done:
-	brelse(bh);
+	fat_brelse(sb, bh);
 	iput(inode);
 	iput(dir);
 	return res;
@@ -548,12 +548,13 @@
 	if (!strncmp(old_name,new_name,MSDOS_NAME)) goto set_hid;
 	exists = fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
 	if (*(unsigned char *) old_de->name == DELETED_FLAG) {
-		if (exists) brelse(new_bh);
+		if (exists)
+			fat_brelse(sb, new_bh);
 		return -ENOENT;
 	}
 	if (exists) {
 		if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
-			brelse(new_bh);
+			fat_brelse(sb, new_bh);
 			return -EIO;
 		}
 		error = S_ISDIR(new_inode->i_mode)
@@ -566,7 +567,7 @@
 		if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
 		if (error) {
 			iput(new_inode);
-			brelse(new_bh);
+			fat_brelse(sb, new_bh);
 			return error;
 		}
 		if (S_ISDIR(new_inode->i_mode)) {
@@ -577,17 +578,17 @@
 		MSDOS_I(new_inode)->i_busy = 1;
 		new_inode->i_dirt = 1;
 		new_de->name[0] = DELETED_FLAG;
-		mark_buffer_dirty(new_bh, 1);
+		fat_mark_buffer_dirty(sb, new_bh, 1);
 		dcache_add(new_dir, new_name, new_len, new_ino);
 		iput(new_inode);
-		brelse(new_bh);
+		fat_brelse(sb, new_bh);
 	}
 	memcpy(old_de->name,new_name,MSDOS_NAME);
 set_hid:
 	old_de->attr = is_hid
 		? (old_de->attr | ATTR_HIDDEN)
 		: (old_de->attr &~ ATTR_HIDDEN);
-	mark_buffer_dirty(old_bh, 1);
+	fat_mark_buffer_dirty(sb, old_bh, 1);
 	/* update binary info for conversion, i_attrs */
 	if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
 		MSDOS_I(old_inode)->i_attrs = is_hid
@@ -632,21 +633,23 @@
 	}
 	exists = fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
 	if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
-		brelse(free_bh);
-		if (exists) brelse(new_bh);
+		fat_brelse(sb, free_bh);
+		if (exists)
+			fat_brelse(sb, new_bh);
 		return -EIO;
 	}
 	if (*(unsigned char *) old_de->name == DELETED_FLAG) {
 		iput(old_inode);
-		brelse(free_bh);
-		if (exists) brelse(new_bh);
+		fat_brelse(sb, free_bh);
+		if (exists)
+			fat_brelse(sb, new_bh);
 		return -ENOENT;
 	}
 	new_inode = NULL; /* to make GCC happy */
 	if (exists) {  /* Trash the old file! */
 		if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
 			iput(old_inode);
-			brelse(new_bh);
+			fat_brelse(sb, new_bh);
 			return -EIO;
 		}
 		error = S_ISDIR(new_inode->i_mode)
@@ -660,14 +663,14 @@
 		if (error) {
 			iput(new_inode);
 			iput(old_inode);
-			brelse(new_bh);
+			fat_brelse(sb, new_bh);
 			return error;
 		}
 		new_inode->i_nlink = 0;
 		MSDOS_I(new_inode)->i_busy = 1;
 		new_inode->i_dirt = 1;
 		new_de->name[0] = DELETED_FLAG;
-		mark_buffer_dirty(new_bh, 1);
+		fat_mark_buffer_dirty(sb, new_bh, 1);
 	}
 	memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
 	memcpy(free_de->name,new_name,MSDOS_NAME);
@@ -677,10 +680,10 @@
 	if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
 		free_de->name[0] = DELETED_FLAG;
 /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
-		brelse(free_bh);
+		fat_brelse(sb, free_bh);
 		if (exists) {
 			iput(new_inode);
-			brelse(new_bh);
+			fat_brelse(sb, new_bh);
 		}
 		return -EIO;
 	}
@@ -695,8 +698,8 @@
 	fat_cache_inval_inode(old_inode);
 	old_inode->i_dirt = 1;
 	old_de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(old_bh, 1);
-	mark_buffer_dirty(free_bh, 1);
+	fat_mark_buffer_dirty(sb, old_bh, 1);
+	fat_mark_buffer_dirty(sb, free_bh, 1);
 	if (exists) {
 		MSDOS_I(new_inode)->i_depend = free_inode;
 		MSDOS_I(free_inode)->i_old = new_inode;
@@ -705,30 +708,30 @@
 		/* free_inode is put after putting new_inode and old_inode */
 		iput(new_inode);
 		dcache_add(new_dir, new_name, new_len, new_ino);
-		brelse(new_bh);
+		fat_brelse(sb, new_bh);
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
 		if ((error = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
 		    &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
 		if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
-			brelse(dotdot_bh);
+			fat_brelse(sb, dotdot_bh);
 			error = -EIO;
 			goto rename_done;
 		}
 		dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
 		    MSDOS_I(new_dir)->i_start;
 		dotdot_inode->i_dirt = 1;
-		mark_buffer_dirty(dotdot_bh, 1);
+		fat_mark_buffer_dirty(sb, dotdot_bh, 1);
 		old_dir->i_nlink--;
 		new_dir->i_nlink++;
 		/* no need to mark them dirty */
 		dotdot_inode->i_nlink = new_dir->i_nlink;
 		iput(dotdot_inode);
-		brelse(dotdot_bh);
+		fat_brelse(sb, dotdot_bh);
 	}
 	error = 0;
 rename_done:
-	brelse(free_bh);
+	fat_brelse(sb, free_bh);
 	iput(old_inode);
 	return error;
 }
@@ -763,7 +766,7 @@
 	else error = rename_diff_dir(old_dir,old_msdos_name,old_len,new_dir,
 		    new_msdos_name,new_len,old_bh,old_de,old_ino,is_hid);
 	fat_unlock_creation();
-	brelse(old_bh);
+	fat_brelse(sb, old_bh);
 rename_done:
 	iput(old_dir);
 	iput(new_dir);
diff -u --recursive --new-file v1.3.99/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v1.3.99/linux/fs/vfat/namei.c	Tue May  7 16:22:37 1996
+++ linux/fs/vfat/namei.c	Fri May 10 07:54:52 1996
@@ -573,7 +573,7 @@
 			if (done) {
 				row++;
 				if (row == slots) {
-					brelse(bh);
+					fat_brelse(sb, bh);
 					/* printk("----- Free offset at %d\n", offset); */
 					return offset;
 				}
@@ -868,7 +868,7 @@
 				return sinfo_out->ino;
 			}
 			memcpy(de, ps, sizeof(struct msdos_dir_slot));
-			mark_buffer_dirty(bh, 1);
+			fat_mark_buffer_dirty(sb, bh, 1);
 		}
 
 		PRINTK(("vfat_find: create file 4\n"));
@@ -888,8 +888,8 @@
 		de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
 
 
-		mark_buffer_dirty(bh, 1);
-		brelse(bh);
+		fat_mark_buffer_dirty(sb, bh, 1);
+		fat_brelse(sb, bh);
 
 		sinfo_out->is_long = (slots > 1) ? 1 : 0;
 		if (sinfo_out->is_long) {
@@ -999,15 +999,17 @@
 	ino = fat_get_entry(dir, &offset, &bh, &de);
 	if (ino < 0) {
 		PRINTK(("vfat_mkdir problem\n"));
-		if (bh) brelse(bh);
+		if (bh)
+			fat_brelse(sb, bh);
 		return ino;
 	}
 	PRINTK(("vfat_create_entry 3\n"));
 
 	if ((*result = iget(dir->i_sb,ino)) != NULL)
 		vfat_read_inode(*result);
-	brelse(bh);
-	if (!*result) return -EIO;
+	fat_brelse(sb, bh);
+	if (!*result)
+		return -EIO;
 	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
 	    CURRENT_TIME;
 	(*result)->i_dirt = 1;
@@ -1058,7 +1060,7 @@
 	de->ctime = de->time;
 	de->adate = de->cdate = de->date;
 	de->size = 0;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 	if ((dot = iget(dir->i_sb,ino)) != NULL)
 		vfat_read_inode(dot);
 	if (!dot) return -EIO;
@@ -1100,20 +1102,20 @@
 	res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
 	PRINTK(("vfat_create_dotdirs 4\n"));
 	if (res < 0) {
-		brelse(bh);
+		fat_brelse(sb, bh);
 		return res;
 	}
 	PRINTK(("vfat_create_dotdirs 5\n"));
 
 	if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
-		brelse(bh);
+		fat_brelse(sb, bh);
 		return res;
 	}
 	PRINTK(("vfat_create_dotdirs 6\n"));
 
 	res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
 	PRINTK(("vfat_create_dotdirs 7\n"));
-	brelse(bh);
+	fat_brelse(sb, bh);
 
 	return res;
 }
@@ -1138,12 +1140,12 @@
 			if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
 			    MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
 			    MSDOS_NAME)) {
-				brelse(bh);
+				fat_brelse(sb, bh);
 				return -ENOTEMPTY;
 			}
 		}
 		if (bh)
-			brelse(bh);
+			fat_brelse(sb, bh);
 	}
 	return 0;
 }
@@ -1176,7 +1178,7 @@
 	dir->i_nlink--;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 	iput(inode);
 
 	return 0;
@@ -1199,7 +1201,7 @@
 	MSDOS_I(inode)->i_busy = 1;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh, 1);
+	fat_mark_buffer_dirty(sb, bh, 1);
 
 	iput(inode);
 	return 0;
@@ -1234,7 +1236,7 @@
 		}
 		(*de)->name[0] = DELETED_FLAG;
 		(*de)->attr = 0;
-		mark_buffer_dirty(*bh, 1);
+		fat_mark_buffer_dirty(sb, *bh, 1);
 	}
 	return 0;
 }
@@ -1265,7 +1267,7 @@
 	dir->i_version = ++event;
 
 rmdir_done:
-	brelse(bh);
+	fat_brelse(sb, bh);
 	return res;
 }
 
@@ -1305,7 +1307,7 @@
 	}
 
 unlink_done:
-	brelse(bh);
+	fat_brelse(sb, bh);
 	return res;
 }
 
@@ -1489,11 +1491,11 @@
 		}
 		old_de->name[0] = DELETED_FLAG;
 		old_de->attr = 0;
-		mark_buffer_dirty(old_bh, 1);
+		fat_mark_buffer_dirty(sb, old_bh, 1);
 	}
 	PRINTK(("vfat_rename 15b\n"));
 
-	mark_buffer_dirty(new_bh, 1);
+	fat_mark_buffer_dirty(sb, new_bh, 1);
 	dcache_add(new_dir, new_name, new_len, new_ino);
 
 	/* XXX: There is some code in the original MSDOS rename that
@@ -1505,29 +1507,33 @@
 		if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
 		    &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
 		if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
-			brelse(dotdot_bh);
+			fat_brelse(sb, dotdot_bh);
 			res = -EIO;
 			goto rename_done;
 		}
 		dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
 		    MSDOS_I(new_dir)->i_start;
 		dotdot_inode->i_dirt = 1;
-		mark_buffer_dirty(dotdot_bh, 1);
+		fat_mark_buffer_dirty(sb, dotdot_bh, 1);
 		old_dir->i_nlink--;
 		new_dir->i_nlink++;
 		/* no need to mark them dirty */
 		dotdot_inode->i_nlink = new_dir->i_nlink;
 		iput(dotdot_inode);
-		brelse(dotdot_bh);
+		fat_brelse(sb, dotdot_bh);
 	}
 
 	if (res > 0) res = 0;
 
 rename_done:
-	if (locked) fat_unlock_creation();
-	if (old_bh) brelse(old_bh);
-	if (new_bh) brelse(new_bh);
-	if (old_inode) iput(old_inode);
+	if (locked)
+		fat_unlock_creation();
+	if (old_bh)
+		fat_brelse(sb, old_bh);
+	if (new_bh)
+		fat_brelse(sb, new_bh);
+	if (old_inode)
+		iput(old_inode);
 	iput(old_dir);
 	iput(new_dir);
 	return res;
diff -u --recursive --new-file v1.3.99/linux/include/asm-alpha/termbits.h linux/include/asm-alpha/termbits.h
--- v1.3.99/linux/include/asm-alpha/termbits.h	Sun Mar 24 13:18:47 1996
+++ linux/include/asm-alpha/termbits.h	Wed May  8 10:32:40 1996
@@ -124,6 +124,7 @@
 #define  B57600   00020
 #define  B115200  00021
 #define  B230400  00022
+#define  B460800  00023
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff -u --recursive --new-file v1.3.99/linux/include/asm-i386/math_emu.h linux/include/asm-i386/math_emu.h
--- v1.3.99/linux/include/asm-i386/math_emu.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-i386/math_emu.h	Mon May  6 16:31:18 1996
@@ -0,0 +1,47 @@
+#ifndef _LINUX_MATH_EMU_H
+#define _LINUX_MATH_EMU_H
+
+
+void restore_i387_soft(struct _fpstate *buf);
+struct _fpstate * save_i387_soft(struct _fpstate * buf);
+
+struct fpu_reg {
+	char sign;
+	char tag;
+	long exp;
+	unsigned sigl;
+	unsigned sigh;
+};
+
+
+/* This structure matches the layout of the data saved to the stack
+   following a device-not-present interrupt, part of it saved
+   automatically by the 80386/80486.
+   */
+struct info {
+	long ___orig_eip;
+	long ___ret_from_system_call;
+	long ___ebx;
+	long ___ecx;
+	long ___edx;
+	long ___esi;
+	long ___edi;
+	long ___ebp;
+	long ___eax;
+	long ___ds;
+	long ___es;
+	long ___fs;
+	long ___gs;
+	long ___orig_eax;
+	long ___eip;
+	long ___cs;
+	long ___eflags;
+	long ___esp;
+	long ___ss;
+	long ___vm86_es; /* This and the following only in vm86 mode */
+	long ___vm86_ds;
+	long ___vm86_fs;
+	long ___vm86_gs;
+};
+
+#endif
diff -u --recursive --new-file v1.3.99/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v1.3.99/linux/include/asm-i386/processor.h	Fri Apr 19 10:08:01 1996
+++ linux/include/asm-i386/processor.h	Thu May  9 07:58:57 1996
@@ -7,6 +7,9 @@
 #ifndef __ASM_I386_PROCESSOR_H
 #define __ASM_I386_PROCESSOR_H
 
+#include <asm/vm86.h>
+#include <asm/math_emu.h>
+
 /*
  * System setup and hardware bug flags..
  * [Note we don't test the 386 multiply bug or popad bug]
diff -u --recursive --new-file v1.3.99/linux/include/asm-i386/termbits.h linux/include/asm-i386/termbits.h
--- v1.3.99/linux/include/asm-i386/termbits.h	Sun Mar 24 13:13:43 1996
+++ linux/include/asm-i386/termbits.h	Wed May  8 10:32:41 1996
@@ -120,6 +120,7 @@
 #define  B57600  0010001
 #define  B115200 0010002
 #define  B230400 0010003
+#define  B460800 0010004
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff -u --recursive --new-file v1.3.99/linux/include/asm-i386/vm86.h linux/include/asm-i386/vm86.h
--- v1.3.99/linux/include/asm-i386/vm86.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-i386/vm86.h	Mon May  2 15:31:55 1994
@@ -0,0 +1,109 @@
+#ifndef _LINUX_VM86_H
+#define _LINUX_VM86_H
+
+/*
+ * I'm guessing at the VIF/VIP flag usage, but hope that this is how
+ * the Pentium uses them. Linux will return from vm86 mode when both
+ * VIF and VIP is set.
+ *
+ * On a Pentium, we could probably optimize the virtual flags directly
+ * in the eflags register instead of doing it "by hand" in vflags...
+ *
+ * Linus
+ */
+
+#define TF_MASK		0x00000100
+#define IF_MASK		0x00000200
+#define IOPL_MASK	0x00003000
+#define NT_MASK		0x00004000
+#define VM_MASK		0x00020000
+#define AC_MASK		0x00040000
+#define VIF_MASK	0x00080000	/* virtual interrupt flag */
+#define VIP_MASK	0x00100000	/* virtual interrupt pending */
+#define ID_MASK		0x00200000
+
+#define BIOSSEG		0x0f000
+
+#define CPU_086		0
+#define CPU_186		1
+#define CPU_286		2
+#define CPU_386		3
+#define CPU_486		4
+#define CPU_586		5
+
+/*
+ * Return values for the 'vm86()' system call
+ */
+#define VM86_TYPE(retval)	((retval) & 0xff)
+#define VM86_ARG(retval)	((retval) >> 8)
+
+#define VM86_SIGNAL	0	/* return due to signal */
+#define VM86_UNKNOWN	1	/* unhandled GP fault - IO-instruction or similar */
+#define VM86_INTx	2	/* int3/int x instruction (ARG = x) */
+#define VM86_STI	3	/* sti/popf/iret instruction enabled virtual interrupts */
+
+/*
+ * This is the stack-layout when we have done a "SAVE_ALL" from vm86
+ * mode - the main change is that the old segment descriptors aren't
+ * useful any more and are forced to be zero by the kernel (and the
+ * hardware when a trap occurs), and the real segment descriptors are
+ * at the end of the structure. Look at ptrace.h to see the "normal"
+ * setup.
+ */
+
+struct vm86_regs {
+/*
+ * normal regs, with special meaning for the segment descriptors..
+ */
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	long __null_ds;
+	long __null_es;
+	long __null_fs;
+	long __null_gs;
+	long orig_eax;
+	long eip;
+	unsigned short cs, __csh;
+	long eflags;
+	long esp;
+	unsigned short ss, __ssh;
+/*
+ * these are specific to v86 mode:
+ */
+	unsigned short es, __esh;
+	unsigned short ds, __dsh;
+	unsigned short fs, __fsh;
+	unsigned short gs, __gsh;
+};
+
+struct revectored_struct {
+	unsigned long __map[8];			/* 256 bits */
+};
+
+struct vm86_struct {
+	struct vm86_regs regs;
+	unsigned long flags;
+	unsigned long screen_bitmap;
+	unsigned long cpu_type;
+	struct revectored_struct int_revectored;
+	struct revectored_struct int21_revectored;
+};
+
+/*
+ * flags masks
+ */
+#define VM86_SCREEN_BITMAP	0x0001
+
+#ifdef __KERNEL__
+
+void handle_vm86_fault(struct vm86_regs *, long);
+void handle_vm86_debug(struct vm86_regs *, long);
+
+#endif
+
+#endif
diff -u --recursive --new-file v1.3.99/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h
--- v1.3.99/linux/include/asm-m68k/serial.h	Tue May  7 16:22:38 1996
+++ linux/include/asm-m68k/serial.h	Wed May  8 07:20:01 1996
@@ -231,7 +231,7 @@
 						boards carrying several UART's,
 						like some Amiga boards. */
 	unsigned short		nr_uarts;    /* UART-counter, that indicates
-						how manu UART's there are on
+						how many UART's there are on
 						the board.  If the board has a
 						IRQ-register, this can be used
 						to check if any of the uarts,
diff -u --recursive --new-file v1.3.99/linux/include/asm-m68k/termbits.h linux/include/asm-m68k/termbits.h
--- v1.3.99/linux/include/asm-m68k/termbits.h	Tue Apr 23 13:57:12 1996
+++ linux/include/asm-m68k/termbits.h	Wed May  8 10:32:41 1996
@@ -121,6 +121,7 @@
 #define  B57600  0010001
 #define  B115200 0010002
 #define  B230400 0010003
+#define  B460800 0010004
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CRTSCTS	  020000000000		/* flow control */
 
diff -u --recursive --new-file v1.3.99/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- v1.3.99/linux/include/asm-mips/ioctls.h	Wed Dec 13 12:39:45 1995
+++ linux/include/asm-mips/ioctls.h	Wed May  8 10:32:41 1996
@@ -232,6 +232,7 @@
 #define  B57600  0010001
 #define  B115200 0010002
 #define  B230400 0010003
+#define  B460800 0010004
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
 #define CRTSCTS	  020000000000		/* flow control */
 #endif
diff -u --recursive --new-file v1.3.99/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v1.3.99/linux/include/asm-ppc/termios.h	Sat Nov 25 19:49:07 1995
+++ linux/include/asm-ppc/termios.h	Wed May  8 10:32:41 1996
@@ -268,6 +268,7 @@
 #define  B57600   00020
 #define  B115200  00021
 #define  B230400  00022
+#define  B460800  00023
 
 #define CSIZE	00001400
 #define   CS5	00000000
diff -u --recursive --new-file v1.3.99/linux/include/asm-sparc/floppy.h linux/include/asm-sparc/floppy.h
--- v1.3.99/linux/include/asm-sparc/floppy.h	Tue May  7 16:22:38 1996
+++ linux/include/asm-sparc/floppy.h	Thu May  9 08:33:23 1996
@@ -66,6 +66,8 @@
 #define fd_cacheflush(addr, size) /* nothing... */
 #define fd_request_irq()          sun_fd_request_irq()
 #define fd_free_irq()             /* nothing... */
+#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
+#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
 
 #define FLOPPY_MOTOR_MASK         0x10
 
diff -u --recursive --new-file v1.3.99/linux/include/asm-sparc/termbits.h linux/include/asm-sparc/termbits.h
--- v1.3.99/linux/include/asm-sparc/termbits.h	Sun Apr 21 19:22:13 1996
+++ linux/include/asm-sparc/termbits.h	Wed May  8 10:32:41 1996
@@ -134,6 +134,7 @@
 #define  B57600  0x00010001
 #define  B115200 0x00010002
 #define  B230400 0x00010003
+#define  B460800 0x00010004
 #define CIBAUD	  0x000f0000  /* input baud rate (not used) */
 #define CRTSCTS	  0x80000000  /* flow control */
 
diff -u --recursive --new-file v1.3.99/linux/include/linux/affs_fs_sb.h linux/include/linux/affs_fs_sb.h
--- v1.3.99/linux/include/linux/affs_fs_sb.h	Tue May  7 16:22:38 1996
+++ linux/include/linux/affs_fs_sb.h	Wed May  8 07:20:01 1996
@@ -43,9 +43,9 @@
 	int s_bm_count;			/* Number of bitmap blocks. */
 	int s_nextzone;			/* Next zone to look for free blocks. */
 	int s_num_zones;		/* Total number of zones. */
-	struct affs_zone *s_zones;	/* The zones themselfes. */
+	struct affs_zone *s_zones;	/* The zones themselves. */
 	char *s_zonemap;		/* Bitmap for zones. */
-	char *s_prefix;			/* Prefix for volumes and assignes. */
+	char *s_prefix;			/* Prefix for volumes and assigns. */
 	int s_prefix_len;		/* Length of prefix. */
 	char s_volume[32];		/* Volume prefix for absolute symlinks. */
 };
diff -u --recursive --new-file v1.3.99/linux/include/linux/amigaffs.h linux/include/linux/amigaffs.h
--- v1.3.99/linux/include/linux/amigaffs.h	Tue May  7 16:22:38 1996
+++ linux/include/linux/amigaffs.h	Wed May  8 07:20:01 1996
@@ -25,7 +25,7 @@
 #elif defined(__BIG_ENDIAN)
 #define BO_EXBITS	0x00UL
 #else
-#error Endianess must be known for affs to work.
+#error Endianness must be known for affs to work.
 #endif
 
 /* The following constants will be checked against the values read native */
diff -u --recursive --new-file v1.3.99/linux/include/linux/binfmts.h linux/include/linux/binfmts.h
--- v1.3.99/linux/include/linux/binfmts.h	Sat Mar 23 14:46:40 1996
+++ linux/include/linux/binfmts.h	Wed May  8 18:28:01 1996
@@ -49,6 +49,7 @@
 extern int init_elf_binfmt(void);
 extern int init_aout_binfmt(void);
 extern int init_script_binfmt(void);
+extern int init_java_binfmt(void);
 
 extern int prepare_binprm(struct linux_binprm *);
 extern void remove_arg_zero(struct linux_binprm *);
diff -u --recursive --new-file v1.3.99/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v1.3.99/linux/include/linux/cdrom.h	Fri Apr 12 15:52:07 1996
+++ linux/include/linux/cdrom.h	Thu May  9 10:35:12 1996
@@ -279,6 +279,12 @@
 
 
 /*
+ * For controlling a changer.  (Used by ATAPI driver.)
+ */
+#define CDROMLOADFROMSLOT	0x531a	/* LOAD disk from slot*/
+
+
+/*
  * CD-ROM-specific SCSI command opcodes
  */
 
diff -u --recursive --new-file v1.3.99/linux/include/linux/kerneld.h linux/include/linux/kerneld.h
--- v1.3.99/linux/include/linux/kerneld.h	Mon Mar 25 08:58:22 1996
+++ linux/include/linux/kerneld.h	Wed May  8 10:32:41 1996
@@ -10,7 +10,23 @@
 #define KERNELD_BLANKER 7 /* from drivers/char/console.c */
 #define KERNELD_ARP 256 /* from net/ipv4/arp.c */
 
+/*
+ * Uncomment the following line for the new kerneld protocol
+ * This includes the pid of the kernel level requestor into the kerneld header
+ */
+/*
+#define NEW_KERNELD_PROTOCOL
+ */
+#ifdef NEW_KERNELD_PROTOCOL
+#define OLDIPC_KERNELD 00040000   /* use the kerneld message channel */
+#define IPC_KERNELD 00140000   /* use the kerneld message channel, new protocol */
+#define KDHDR (sizeof(long) + sizeof(short) + sizeof(short))
+#define NULL_KDHDR 0, 2, 0
+#else
 #define IPC_KERNELD 00040000   /* use the kerneld message channel */
+#define KDHDR (sizeof(long))
+#define NULL_KDHDR 0
+#endif
 #define KERNELD_MAXCMD 0x7ffeffff
 #define KERNELD_MINSEQ 0x7fff0000 /* "commands" legal up to 0x7ffeffff */
 #define KERNELD_WAIT 0x80000000
@@ -19,6 +35,10 @@
 struct kerneld_msg {
 	long mtype;
 	long id;
+#ifdef NEW_KERNELD_PROTOCOL
+	short version;
+	short pid;
+#endif
 #ifdef __KERNEL__
 	char *text;
 #else
diff -u --recursive --new-file v1.3.99/linux/include/linux/math_emu.h linux/include/linux/math_emu.h
--- v1.3.99/linux/include/linux/math_emu.h	Tue May  7 16:22:38 1996
+++ linux/include/linux/math_emu.h	Thu Jan  1 02:00:00 1970
@@ -1,47 +0,0 @@
-#ifndef _LINUX_MATH_EMU_H
-#define _LINUX_MATH_EMU_H
-
-
-void restore_i387_soft(struct _fpstate *buf);
-struct _fpstate * save_i387_soft(struct _fpstate * buf);
-
-struct fpu_reg {
-	char sign;
-	char tag;
-	long exp;
-	unsigned sigl;
-	unsigned sigh;
-};
-
-
-/* This structure matches the layout of the data saved to the stack
-   following a device-not-present interrupt, part of it saved
-   automatically by the 80386/80486.
-   */
-struct info {
-	long ___orig_eip;
-	long ___ret_from_system_call;
-	long ___ebx;
-	long ___ecx;
-	long ___edx;
-	long ___esi;
-	long ___edi;
-	long ___ebp;
-	long ___eax;
-	long ___ds;
-	long ___es;
-	long ___fs;
-	long ___gs;
-	long ___orig_eax;
-	long ___eip;
-	long ___cs;
-	long ___eflags;
-	long ___esp;
-	long ___ss;
-	long ___vm86_es; /* This and the following only in vm86 mode */
-	long ___vm86_ds;
-	long ___vm86_fs;
-	long ___vm86_gs;
-};
-
-#endif
diff -u --recursive --new-file v1.3.99/linux/include/linux/msg.h linux/include/linux/msg.h
--- v1.3.99/linux/include/linux/msg.h	Mon Mar 25 10:28:03 1996
+++ linux/include/linux/msg.h	Wed May  8 10:32:41 1996
@@ -60,6 +60,7 @@
     struct msg *msg_next;   /* next message on queue */
     long  msg_type;          
     char *msg_spot;         /* message text address */
+    time_t msg_stime;       /* msgsnd time */
     short msg_ts;           /* message text size */
 };
 
diff -u --recursive --new-file v1.3.99/linux/include/linux/random.h linux/include/linux/random.h
--- v1.3.99/linux/include/linux/random.h	Sun May  5 08:52:05 1996
+++ linux/include/linux/random.h	Wed May  8 10:32:41 1996
@@ -7,28 +7,30 @@
 #ifndef _LINUX_RANDOM_H
 #define _LINUX_RANDOM_H
 
+#include <linux/ioctl.h>
+
 /* ioctl()'s for the random number generator */
 
 /* Get the entropy count. */
-#define RNDGETENTCNT	0x01080000
+#define RNDGETENTCNT	_IOR( 'R', 0x00, int )
 
 /* Add to (or subtract from) the entropy count.  (Superuser only.) */
-#define RNDADDTOENTCNT	0x01080001
+#define RNDADDTOENTCNT	_IOW( 'R', 0x01, int )
 
 /* Get the contents of the entropy pool.  (Superuser only.) */
-#define RNDGETPOOL	0x01080002
+#define RNDGETPOOL	_IOR( 'R', 0x02, int [2] )
 
 /* 
  * Write bytes into the entropy pool and add to the entropy count.
  * (Superuser only.)
  */
-#define RNDADDENTROPY	0x01080003
+#define RNDADDENTROPY	_IOW( 'R', 0x03, int [2] )
 
 /* Clear entropy count to 0.  (Superuser only.) */
-#define RNDZAPENTCNT	0x01080004
+#define RNDZAPENTCNT	_IO( 'R', 0x04 )
 
 /* Clear the entropy pool and associated counters.  (Superuser only.) */
-#define RNDCLEARPOOL	0x01080006
+#define RNDCLEARPOOL	_IO( 'R', 0x06 )
 
 struct rand_pool_info {
 	int	entropy_count;
diff -u --recursive --new-file v1.3.99/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.3.99/linux/include/linux/sched.h	Sat Apr 27 15:20:07 1996
+++ linux/include/linux/sched.h	Fri May 10 11:33:52 1996
@@ -74,8 +74,6 @@
 #include <linux/time.h>
 #include <linux/param.h>
 #include <linux/resource.h>
-#include <linux/vm86.h>
-#include <linux/math_emu.h>
 #include <linux/ptrace.h>
 #include <linux/timer.h>
 
diff -u --recursive --new-file v1.3.99/linux/include/linux/vm86.h linux/include/linux/vm86.h
--- v1.3.99/linux/include/linux/vm86.h	Mon May  2 15:31:55 1994
+++ linux/include/linux/vm86.h	Thu Jan  1 02:00:00 1970
@@ -1,109 +0,0 @@
-#ifndef _LINUX_VM86_H
-#define _LINUX_VM86_H
-
-/*
- * I'm guessing at the VIF/VIP flag usage, but hope that this is how
- * the Pentium uses them. Linux will return from vm86 mode when both
- * VIF and VIP is set.
- *
- * On a Pentium, we could probably optimize the virtual flags directly
- * in the eflags register instead of doing it "by hand" in vflags...
- *
- * Linus
- */
-
-#define TF_MASK		0x00000100
-#define IF_MASK		0x00000200
-#define IOPL_MASK	0x00003000
-#define NT_MASK		0x00004000
-#define VM_MASK		0x00020000
-#define AC_MASK		0x00040000
-#define VIF_MASK	0x00080000	/* virtual interrupt flag */
-#define VIP_MASK	0x00100000	/* virtual interrupt pending */
-#define ID_MASK		0x00200000
-
-#define BIOSSEG		0x0f000
-
-#define CPU_086		0
-#define CPU_186		1
-#define CPU_286		2
-#define CPU_386		3
-#define CPU_486		4
-#define CPU_586		5
-
-/*
- * Return values for the 'vm86()' system call
- */
-#define VM86_TYPE(retval)	((retval) & 0xff)
-#define VM86_ARG(retval)	((retval) >> 8)
-
-#define VM86_SIGNAL	0	/* return due to signal */
-#define VM86_UNKNOWN	1	/* unhandled GP fault - IO-instruction or similar */
-#define VM86_INTx	2	/* int3/int x instruction (ARG = x) */
-#define VM86_STI	3	/* sti/popf/iret instruction enabled virtual interrupts */
-
-/*
- * This is the stack-layout when we have done a "SAVE_ALL" from vm86
- * mode - the main change is that the old segment descriptors aren't
- * useful any more and are forced to be zero by the kernel (and the
- * hardware when a trap occurs), and the real segment descriptors are
- * at the end of the structure. Look at ptrace.h to see the "normal"
- * setup.
- */
-
-struct vm86_regs {
-/*
- * normal regs, with special meaning for the segment descriptors..
- */
-	long ebx;
-	long ecx;
-	long edx;
-	long esi;
-	long edi;
-	long ebp;
-	long eax;
-	long __null_ds;
-	long __null_es;
-	long __null_fs;
-	long __null_gs;
-	long orig_eax;
-	long eip;
-	unsigned short cs, __csh;
-	long eflags;
-	long esp;
-	unsigned short ss, __ssh;
-/*
- * these are specific to v86 mode:
- */
-	unsigned short es, __esh;
-	unsigned short ds, __dsh;
-	unsigned short fs, __fsh;
-	unsigned short gs, __gsh;
-};
-
-struct revectored_struct {
-	unsigned long __map[8];			/* 256 bits */
-};
-
-struct vm86_struct {
-	struct vm86_regs regs;
-	unsigned long flags;
-	unsigned long screen_bitmap;
-	unsigned long cpu_type;
-	struct revectored_struct int_revectored;
-	struct revectored_struct int21_revectored;
-};
-
-/*
- * flags masks
- */
-#define VM86_SCREEN_BITMAP	0x0001
-
-#ifdef __KERNEL__
-
-void handle_vm86_fault(struct vm86_regs *, long);
-void handle_vm86_debug(struct vm86_regs *, long);
-
-#endif
-
-#endif
diff -u --recursive --new-file v1.3.99/linux/include/scsi/scsi_ioctl.h linux/include/scsi/scsi_ioctl.h
--- v1.3.99/linux/include/scsi/scsi_ioctl.h	Sun May  5 08:52:05 1996
+++ linux/include/scsi/scsi_ioctl.h	Thu May  9 07:38:41 1996
@@ -13,8 +13,12 @@
 #define	SCSI_REMOVAL_PREVENT	1
 #define	SCSI_REMOVAL_ALLOW	0
 
+#ifdef __KERNEL__
+
 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
+
+#endif
 
 #endif
 
diff -u --recursive --new-file v1.3.99/linux/init/main.c linux/init/main.c
--- v1.3.99/linux/init/main.c	Mon Apr 29 18:05:20 1996
+++ linux/init/main.c	Fri May 10 07:44:05 1996
@@ -62,6 +62,7 @@
 extern void buff_setup(char *str, int *ints);
 extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
+extern void msmouse_setup(char *str, int *ints);
 extern void lp_setup(char *str, int *ints);
 extern void eth_setup(char *str, int *ints);
 extern void xd_setup(char *str, int *ints);
@@ -273,6 +274,9 @@
 #endif
 #ifdef CONFIG_BUSMOUSE
 	{ "bmouse=", bmouse_setup },
+#endif
+#ifdef CONFIG_MS_BUSMOUSE
+	{ "msmouse=", msmouse_setup },
 #endif
 #ifdef CONFIG_SCSI_SEAGATE
 	{ "st0x=", st0x_setup },
diff -u --recursive --new-file v1.3.99/linux/ipc/msg.c linux/ipc/msg.c
--- v1.3.99/linux/ipc/msg.c	Tue May  7 16:22:40 1996
+++ linux/ipc/msg.c	Wed May  8 10:32:41 1996
@@ -2,8 +2,9 @@
  * linux/ipc/msg.c
  * Copyright (C) 1992 Krishna Balasubramanian 
  *
- * Kerneld extensions by Bjorn Ekwall <bj0rn@blox.se> in May 1995
+ * Kerneld extensions by Bjorn Ekwall <bj0rn@blox.se> in May 1995, and May 1996
  *
+ * See <linux/kerneld.h> for the (optional) new kerneld protocol
  */
 
 #include <linux/config.h>
@@ -46,6 +47,39 @@
 	return;
 }
 
+/*
+ * If the send queue is full, try to free any old messages.
+ * These are most probably unwanted, since noone has picked them up...
+ */
+#define MSG_FLUSH_TIME 10 /* seconds */
+static void flush_msg(struct msqid_ds *msq)
+{
+	struct msg *nmsg;
+	unsigned long flags;
+	int flushed = 0;
+
+	save_flags(flags);
+	cli();
+
+	/* messages were put on the queue in time order */
+	while ( (nmsg = msq->msg_first) &&
+		((CURRENT_TIME - nmsg->msg_stime) > MSG_FLUSH_TIME)) {
+		msgbytes -= nmsg->msg_ts; 
+		msghdrs--; 
+		msq->msg_cbytes -= nmsg->msg_ts;
+		msq->msg_qnum--;
+		msq->msg_first = nmsg->msg_next;
+		++flushed;
+		kfree(nmsg);
+	}
+
+	if (msq->msg_qnum == 0)
+		msq->msg_first = msq->msg_last = NULL;
+	restore_flags(flags);
+	if (flushed)
+		printk(KERN_WARNING "flushed %d old SYSVIPC messages", flushed);
+}
+
 static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
 {
 	int id, err;
@@ -53,6 +87,7 @@
 	struct ipc_perm *ipcp;
 	struct msg *msgh;
 	long mtype;
+	unsigned long flags;
 	
 	if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
 		return -EINVAL;
@@ -81,7 +116,7 @@
 	if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) 
 		return -EIDRM;
 	/*
-	 * Non-root processes may send to kerneld! 
+	 * Non-root kernel level processes may send to kerneld! 
 	 * i.e. no permission check if called from the kernel
 	 * otoh we don't want user level non-root snoopers...
 	 */
@@ -90,23 +125,26 @@
 			return -EACCES;
 	
 	if (msgsz + msq->msg_cbytes > msq->msg_qbytes) { 
-		/* no space in queue */
-		if (msgflg & IPC_NOWAIT)
-			return -EAGAIN;
-		if (current->signal & ~current->blocked)
-			return -EINTR;
-		if (intr_count) {
-			/* Very unlikely, but better safe than sorry... */
-			printk("Ouch, kerneld:msgsnd wants to sleep at interrupt!\n");
-			return -EINTR;
+		if ((kerneld_msqid != -1) && (kerneld_msqid == msqid))
+			flush_msg(msq); /* flush the kerneld channel only */
+		if (msgsz + msq->msg_cbytes > msq->msg_qbytes) { 
+			/* still no space in queue */
+			if (msgflg & IPC_NOWAIT)
+				return -EAGAIN;
+			if (current->signal & ~current->blocked)
+				return -EINTR;
+			if (intr_count) {
+				/* Very unlikely, but better safe than sorry */
+				printk(KERN_WARNING "Ouch, kerneld:msgsnd buffers full!\n");
+				return -EINTR;
+			}
+			interruptible_sleep_on (&msq->wwait);
+			goto slept;
 		}
-		interruptible_sleep_on (&msq->wwait);
-		goto slept;
 	}
 	
 	/* allocate message header and text space*/ 
-	msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz,
-		(intr_count ? GFP_ATOMIC : GFP_USER));
+	msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_ATOMIC);
 	if (!msgh)
 		return -ENOMEM;
 	msgh->msg_spot = (char *) (msgh + 1);
@@ -122,9 +160,8 @@
 		 * Note that the kernel supplies a pointer
 		 * but the user-level kerneld uses a char array...
 		 */
-		memcpy(msgh->msg_spot, (char *)(&(kdmp->id)), sizeof(long)); 
-		memcpy(msgh->msg_spot + sizeof(long), kdmp->text,
-			msgsz - sizeof(long)); 
+		memcpy(msgh->msg_spot, (char *)(&(kdmp->id)), KDHDR); 
+		memcpy(msgh->msg_spot + KDHDR, kdmp->text, msgsz - KDHDR); 
 	}
 	else
 		memcpy_fromfs (msgh->msg_spot, msgp->mtext, msgsz); 
@@ -136,20 +173,25 @@
 	}
 
 	msgh->msg_next = NULL;
+	msgh->msg_ts = msgsz;
+	msgh->msg_type = mtype;
+	msgh->msg_stime = CURRENT_TIME;
+
+	save_flags(flags);
+	cli();
 	if (!msq->msg_first)
 		msq->msg_first = msq->msg_last = msgh;
 	else {
 		msq->msg_last->msg_next = msgh;
 		msq->msg_last = msgh;
 	}
-	msgh->msg_ts = msgsz;
-	msgh->msg_type = mtype;
 	msq->msg_cbytes += msgsz;
 	msgbytes  += msgsz;
 	msghdrs++;
 	msq->msg_qnum++;
 	msq->msg_lspid = current->pid;
 	msq->msg_stime = CURRENT_TIME;
+	restore_flags(flags);
 	if (msq->rwait)
 		wake_up (&msq->rwait);
 	return 0;
@@ -166,20 +208,24 @@
 {
 	struct msqid_ds *msq;
 	struct msg *tmsg;
+	unsigned long flags;
 
 	msq = msgque [ (unsigned int) kerneld_msqid % MSGMNI ];
 	if (msq == IPC_NOID || msq == IPC_UNUSED)
 		return;
 
+	save_flags(flags);
+	cli();
 	for (tmsg = msq->msg_first; tmsg; tmsg = tmsg->msg_next)
 		if (*(long *)(tmsg->msg_spot) == msgid)
 			break;
+	restore_flags(flags);
 	if (tmsg) { /* still there! */
-		struct kerneld_msg kmsp = { msgid, -ENODEV, "" };
+		struct kerneld_msg kmsp = { msgid, NULL_KDHDR, "" };
 
-		printk(KERN_ALERT "Ouch, kerneld timed out, message failed\n");
-		real_msgsnd(kerneld_msqid, (struct msgbuf *)&kmsp,
-			sizeof(long),
+		printk(KERN_ALERT "Ouch, no kerneld for message %ld\n", msgid);
+		kmsp.id = -ENODEV;
+		real_msgsnd(kerneld_msqid, (struct msgbuf *)&kmsp, KDHDR,
 			S_IRUSR | S_IWUSR | IPC_KERNELD | MSG_NOERROR);
 	}
 }
@@ -192,6 +238,7 @@
 	struct msg *tmsg, *leastp = NULL;
 	struct msg *nmsg = NULL;
 	int id, err;
+	unsigned long flags;
 
 	if (msqid < 0 || (long) msgsz < 0)
 		return -EINVAL;
@@ -236,15 +283,18 @@
 		}
 		if ((msgflg & IPC_KERNELD) == 0) {
 			/*
-			 * Non-root processes may receive from kerneld! 
+			 * All kernel level processes may receive from kerneld! 
 			 * i.e. no permission check if called from the kernel
 			 * otoh we don't want user level non-root snoopers...
 			 */
 			if (ipcperms (ipcp, S_IRUGO)) {
-				DROP_TIMER;
+				DROP_TIMER; /* Not needed, but doesn't hurt */
 				return -EACCES;
 			}
 		}
+
+		save_flags(flags);
+		cli();
 		if (msgtyp == 0) 
 			nmsg = msq->msg_first;
 		else if (msgtyp > 0) {
@@ -269,14 +319,16 @@
 			if (leastp && leastp->msg_type <= - msgtyp)
 				nmsg = leastp;
 		}
+		restore_flags(flags);
 		
 		if (nmsg) { /* done finding a message */
 			DROP_TIMER;
 			if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) {
-				DROP_TIMER;
 				return -E2BIG;
 			}
 			msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
+			save_flags(flags);
+			cli();
 			if (nmsg ==  msq->msg_first)
 				msq->msg_first = nmsg->msg_next;
 			else {
@@ -296,6 +348,7 @@
 			msgbytes -= nmsg->msg_ts; 
 			msghdrs--; 
 			msq->msg_cbytes -= nmsg->msg_ts;
+			restore_flags(flags);
 			if (msq->wwait)
 				wake_up (&msq->wwait);
 			/*
@@ -306,23 +359,21 @@
 				struct kerneld_msg *kdmp = (struct kerneld_msg *) msgp;
 
 				memcpy((char *)(&(kdmp->id)),
-					nmsg->msg_spot,
-					sizeof(long)); 
+					nmsg->msg_spot, KDHDR); 
 				/*
 				 * Note that kdmp->text is a pointer
 				 * when called from kernel space!
 				 */
-				if ((msgsz > sizeof(long)) && kdmp->text)
+				if ((msgsz > KDHDR) && kdmp->text)
 					memcpy(kdmp->text,
-						nmsg->msg_spot + sizeof(long),
-						msgsz - sizeof(long)); 
+						nmsg->msg_spot + KDHDR,
+						msgsz - KDHDR); 
 			}
 			else {
 				put_user (nmsg->msg_type, &msgp->mtype);
 				memcpy_tofs (msgp->mtext, nmsg->msg_spot, msgsz);
 			}
 			kfree(nmsg);
-			DROP_TIMER;
 			return msgsz;
 		} else {  /* did not find a message */
 			if (msgflg & IPC_NOWAIT) {
@@ -333,12 +384,6 @@
 				DROP_TIMER;
 				return -EINTR; 
 			}
-			if (intr_count) {
-				DROP_TIMER;
-				/* Won't happen... */
-				printk("Ouch, kerneld:msgrcv wants to sleep at interrupt!\n");
-				return -EINTR;
-			}
 			interruptible_sleep_on (&msq->rwait);
 		}
 	} /* end while */
@@ -348,14 +393,14 @@
 
 asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
 {
-	/* IPC_KERNELD is used as a marker for kernel calls */
+	/* IPC_KERNELD is used as a marker for kernel level calls */
 	return real_msgsnd(msqid, msgp, msgsz, msgflg & ~IPC_KERNELD);
 }
 
 asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
 	long msgtyp, int msgflg)
 {
-	/* IPC_KERNELD is used as a marker for kernel calls */
+	/* IPC_KERNELD is used as a marker for kernel level calls */
 	return real_msgrcv (msqid, msgp, msgsz, msgtyp, msgflg & ~IPC_KERNELD);
 }
 
@@ -431,6 +476,12 @@
 		int i;
 		if (!suser())
 			return -EPERM;
+#ifdef NEW_KERNELD_PROTOCOL
+		if ((msgflg & IPC_KERNELD) == OLDIPC_KERNELD) {
+			printk(KERN_ALERT "Please recompile your kerneld daemons!\n");
+			return -EPERM;
+		}
+#endif
 		if ((kerneld_msqid == -1) && (kerneld_msqid =
 				newque(IPC_PRIVATE, msgflg & S_IRWXU)) < 0)
 			return -ENOSPC;
@@ -648,10 +699,10 @@
  * The message type from the kernel to kerneld is used to specify _what_
  * function we want kerneld to perform. 
  *
- * The "normal" message area is divided into a long, followed by a char array.
- * The long is used to hold the sequence number of the request, which will
+ * The "normal" message area is divided into a header, followed by a char array.
+ * The header is used to hold the sequence number of the request, which will
  * be used as the return message type from kerneld back to the kernel.
- * In the return message, the long will be used to store the exit status
+ * In the return message, the header will be used to store the exit status
  * of the kerneld "job", or task.
  * The character array is used to pass parameters to kerneld and (optional)
  * return information from kerneld back to the kernel.
@@ -666,7 +717,7 @@
  *	ret_size is the size of the (optional) return _value,
  *		OR-ed with KERNELD_WAIT if we want an answer
  *	msgsize is the size (in bytes) of the message, not including
- *		the long that is always sent first in a kerneld message
+ *		the header that is always sent first in a kerneld message
  *	text is the parameter for the kerneld specific task
  *	ret_val is NULL or the kernel address where an expected answer
  *		from kerneld should be placed.
@@ -680,8 +731,9 @@
 	int status = -ENOSYS;
 #ifdef CONFIG_KERNELD
 	static int id = KERNELD_MINSEQ;
-	struct kerneld_msg kmsp = { msgtype, 0, (char *)text };
+	struct kerneld_msg kmsp = { msgtype, NULL_KDHDR, (char *)text };
 	int msgflg = S_IRUSR | S_IWUSR | IPC_KERNELD | MSG_NOERROR;
+	unsigned long flags;
 
 	if (kerneld_msqid == -1)
 		return -ENODEV;
@@ -689,12 +741,19 @@
 	/* Do not wait for an answer at interrupt-time! */
 	if (intr_count)
 		ret_size &= ~KERNELD_WAIT;
+#ifdef NEW_KERNELD_PROTOCOL
+	else
+		kmsp.pid = current->pid;
+#endif
 
-	msgsz += sizeof(long);
+	msgsz += KDHDR;
 	if (ret_size & KERNELD_WAIT) {
-		if (++id <= 0)
+		save_flags(flags);
+		cli();
+		if (++id <= 0) /* overflow */
 			id = KERNELD_MINSEQ;
 		kmsp.id = id;
+		restore_flags(flags);
 	}
 
 	status = real_msgsnd(kerneld_msqid, (struct msgbuf *)&kmsp, msgsz, msgflg);
@@ -702,7 +761,7 @@
 		ret_size &= ~KERNELD_WAIT;
 		kmsp.text = (char *)ret_val;
 		status = real_msgrcv(kerneld_msqid, (struct msgbuf *)&kmsp,
-				sizeof(long) + ((ret_val)?ret_size:0),
+				KDHDR + ((ret_val)?ret_size:0),
 				kmsp.id, msgflg);
 		if (status > 0) /* a valid answer contains at least a long */
 			status = kmsp.id;
diff -u --recursive --new-file v1.3.99/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v1.3.99/linux/net/ipv4/arp.c	Tue May  7 16:22:41 1996
+++ linux/net/ipv4/arp.c	Fri May 10 11:27:35 1996
@@ -1431,7 +1431,7 @@
  *	all possible race conditions should be resolved by
  *	cli()/sti() pairs.
  *
- *	Important note: hhs never disapear from lists, if ARP_LOCKED,
+ *	Important note: hhs never disappear from lists, if ARP_LOCKED,
  *	this fact allows to scan hh lists with enabled interrupts,
  *	but results in generating duplicate hh entries.
  *	It is harmless. (and I've never seen such event)
@@ -2036,7 +2036,7 @@
 		entry->mask = mask;
 		entry->flags = r->arp_flags;
 
-		entry->next = (*entryp)->next;
+		entry->next = *entryp;
 		*entryp = entry;
 	}
 
