diff -u --recursive --new-file v2.0.8/linux/CREDITS linux/CREDITS
--- v2.0.8/linux/CREDITS	Tue Jul 23 08:23:11 1996
+++ linux/CREDITS	Thu Jul 25 09:08:27 1996
@@ -1004,9 +1004,10 @@
 
 N: David C. Niemi
 E: niemi@erols.com
-D: Mtools/VFAT/floppy work, benchmarking, random kernel dilettante
+D: Assistant maintainer of Mtools, fdutils, and floppy driver
+D: Administrator of WAUUG Linux Server, http://linux.wauug.org
 S: 2364 Old Trail Drive
-S: Reston, Virginia 22091
+S: Reston, Virginia 20191
 S: USA
 
 N: Michael O'Reilly
@@ -1449,7 +1450,7 @@
 S: USA
 
 N: Hans-Joachim Widmaier
-E: jbhr@sofal.tynet.sub.org
+E: hjw@zvw.de
 D: AFFS rewrite
 S: Eichenweg 16
 S: 73650 Winterbach
diff -u --recursive --new-file v2.0.8/linux/Documentation/Changes linux/Documentation/Changes
--- v2.0.8/linux/Documentation/Changes	Wed Jul 17 08:12:14 1996
+++ linux/Documentation/Changes	Tue Jul 23 10:26:49 1996
@@ -22,7 +22,11 @@
 documento, consultad la traduccion de Alfredo Sanjuan en
 http://slug.ctv.es/~alfredo/Cambios.html.
 
-Last updated: July 13, 1996.
+   Akik magyarul szeretnenek olvasni az uj kernellel kapcsolatos
+valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
+http://www.datanet.hu/generations/linux/newkernel.html.
+
+Last updated: July 21, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -40,7 +44,9 @@
 - Gpm			 1.09
 - SysVinit		 2.64
 - Util-linux		 2.5
+- Mount                  2.5k
 - Net-tools              1.32-alpha
+- Kbd                    0.91
 
 Upgrade notes
 *************
@@ -225,6 +231,15 @@
    For those of you needing non-ASCII character/font support, you should
 upgrade to ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/kbd-0.91.tar.gz.
 
+Mount
+=====
+
+   The mount util is distributed as part of util-linux, which is
+currently at release 2.5.  Some may find, especially when using the
+loop or xiafs file system, NFS, or automounting, that they need to
+upgrade to the latest release of mount, available from
+ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz.
+
 Console
 =======
 
@@ -318,7 +333,7 @@
 Sound driver
 ============
 
-   The sound driver was upgraded in the 1.3.x kernels, breaking vplay.
+   The sound driver was upgraded in the 2.0.x kernels, breaking vplay.
 To fix this problem, get a new version of the sndkit from
 ftp://ftp.best.com/pub/front/tasd/snd-util-3.5.tar.gz.  Some users
 report that various other sound utils (cdd2wav-sbpcd, for example) need
@@ -352,7 +367,7 @@
 file as a file system, which can allow for all sorts of cool things
 like encrypted file systems and such.  To use it, you'll need a
 modified version of mount from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5X.tar.gz; preliminary work
+ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz; preliminary work
 on encrypted file system support can be found in
 ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz.
 
@@ -463,7 +478,9 @@
 pages due to changes in groff.  If your man pages display <AD> for -
 when present at the end of a line, try setting an appropriate value
 (many have reported success with "latin1", for example) for the
-environmental variable LESSCHARSET.
+environmental variable LESSCHARSET.  Another, and probably better,
+solution is to edit the file /usr/lib/man.config and change all
+`-Tlatin1' options to `-Tascii'.
 
 How to know the version of the installed programs
 *************************************************
diff -u --recursive --new-file v2.0.8/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt
--- v2.0.8/linux/Documentation/filesystems/affs.txt	Mon May 20 08:20:58 1996
+++ linux/Documentation/filesystems/affs.txt	Thu Jul 25 09:08:28 1996
@@ -1,26 +1,28 @@
 Amiga filesystems Overview
 ==========================
 
-Not all varieties of the Amiga filesystems are supported.  The Amiga
-currently knows 6 different filesystems:
+Not all varieties of the Amiga filesystems are supported for reading and
+writing. The Amiga currently knows 6 different filesystems:
 
 DOS\0		The old or original filesystem, not really suited for
 		hard disks and normally not used on them, either.
+		Supported read/write.
 
-DOS\1		The original Fast File System. Supported.
+DOS\1		The original Fast File System. Supported read/write.
 
 DOS\2		The old "international" filesystem. International means that
 		a bug has been fixed so that accented ("international") letters
 		in file names are case-insensitive, as they ought to be.
+		Supported read/write.
 
-DOS\3		The "international" Fast File System.  Supported.
+DOS\3		The "international" Fast File System.  Supported read/write.
 
 DOS\4		The original filesystem with directory cache. The directory
 		cache speeds up directory accesses on floppies considerably,
 		but slows down file creation/deletion. Doesn't make much
-		sense on hard disks. Not supported.
+		sense on hard disks. Supported read only.
 
-DOS\5		The Fast File System with directory cache. Not supported.
+DOS\5		The Fast File System with directory cache. Supported read only.
 
 All of the above filesystems allow block sizes from 512 to 32K bytes.
 Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks
@@ -47,9 +49,6 @@
 
 setgid[=gid]	Same as above, but for gid.
 
-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, regardless
 		of the original permissions. Directories will get an x
 		permission, if the corresponding r bit is set.
@@ -72,6 +71,13 @@
 verbose		The volume name, file system type and block size will
 		be written to the syslog.
 
+prefix=path	Path will be prefixed to every absolute path name of
+		symbolic links on an AFFS partition. Default = /
+
+volume=name	When symbolic links with an absolute path are created
+		on an AFFS partition, volume will be prepended as the
+		volume name. Default = "" (empty string).
+
 Handling of the Users/Groups and protection flags
 =================================================
 
@@ -109,9 +115,33 @@
 Newly created files and directories will get the user and group id
 of the current user and a mode according to the umask.
 
-Command line example
-====================
-    mount  Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,size=1760
+Symbolic links
+==============
+
+Although the Amiga and Linux file systems resemble each other, there
+are some, not always subtle, differences. One of them becomes apparent
+with symbolic links. While Linux has a file system with exactly one
+root directory, the Amiga has a seperate root directory for each
+file system (i. e. partition, floppy disk, ...). With the Amiga,
+these entities are called "volumes". They have symbolic names which
+can be used to access them. Thus, symbolic links can point to a
+different volume. AFFS turns the volume name into a directory name
+and prepends the prefix path (see prefix option) to it.
+
+Example:
+You mount all your Amiga partitions under /amiga/<volume> (where
+<volume> is the name of the volume), and you give the option
+"prefix=/amiga/" when mounting all your AFFS partitions. (They
+might be "User", "WB" and "Graphics", the mount points /amiga/User,
+/amiga/WB and /amiga/Graphics). A symbolic link referring to
+"User:sc/include/dos/dos.h" will be followed to
+"/amiga/User/sc/include/dos/dos.h".
+
+Examples
+========
+
+Command line
+    mount  Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,reserved=4
     mount  /dev/sda3 /Amiga -t affs
 
 /etc/fstab example
@@ -151,7 +181,7 @@
     ln -s /bin/true /etc/fs/mkfs.affs
 
 It's not possible to read floppy disks with a normal PC or workstation
-due to an incompatibility to the Amiga floppy controller.
+due to an incompatibility with the Amiga floppy controller.
 
 If you are interested in an Amiga Emulator for Linux, look at
 
diff -u --recursive --new-file v2.0.8/linux/Documentation/ide.txt linux/Documentation/ide.txt
--- v2.0.8/linux/Documentation/ide.txt	Mon Jul  8 16:09:50 1996
+++ linux/Documentation/ide.txt	Tue Jul 23 11:33:32 1996
@@ -107,7 +107,7 @@
 Interfaces beyond the first two are not normally probed for, but may be
 specified using kernel "command line" options.  For example,
 
-	ide3=0x168,0x36e,10	/* ioports 0x1e8-0x1ef,0x3f0, irq 11 */
+	ide3=0x168,0x36e,10	/* ioports 0x168-0x16f,0x36e, irq 11 */
 
 Normally the irq number need not be specified, as ide.c will probe for it:
 
@@ -119,6 +119,9 @@
 	ide1=0x170,0x376,15
 	ide2=0x1e8,0x3ee,11
 	ide3=0x168,0x36e,10
+
+Note that the first parameter reserves 8 contiguous ioports, whereas the
+second value denotes a single ioport. If in doubt, do a 'cat /proc/ioports'.
 
 In all probability the device uses these ports and irqs if it is attached
 to the appropriate ide channel.  Pass the parameter for the correct ide
diff -u --recursive --new-file v2.0.8/linux/Makefile linux/Makefile
--- v2.0.8/linux/Makefile	Tue Jul 23 08:23:11 1996
+++ linux/Makefile	Tue Jul 23 08:22:48 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 8
+SUBLEVEL = 9
 
 ARCH = i386
 
diff -u --recursive --new-file v2.0.8/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.0.8/linux/arch/alpha/defconfig	Wed Jul 17 08:12:15 1996
+++ linux/arch/alpha/defconfig	Thu Jul 25 20:24:49 1996
@@ -62,6 +62,7 @@
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # Networking options
diff -u --recursive --new-file v2.0.8/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.0.8/linux/arch/i386/Makefile	Tue Jul 23 08:23:11 1996
+++ linux/arch/i386/Makefile	Thu Jul 25 19:35:00 1996
@@ -40,7 +40,7 @@
 OBJDUMP=$(CROSS_COMPILE)objdump
 OBJDUMP_FLAGS=-k -q 
 ENCAPS=$(CROSS_COMPILE)encaps
-OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment
+OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -R .stab -R .stabstr
 ZLDFLAGS=-e startup_32 
 LDFLAGS=-e stext
 ZIMAGE_OFFSET=0x1000
diff -u --recursive --new-file v2.0.8/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.0.8/linux/drivers/block/Config.in	Thu Jun  6 17:42:32 1996
+++ linux/drivers/block/Config.in	Tue Jul 23 11:33:32 1996
@@ -16,13 +16,13 @@
   bool '   Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA
   bool '   CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
   if [ "$CONFIG_PCI" = "y" ]; then
-    bool '   Intel 430FX (Triton) chipset DMA support' CONFIG_BLK_DEV_TRITON
     bool '   RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
+    bool '   Intel 82371 PIIX (Triton I/II) DMA support' CONFIG_BLK_DEV_TRITON
   fi
   bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
   if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
     comment 'Note: most of these also require special kernel boot parameters'
-    bool '      ALI M1439/M1445 support' CONFIG_BLK_DEV_ALI14XX
+    bool '      ALI M14xx       support' CONFIG_BLK_DEV_ALI14XX
     bool '      DTC-2278        support' CONFIG_BLK_DEV_DTC2278
     bool '      Holtek HT6560B  support' CONFIG_BLK_DEV_HT6560B
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -50,6 +50,8 @@
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
   define_bool CONFIG_BLK_DEV_HD y
+else
+  define_bool CONFIG_BLK_DEV_HD n
 fi
 
 endmenu
diff -u --recursive --new-file v2.0.8/linux/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c
--- v2.0.8/linux/drivers/block/ali14xx.c	Mon Feb 12 07:04:02 1996
+++ linux/drivers/block/ali14xx.c	Tue Jul 23 11:33:32 1996
@@ -7,6 +7,8 @@
 /*
  * ALI M14xx chipset EIDE controller
  *
+ * Works for ALI M1439/1443/1445/1487/1489 chipsets.
+ *
  * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
  * Derek's notes follow:
  *
@@ -23,6 +25,16 @@
  *
  * Derek Noonburg  (derekn@ece.cmu.edu)
  * 95-sep-26
+ *
+ * Update 96-jul-13:
+ *
+ * I've since upgraded to two disks and a CD-ROM, with no trouble, and
+ * I've also heard from several others who have used it successfully.
+ * This driver appears to work with both the 1443/1445 and the 1487/1489
+ * chipsets.  I've added support for PIO mode 4 for the 1487.  This
+ * seems to work just fine on the 1443 also, although I'm not sure it's
+ * advertised as supporting mode 4.  (I've been running a WDC AC21200 in
+ * mode 4 for a while now with no trouble.)  -Derek
  */
 
 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
@@ -45,8 +57,8 @@
  * from 25 to 50.  Setting this too *low* will make the EIDE
  * controller unable to communicate with the disks.
  *
- * I suggest using a default of 50, since it should work ok with any
- * system.  (Low values cause problems because it multiplies by bus speed
+ * The value is 50 by default -- this should work ok with any system.
+ * (Low values cause problems because it multiplies by bus speed
  * to get cycles, and thus gets a too-small cycle count and tries to
  * access the disks too fast.  I tried this once under DOS and it locked
  * up the system.)	-- derekn@vw.ece.cmu.edu
@@ -71,11 +83,13 @@
 };
 
 /* default timing parameters for each PIO mode */
-static struct { int time1, time2; } timeTab[4] = {
+#define ALI_MAX_PIO 4
+static struct { int time1, time2; } timeTab[ALI_MAX_PIO+1] = {
 	{600, 165},	/* PIO 0 */
 	{383, 125},	/* PIO 1 */
 	{240, 100},	/* PIO 2 */
-	{180,  80}	/* PIO 3 */
+	{180,  80},	/* PIO 3 */
+	{120,  70}	/* PIO 4 */
 };
 
 /* timing parameter registers for each drive */
@@ -127,20 +141,20 @@
 
 	if (pio == 255)
 		pio = ide_get_best_pio_mode(drive);
-	if (pio > 3)
-		pio = 3;
+	if (pio > ALI_MAX_PIO)
+		pio = ALI_MAX_PIO;
 
 	/* calculate timing, according to PIO mode */
 	time1 = timeTab[pio].time1;
 	time2 = timeTab[pio].time2;
-	if (pio == 3) {
+	if (pio >= 3) {
 		time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
 		if (time1a != 0 && time1a < time1)
 			time1 = time1a;
 	}
 	param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
 	param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
-	if (pio != 3) {
+	if (pio < 3) {
 		param3 += 8;
 		param4 += 8;
 	}
diff -u --recursive --new-file v2.0.8/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v2.0.8/linux/drivers/block/cmd640.c	Sun May  5 08:51:58 1996
+++ linux/drivers/block/cmd640.c	Tue Jul 23 11:33:32 1996
@@ -1,15 +1,26 @@
 /*
- *  linux/drivers/block/cmd640.c	Version 0.09  Mar 19, 1996
+ *  linux/drivers/block/cmd640.c	Version 0.12  Jul 22, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
 
 /*
- *  Principal Author/Maintainer:  abramov@cecmow.enet.dec.com (Igor Abramov)
+ *  Original author:	abramov@cecmow.enet.dec.com (Igor Abramov)
+ *
+ *  Maintained by:	s0033las@sun10.vsz.bme.hu (Laszlo Peter)
+ *			mlord@pobox.com (Mark Lord)
  *
  *  This file provides support for the advanced features and bugs
  *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
  *
+ *  These chips are basically fucked by design, and getting this driver
+ *  to work on every motherboard design that uses this screwed chip seems
+ *  bloody well impossible.  However, we're still trying.
+ *
+ *  We think version 0.12 should work for most folks.
+ *  User feedback is essential.
+ *
+ *
  *  Version 0.01	Initial version, hacked out of ide.c,
  *			and #include'd rather than compiled separately.
  *			This will get cleaned up in a subsequent release.
@@ -23,8 +34,8 @@
  *			with read ahead mode. Separate function for setting
  *			readahead is added, possibly it will be called some
  *			day from ioctl processing code.
- *  
- *  Version 0.04	Now configs/compiles separate from ide.c  -ml 
+ *
+ *  Version 0.04	Now configs/compiles separate from ide.c  -ml
  *
  *  Version 0.05	Major rewrite of interface timing code.
  *			Added new function cmd640_set_mode to set PIO mode
@@ -33,9 +44,9 @@
  *  Version 0.06	More code cleanup. Readahead is enabled only for
  *			detected hard drives, not included in readahead
  *			black list.
- * 
+ *
  *  Version 0.07	Changed to more conservative drive tuning policy.
- *			Unknown drives, which report PIO < 4 are set to 
+ *			Unknown drives, which report PIO < 4 are set to
  *			(reported_PIO - 1) if it is supported, or to PIO0.
  *			List of known drives extended by info provided by
  *			CMD at their ftp site.
@@ -44,7 +55,12 @@
  *
  *  Version 0.09	Try to be smarter about 2nd port enabling.  -ml
  *  Version 0.10	Be nice and don't reset 2nd port.  -ml
- *			
+ *  Version 0.11	Try to handle more wierd situations.  -ml
+ *
+ *  Version 0.12	Lots of bug fixes from Laszlo Peter
+ *			irq unmasking disabled for reliability.  -lp
+ *			try to be even smarter about the second port.  -lp
+ *			tidy up source code formatting.  -ml
  */
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
@@ -61,6 +77,8 @@
 #include "ide.h"
 #include "ide_modes.h"
 
+#define PARANOID_ABOUT_CMD640	1	/* used to tag superstitious code */
+
 int cmd640_vlb = 0;
 
 /*
@@ -109,8 +127,8 @@
 static ide_tuneproc_t cmd640_tune_drive;
 
 /* Interface to access cmd640x registers */
-static void (*put_cmd640_reg)(int reg_no, int val);
-       byte (*get_cmd640_reg)(int reg_no);
+void (*put_cmd640_reg)(int reg_no, int val);
+byte (*get_cmd640_reg)(int reg_no);
 
 enum { none, vlb, pci1, pci2 };
 static int	bus_type = none;
@@ -119,8 +137,9 @@
 static int 	bus_speed; /* MHz */
 
 /*
- * For some unknown reasons pcibios functions which read and write registers
- * do not always work with cmd640. We use direct IO instead.
+ * The CMD640x chip does not support DWORD config write cycles, but some
+ * of the BIOSes use them to implement the config services.
+ * We use direct IO instead.
  */
 
 /* PCI method 1 access */
@@ -302,18 +321,17 @@
  *  Returns 1 if an IDE interface/drive exists at 0x170,
  *  Returns 0 otherwise.
  */
-int secondary_port_responding (void)
+static int secondary_port_responding (void)
 {
 	/*
 	 * Test for hardware at 0x170 (secondary IDE port).
-	 * Leave the enable-bit alone if something responds.
 	 */
-	outb_p(0x0a,0x176);		/* select drive0 */
-	udelay(1);
-	if (inb_p(0x176) == 0xff) {
-		outb_p(0x0b,0x176);	/* select drive1 */
-		udelay(1);
-		if (inb_p(0x176) == 0xff)
+	outb_p(0xa0, 0x170 + IDE_SELECT_OFFSET);	/* select drive0 */
+	udelay(100);
+	if (inb_p(0x170 + IDE_SELECT_OFFSET) != 0xa0) {
+		outb_p(0xb0, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
+		udelay(100);
+		if (inb_p(0x170 + IDE_SELECT_OFFSET) != 0xb0)
 			return 0;	/* nothing is there */
 	}
 	return 1;			/* something is there */
@@ -325,8 +343,9 @@
 
 int ide_probe_for_cmd640x(void)
 {
-	int  second_port_toggled = 0;
-        byte b;
+	int second_port_toggled = 0;
+	int second_port_cmd640 = 0;
+	byte b;
 
 	if (probe_for_cmd640_pci1()) {
 		bus_type = pci1;
@@ -339,10 +358,12 @@
 		return 0;
 	}
 
+#ifdef PARANOID_ABOUT_CMD640
 	ide_hwifs[0].serialized = 1;	/* ensure this *always* gets set */
 	ide_hwifs[1].serialized = 1;	/* ensure this *always* gets set */
+#endif
 
-#if 0	
+#if 0
 	/* Dump initial state of chip registers */
 	for (b = 0; b != 0xff; b++) {
 		printk(" %2x%c", get_cmd640_reg(b),
@@ -374,33 +395,55 @@
 	/*
 	 * Setup the most conservative timings for all drives,
 	 */
+
+	put_cmd640_reg(CMDTIM, 0);
+
 	put_cmd640_reg(ARTTIM0, 0xc0);
 	put_cmd640_reg(ARTTIM1, 0xc0);
-	put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */
+	put_cmd640_reg(ARTTIM23, 0xcc); /* disable read-ahead for drives 2&3 */
+
+	put_cmd640_reg(DRWTIM0, 0);
+	put_cmd640_reg(DRWTIM1, 0);
+	put_cmd640_reg(DRWTIM23, 0);
 
 	/*
 	 * Set the maximum allowed bus speed (it is safest until we
 	 * 				      find how to detect bus speed)
 	 * Normally PCI bus runs at 33MHz, but often works overclocked to 40
 	 */
-	bus_speed = (bus_type == vlb) ? 50 : 40; 
+	bus_speed = (bus_type == vlb) ? 50 : 40;
 
-        /*
+	/*
 	 * Setup Control Register
 	 */
-	b = get_cmd640_reg(CNTRL);	
-
-	if (!secondary_port_responding()) {
-		b ^= CNTRL_ENA_2ND;	/* toggle the bit */
-		second_port_toggled = 1;
-	}
+	b = get_cmd640_reg(CNTRL);
 
 	/*
 	 * Disable readahead for drives at primary interface
 	 */
 	b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
+	put_cmd640_reg(CNTRL, b);
+
+	if (!ide_hwifs[1].noprobe) {
+
+		if (secondary_port_responding()) {
+
+			if ((b & CNTRL_ENA_2ND) || (bus_type == vlb))
+				second_port_cmd640 = 1;
+
+		} else if (!(b & CNTRL_ENA_2ND) && (bus_type != vlb)) {
 
-        put_cmd640_reg(CNTRL, b);
+			second_port_toggled = 1;
+			put_cmd640_reg(CNTRL, b | CNTRL_ENA_2ND); /* Enable second interface */
+
+			if (secondary_port_responding())
+				second_port_cmd640 = 1;
+			else {
+				second_port_toggled = 0;
+				put_cmd640_reg(CNTRL, b); /* Disable second interface */
+			}
+		}
+	}
 
 	/*
 	 * Note that we assume that the first interface is at 0x1f0,
@@ -408,6 +451,8 @@
 	 */
 	ide_hwifs[0].chipset = ide_cmd640;
 	ide_hwifs[0].tuneproc = &cmd640_tune_drive;
+	ide_hwifs[0].no_unmask = 1;
+
 	if (ide_hwifs[0].drives[0].autotune == 0)
 		ide_hwifs[0].drives[0].autotune = 1;
 	if (ide_hwifs[0].drives[1].autotune == 0)
@@ -416,27 +461,29 @@
 	/*
 	 * Initialize 2nd IDE port, if required
 	 */
-	if (secondary_port_responding()) {
+	if (second_port_cmd640) {
+
+#ifndef PARANOID_ABOUT_CMD640
+		ide_hwifs[0].serialized = 1;
+		ide_hwifs[1].serialized = 1;
+#endif
+
 		ide_hwifs[1].chipset = ide_cmd640;
 		ide_hwifs[1].tuneproc = &cmd640_tune_drive;
+		ide_hwifs[1].no_unmask = 1;
+
 		if (ide_hwifs[1].drives[0].autotune == 0)
 			ide_hwifs[1].drives[0].autotune = 1;
 		if (ide_hwifs[1].drives[1].autotune == 0)
 			ide_hwifs[1].drives[1].autotune = 1;
-		/* disable read-ahead for drives 2 & 3 */
-		put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3));
 
-		if (second_port_toggled) {
-			/* reset PIO timings for drives 2 & 3 */
-			put_cmd640_reg(DRWTIM23, 0);
-		}
 #if 0
 		/* reset the secondary interface */
 		cmd640_reset_controller(1);
 #endif
 	}
 
-	printk("ide: buggy CMD640%c interface on ", 
+	printk("ide: buggy CMD640%c interface on ",
 	       'A' - 1 + cmd640_chip_version);
 	switch (bus_type) {
 		case vlb :
@@ -450,15 +497,12 @@
 			break;
 	}
 
-#if 0
-	/* reset PIO timings for drives 1 & 2 */
-	put_cmd640_reg(CMDTIM, 0);
-#endif /* 0 */
-
 	/*
 	 * Tell everyone what we did to their system
 	 */
-	printk("; serialized, secondary port %s\n", second_port_toggled ? "toggled" : "untouched");
+	printk(":%s serialized, second port %s\n",
+		second_port_cmd640 ? "" : " not",
+		second_port_toggled ? "toggled" : "untouched");
 	return 1;
 }
 
@@ -470,7 +514,7 @@
 	if (bus_type == none || a == 1)
 		return 0;
 	a = 1;
-	b = get_cmd640_reg(CNTRL);	
+	b = get_cmd640_reg(CNTRL);
 	b &= ~CNTRL_ENA_2ND;
 	put_cmd640_reg(CNTRL, b);
 	return 1;
@@ -482,35 +526,48 @@
  *  in the future it could be called from ioctl
  */
 
-static void set_readahead_mode(int mode, int if_num, int dr_num)
+static void set_readahead_mode(ide_drive_t* drive, int mode)
 {
-	static int masks[2][2] = 
-		{ 
-			{CNTRL_DIS_RA0, CNTRL_DIS_RA1}, 
+	static int masks[2][2] =
+		{
+			{CNTRL_DIS_RA0, CNTRL_DIS_RA1},
 			{DIS_RA2, 	DIS_RA3}
 		};
-
-	int port = (if_num == 0) ? CNTRL : ARTTIM23;
-	int mask = masks[if_num][dr_num];
 	byte b;
 
+	int interface_number = HWIF(drive)->index;
+	int drive_number = drive->select.b.unit;
+
+	int port = (interface_number == 0) ? CNTRL : ARTTIM23;
+	int mask = masks[interface_number][drive_number];
+
 	b = get_cmd640_reg(port);
+
+	/*
+	 * I don't know why it is necessary, but without this my machine
+	 * locks up, if bus_speed is not correct. And it even allows me
+	 * to use 32 bit transfers on the primary port (hdparm -c1).
+	 */
+	if ((interface_number == 0) && mode)
+		b|=0x27;
+
 	if (mode)
 		b &= ~mask;	/* Enable readahead for specific drive */
 	else
 		b |= mask;	/* Disable readahead for specific drive */
+
 	put_cmd640_reg(port, b);
-}		
+}
 
-static struct readahead_black_list {
+static const struct readahead_black_list {
 	const char* 	name;
-	int		mode;	
+	int		mode;
 } drives_ra[] = {
-        { "QUANTUM LIGHTNING 540A", 0 },
-        { "ST3655A",	0 },
-        { "SAMSUNG",	0 },	/* Be conservative */
- 	{ NULL, 0 }
-};	
+	{ "QUANTUM LIGHTNING 540A", 0 },
+	{ "ST3655A",	0 },
+	{ "SAMSUNG",	0 },	/* Be conservative */
+	{ NULL,		0 }
+};
 
 static int strmatch(const char* pattern, const char* name) {
 	char c1, c2;
@@ -534,7 +591,7 @@
 			return drives_ra[i].mode;
 		}
 	}
-        return -1;
+	return -1;
 }
 
 static int arttim[4]  = {2, 2, 2, 2};	/* Address setup count (in clocks) */
@@ -542,7 +599,7 @@
 static int r_count[4] = {1, 1, 1, 1};	/* Recovery count (encoded) */
 
 /*
- * Convert address setup count from number of clocks 
+ * Convert address setup count from number of clocks
  * to representation used by controller
  */
 
@@ -575,6 +632,7 @@
 {
 	int	b_reg;
 	int	ac, rc, at;
+	byte b;
 
 	/*
 	 * Set address setup count and drive read/write timing registers.
@@ -588,22 +646,28 @@
 		at = arttim[dr_num];
 		ac = a_count[dr_num];
 		rc = r_count[dr_num];
+		b = pack_arttim(at);
 	} else {
 		b_reg = ARTTIM23;
 		at = max(arttim[2], arttim[3]);
 		ac = max(a_count[2], a_count[3]);
 		rc = max(r_count[2], r_count[3]);
+
+		/*
+		 * Protect the readahead bits
+		 */
+		b = pack_arttim(at) | (get_cmd640_reg(ARTTIM23) & (DIS_RA2 | DIS_RA3));
 	}
 
-	put_cmd640_reg(b_reg, pack_arttim(at));
+	put_cmd640_reg(b_reg, b);
 	put_cmd640_reg(b_reg + 1, pack_counts(ac, rc));
 
 	/*
-	 * Update CMDTIM (IDE Command Block Timing Register) 
+	 * Update CMDTIM (IDE Command Block Timing Register)
 	 */
 
-	ac = max4(r_count);
-	rc = max4(a_count);
+	ac = max4(a_count);
+	rc = max4(r_count);
 	put_cmd640_reg(CMDTIM, pack_counts(ac, rc));
 }
 
@@ -611,17 +675,17 @@
  * Standard timings for PIO modes
  */
 
-static struct pio_timing {
-	int	mc_time;	/* Minimal cycle time (ns) */
-	int	av_time;	/* Address valid to DIOR-/DIOW- setup (ns) */
-	int	ds_time;	/* DIOR data setup	(ns) */
+static const struct pio_timing {
+	int	mc_time;	/* Address setup (ns) min */
+	int	av_time;	/* Active pulse (ns) min */
+	int	ds_time;	/* Cycle time (ns) min = Active pulse + Recovery pulse */
 } pio_timings[6] = {
 	{ 70,	165,	600 },	/* PIO Mode 0 */
 	{ 50,	125,	383 },	/* PIO Mode 1 */
 	{ 30,	100,	240 },	/* PIO Mode 2 */
-	{ 30,	80,	180 },	/* PIO Mode 3 */
-	{ 25,	70,	125 },	/* PIO Mode 4  -- should be 120, not 125 */
-	{ 20,	50,	100 }	/* PIO Mode ? (nonstandard) */
+	{ 30,	80,	180 },	/* PIO Mode 3 w/IORDY */
+	{ 25,	70,	125 },	/* PIO Mode 4 w/IORDY -- should be 120, not 125 */
+	{ 20,	50,	100 }	/* PIO Mode 5 w/IORDY (nonstandard) */
 };
 
 static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
@@ -657,11 +721,13 @@
 	int i;
 
 	p_base = if_num ? 0x170 : 0x1f0;
-	outb_p(3, p_base + 1);
-	outb_p(mode_num | 8, p_base + 2);
-	outb_p((drv_num | 0xa) << 4, p_base + 6);
-	outb_p(0xef, p_base + 7);
-	for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
+
+	outb_p(3, p_base + IDE_FEATURE_OFFSET);
+	outb_p(mode_num | 0x08, p_base + IDE_NSECTOR_OFFSET);
+	outb_p((drv_num | 0x0a) << 4, p_base + IDE_SELECT_OFFSET);
+	outb_p(WIN_SETFEATURES, p_base + IDE_COMMAND_OFFSET);
+
+	for (i = 0; (i < 100) && (inb(p_base + IDE_STATUS_OFFSET) & BUSY_STAT); i++)
 		udelay(10000);
 }
 
@@ -669,11 +735,13 @@
  * Set a specific pio_mode for a drive
  */
 
-static void cmd640_set_mode(ide_drive_t* drive, int pio_mode) {
+static void cmd640_set_mode(ide_drive_t* drive, byte pio_mode, int ds_time) {
 	int interface_number;
 	int drive_number;
 	int clock_time; /* ns */
-	int mc_time, av_time, ds_time;
+	int mc_time, av_time;
+
+	if (pio_mode > 5) return;
 
 	interface_number = HWIF(drive)->index;
 	drive_number = drive->select.b.unit;
@@ -681,7 +749,7 @@
 
 	mc_time = pio_timings[pio_mode].mc_time;
 	av_time = pio_timings[pio_mode].av_time;
-	ds_time = pio_timings[pio_mode].ds_time;
+	ds_time = (ds_time != 0) ? ds_time : pio_timings[pio_mode].ds_time;
 
 	cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
 				interface_number*2 + drive_number);
@@ -691,29 +759,29 @@
 
 /*
  * Drive PIO mode "autoconfiguration".
- * Ideally, this code should *always* call cmd640_set_mode(), but it doesn't.
  */
 
 static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
-	int interface_number;
-	int drive_number;
-	int clock_time; /* ns */
 	int max_pio;
-	int mc_time, av_time, ds_time;
-	struct hd_driveid* id;
+	int ds_time;
 	int readahead;	/* there is a global named read_ahead */
+	int overridden;
+	int iordy;
+	struct hd_driveid* id;
 
 	if (pio_mode != 255) {
-		cmd640_set_mode(drive, pio_mode);
+		cmd640_set_mode(drive, pio_mode, 0);
 		return;
 	}
 
-	interface_number = HWIF(drive)->index;
-	drive_number = drive->select.b.unit;
-	clock_time = 1000/bus_speed;
+	overridden = 0;
+	iordy = 0;
 	id = drive->id;
+
 	if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) {
 		ds_time = pio_timings[max_pio].ds_time;
+		overridden = 1;
+		iordy = (max_pio > 2);
 	} else {
 		max_pio = id->tPIO;
 		ds_time = pio_timings[max_pio].ds_time;
@@ -723,27 +791,28 @@
 				else if (id->eide_pio_modes & 2) max_pio = 4;
 				else max_pio = 3;
 				ds_time = id->eide_pio_iordy;
+				iordy = 1;
 			} else {
 				ds_time = id->eide_pio;
 			}
-			if (ds_time == 0)
+			if (ds_time == 0) {
 				ds_time = pio_timings[max_pio].ds_time;
+				iordy = (max_pio > 2);
+			}
 		}
 
 		/*
 		 * Conservative "downgrade"
 		 */
 		if (max_pio < 4 && max_pio != 0) {
-			max_pio -= 1;
-			ds_time = pio_timings[max_pio].ds_time;		
+			max_pio--;
+			overridden = 1;
+			iordy = (max_pio > 2);
+			ds_time = pio_timings[max_pio].ds_time;
 		}
 	}
-	mc_time = pio_timings[max_pio].mc_time;
-	av_time = pio_timings[max_pio].av_time;
-	cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
-				interface_number*2 + drive_number);
-	set_pio_mode(interface_number, drive_number, max_pio);
-	cmd640_set_timing(interface_number, drive_number);
+
+	cmd640_set_mode(drive, max_pio, ds_time);
 
 	/*
 	 * Disable (or set) readahead mode
@@ -754,10 +823,13 @@
 		readahead = known_drive_readahead(id->model);
 		if (readahead == -1)
 	        	readahead = 1;	/* Mmmm.. probably be 0 ?? */
-		set_readahead_mode(readahead, interface_number, drive_number);
-	}   
+		set_readahead_mode(drive, readahead);
+	}
 
-	printk ("Mode and Timing set to PIO%d, Readahead is %s\n", 
-		max_pio, readahead ? "enabled" : "disabled");
+	printk ("Drive Timing: PIO Mode %d (%dns) %s/IORDY%s, Read-ahead: %s\n",
+		max_pio,
+		ds_time,
+		iordy ? "w" : "wo",
+		overridden ? " (overriding vendor mode)" : "",
+		readahead ? "enabled" : "disabled");
 }
-
diff -u --recursive --new-file v2.0.8/linux/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c
--- v2.0.8/linux/drivers/block/dtc2278.c	Sun May  5 08:51:58 1996
+++ linux/drivers/block/dtc2278.c	Tue Jul 23 11:33:32 1996
@@ -41,8 +41,8 @@
  *
  * DTC2278S has only a single IDE interface.
  * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
- * DTC2278E has onboard BIOS, while the others do not.
- * DTC2278EB: "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
+ * DTC2278E also has serial ports and a printer port
+ * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
  *
  * There may be a fourth controller type. The S and D versions use the
  * Winbond chip, and I think the E version does also.
diff -u --recursive --new-file v2.0.8/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.0.8/linux/drivers/block/genhd.c	Mon May 20 08:20:58 1996
+++ linux/drivers/block/genhd.c	Thu Jul 25 09:08:28 1996
@@ -551,6 +551,88 @@
 
 #endif /* CONFIG_SUN_PARTITION */
 
+#ifdef CONFIG_AMIGA_PARTITION
+#include <asm/byteorder.h>
+#include <linux/affs_hardblocks.h>
+
+static __inline__ __u32
+checksum_block(__u32 *m, int size)
+{
+	__u32 sum = 0;
+
+	while (size--)
+		sum += htonl(*m++);
+	return sum;
+}
+
+static int
+amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
+{
+	struct buffer_head	*bh;
+	struct RigidDiskBlock	*rdb;
+	struct PartitionBlock	*pb;
+	int			 start_sect;
+	int			 nr_sects;
+	int			 blk;
+	int			 part, res;
+
+	set_blocksize(dev,512);
+	res = 0;
+
+	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if(!(bh = bread(dev,blk,512))) {
+			printk("Dev %d: unable to read RDB block %d\n",dev,blk);
+			goto rdb_done;
+		}
+		if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
+			rdb = (struct RigidDiskBlock *)bh->b_data;
+			if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
+				printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk);
+				brelse(bh);
+				continue;
+			}
+			printk(" RDSK");
+			blk = htonl(rdb->rdb_PartitionList);
+			brelse(bh);
+			for (part = 1; blk > 0 && part <= 16; part++) {
+				if (!(bh = bread(dev,blk,512))) {
+					printk("Dev %d: unable to read partition block %d\n",
+						       dev,blk);
+					goto rdb_done;
+				}
+				pb  = (struct PartitionBlock *)bh->b_data;
+				blk = htonl(pb->pb_Next);
+				if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
+				    (__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+					
+					/* Tell Kernel about it */
+
+					if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
+							  htonl(pb->pb_Environment[9])) *
+							 htonl(pb->pb_Environment[3]) *
+							 htonl(pb->pb_Environment[5]))) {
+						continue;
+					}
+					start_sect = htonl(pb->pb_Environment[9]) *
+						     htonl(pb->pb_Environment[3]) *
+						     htonl(pb->pb_Environment[5]);
+					add_partition(hd,current_minor,start_sect,nr_sects);
+					current_minor++;
+					res = 1;
+				}
+				brelse(bh);
+			}
+			printk("\n");
+			break;
+		}
+	}
+
+rdb_done:
+	set_blocksize(dev,BLOCK_SIZE);
+	return res;
+}
+#endif /* CONFIG_AMIGA_PARTITION */
+
 static void check_partition(struct gendisk *hd, kdev_t dev)
 {
 	static int first_time = 1;
@@ -582,6 +664,10 @@
 #endif
 #ifdef CONFIG_SUN_PARTITION
 	if(sun_partition(hd, dev, first_sector))
+		return;
+#endif
+#ifdef CONFIG_AMIGA_PARTITION
+	if(amiga_partition(hd, dev, first_sector))
 		return;
 #endif
 	printk(" unknown partition table\n");
diff -u --recursive --new-file v2.0.8/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.0.8/linux/drivers/block/ide.c	Tue Jul 23 08:23:12 1996
+++ linux/drivers/block/ide.c	Wed Jul 24 07:48:47 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.43  May 14, 1996
+ *  linux/drivers/block/ide.c	Version 5.45  Jul 22, 1996
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors (see below)
  */
@@ -238,6 +238,11 @@
  * Version 5.42		simplify irq-masking after probe
  *			fix NULL pointer deref in save_match()
  * Version 5.43		Ugh.. unexpected_intr is back: try to exterminate it
+ * Version 5.44		Fix for "irq probe failed" on cmd640
+ *			change path on message regarding MAKEDEV.ide
+ *			add a throttle to the unexpected_intr() messages
+ * Version 5.45		fix ugly parameter parsing bugs (thanks Derek)
+ *			include Gadi's magic fix for cmd640 unexpected_intr
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -284,7 +289,6 @@
 #endif /* CONFIG_BLK_DEV_PROMISE */
 
 static const byte	ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
-
 static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
 static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
 
@@ -580,6 +584,8 @@
 	gd->part  = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
 	bs        = kmalloc (minors*sizeof(int), GFP_KERNEL);
 
+	memset(gd->part, 0, minors * sizeof(struct hd_struct));
+
 	/* cdroms and msdos f/s are examples of non-1024 blocksizes */
 	blksize_size[hwif->major] = bs;
 	for (unit = 0; unit < minors; ++unit)
@@ -1619,6 +1625,7 @@
 	byte stat;
 	unsigned int unit;
 	ide_hwif_t *hwif = hwgroup->hwif;
+	static unsigned long last_time = 0;
 
 	/*
 	 * handle the unexpected interrupt
@@ -1630,8 +1637,12 @@
 				if (!drive->present)
 					continue;
 				SELECT_DRIVE(hwif,drive);
-				if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT))
-					(void) ide_dump_status(drive, "unexpected_intr", stat);
+				if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) {
+					if ((last_time + (HZ/2)) < jiffies && !drive->ignore_unexp) {
+						last_time = jiffies;
+						(void) ide_dump_status(drive, "unexpected_intr", stat);
+					}
+				}
 				if ((stat & DRQ_STAT))
 					try_to_flush_leftover_data(drive);
 			}
@@ -1645,8 +1656,8 @@
  */
 void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
-	ide_hwgroup_t  *hwgroup = dev_id;
-	ide_handler_t  *handler;
+	ide_hwgroup_t *hwgroup = dev_id;
+	ide_handler_t *handler;
 
 	if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
 		ide_drive_t *drive = hwgroup->drive;
@@ -1658,7 +1669,7 @@
 		cli();	/* this is necessary, as next rq may be different irq */
 		if (hwgroup->handler == NULL) {
 			SET_RECOVERY_TIMER(HWIF(drive));
-			ide_do_request(hwgroup);
+ 			ide_do_request(hwgroup);
 		}
 	} else {
 		unexpected_intr(irq, hwgroup);
@@ -1899,8 +1910,13 @@
 	};
 
 	drive->part[0].nr_sects = current_capacity(drive);
-	if (drive->media == ide_disk)
-		resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
+	if (drive->media != ide_disk)
+		drive->part[0].start_sect = -1;
+	resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (drive->media == ide_cdrom)
+		ide_cdrom_setup(drive);
+#endif /* CONFIG_BLK_DEV_IDECD */
 
 	drive->busy = 0;
 	wake_up(&drive->wqueue);
@@ -2194,7 +2210,7 @@
 		if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
 		 || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
 		 || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
-			bswap = 0;	/* Vertos drives may still be weird */
+			bswap ^= 1;	/* Vertos drives may still be weird */
 	}
 	ide_fixstring (id->model,     sizeof(id->model),     bswap);
 	ide_fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
@@ -2367,10 +2383,15 @@
  */
 static int try_to_identify (ide_drive_t *drive, byte cmd)
 {
-	int hd_status, rc;
+	int irqs, rc;
 	unsigned long timeout;
-	int irqs = 0;
+#ifdef CONFIG_BLK_DEV_CMD640
+	int retry = 0;
+	int hd_status;
 
+try_again:
+#endif /* CONFIG_BLK_DEV_CMD640 */
+	irqs = 0;
 	if (!HWIF(drive)->irq) {		/* already got an IRQ? */
 		probe_irq_off(probe_irq_on());	/* clear dangling irqs */
 		irqs = probe_irq_on();		/* start monitoring irqs */
@@ -2428,16 +2449,28 @@
 			irqs = probe_irq_on();
 			OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
 			udelay(5);
-			(void) GET_STAT();	/* clear drive IRQ */
 			(void) probe_irq_off(irqs);
+			(void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */
+			(void) GET_STAT();	/* clear drive IRQ */
+
 		} 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) {
 				extern byte (*get_cmd640_reg)(int);
+				byte reg9  = get_cmd640_reg(0x09);
 				printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
-				printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, get_cmd640_reg(9));
+				printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, reg9);
 				printk("%s: cmd640 reg 51h == 0x%02x\n", drive->name, get_cmd640_reg(0x51));
+				if (reg9 == 0x0a) {
+					printk("%s: perhaps PCI INTA has not been set to IRQ15?\n", drive->name);
+					if (retry++ == 0) {
+						extern void (*put_cmd640_reg)(int, int);
+						printk("%s: switching secondary interface to legacy mode\n", drive->name);
+						put_cmd640_reg(0x09,0x00);
+						goto try_again;
+					}
+				}
 			}
 #endif /* CONFIG_BLK_DEV_CMD640 */
 		}
@@ -2832,7 +2865,7 @@
 		/*
 		 * Cryptic check to ensure chipset not already set for hwif:
 		 */
-		if (i != -1 && i != -2) {
+		if (i >= 0 || i <= -5) {
 			if (hwif->chipset != ide_unknown)
 				goto bad_option;
 			if (i < 0 && ide_hwifs[1].chipset != ide_unknown)
@@ -2841,7 +2874,7 @@
 		/*
 		 * Interface keywords work only for ide0:
 		 */
-		if (i <= -6 && hw != 0)
+		if (i <= -5 && hw != 0)
 			goto bad_hwif;
 
 		switch (i) {
@@ -3058,7 +3091,9 @@
 static int init_irq (ide_hwif_t *hwif)
 {
 	unsigned long flags;
+#if MAX_HWIFS > 1
 	unsigned int index;
+#endif /* MAX_HWIFS > 1 */
 	ide_hwgroup_t *hwgroup;
 	ide_hwif_t *match = NULL;
 
diff -u --recursive --new-file v2.0.8/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.0.8/linux/drivers/block/ide.h	Sat May 11 10:42:05 1996
+++ linux/drivers/block/ide.h	Thu Jul 25 20:27:39 1996
@@ -135,7 +135,11 @@
  * Timeouts for various operations:
  */
 #define WAIT_DRQ	(5*HZ/100)	/* 50msec - spec allows up to 20ms */
+#ifdef CONFIG_APM
+#define WAIT_READY	(5*HZ)		/* 5sec - some laptops are very slow */
+#else
 #define WAIT_READY	(3*HZ/100)	/* 30msec - should be instantaneous */
+#endif /* CONFIG_APM */
 #define WAIT_PIDENTIFY	(1*HZ)	/* 1sec   - should be less than 3ms (?) */
 #define WAIT_WORSTCASE	(30*HZ)	/* 30sec  - worst case when spinning up */
 #define WAIT_CMD	(10*HZ)	/* 10sec  - maximum wait for an IRQ to happen */
@@ -292,6 +296,18 @@
 		} b;
 	} special_t;
 
+#ifdef __BIG_ENDIAN_BITFIELD
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned bit7		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned head		: 4;	/* always zeros here */
+	} b;
+	} select_t;
+#else /* __BIG_ENDIAN_BITFIELD */
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -302,6 +318,7 @@
 		unsigned bit7		: 1;	/* always 1 */
 	} b;
 	} select_t;
+#endif /* __BIG_ENDIAN_BITFIELD */
 
 typedef struct ide_drive_s {
 	special_t	special;	/* special action flags */
@@ -315,6 +332,7 @@
 	unsigned unmask		: 1;	/* flag: okay to unmask other irqs */
 	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
 	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
+	unsigned ignore_unexp	: 1;	/* flag: ignore unexpected_intr's */
 #if FAKE_FDISK_FOR_EZDRIVE
 	unsigned remap_0_to_1	: 1;	/* flag: partitioned with ezdrive */
 #endif /* FAKE_FDISK_FOR_EZDRIVE */
@@ -324,7 +342,7 @@
 	byte		ready_stat;	/* min status value for drive ready */
 	byte		mult_count;	/* current multiple sector setting */
 	byte 		mult_req;	/* requested multiple sector setting */
-	byte 		pio_req;	/* requested multiple sector setting */
+	byte 		pio_req;	/* requested drive pio setting */
 	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
 	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
 	byte		sect0;		/* offset of first sector for DM6:DDO */
diff -u --recursive --new-file v2.0.8/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v2.0.8/linux/drivers/block/triton.c	Wed Apr 10 17:02:24 1996
+++ linux/drivers/block/triton.c	Thu Jul 25 07:18:32 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/triton.c	Version 1.10  Apr 3, 1996
+ *  linux/drivers/block/triton.c	Version 1.12  Jul 24, 1996
  *
  *  Copyright (c) 1995-1996  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -322,7 +322,7 @@
 
 /*
  * print_triton_drive_flags() displays the currently programmed options
- * in the 430FX (Triton) chipset for a given drive.
+ * in the 82371 (Triton) for a given drive.
  *
  *	If fastDMA  is "no", then slow ISA timings are used for DMA data xfers.
  *	If fastPIO  is "no", then slow ISA timings are used for PIO data xfers.
@@ -382,7 +382,7 @@
 	unsigned short pcicmd;
 	unsigned int bmiba, timings;
 
-	printk("ide: 430FX (Triton) on PCI bus %d function %d\n", bus, fn);
+	printk("ide: 82371 PIIX (Triton) on PCI bus %d function %d\n", bus, fn);
 	/*
 	 * See if IDE and BM-DMA features are enabled:
 	 */
@@ -439,14 +439,14 @@
 		unsigned short time;
 		if (hwif->io_base == 0x1f0) {
 			time = timings & 0xffff;
-			if ((timings & 0x8000) == 0)	/* interface enabled? */
+			if ((time & 0x8000) == 0)	/* interface enabled? */
 				continue;
 			hwif->chipset = ide_triton;
 			if (dma_enabled)
 				init_triton_dma(hwif, bmiba);
 		} else if (hwif->io_base == 0x170) {
 			time = timings >> 16;
-			if ((timings & 0x8000) == 0)	/* interface enabled? */
+			if ((time & 0x8000) == 0)	/* interface enabled? */
 				continue;
 			hwif->chipset = ide_triton;
 			if (dma_enabled)
diff -u --recursive --new-file v2.0.8/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.0.8/linux/drivers/cdrom/mcdx.c	Thu Jun  6 22:35:43 1996
+++ linux/drivers/cdrom/mcdx.c	Tue Jul 23 10:26:54 1996
@@ -39,7 +39,7 @@
  *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
  *  Gerd Knorr (he lent me his PhotoCD)
  *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang up's)
+ *  Andreas Kies (testing the mysterious hang-ups)
  *  Heiko Eissfeldt (VERIFY_READ/WRITE)
  *  Marcin Dalecki (improved performance, shortened code)
  *  ... somebody forgotten?
diff -u --recursive --new-file v2.0.8/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.0.8/linux/drivers/char/keyboard.c	Mon May 13 23:02:48 1996
+++ linux/drivers/char/keyboard.c	Thu Jul 25 20:24:49 1996
@@ -18,6 +18,7 @@
  */
 
 #define KEYBOARD_IRQ 1
+#define DISABLE_KBD_DURING_INTERRUPTS 0
 
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -69,14 +70,6 @@
 #define KBD_DEFLOCK 0
 #endif
 
-/*
- * The default IO slowdown is doing 'inb()'s from 0x61, which should be
- * safe. But as that is the keyboard controller chip address, we do our
- * slowdowns here by doing short jumps: the keyboard controller should
- * be able to keep up
- */
-#define REALLY_SLOW_IO
-#define SLOW_IO_BY_JUMPING
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -337,48 +330,31 @@
 	    e0_keys[scancode - 128];
 }
 
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#if DISABLE_KBD_DURING_INTERRUPTS
+#define disable_keyboard()	do { send_cmd(0xAD); kb_wait(); } while (0)
+#define enable_keyboard()	send_cmd(0xAE)
+#else
+#define disable_keyboard()	/* nothing */
+#define enable_keyboard()	/* nothing */
+#endif
+
+static void handle_scancode(unsigned char scancode)
 {
-	unsigned char scancode, keycode;
+	unsigned char keycode;
 	static unsigned int prev_scancode = 0;   /* remember E0, E1 */
 	char up_flag;				 /* 0 or 0200 */
 	char raw_mode;
-	int status;
 
-	pt_regs = regs;
-	send_cmd(0xAD);		/* disable keyboard */
-	kb_wait();
-	status = inb_p(0x64);
-	if ((status & kbd_read_mask) != 0x01) {
-	  /*
-	   * On some platforms (Alpha XL for one), the init code may leave
-	   *  an interrupt hanging, yet with status indicating no data.
-	   * After making sure that there's no data indicated and its not a
-	   *  mouse interrupt, we will read the data register to clear it.
-	   * If we don't do this, the data reg stays full and will not
-	   *  allow new data or interrupt from the keyboard. Sigh...
-	   */
-	  if (!(status & 0x21)) { /* neither ODS nor OBF */
-	    scancode = inb(0x60); /* read data anyway */
-#if 0
-	    printk(KERN_DEBUG "keyboard: status 0x%x  mask 0x%x  data 0x%x\n",
-		   status, kbd_read_mask, scancode);
-#endif
-	  }
-	  goto end_kbd_intr;
-	}
-	scancode = inb(0x60);
-	mark_bh(KEYBOARD_BH);
 	if (reply_expected) {
 	  /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
 	  /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
 		reply_expected = 0;
 		if (scancode == 0xfa) {
 			acknowledge = 1;
-			goto end_kbd_intr;
+			return;
 		} else if (scancode == 0xfe) {
 			resend = 1;
-			goto end_kbd_intr;
+			return;
 		}
 		/* strange ... */
 		reply_expected = 1;
@@ -392,7 +368,7 @@
 		printk(KERN_INFO "keyboard buffer overflow\n");
 #endif
 		prev_scancode = 0;
-		goto end_kbd_intr;
+		return;
 	}
 	do_poke_blanked_console = 1;
 	mark_bh(CONSOLE_BH);
@@ -417,12 +393,12 @@
 #endif
 #endif
 		prev_scancode = 0;
-		goto end_kbd_intr;
+		return;
 	}
 
 	if (scancode == 0xe0 || scancode == 0xe1) {
 		prev_scancode = scancode;
-		goto end_kbd_intr;
+		return;
  	}
 
  	/*
@@ -439,7 +415,7 @@
 	  if (prev_scancode != 0xe0) {
 	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
 		  prev_scancode = 0x100;
-		  goto end_kbd_intr;
+		  return;
 	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
 		  keycode = E1_PAUSE;
 		  prev_scancode = 0;
@@ -449,7 +425,7 @@
 		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
 #endif
 		  prev_scancode = 0;
-		  goto end_kbd_intr;
+		  return;
 	      }
 	  } else {
 	      prev_scancode = 0;
@@ -467,7 +443,7 @@
 	       *  So, we should also ignore the latter. - aeb@cwi.nl
 	       */
 	      if (scancode == 0x2a || scancode == 0x36)
-		goto end_kbd_intr;
+		return;
 
 	      if (e0_keys[scancode])
 		keycode = e0_keys[scancode];
@@ -477,7 +453,7 @@
 		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
 			   scancode);
 #endif
-		  goto end_kbd_intr;
+		  return;
 	      }
 	  }
 	} else if (scancode >= SC_LIM) {
@@ -500,7 +476,7 @@
 			 " - ignored\n", scancode);
 #endif
 	      }
-	      goto end_kbd_intr;
+	      return;
 	  }
  	} else
 	  keycode = scancode;
@@ -526,12 +502,12 @@
  		rep = set_bit(keycode, key_down);
 
 	if (raw_mode)
-		goto end_kbd_intr;
+		return;
 
 	if (kbd->kbdmode == VC_MEDIUMRAW) {
 		/* soon keycodes will require more than one byte */
  		put_queue(keycode + up_flag);
-		goto end_kbd_intr;
+		return;
  	}
 
  	/*
@@ -592,9 +568,32 @@
 #endif
 		}
 	}
+}
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char status;
 
-end_kbd_intr:
-	send_cmd(0xAE);         /* enable keyboard */
+	pt_regs = regs;
+	disable_keyboard();
+
+	status = inb_p(0x64);
+	do {
+		unsigned char scancode;
+
+		/* mouse data? */
+		if (status & kbd_read_mask & 0x20)
+			break;
+
+		scancode = inb(0x60);
+		if (status & 0x01)
+			handle_scancode(scancode);
+
+		status = inb(0x64);
+	} while (status & 0x01);
+
+	mark_bh(KEYBOARD_BH);
+	enable_keyboard();
 }
 
 static void put_queue(int ch)
diff -u --recursive --new-file v2.0.8/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.0.8/linux/drivers/char/mem.c	Wed Jul  3 22:05:08 1996
+++ linux/drivers/char/mem.c	Thu Jul 25 16:52:13 1996
@@ -176,6 +176,8 @@
 	for (left = count; left > 0; left--) {
 		put_user(0,buf);
 		buf++;
+		if (need_resched)
+			schedule();
 	}
 	return count;
 }
diff -u --recursive --new-file v2.0.8/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.0.8/linux/drivers/char/psaux.c	Tue Jul 23 08:23:12 1996
+++ linux/drivers/char/psaux.c	Tue Jul 23 06:48:28 1996
@@ -25,10 +25,6 @@
  * Rearranged SIGIO support to use code from tty_io.  9Sept95 ctm@ardi.com
  *
  * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
- *
- * Fixed keyboard lockups at open time (intervening kbd interrupts), handle
- * RESEND replies, better error checking
- * 3-Jul-96 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  */
 
 /* Uncomment the following line if your mouse needs initialization. */
@@ -61,10 +57,8 @@
 #define AUX_STATUS	0x64		/* Aux device status reg */
 
 /* aux controller status bits */
-#define AUX_KOBUF_FULL	0x01		/* output buffer (from controller) full */
 #define AUX_OBUF_FULL	0x21		/* output buffer (from device) full */
 #define AUX_IBUF_FULL	0x02		/* input buffer (to device) full */
-#define AUX_TIMEOUT	0x40		/* controller reports timeout */
 
 /* aux controller commands */
 #define AUX_CMD_WRITE	0x60		/* value to write to controller */
@@ -87,14 +81,6 @@
 #define AUX_DISABLE_DEV	0xf5		/* disable aux device */
 #define AUX_RESET	0xff		/* reset aux device */
 
-/* kbd controller commands */
-#define KBD_DISABLE	0xad
-#define KBD_ENABLE	0xae
-
-/* replies */
-#define AUX_ACK		0xfa
-#define AUX_RESEND	0xfe
-
 #define MAX_RETRIES	60		/* some aux operations take long time*/
 #if defined(__alpha__) && !defined(CONFIG_PCI)
 # define AUX_IRQ	9		/* Jensen is odd indeed */
@@ -135,6 +121,7 @@
 static int aux_count = 0;
 static int aux_present = 0;
 static int poll_aux_status(void);
+static int poll_aux_status_nosleep(void);
 static int fasync_aux(struct inode *inode, struct file *filp, int on);
 
 #ifdef CONFIG_82C710_MOUSE
@@ -149,70 +136,49 @@
 
 
 /*
- * Write a byte to the kbd controller and wait for it being processed
+ * Write to aux device
  */
 
-static int aux_write_byte(int val,int port)
+static void aux_write_dev(int val)
 {
-	outb_p(val, port);
-	return poll_aux_status();
+	poll_aux_status();
+	outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);	/* write magic cookie */
+	poll_aux_status();
+	outb_p(val,AUX_OUTPUT_PORT);		/* write data */
 }
 
 /*
- * Write to device, handle returned resend requests and wait for ack
+ * Write to device & handle returned ack
  */
+#if defined INITIALIZE_DEVICE
 static int aux_write_ack(int val)
 {
-	int rv, retries = 0, stat;
+	int retries = 0;
 
-  repeat:
-	if (poll_aux_status() < 0)
-		return -1;
-	outb_p(AUX_MAGIC_WRITE, AUX_COMMAND);
-	if (poll_aux_status() < 0)
-		return -1;
-	outb_p(val, AUX_OUTPUT_PORT);
-
-	if ((rv = poll_aux_status()) < 0)
-		/* timeout */
-		return -1;
-	else if (rv == AUX_RESEND)
-	    /* controller needs last byte again... */
-		goto repeat;
-	else if (rv == AUX_ACK)
-	    /* already got ACK */
-		return 0;
-	else {
-		/* wait for ACK from controller */
-		while (retries < MAX_RETRIES) {
-			stat = inb_p(AUX_STATUS);
-			if ((stat & AUX_OBUF_FULL) == AUX_OBUF_FULL &&
-				inb_p(AUX_INPUT_PORT) == AUX_ACK)
-				return 0;
-			current->state = TASK_INTERRUPTIBLE;
-			current->timeout = jiffies + (5*HZ + 99) / 100;
-			schedule();
-			retries++;
-		}
-		return -1;
+	poll_aux_status_nosleep();
+	outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
+	poll_aux_status_nosleep();
+	outb_p(val,AUX_OUTPUT_PORT);
+	poll_aux_status_nosleep();
+
+	if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
+	{
+		return (inb(AUX_INPUT_PORT));
 	}
+	return 0;
 }
+#endif /* INITIALIZE_DEVICE */
 
 /*
  * Write aux device command
  */
 
-static int aux_write_cmd(int val)
+static void aux_write_cmd(int val)
 {
-	if (poll_aux_status() < 0)
-		return -1;
-	outb_p(AUX_CMD_WRITE, AUX_COMMAND);
-	if (poll_aux_status() < 0)
-		return -1;
-	outb_p(val, AUX_OUTPUT_PORT);
-	if (poll_aux_status() < 0)
-		return -1;
-	return 0;
+	poll_aux_status();
+	outb_p(AUX_CMD_WRITE,AUX_COMMAND);
+	poll_aux_status();
+	outb_p(val,AUX_OUTPUT_PORT);
 }
 
 
@@ -292,19 +258,10 @@
 	fasync_aux(inode, file, 0);
 	if (--aux_count)
 		return;
-	/* disable keyboard to avoid clashes with multi-byte command sequences */
+	aux_write_cmd(AUX_INTS_OFF);		/* disable controller ints */
+	poll_aux_status();
+	outb_p(AUX_DISABLE,AUX_COMMAND);      	/* Disable Aux device */
 	poll_aux_status();
-	if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
-		printk(KERN_ERR "psaux: controller timeout\n");
-	/* disable controller ints */
-	if (aux_write_cmd(AUX_INTS_OFF) < 0)
-		printk(KERN_ERR "psaux: controller timeout\n");
-	/* Disable Aux device */
-	if (aux_write_byte(AUX_DISABLE, AUX_COMMAND) < 0)
-		printk(KERN_ERR "psaux: controller timeout\n");
-	/* re-enable keyboard */
-	if (aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
-		printk(KERN_ERR "psaux: controller timeout\n");
 	free_irq(AUX_IRQ, NULL);
 	MOD_DEC_USE_COUNT;
 }
@@ -349,7 +306,7 @@
 		return -ENODEV;
 	if (aux_count++)
 		return 0;
-	if (poll_aux_status() < 0) {
+	if (!poll_aux_status()) {
 		aux_count--;
 		return -EBUSY;
 	}
@@ -360,27 +317,12 @@
 	}
 	MOD_INC_USE_COUNT;
 	poll_aux_status();
-	/* disable keyboard to avoid clashes with multi-byte command sequences */
-	if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
-		goto open_error;
-	/* Enable Aux in kbd controller */
-	if (aux_write_byte(AUX_ENABLE, AUX_COMMAND) < 0)
-		goto open_error;
-	/* enable aux device */
-	if (aux_write_ack(AUX_ENABLE_DEV) < 0)
-		goto open_error;
-	/* enable controller ints */
-	if (aux_write_cmd(AUX_INTS_ON) < 0)
-		goto open_error;
-	/* re-enable keyboard */
-	if (aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
-		goto open_error;
-
+	outb_p(AUX_ENABLE,AUX_COMMAND);		/* Enable Aux */
+	aux_write_dev(AUX_ENABLE_DEV);		/* enable aux device */
+	aux_write_cmd(AUX_INTS_ON);		/* enable controller ints */
+	poll_aux_status();
 	aux_ready = 0;
 	return 0;
-  open_error:
-	printk( KERN_ERR "psaux: controller timeout\n" );
-	return -EIO;
 }
 
 #ifdef CONFIG_82C710_MOUSE
@@ -436,31 +378,17 @@
 static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count)
 {
 	int i = count;
-	int rv = 0;
-	
-	/* temporary disable keyboard to avoid clashes with multi-byte command
-	 * sequence */
-	if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
-		return -EIO;
 
 	while (i--) {
-		if (poll_aux_status() < 0) {
-			rv = -EIO;
-			break;
-		}
+		if (!poll_aux_status())
+			return -EIO;
 		outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
-		if (poll_aux_status() < 0) {
-			rv = -EIO;
-			break;
-		}
+		if (!poll_aux_status())
+			return -EIO;
 		outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
 	}
-	/* reenable keyboard */
-	if (poll_aux_status() < 0 || aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
-		rv = -EIO;
-
 	inode->i_mtime = CURRENT_TIME;
-	return rv ? rv : count;
+	return count;
 }
 
 
@@ -591,11 +519,13 @@
 		aux_write_ack(AUX_SET_RES);
 		aux_write_ack(3);			/* 8 counts per mm */
 		aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
+		poll_aux_status_nosleep();
 #endif /* INITIALIZE_DEVICE */
-		/* Disable Aux device and its interrupts on the controller */
-		if (aux_write_byte(AUX_DISABLE, AUX_COMMAND) < 0 ||
-		    aux_write_cmd(AUX_INTS_OFF) < 0)
-		    printk(KERN_ERR "psaux: controller timeout\n");
+		outb_p(AUX_DISABLE,AUX_COMMAND);   /* Disable Aux device */
+		poll_aux_status_nosleep();
+		outb_p(AUX_CMD_WRITE,AUX_COMMAND);
+		poll_aux_status_nosleep();             /* Disable interrupts */
+		outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /*  on the controller */
 	}
 	return 0;
 }
@@ -603,7 +533,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	return psaux_init();
+	return psaux_init(); /*?? Bjorn */
 }
 
 void cleanup_module(void)
@@ -615,18 +545,28 @@
 static int poll_aux_status(void)
 {
 	int retries=0;
-	int reply=0;
 
-	while ((inb(AUX_STATUS) & (AUX_KOBUF_FULL|AUX_IBUF_FULL)) &&
-	       retries < MAX_RETRIES) {
+	while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
  		if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
-			reply = inb_p(AUX_INPUT_PORT);
+			inb_p(AUX_INPUT_PORT);
 		current->state = TASK_INTERRUPTIBLE;
 		current->timeout = jiffies + (5*HZ + 99) / 100;
 		schedule();
 		retries++;
 	}
-	return (retries==MAX_RETRIES) ? -1 : reply;
+	return !(retries==MAX_RETRIES);
+}
+
+static int poll_aux_status_nosleep(void)
+{
+	int retries = 0;
+
+	while ((inb(AUX_STATUS)&0x03) && retries < 1000000) {
+ 		if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
+			inb_p(AUX_INPUT_PORT);
+		retries++;
+	}
+	return !(retries == 1000000);
 }
 
 #ifdef CONFIG_82C710_MOUSE
diff -u --recursive --new-file v2.0.8/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.0.8/linux/drivers/char/tty_io.c	Wed Jul  3 22:05:08 1996
+++ linux/drivers/char/tty_io.c	Wed Jul 24 10:53:39 1996
@@ -755,9 +755,48 @@
 	return i;
 }
 
+/*
+ * Split writes up in sane blocksizes to avoid
+ * denial-of-service type attacks
+ */
+static inline int do_tty_write(
+	int (*write)(struct tty_struct *, struct file *, const unsigned char *, unsigned int),
+	struct inode *inode,
+	struct tty_struct *tty,
+	struct file *file,
+	const unsigned char *buf,
+	unsigned int count)
+{
+	int ret = 0, written = 0;
+
+	for (;;) {
+		unsigned int size = PAGE_SIZE*2;
+		if (size > count)
+			size = count;
+		ret = write(tty, file, buf, size);
+		if (ret <= 0)
+			break;
+		count -= ret;
+		written += ret;
+		if (!count)
+			break;
+		ret = -ERESTARTSYS;
+		if (current->signal & ~current->blocked)
+			break;
+		if (need_resched)
+			schedule();
+	}
+	if (written) {
+		inode->i_mtime = CURRENT_TIME;
+		ret = written;
+	}
+	return ret;
+}
+
+
 static int tty_write(struct inode * inode, struct file * file, const char * buf, int count)
 {
-	int i, is_console;
+	int is_console;
 	struct tty_struct * tty;
 
 	is_console = (inode->i_rdev == CONSOLE_DEV);
@@ -781,14 +820,12 @@
 		}
 	}
 #endif
-	if (tty->ldisc.write)
-		/* XXX casts are for what kernel-wide prototypes should be. */
-		i = (tty->ldisc.write)(tty,file,(const unsigned char *)buf,(unsigned int)count);
-	else
-		i = -EIO;
-	if (i > 0)
-		inode->i_mtime = CURRENT_TIME;
-	return i;
+	if (!tty->ldisc.write)
+		return -EIO;
+	return do_tty_write(tty->ldisc.write,
+		inode, tty, file,
+		(const unsigned char *)buf,
+		(unsigned int)count);
 }
 
 /*
diff -u --recursive --new-file v2.0.8/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.0.8/linux/drivers/scsi/ChangeLog.ncr53c8xx	Wed Jul 17 08:12:16 1996
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Tue Jul 23 10:26:41 1996
@@ -1,3 +1,27 @@
+Sun Jul 21  00:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c, README.ncr53c8xx
+	Add the ncr53c8xx_select_queue_depths() function.
+	Set queue_depth to SCSI_NCR_MAX_TAGS (4 by default) for devices that 
+	support tagged command queueing.
+	For other devices, set queue_depth to 1. No need to queue a command 
+	to the driver if this command cannot be sent to the device.
+	Each time the driver hide io requests from the kernel and/or from the 
+	driver, it may break a little (or a lot) optimization algorithms that 
+	try to increase throughput by reordering io requests.
+	It is better to enable the disk write caching to reduce latencies for 
+	write operations, and to trust asynchronous read ahead from the device 
+	and from the kernel that can reduce latencies for read operations, 
+	even when tagged command queuing is not supported or enabled.
+
+Sat Jul 20  20:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c
+	Minor changes:
+	- Problem of "CCB address mismatch" that happens with the 3 versions 
+	  of the driver. The CCB is correct and Stefan Esser suggests a little 
+	  patch that seems to be a bypass.
+	  Stefan says he will change that in a future version of the BSD driver.
+	- Set burst transfers to 8 for 815 chips.
+
 Sun Jul 14  15:00 1996 Gerard Roudier (groudier@club-internet.fr)
 	* ncr53c8xx.c, Configure.help
 	Memory mapped io donnot work under linux/Alpha for the driver.
diff -u --recursive --new-file v2.0.8/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.0.8/linux/drivers/scsi/ncr53c8xx.c	Wed Jul 17 08:12:16 1996
+++ linux/drivers/scsi/ncr53c8xx.c	Tue Jul 23 10:26:41 1996
@@ -40,7 +40,7 @@
 */
 
 /*
-**	23 June 1996, version 1.12
+**	21 July 1996, version 1.12b
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -424,6 +424,10 @@
 
 #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f))
 
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
+static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist);
+#endif
+
 #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
 static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
 #else
@@ -3494,6 +3498,9 @@
 	instance->io_port	= io_port;
 	instance->n_io_port	= 128;
 	instance->dma_channel	= 0;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
+	instance->select_queue_depths = ncr53c8xx_select_queue_depths;
+#endif
 
 	/*
 	**	Patch script to physical addresses
@@ -4786,7 +4793,7 @@
 	else
 /**	NCR53C815			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
-		OUTB(nc_dmode, 0x00);	/* Set 2-transfer burst */
+		OUTB(nc_dmode, 0x80);	/* Set 8-transfer burst */
 	}
 	else
 /**	NCR53C825			**/
@@ -5874,7 +5881,7 @@
 	if (cp != np->header.cp) {
 	    printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n", 
 		    ncr_name (np), (u_long) cp, (u_long) np->header.cp);
-	    return;
+/*	    return;*/
 	}
 
 	/*
@@ -7521,6 +7528,30 @@
 		       (int) irq, bus, (uchar) device_fn);
 }
 
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
+/*
+**   Linux select queue depths function
+*/
+static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist)
+{
+	struct scsi_device *device;
+
+	for (device = devlist; device; device = device->next) {
+		if (device->host == host) {
+			if (device->tagged_supported) {
+				device->queue_depth = SCSI_NCR_MAX_TAGS;
+			}
+			else {
+				device->queue_depth = 1;
+			}
+#ifdef DEBUG
+printk("ncr53c8xx_select_queue_depth: id=%d, lun=%d, queue_depth=%d\n",
+	device->id, device->lun, device->queue_depth);
+#endif
+		}
+	}
+}
+#endif
 
 /*
 **   Linux entry point of queuecommand() function
diff -u --recursive --new-file v2.0.8/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.0.8/linux/drivers/scsi/ncr53c8xx.h	Sat Jul  6 14:51:24 1996
+++ linux/drivers/scsi/ncr53c8xx.h	Tue Jul 23 10:26:41 1996
@@ -196,7 +196,7 @@
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
 
-#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12a)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
@@ -207,7 +207,7 @@
 #else
 
 
-#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12a)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
diff -u --recursive --new-file v2.0.8/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.0.8/linux/drivers/scsi/scsi.c	Wed Jul 10 15:20:26 1996
+++ linux/drivers/scsi/scsi.c	Tue Jul 23 10:26:49 1996
@@ -2875,11 +2875,32 @@
     for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
 	host = SDpnt->host;
 
-	if(SDpnt->type != TYPE_TAPE)
+	/*
+	 * sd and sr drivers allocate scatterlists.
+	 * sr drivers may allocate for each command 1x2048 or 2x1024 extra 
+	 * buffers for 2k sector size and 1k fs.
+	 * sg driver allocates buffers < 4k.
+	 * st driver does not need buffers from the dma pool.
+	 * estimate 4k buffer/command for devices of unknown type (should panic).
+	 */
+	if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM ||
+	    SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) {
 	    new_dma_sectors += ((host->sg_tablesize *
 	                         sizeof(struct scatterlist) + 511) >> 9) *
 	                       SDpnt->queue_depth;
-	
+	    if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM)
+	        new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth;
+	}
+	else if (SDpnt->type == TYPE_SCANNER || SDpnt->type == TYPE_PROCESSOR) {
+	    new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
+	}
+	else {
+	    if (SDpnt->type != TYPE_TAPE) {
+	        printk("resize_dma_pool: unknown device type %d\n", SDpnt->type);
+	        new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
+	    }
+        }
+
 	if(host->unchecked_isa_dma &&
 	   scsi_need_isa_bounce_buffers &&
 	   SDpnt->type != TYPE_TAPE) {
@@ -2888,7 +2909,11 @@
 	    new_need_isa_buffer++;
 	}
     }
-    
+
+#ifdef DEBUG_INIT
+    printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors);
+#endif
+
     /* limit DMA memory to 32MB: */
     new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
     
@@ -2945,6 +2970,12 @@
     dma_sectors = new_dma_sectors;
     need_isa_buffer = new_need_isa_buffer;
     restore_flags(flags);
+
+#ifdef DEBUG_INIT
+    printk("resize_dma_pool: dma free sectors   = %d\n", dma_free_sectors);
+    printk("resize_dma_pool: dma sectors        = %d\n", dma_sectors);
+    printk("resize_dma_pool: need isa buffers   = %d\n", need_isa_buffer);
+#endif
 }
 
 #ifdef CONFIG_MODULES		/* a big #ifdef block... */
diff -u --recursive --new-file v2.0.8/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.0.8/linux/drivers/sound/dmabuf.c	Sat Jul  6 14:51:26 1996
+++ linux/drivers/sound/dmabuf.c	Tue Jul 23 10:26:49 1996
@@ -582,7 +582,7 @@
       if (!audio_devs[dev]->go)
 	tmout = 0;
       else
-	tmout = 2 * HZ;
+	tmout = 10 * HZ;
 
 
       {
diff -u --recursive --new-file v2.0.8/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v2.0.8/linux/drivers/sound/pss.c	Sat Jul  6 14:51:27 1996
+++ linux/drivers/sound/pss.c	Tue Jul 23 10:26:53 1996
@@ -832,7 +832,9 @@
 void
 unload_pss_mpu (struct address_info *hw_config)
 {
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   unload_mpu401 (hw_config);
+#endif
 }
 
 void
diff -u --recursive --new-file v2.0.8/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.0.8/linux/fs/affs/inode.c	Tue May 21 19:52:37 1996
+++ linux/fs/affs/inode.c	Thu Jul 25 09:08:28 1996
@@ -44,16 +44,26 @@
 	lock_super(sb);
 	for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
 		affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
-	ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
-	secs_to_datestamp(CURRENT_TIME,&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
-	affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
-	mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
+	if (!(sb->s_flags & MS_RDONLY)) {
+		ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
+		secs_to_datestamp(CURRENT_TIME,
+				  &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
+		affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
+		mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
+	}
 
 	if (sb->u.affs_sb.s_flags & SF_PREFIX)
 		kfree(sb->u.affs_sb.s_prefix);
 	kfree(sb->u.affs_sb.s_bitmap);
 	affs_brelse(sb->u.affs_sb.s_root_bh);
+
+	/* I'm not happy with this. It would be better to save the previous
+	 * value of this devices blksize_size[][] in the super block and
+	 * restore it here, but with the affs superblock being quite large
+	 * already ...
+	 */
 	set_blocksize(sb->s_dev,BLOCK_SIZE);
+
 	sb->s_dev = 0;
 	unlock_super(sb);
 	MOD_DEC_USE_COUNT;
@@ -63,13 +73,8 @@
 static void
 affs_write_super(struct super_block *sb)
 {
-	int			 i, clean = 2;
+	int	 i, clean = 2;
 
-	if ((sb->u.affs_sb.s_flags & SF_USE_MP) && !sb->u.affs_sb.s_uid && sb->s_covered) {
-		sb->s_mounted->i_uid = sb->u.affs_sb.s_uid = sb->s_covered->i_uid;
-		sb->s_mounted->i_gid = sb->u.affs_sb.s_gid = sb->s_covered->i_gid;
-		sb->u.affs_sb.s_flags &= ~SF_USE_MP;
-	}
 	if (!(sb->s_flags & MS_RDONLY)) {
 		lock_super(sb);
 		for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {
@@ -149,13 +154,6 @@
 			}
 			*mount_opts |= SF_IMMUTABLE;
 		}
-		if (!strcmp(this_char,"usemp")) {
-			if (value) {
-				printk("AFFS: option usemp does not take an argument\n");
-				return 0;
-			}
-			*mount_opts |= SF_USE_MP;
-		}
 		else if (!strcmp(this_char,"verbose")) {
 			if (value) {
 				printk("AFFS: option verbose does not take an argument\n");
@@ -380,6 +378,16 @@
 	bb = affs_bread(dev,0,s->s_blocksize);
 	if (bb) {
 		chksum = htonl(*(__u32 *)bb->b_data);
+
+		/* Dircache filesystems are compatible with non-dircache ones
+		 * when reading. As long as they aren't supported, writing is
+		 * not recommended.
+		 */
+		if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
+		     || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {
+			printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev));
+			s->s_flags |= MS_RDONLY;
+		}
 		switch (chksum) {
 			case MUFS_FS:
 			case MUFS_INTLFFS:
@@ -388,9 +396,11 @@
 			case FS_INTLFFS:
 				s->u.affs_sb.s_flags |= SF_INTL;
 				break;
+			case MUFS_DCFFS:
 			case MUFS_FFS:
 				s->u.affs_sb.s_flags |= SF_MUFS;
 				break;
+			case FS_DCFFS:
 			case FS_FFS:
 				break;
 			case MUFS_OFS:
@@ -399,20 +409,13 @@
 			case FS_OFS:
 				s->u.affs_sb.s_flags |= SF_OFS;
 				break;
+			case MUFS_DCOFS:
 			case MUFS_INTLOFS:
 				s->u.affs_sb.s_flags |= SF_MUFS;
-				/* fall thru */
+			case FS_DCOFS:
 			case FS_INTLOFS:
 				s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
 				break;
-			case FS_DCOFS:
-			case FS_DCFFS:
-			case MUFS_DCOFS:
-			case MUFS_DCFFS:
-				if (!silent)
-					printk("AFFS: Unsupported filesystem on device %s: %08X\n",
-					        kdevname(dev),chksum);
-				if (0)
 			default:
 				printk("AFFS: Unknown filesystem on device %s: %08X\n",
 				       kdevname(dev),chksum);
@@ -432,8 +435,8 @@
 		       (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
 	}
 
-	s->s_magic = AFFS_SUPER_MAGIC;
-	s->s_flags = MS_NODEV | MS_NOSUID;
+	s->s_magic  = AFFS_SUPER_MAGIC;
+	s->s_flags |= MS_NODEV | MS_NOSUID;
 
 	/* Keep super block in cache */
 	if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) {
@@ -587,6 +590,7 @@
 	affs_brelse(s->u.affs_sb.s_root_bh);
 	if (s->u.affs_sb.s_bitmap)
 		kfree(s->u.affs_sb.s_bitmap);
+	set_blocksize(dev,BLOCK_SIZE);
 	s->s_dev = 0;
 	unlock_super(s);
 	MOD_DEC_USE_COUNT;
@@ -787,7 +791,7 @@
 					gid = inode->i_gid ^ ~0;
 			}
 			if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETUID))
-				file_end->owner_gid = ntohs(uid);
+				file_end->owner_uid = ntohs(uid);
 			if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETGID))
 				file_end->owner_gid = ntohs(gid);
 		}
diff -u --recursive --new-file v2.0.8/linux/fs/inode.c linux/fs/inode.c
--- v2.0.8/linux/fs/inode.c	Fri Apr 19 10:08:01 1996
+++ linux/fs/inode.c	Wed Jul 24 07:03:07 1996
@@ -476,20 +476,11 @@
 	return;
 }
 
-static inline unsigned long value(struct inode * inode)
-{
-	if (inode->i_lock)  
-		return 1000;
-	if (inode->i_dirt)
-		return 1000;
-	return inode->i_nrpages;
-}
-
 struct inode * get_empty_inode(void)
 {
 	static int ino = 0;
 	struct inode * inode, * best;
-	unsigned long badness = 1000;
+	unsigned long badness;
 	int i;
 
 	if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1))
@@ -497,50 +488,54 @@
 repeat:
 	inode = first_inode;
 	best = NULL;
+	badness = 1000;
 	for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
 		if (!inode->i_count) {
-			unsigned long i = value(inode);
+			unsigned long i = 999;
+			if (!(inode->i_lock | inode->i_dirt))
+				i = inode->i_nrpages;
 			if (i < badness) {
 				best = inode;
-				if ((badness = i) == 0)
-					break;
+				if (!i)
+					goto found_good;
+				badness = i;
 			}
 		}
 	}
-	if (badness)
-		if (nr_inodes < max_inodes) {
-			if (grow_inodes() == 0)
-				goto repeat;
-		}
-	inode = best;
-	if (!inode) {
+	if (nr_inodes < max_inodes) {
+		if (grow_inodes() == 0)
+			goto repeat;
+		best = NULL;
+	}
+	if (!best) {
 		printk("VFS: No free inodes - contact Linus\n");
 		sleep_on(&inode_wait);
 		goto repeat;
 	}
-	if (inode->i_lock) {
-		wait_on_inode(inode);
+	if (best->i_lock) {
+		wait_on_inode(best);
 		goto repeat;
 	}
-	if (inode->i_dirt) {
-		write_inode(inode);
+	if (best->i_dirt) {
+		write_inode(best);
 		goto repeat;
 	}
-	if (inode->i_count)
+	if (best->i_count)
 		goto repeat;
-	clear_inode(inode);
-	inode->i_count = 1;
-	inode->i_nlink = 1;
-	inode->i_version = ++event;
-	inode->i_sem.count = 1;
-	inode->i_ino = ++ino;
-	inode->i_dev = 0;
+found_good:
+	clear_inode(best);
+	best->i_count = 1;
+	best->i_nlink = 1;
+	best->i_version = ++event;
+	best->i_sem.count = 1;
+	best->i_ino = ++ino;
+	best->i_dev = 0;
 	nr_free_inodes--;
 	if (nr_free_inodes < 0) {
 		printk ("VFS: get_empty_inode: bad free inode count.\n");
 		nr_free_inodes = 0;
 	}
-	return inode;
+	return best;
 }
 
 struct inode * get_pipe_inode(void)
diff -u --recursive --new-file v2.0.8/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.0.8/linux/fs/isofs/dir.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/isofs/dir.c	Tue Jul 23 10:26:40 1996
@@ -5,9 +5,11 @@
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
  *
+ *  Steve Beynon		       : Missing last directory entries fixed
+ *  (stephen@askone.demon.co.uk)      : 21st June 1996
+ * 
  *  isofs directory handling functions
  */
-
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/iso_fs.h>
@@ -133,9 +135,13 @@
 #ifdef DEBUG
 		printk("Block, offset, f_pos: %x %x %x\n",
 		       block, offset, filp->f_pos);
+	        printk("inode->i_size = %x\n",inode->i_size);
 #endif
 		/* Next directory_record on next CDROM sector */
 		if (offset >= bufsize) {
+#ifdef DEBUG
+		        printk("offset >= bufsize\n");
+#endif
 			brelse(bh);
 			offset = 0;
 			block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
@@ -151,6 +157,10 @@
 		inode_number = (block << bufbits) + (offset & (bufsize - 1));
 
 		de_len = *(unsigned char *) de;
+#ifdef DEBUG
+		printk("de_len = %ld\n", de_len);
+#endif
+	    
 
 		/* If the length byte is zero, we should move on to the next
 		   CDROM sector.  If we are at the end of the directory, we
@@ -175,15 +185,31 @@
 		   If not, put the two halves together in "tmpde" */
 		next_offset = offset + de_len;
 		if (next_offset > bufsize) {
+#ifdef DEBUG
+		        printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
+#endif
 			next_offset &= (bufsize - 1);
-			memcpy(tmpde, de, bufsize - offset);
+		        memcpy(tmpde, de, bufsize - offset);
 			brelse(bh);
 			block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
 			if (!block)
+		        {
 				return 0;
-			bh = breada(inode->i_dev, block, bufsize, filp->f_pos+de_len, inode->i_size);
+			}
+		  
+			bh = breada(inode->i_dev, block, bufsize, 
+				    filp->f_pos, 
+				    inode->i_size);
 			if (!bh)
+		        {
+#ifdef DEBUG
+                 		printk("!bh block=%ld, bufsize=%ld\n",block,bufsize); 
+ 				printk("filp->f_pos = %ld\n",filp->f_pos);
+				printk("inode->i_size = %ld\n", inode->i_size);
+#endif
 				return 0;
+			}
+		  
 			memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
 			de = tmpde;
 		}
diff -u --recursive --new-file v2.0.8/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.0.8/linux/fs/isofs/inode.c	Sat Jun  1 20:11:33 1996
+++ linux/fs/isofs/inode.c	Tue Jul 23 10:27:00 1996
@@ -189,7 +189,7 @@
 	  printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 	}
 #endif 0
-      if ((i==0)&&(ms_info.xa_flag)) vol_desc_start=ms_info.addr.lba;
+      if (i==0) vol_desc_start=ms_info.addr.lba;
     }
   return vol_desc_start;
 }
diff -u --recursive --new-file v2.0.8/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- v2.0.8/linux/include/asm-m68k/ide.h	Tue Apr 23 13:57:12 1996
+++ linux/include/asm-m68k/ide.h	Tue Jul 23 11:33:32 1996
@@ -62,6 +62,31 @@
 #undef HD_DATA
 #define HD_DATA NULL
 
+/* MSch: changed sti() to STI() wherever possible in ide.c; moved STI() def. 
+ * to asm/ide.h 
+ */
+/* The Atari interrupt structure strictly requires that the IPL isn't lowered
+ * uncontrolled in an interrupt handler. In the concrete case, the IDE
+ * interrupt is already a slow int, so the irq is already disabled at the time
+ * the handler is called, and the IPL has been lowered to the minimum value
+ * possible. To avoid going below that, STI() checks for being called inside
+ * an interrupt, and in that case it does nothing. Hope that is reasonable and
+ * works. (Roman)
+ */
+#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA)
+#define	STI()					\
+    do {					\
+	if (!intr_count) sti();			\
+    } while(0)
+#elif defined(CONFIG_ATARI)
+#define	STI()						\
+    do {						\
+	if (!MACH_IS_ATARI || !intr_count) sti();	\
+    } while(0)
+#else /* !defined(CONFIG_ATARI) */
+#define	STI()	sti()
+#endif
+
 #define SELECT_DRIVE(hwif,drive)  OUT_BYTE((drive)->select.all, hwif->io_base+IDE_SELECT_OFFSET);
 
 #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, wcount<<1)
diff -u --recursive --new-file v2.0.8/linux/include/linux/affs_fs_sb.h linux/include/linux/affs_fs_sb.h
--- v2.0.8/linux/include/linux/affs_fs_sb.h	Tue May 21 19:52:37 1996
+++ linux/include/linux/affs_fs_sb.h	Thu Jul 25 09:08:28 1996
@@ -64,7 +64,6 @@
 #define SF_SETUID	0x0010		/* Ignore Amiga uid */
 #define SF_SETGID	0x0020		/* Ignore Amiga gid */
 #define SF_SETMODE	0x0040		/* Ignore Amiga protection bits */
-#define SF_USE_MP	0x0080		/* Use uid and gid from mount point */
 #define SF_MUFS		0x0100		/* Use MUFS uid/gid mapping */
 #define SF_OFS		0x0200		/* Old filesystem */
 #define SF_PREFIX	0x0400		/* Buffer for prefix is allocated */
diff -u --recursive --new-file v2.0.8/linux/ipc/shm.c linux/ipc/shm.c
--- v2.0.8/linux/ipc/shm.c	Sat Apr 27 15:20:07 1996
+++ linux/ipc/shm.c	Tue Jul 23 10:26:53 1996
@@ -467,6 +467,7 @@
 	int err;
 	unsigned int id;
 	unsigned long addr;
+	unsigned long len;
 
 	if (shmid < 0) {
 		/* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */
@@ -490,6 +491,12 @@
 		else
 			return -EINVAL;
 	}
+	/*
+	 * Check if addr exceeds TASK_SIZE (from do_mmap)
+	 */
+	len = PAGE_SIZE*shp->shm_npages;
+       if (addr >= TASK_SIZE || len > TASK_SIZE  || addr > TASK_SIZE - len)
+		return -EINVAL;
 	/*
 	 * If shm segment goes below stack, make sure there is some
 	 * space left for the stack to grow (presently 4 pages).
diff -u --recursive --new-file v2.0.8/linux/mm/filemap.c linux/mm/filemap.c
--- v2.0.8/linux/mm/filemap.c	Tue Jul 23 08:23:15 1996
+++ linux/mm/filemap.c	Tue Jul 23 10:26:40 1996
@@ -415,7 +415,7 @@
  * Reasonable means, in this context, not too large but not too small.
  * The actual maximum value is:
  *	MAX_READAHEAD + PAGE_SIZE = 76k is CONFIG_READA_SMALL is undefined
- *      and 32K if defined.
+ *      and 32K if defined (4K page size assumed).
  *
  * Asynchronous read-ahead benefits:
  * ---------------------------------
@@ -442,15 +442,17 @@
  * - The total memory pool usage for the file access stream.
  *   This maximum memory usage is implicitly 2 IO read chunks:
  *   2*(MAX_READAHEAD + PAGE_SIZE) = 156K if CONFIG_READA_SMALL is undefined,
- *   64k if defined.
+ *   64k if defined (4K page size assumed).
  */
 
-#if 0 /* small readahead */
-#define MAX_READAHEAD (PAGE_SIZE*7)
-#define MIN_READAHEAD (PAGE_SIZE*2)
-#else
-#define MAX_READAHEAD (PAGE_SIZE*18)
-#define MIN_READAHEAD (PAGE_SIZE*3)
+#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
+
+#if 0  /* small readahead */
+#define MAX_READAHEAD PageAlignSize(4096*7)
+#define MIN_READAHEAD PageAlignSize(4096*2)
+#else /* large readahead */
+#define MAX_READAHEAD PageAlignSize(4096*18)
+#define MIN_READAHEAD PageAlignSize(4096*3)
 #endif
 
 static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode,
diff -u --recursive --new-file v2.0.8/linux/mm/memory.c linux/mm/memory.c
--- v2.0.8/linux/mm/memory.c	Tue Jul 23 08:23:15 1996
+++ linux/mm/memory.c	Tue Jul 23 14:03:43 1996
@@ -756,26 +756,6 @@
 	return -EFAULT;
 }
 
-static inline void get_empty_page(struct task_struct * tsk, struct vm_area_struct * vma,
-	pte_t * page_table, int write_access)
-{
-	pte_t pte;
-
-	pte = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot));
-	if (write_access) {
-		unsigned long page = get_free_page(GFP_KERNEL);
-		pte = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-		vma->vm_mm->rss++;
-		tsk->min_flt++;
-		if (!page) {
-			oom(tsk);
-			pte = BAD_PAGE;
-		}
-		flush_page_to_ram(page);
-	}
-	put_page(page_table, pte);
-}
-
 /*
  * This function zeroes out partial mmap'ed pages at truncation time..
  */
@@ -886,6 +866,9 @@
  * tries to share with existing pages, but makes a separate copy if
  * the "write_access" parameter is true in order to avoid the next
  * page fault.
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
  */
 void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
 	unsigned long address, int write_access)
@@ -938,21 +921,29 @@
 		entry = pte_mkwrite(pte_mkdirty(entry));
 	} else if (mem_map[MAP_NR(page)].count > 1 && !(vma->vm_flags & VM_SHARED))
 		entry = pte_wrprotect(entry);
-	flush_cache_page(vma, address);
 	put_page(page_table, entry);
 	/* no need to invalidate: a not-present page shouldn't be cached */
 	return;
 
+anonymous_page:
+	entry = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot));
+	if (write_access) {
+		unsigned long page = __get_free_page(GFP_KERNEL);
+		if (!page)
+			goto sigbus;
+		memset((void *) page, 0, PAGE_SIZE);
+		entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+		vma->vm_mm->rss++;
+		tsk->min_flt++;
+		flush_page_to_ram(page);
+	}
+	put_page(page_table, entry);
+	return;
+
 sigbus:
 	force_sig(SIGBUS, current);
-	flush_cache_page(vma, address);
 	put_page(page_table, BAD_PAGE);
 	/* no need to invalidate, wasn't present */
-	return;
-
-anonymous_page:
-	flush_cache_page(vma, address);
-	get_empty_page(tsk, vma, page_table, write_access);
 	return;
 
 swap_page:
