diff -u --recursive --new-file v2.1.97/linux/Makefile linux/Makefile
--- v2.1.97/linux/Makefile	Thu Apr 23 20:21:27 1998
+++ linux/Makefile	Tue Apr 21 16:29:21 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 97
+SUBLEVEL = 98
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
diff -u --recursive --new-file v2.1.97/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.1.97/linux/arch/alpha/Makefile	Wed Apr  1 20:11:47 1998
+++ linux/arch/alpha/Makefile	Thu Apr 23 11:41:17 1998
@@ -37,11 +37,9 @@
 $(shell rm -f ./GAS_VER)
 
 ifneq ($(OLD_GAS),yes)
- CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE
-
 # if PYXIS, then enable use of BWIO space
  ifeq ($(CONFIG_ALPHA_PYXIS),y)
-  CFLAGS := $(CFLAGS) -DBWIO_ENABLED
+  CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED
  endif
 endif
 
diff -u --recursive --new-file v2.1.97/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.97/linux/arch/i386/kernel/irq.c	Fri Apr 10 13:03:48 1998
+++ linux/arch/i386/kernel/irq.c	Wed Apr 22 18:42:45 1998
@@ -337,7 +337,7 @@
 		if (IO_APIC_IRQ(i))
 			p += sprintf(p, " IO-APIC ");
 		else
-			p += sprintf(p, "  XT PIC ");
+			p += sprintf(p, "  XT-PIC ");
 		p += sprintf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next) {
@@ -669,7 +669,6 @@
  */
 static void disable_8259A_irq(unsigned int irq)
 {
-	disabled_irq[irq]++;
 	cached_irq_mask |= 1 << irq;
 	set_8259A_irq_mask(irq);
 }
@@ -677,7 +676,7 @@
 #ifdef __SMP__
 static void disable_ioapic_irq(unsigned int irq)
 {
-	disabled_irq[irq]++;
+	disabled_irq[irq] = 1;
 	/*
 	 * We do not disable IO-APIC irqs in hardware ...
 	 */
@@ -688,12 +687,6 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	if (disabled_irq[irq])
-		disabled_irq[irq]--;
-	else {
-		spin_unlock_irqrestore(&irq_controller_lock, flags);
-		return;
-	}
 	cached_irq_mask &= ~(1 << irq);
 	set_8259A_irq_mask(irq);
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
@@ -706,13 +699,8 @@
 	int cpu = smp_processor_id();
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	if (disabled_irq[irq])
-		disabled_irq[irq]--;
-	else {
-		spin_unlock_irqrestore(&irq_controller_lock, flags);
-		return;
-	}
-#if 0
+	disabled_irq[irq] = 0;
+
 	/*
 	 * In the SMP+IOAPIC case it might happen that there are an unspecified
 	 * number of pending IRQ events unhandled. These cases are very rare,
@@ -720,7 +708,7 @@
 	 * better to do it this way as thus we dont have to be aware of
 	 * 'pending' interrupts in the IRQ path, except at this point.
 	 */
-	if (!disabled_irq[irq] && irq_events[irq]) {
+	if (irq_events[irq]) {
 		if (!ipi_pending[irq]) {
 			ipi_pending[irq] = 1;
 			--irq_events[irq];
@@ -728,36 +716,6 @@
 		}
 	}
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
-#else
-	if (!disabled_irq[irq] && irq_events[irq]) {
-		struct pt_regs regs; /* FIXME: these are fake currently */
-
-		disabled_irq[irq]++;
-		hardirq_enter(cpu);
-		spin_unlock(&irq_controller_lock);
-
-		release_irqlock(cpu);
-		while (test_bit(0,&global_irq_lock)) mb();
-again:
-		handle_IRQ_event(irq, &regs);
-
-		spin_lock(&irq_controller_lock);
-		disabled_irq[irq]--;
-		should_handle_irq=0;
-		if (--irq_events[irq] && !disabled_irq[irq]) {
-			should_handle_irq=1;
-			disabled_irq[irq]++;
-		}
-		spin_unlock(&irq_controller_lock);
-
-		if (should_handle_irq)
-			goto again;
-
-		irq_exit(cpu, irq);
-		__restore_flags(flags);
-	} else
-		spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
 }
 #endif
 
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.1.97/linux/arch/ppc/8xx_io/commproc.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/8xx_io/commproc.c	Thu Apr 23 15:57:01 1998
@@ -21,7 +21,6 @@
  * applications that require more DP ram, we can expand the boundaries
  * but then we have to be careful of any downloaded microcode.
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.1.97/linux/arch/ppc/8xx_io/enet.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/8xx_io/enet.c	Thu Apr 23 15:57:04 1998
@@ -21,7 +21,6 @@
  * small packets.
  *
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.1.97/linux/arch/ppc/boot/head.S	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/boot/head.S	Thu Apr 23 15:57:04 1998
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include "../kernel/ppc_defs.h"
 #include "../kernel/ppc_asm.tmpl"
 #include <asm/processor.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.1.97/linux/arch/ppc/kernel/idle.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/idle.c	Thu Apr 23 15:57:04 1998
@@ -13,6 +13,7 @@
  */
 #define __KERNEL_SYSCALLS__
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.1.97/linux/arch/ppc/kernel/misc.S	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/misc.S	Thu Apr 23 15:57:05 1998
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/sys.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.1.97/linux/arch/ppc/kernel/pmac_pci.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/pmac_pci.c	Thu Apr 23 15:57:05 1998
@@ -12,6 +12,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.1.97/linux/arch/ppc/kernel/ppc_htab.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/ppc_htab.c	Thu Apr 23 15:57:05 1998
@@ -12,6 +12,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.1.97/linux/arch/ppc/kernel/softemu8xx.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/softemu8xx.c	Thu Apr 23 15:57:05 1998
@@ -25,7 +25,6 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
-#include <linux/config.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.1.97/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.1.97/linux/arch/ppc/kernel/time.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/time.c	Thu Apr 23 15:57:05 1998
@@ -19,6 +19,7 @@
  * creating a software PLL, I have set HZ to 128.  -- Dan
  */
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.97/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.1.97/linux/arch/sparc/kernel/smp.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/smp.c	Thu Apr 23 15:57:05 1998
@@ -4,7 +4,6 @@
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <linux/config.h> /* for CONFIG_PROFILE */
 #include <asm/head.h>
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.97/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.1.97/linux/arch/sparc/kernel/sun4c_irq.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/sun4c_irq.c	Thu Apr 23 15:57:05 1998
@@ -9,7 +9,6 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
-#include <linux/config.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.97/linux/drivers/block/ide.c	Tue Apr 14 14:29:20 1998
+++ linux/drivers/block/ide.c	Wed Apr 22 12:15:31 1998
@@ -1118,10 +1118,9 @@
  * conditions in the event that an unexpected interrupt occurs while
  * we are in the driver.
  *
- * Note that when an interrupt is used to reenter the driver, the first level
- * handler will already have masked the irq that triggered, but any other ones
- * for the hwgroup will still be unmasked.  The driver tries to be careful
- * about such things.
+ * Note that the io-request lock will guarantee that the driver never gets
+ * re-entered even on another interrupt level, so we no longer need to
+ * mask the irq's.
  */
 static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
 {
@@ -1132,13 +1131,7 @@
 		del_timer(&hwgroup->timer);
 		ide_get_lock(&ide_lock, ide_intr, hwgroup);
 		hwgroup->active = 1;
-		do {
-			disable_irq(hwif->irq);
-		} while ((hwif = hwif->next) != hgif);
 		ide_do_request (hwgroup);
-		do {
-			enable_irq(hwif->irq);
-		} while ((hwif = hwif->next) != hgif);
 	}
 }
 
@@ -1274,10 +1267,6 @@
 	if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
 		return;
 
-	do {
-		if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq))
-			disable_irq(hwif->irq);
-	} while ((hwif = hwif->next) != hwgroup->hwif);
 	if (IDE_IRQ_EQUAL(irq, hwif->irq)
 	    && (handler = hwgroup->handler) != NULL) {
 		ide_drive_t *drive = hwgroup->drive;
@@ -1309,10 +1298,6 @@
 	}
 	__cli();
 	hwif = hwgroup->hwif;
-	do {
-		if (!IDE_IRQ_EQUAL(hwif->irq, irq))
-			enable_irq(hwif->irq);
-	} while ((hwif = hwif->next) != hwgroup->hwif);
 }
 
 /*
diff -u --recursive --new-file v2.1.97/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.97/linux/drivers/char/lp.c	Thu Apr 23 20:21:32 1998
+++ linux/drivers/char/lp.c	Thu Apr 23 15:55:57 1998
@@ -658,7 +658,7 @@
 
 #else
 
-static int parport[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int parport_nr[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
 static int reset __initdata = 0;
 
 static int parport_ptr = 0;
@@ -668,21 +668,21 @@
 	if (!str) {
 		if (ints[0] == 0 || ints[1] == 0) {
 			/* disable driver on "lp=" or "lp=0" */
-			parport[0] = LP_PARPORT_OFF;
+			parport_nr[0] = LP_PARPORT_OFF;
 		} else {
 			printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
 		}
 	} else if (!strncmp(str, "parport", 7)) {
 		int n = simple_strtoul(str+7, NULL, 10);
 		if (parport_ptr < LP_NO)
-			parport[parport_ptr++] = n;
+			parport_nr[parport_ptr++] = n;
 		else
 			printk(KERN_INFO "lp: too many ports, %s ignored.\n",
 			       str);
 	} else if (!strcmp(str, "auto")) {
-		parport[0] = LP_PARPORT_AUTO;
+		parport_nr[0] = LP_PARPORT_AUTO;
 	} else if (!strcmp(str, "none")) {
-		parport[parport_ptr++] = LP_PARPORT_NONE;
+		parport_nr[parport_ptr++] = LP_PARPORT_NONE;
 	} else if (!strcmp(str, "reset")) {
 		reset = 1;
 	}
diff -u --recursive --new-file v2.1.97/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.1.97/linux/drivers/macintosh/macserial.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/macserial.c	Thu Apr 23 15:57:05 1998
@@ -7,6 +7,7 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/misc/parport_procfs.c linux/drivers/misc/parport_procfs.c
--- v2.1.97/linux/drivers/misc/parport_procfs.c	Wed Apr  8 19:36:26 1998
+++ linux/drivers/misc/parport_procfs.c	Thu Apr 23 15:59:18 1998
@@ -100,10 +100,6 @@
 out_ok:
 	pp->irq = newirq;
 
-	if (oldirq != PARPORT_IRQ_NONE && newirq == PARPORT_IRQ_NONE &&
-	    cad && cad->irq_func)
-		cad->irq_func(pp->irq, cad->private, NULL);
-
 out:
 	return retval;
 }
diff -u --recursive --new-file v2.1.97/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.1.97/linux/drivers/misc/parport_share.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/misc/parport_share.c	Wed Apr 22 19:01:06 1998
@@ -34,7 +34,7 @@
 
 #undef PARPORT_PARANOID
 
-#define PARPORT_DEFAULT_TIMESLICE	(HZ/10)
+#define PARPORT_DEFAULT_TIMESLICE	(HZ/5)
 
 static struct parport *portlist = NULL, *portlist_tail = NULL;
 static int portcount = 0;
diff -u --recursive --new-file v2.1.97/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.1.97/linux/drivers/net/sunlance.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/net/sunlance.c	Thu Apr 23 15:57:05 1998
@@ -66,6 +66,7 @@
 static char *lancestr = "LANCE";
 static char *lancedma = "LANCE DMA";
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.97/linux/drivers/pci/pci.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/pci/pci.c	Thu Apr 23 16:00:37 1998
@@ -323,7 +323,7 @@
 	pci_quirks_init();
 #endif
 
-#ifdef CONFIG_PROC
+#ifdef CONFIG_PROC_FS
 	pci_proc_init();
 #endif
 }
diff -u --recursive --new-file v2.1.97/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.1.97/linux/drivers/pci/proc.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/pci/proc.c	Thu Apr 23 15:57:05 1998
@@ -6,6 +6,7 @@
  *	Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c
--- v2.1.97/linux/drivers/sbus/char/bwtwo.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/bwtwo.c	Thu Apr 23 15:57:05 1998
@@ -6,6 +6,7 @@
  * Copyright (C) 1998 Pavel Machek    (pavel@ucw.cz)
  */
 
+#include <linux/config.h>
 #include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/malloc.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/sbus/char/sbuscons.c linux/drivers/sbus/char/sbuscons.c
--- v2.1.97/linux/drivers/sbus/char/sbuscons.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/sbuscons.c	Thu Apr 23 15:57:05 1998
@@ -46,6 +46,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.1.97/linux/drivers/sbus/dvma.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/dvma.c	Thu Apr 23 15:57:05 1998
@@ -3,6 +3,7 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.1.97/linux/drivers/scsi/BusLogic.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/scsi/BusLogic.c	Thu Apr 23 15:58:25 1998
@@ -1124,7 +1124,7 @@
     If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
     Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
   */
-  if (!BusLogic_ProbeOptions.NoProbePCI && pcibios_present())
+  if (!BusLogic_ProbeOptions.NoProbePCI && pci_present())
     {
       if (BusLogic_ProbeOptions.MultiMasterFirst)
 	{
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.1.97/linux/drivers/scsi/eata.c	Tue Apr 14 14:29:22 1998
+++ linux/drivers/scsi/eata.c	Thu Apr 23 15:54:54 1998
@@ -1,6 +1,14 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
- *   
+ *
+ *      18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
+ *          Reworked interrupt handler.
+ *
+ *      11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
+ *          Major reliability improvement: when a batch with overlapping
+ *          requests is detected, requests are queued one at a time
+ *          eliminating any possible board or drive reordering.
+ *
  *      10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
  *          Improved SMP support (if linux version >= 2.1.95).
  *
@@ -8,7 +16,7 @@
  *          Added support for new PCI code and IO-APIC remapping of irqs.
  *          Performance improvement: when sequential i/o is detected,
  *          always use direct sort instead of reverse sort.
- *   
+ *
  *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
  *          io_port is now unsigned long.
  *
@@ -16,7 +24,6 @@
  *          Use new scsi error handling code (if linux version >= 2.1.88).
  *          Use new interrupt code.
  *
- *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
@@ -30,7 +37,7 @@
  *          Use of serial_number_at_timeout in abort and reset processing.
  *          Use of the __initfunc and __initdata macro in setup code.
  *          Minor cleanups in the list_statistics code.
- *          Increased controller busy timeout in order to better support 
+ *          Increased controller busy timeout in order to better support
  *          slow SCSI devices.
  *
  *      24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26
@@ -39,7 +46,7 @@
  *          Fixed data transfer direction for some SCSI opcodes.
  *          Immediate acknowledge to request sense commands.
  *          Linked commands to each disk device are now reordered by elevator
- *          sorting. Rare cases in which reordering of write requests could 
+ *          sorting. Rare cases in which reordering of write requests could
  *          cause wrong results are managed.
  *          Fixed spurious timeouts caused by long simple queue tag sequences.
  *          New command line option (tm:[0-3]) to choose the type of tags:
@@ -105,7 +112,7 @@
  *
  *      28 Jan 1995 rev. 1.14 for linux 1.1.86
  *          Added module support.
- *          Log and do a retry when a disk drive returns a target status 
+ *          Log and do a retry when a disk drive returns a target status
  *          different from zero on a recovered error.
  *
  *      24 Jan 1995 rev. 1.13 for linux 1.1.85
@@ -119,7 +126,7 @@
  *
  *      17 Dec 1994 rev. 1.11 for linux 1.1.74
  *          Use the scsicam_bios_param routine. This allows an easy
- *          migration path from disk partition tables created using 
+ *          migration path from disk partition tables created using
  *          different SCSI drivers and non optimal disk geometry.
  *
  *      15 Dec 1994 rev. 1.10 for linux 1.1.74
@@ -173,10 +180,10 @@
  *  The DPT PM2001 provides only the EATA/PIO interface and hence is not
  *  supported by this driver.
  *
- *  This code has been tested with up to 3 Distributed Processing Technology 
+ *  This code has been tested with up to 3 Distributed Processing Technology
  *  PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers,
  *  in any combination of private and shared IRQ.
- *  PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS 
+ *  PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS
  *  v003.D0, firmware v07G.0).
  *
  *  DPT SmartRAID boards support "Hardware Array" - a group of disk drives
@@ -186,14 +193,14 @@
  *
  *  WARNING: to create a RAID-0 "Hardware Array" you must select "Other Unix"
  *  as the current OS in the DPTMGR "Initial System Installation" menu.
- *  Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0), 
+ *  Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0),
  *  which is not supported by the actual SCSI subsystem.
  *  To get the "Array Group" functionality, the Linux MD driver must be used
  *  instead of the DPT "Array Group" feature.
  *
  *  Multiple ISA, EISA and PCI boards can be configured in the same system.
  *  It is suggested to put all the EISA boards on the same IRQ level, all
- *  the PCI  boards on another IRQ level, while ISA boards cannot share 
+ *  the PCI  boards on another IRQ level, while ISA boards cannot share
  *  interrupts.
  *
  *  If you configure multiple boards on the same IRQ, the interrupt must
@@ -206,7 +213,7 @@
  *  bus, or even if you system has no EISA bus at all.
  *  Do not force any ISA address on EATA PCI boards.
  *
- *  If PCI bios support is configured into the kernel, BIOS32 is used to 
+ *  If PCI bios support is configured into the kernel, BIOS32 is used to
  *  include in the list of i/o ports to be probed all the PCI SCSI controllers.
  *
  *  Due to a DPT BIOS "feature", it might not be possible to force an EISA
@@ -215,11 +222,11 @@
  *
  *  The sequence of detection probes is:
  *
- *  - ISA 0x1F0; 
+ *  - ISA 0x1F0;
  *  - PCI SCSI controllers (only if BIOS32 is available);
  *  - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15);
  *  - ISA  0x170, 0x230, 0x330.
- * 
+ *
  *  The above list of detection probes can be totally replaced by the
  *  boot command line option: "eata=port0,port1,port2,...", where the
  *  port0, port1... arguments are ISA/EISA/PCI addresses to be probed.
@@ -261,15 +268,15 @@
  *  in the elevator sorting queue. When the active command completes, the
  *  commands in this queue are sorted by sector address. The sort is chosen
  *  between increasing or decreasing by minimizing the seek distance between
- *  the sector of the commands just completed and the sector of the first 
- *  command in the list to be sorted. 
+ *  the sector of the commands just completed and the sector of the first
+ *  command in the list to be sorted.
  *  Trivial math assures that the unsorted average seek distance when doing
  *  random seeks over S sectors is S/3.
  *  When (Q-1) requests are uniformly distributed over S sectors, the average
  *  distance between two adjacent requests is S/((Q-1) + 1), so the sorted
  *  average seek distance for (Q-1) random requests over S sectors is S/Q.
  *  The elevator sorting hence divides the seek distance by a factor Q/3.
- *  The above pure geometric remarks are valid in all cases and the 
+ *  The above pure geometric remarks are valid in all cases and the
  *  driver effectively reduces the seek distance by the predicted factor
  *  when there are Q concurrent read i/o operations on the device, but this
  *  does not necessarily results in a noticeable performance improvement:
@@ -277,7 +284,7 @@
  *
  *  Note: command reordering inside a batch of queued commands could cause
  *        wrong results only if there is at least one write request and the
- *        intersection (sector-wise) of all requests is not empty. 
+ *        intersection (sector-wise) of all requests is not empty.
  *        When the driver detects a batch including overlapping requests
  *        (a really rare event) strict serial (pid) order is enforced.
  *  ----------------------------------------------------------------------------
@@ -316,7 +323,11 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
 #include <asm/spinlock.h>
+#endif
+
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -359,7 +370,7 @@
 #undef  DEBUG_RESET
 
 #define MAX_ISA 4
-#define MAX_VESA 0 
+#define MAX_VESA 0
 #define MAX_EISA 15
 #define MAX_PCI 16
 #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
@@ -499,7 +510,7 @@
    unchar target_status;       /* SCSI status received after data transfer */
    unchar unused[2];
    ulong inv_res_len;          /* Number of bytes not transferred */
-   Scsi_Cmnd *SCpnt;           /* Address set in cp */
+   struct mscp *cpp;           /* Address set in cp */
    char mess[12];
    };
 
@@ -515,7 +526,7 @@
            reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
                sg:1,     /* Use Scatter/Gather */
                  :1,
-           interp:1,     /* The controller interprets cp, not the target */ 
+           interp:1,     /* The controller interprets cp, not the target */
              dout:1,     /* Direction of Transfer is Out (Host to Target) */
               din:1;     /* Direction of Transfer is In (Target to Host) */
    unchar sense_len;     /* Request Sense Length */
@@ -535,10 +546,11 @@
    unchar mess[3];       /* Massage to/from Target */
    unchar cdb[12];       /* Command Descriptor Block */
    ulong  data_len;      /* If sg=0 Data Length, if sg=1 sglist length */
-   Scsi_Cmnd *SCpnt;     /* Address to be returned in sp */
+   struct mscp *cpp;     /* Address to be returned in sp */
    ulong  data_address;  /* If sg=0 Data Address, if sg=1 sglist address */
    ulong  sp_addr;       /* Address where sp is DMA'ed when cp completes */
    ulong  sense_addr;    /* Address where Sense Data is DMA'ed on error */
+   Scsi_Cmnd *SCpnt;
    unsigned int index;   /* cp index */
    struct sg_list *sglist;
    };
@@ -558,7 +570,7 @@
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or EISA/PCI */
    unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
-   struct mssp sp[MAX_MAILBOXES];       /* Returned status for this board */
+   struct mssp sp[2];                   /* Returned status for this board */
    };
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -568,7 +580,7 @@
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
 
-static unsigned long io_port[] __initdata = { 
+static unsigned long io_port[] __initdata = {
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -583,11 +595,11 @@
 
    /* MAX_EISA ports */
    0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88,
-   0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 
+   0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88,
 
    /* Other (MAX_ISA - 1) ports */
    0x170,  0x230,  0x330,
- 
+
    /* End of list */
    0x0
    };
@@ -627,7 +639,7 @@
 
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
-   int j, ntag = 0, nuntag = 0, tqd, utqd; 
+   int j, ntag = 0, nuntag = 0, tqd, utqd;
    unsigned long flags;
 
    save_flags(flags);
@@ -792,14 +804,14 @@
    if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE;
 
    /* Read the info structure */
-   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) 
+   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0]))
       return FALSE;
 
    /* Check the controller "EATA" signature */
    if (info.sign != EATA_SIGNATURE) return FALSE;
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
-      printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
+      printk("%s: config structure size (%ld bytes) too short, detaching.\n",
              name, DEV2H(info.data_len));
       return FALSE;
       }
@@ -956,7 +968,7 @@
 
    /* DPT PM2012 does not allow to detect can_queue correctly */
    if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue  < 2) {
-      printk("%s: detect, wrong n. of Mbox %d, fixed.\n",
+      printk("%s: detect, wrong n. of mbox %d, fixed.\n",
              BN(j), sh[j]->can_queue);
       sh[j]->can_queue = MAX_MAILBOXES;
       }
@@ -984,14 +996,14 @@
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
-            sh[j]->sg_tablesize * sizeof(struct sg_list), 
+            sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
          printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
          eata2x_release(sh[j]);
          return FALSE;
          }
-      
-   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
@@ -1032,7 +1044,7 @@
 
    if (protocol_rev == 'C')
       printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\
-             "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest, 
+             "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest,
              info.pci, info.eisa, info.raidnum);
 #endif
 
@@ -1047,8 +1059,8 @@
 
       if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
 
-      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; 
-   
+      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
+
       io_port[i] = 0;
       setup_done = TRUE;
       }
@@ -1099,7 +1111,7 @@
              continue;
 
       /* Reverse the returned address order */
-      io_port[MAX_INT_PARAM + MAX_PCI - k] = 
+      io_port[MAX_INT_PARAM + MAX_PCI - k] =
              (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
       }
 
@@ -1127,7 +1139,7 @@
              continue;
 
       /* Reverse the returned address order */
-      io_port[MAX_INT_PARAM + MAX_PCI - k] = 
+      io_port[MAX_INT_PARAM + MAX_PCI - k] =
              (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
       }
 
@@ -1166,7 +1178,7 @@
       if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
       }
 
-   if (j > 0) 
+   if (j > 0)
       printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
    num_boards = j;
@@ -1197,7 +1209,7 @@
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
-      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 
+      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
       0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
       };
 
@@ -1215,16 +1227,16 @@
    if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
 
    if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
-      SCpnt->result = DID_OK << 16; 
+      SCpnt->result = DID_OK << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 0;
       }
 
-   /* i is the mailbox number, look for the first free mailbox 
+   /* i is the mailbox number, look for the first free mailbox
       starting from last_cp_used */
    i = HD(j)->last_cp_used + 1;
 
@@ -1241,17 +1253,17 @@
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
-      if (HD(j)->in_reset) 
+      if (HD(j)->in_reset)
          printk("%s: qcomm, already in reset.\n", BN(j));
       else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
-               == SCSI_RESET_SUCCESS) 
+               == SCSI_RESET_SUCCESS)
          panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
-      SCpnt->result = DID_BUS_BUSY << 16; 
+      SCpnt->result = DID_BUS_BUSY << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -1261,13 +1273,12 @@
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
 
    /* Set pointer to status packet structure */
-   spp = &HD(j)->sp[i];
-
-   memset(spp, 0, sizeof(struct mssp));
+   spp = &HD(j)->sp[0];
 
    /* The EATA protocol uses Big Endian format */
    cpp->sp_addr = V2DEV(spp);
 
+   cpp->cpp = cpp;
    SCpnt->scsi_done = done;
    cpp->index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
@@ -1297,11 +1308,11 @@
    cpp->one = TRUE;
    cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
-   cpp->lun = SCpnt->lun;  
+   cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer); 
+   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
    cpp->sense_len = sizeof SCpnt->sense_buffer;
-   
+
    if (SCpnt->device->tagged_queue) {
 
       if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] ||
@@ -1341,13 +1352,13 @@
 
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
-      SCpnt->result = DID_ERROR << 16; 
+      SCpnt->result = DID_ERROR << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
              " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
              SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -1373,7 +1384,7 @@
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
-   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", 
+   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
           BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
@@ -1441,7 +1452,7 @@
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
           BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
@@ -1502,10 +1513,10 @@
       if (SCpnt->host_scribble == NULL)
          panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
+      if (*(unsigned int *)SCpnt->host_scribble != i)
          panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
-      if (SCpnt->scsi_done == NULL) 
+      if (SCpnt->scsi_done == NULL)
          panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
@@ -1588,7 +1599,7 @@
    for (i = 0; i < n - 1; i++) {
       k = i;
 
-      for (j = k + 1; j < n; j++) 
+      for (j = k + 1; j < n; j++)
          if (rev) {
             if (sk[j] > sk[k]) k = j;
             }
@@ -1605,7 +1616,7 @@
    return;
    }
 
-static inline void reorder(unsigned int j, unsigned long cursec,
+static inline int reorder(unsigned int j, unsigned long cursec,
                  unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
    Scsi_Cmnd *SCpnt;
    struct mscp *cpp;
@@ -1625,10 +1636,10 @@
       printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
              " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
              ovlcount, readycount, readysorted, sortcount, revcount,
-             seeknosort / (readycount + 1), 
+             seeknosort / (readycount + 1),
              seeksorted / (readycount + 1));
 
-   if (n_ready <= 1) return;
+   if (n_ready <= 1) return FALSE;
 
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
@@ -1645,7 +1656,7 @@
 
       if (sl[n] < sl[n - 1]) s = FALSE;
       if (sl[n] > sl[n - 1]) r = FALSE;
-   
+
       if (link_statistics) {
          if (sl[n] > sl[n - 1])
             seek += sl[n] - sl[n - 1];
@@ -1670,7 +1681,7 @@
       ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
 
       if (!n) continue;
- 
+
       if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
           || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
       }
@@ -1679,9 +1690,9 @@
 
    if (link_statistics) {
       if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
-      batchcount++; readycount += n_ready, seeknosort += seek / 1024; 
+      batchcount++; readycount += n_ready, seeknosort += seek / 1024;
       if (input_only) inputcount++;
-      if (overlap) { ovlcount++; seeksorted += seek / 1024; }
+      if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
       else seeksorted += (iseek + maxsec - minsec) / 1024;
       if (rev && !r)     {  revcount++; readysorted += n_ready; }
       if (!rev && !s)    { sortcount++; readysorted += n_ready; }
@@ -1696,10 +1707,11 @@
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
                 SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
                 SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
-                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), 
+                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->din);
          }
 #endif
+   return overlap;
 }
 
 static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
@@ -1721,13 +1733,13 @@
       il[n_ready++] = k;
       }
 
-   reorder(j, cursec, ihdlr, il, n_ready);
-  
+   if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
+
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
 
       if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
-         printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\
+         printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
                 " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
                 SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
          HD(j)->cp_stat[k] = ABORTING;
@@ -1739,196 +1751,201 @@
 
 }
 
-static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
+static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, c, status, tstatus, reg;
-   unsigned int n, n_ready, il[MAX_MAILBOXES];
-   struct mssp *spp;
+   unsigned int i, k, c, status, tstatus, reg;
+   struct mssp *dspp, *spp;
    struct mscp *cpp;
 
-   /* Check if the interrupt must be processed by this handler */
-   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
- 
    if (sh[j]->irq != irq)
        panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
- 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
-                        HD(j)->iocount);
- 
+
    /* Check if this board need to be serviced */
    if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return;
 
-   n_ready = 0;
-
-   /* Find the mailboxes to be serviced on this board */
-   for (i = 0; i < sh[j]->can_queue; i++) {
-      spp = &HD(j)->sp[i];
+   HD(j)->iocount++;
 
-      /* Check if this mailbox has completed the operation */
-      if (spp->eoc == FALSE) continue;
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-      spp->eoc = FALSE;
-      il[n_ready++] = i;
+   /* Check if this board is still busy */
+   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      reg = inb(sh[j]->io_port + REG_STATUS);
+      printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+      return;
       }
 
+   dspp = &HD(j)->sp[0];
+   spp  = &HD(j)->sp[1];
+
+   /* Make a local copy just before clearing the interrupt indication */
+   memcpy(spp, dspp, sizeof(struct mssp));
+
+   /* Clear the completion flag and cp pointer on the dynamic copy of sp */
+   memset(dspp, 0, sizeof(struct mssp));
+
    /* Read the status register to clear the interrupt indication */
    reg = inb(sh[j]->io_port + REG_STATUS);
 
-   /* Mailbox service loop */
-   for (n = 0; n < n_ready; n++) {
-      i = il[n];
-      spp = &HD(j)->sp[i];
-
-      if (HD(j)->cp_stat[i] == IGNORE) {
-         HD(j)->cp_stat[i] = FREE;
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == LOCKED) {
-         HD(j)->cp_stat[i] = FREE;
-         printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
-                HD(j)->iocount);
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == FREE) {
-         printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
-                HD(j)->iocount);
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == IN_RESET)
-         printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-      else if (HD(j)->cp_stat[i] != IN_USE) 
-         panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", 
-               BN(j), i, HD(j)->cp_stat[i]);
+   /* Reject any sp with supspect data */
+   if (spp->eoc == FALSE) 
+      printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+   if (spp->cpp == NULL) 
+      printk("%s: ihdlr, spp->cpp == NULL,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+   if (spp->eoc == FALSE || spp->cpp == NULL) return;
+
+   cpp = spp->cpp;
+
+   /* Find the mailbox to be serviced on this board */
+   i = cpp - HD(j)->cp;
+
+   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
+                                     || i >= sh[j]->can_queue)
+      panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
+            cpp, HD(j)->cp);
 
+   if (HD(j)->cp_stat[i] == IGNORE) {
+      HD(j)->cp_stat[i] = FREE;
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == LOCKED) {
       HD(j)->cp_stat[i] = FREE;
-      cpp = &HD(j)->cp[i];
-      SCpnt = spp->SCpnt;
+      printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == FREE) {
+      printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == IN_RESET)
+      printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE)
+      panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n",
+            BN(j), i, HD(j)->cp_stat[i]);
+
+   HD(j)->cp_stat[i] = FREE;
+   SCpnt = cpp->SCpnt;
+
+   if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
+
+   if (SCpnt->host_scribble == NULL)
+      panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+            SCpnt->pid, SCpnt);
+
+   if (*(unsigned int *)SCpnt->host_scribble != i)
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
-      if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
+   if (linked_comm && SCpnt->device->queue_depth > 2
+                                     && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
 
-      if (SCpnt != cpp->SCpnt)
-         panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i,
-               SCpnt, cpp->SCpnt);
+   tstatus = status_byte(spp->target_status);
 
-      if (SCpnt->host_scribble == NULL)
-         panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
-               SCpnt->pid, SCpnt);
+   switch (spp->adapter_status) {
+      case ASOK:     /* status OK */
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
-         panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n",
-              BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+         /* Forces a reset if a disk drive keeps returning BUSY */
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
+            status = DID_ERROR << 16;
 
-      if (linked_comm && SCpnt->device->queue_depth > 2
-                                        && TLDEV(SCpnt->device->type))
-      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
+         /* If there was a bus reset, redo operation on each target */
+         else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                  && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+            status = DID_BUS_BUSY << 16;
+
+         /* Works around a flaw in scsi.c */
+         else if (tstatus == CHECK_CONDITION
+                  && SCpnt->device->type == TYPE_DISK
+                  && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+            status = DID_BUS_BUSY << 16;
 
-      tstatus = status_byte(spp->target_status);
+         else
+            status = DID_OK << 16;
 
-      switch (spp->adapter_status) {
-         case ASOK:     /* status OK */
+         if (tstatus == GOOD)
+            HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
+
+         if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+            printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j),
+                   SCpnt->channel, SCpnt->target, SCpnt->lun,
+                   SCpnt->pid, spp->target_status,
+                   SCpnt->sense_buffer[2]);
+
+         HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
+
+         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+
+         break;
+      case ASST:     /* Selection Time Out */
+      case 0x02:     /* Command Time Out   */
 
-            /* Forces a reset if a disk drive keeps returning BUSY */
-            if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-               status = DID_ERROR << 16;
-
-            /* If there was a bus reset, redo operation on each target */
-            else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-                     && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-               status = DID_BUS_BUSY << 16;
-
-            /* Works around a flaw in scsi.c */
-            else if (tstatus == CHECK_CONDITION
-                     && SCpnt->device->type == TYPE_DISK
-                     && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-               status = DID_BUS_BUSY << 16;
-
-            else
-               status = DID_OK << 16;
-
-            if (tstatus == GOOD)
-               HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-
-            if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-               printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                      "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-                      SCpnt->channel, SCpnt->target, SCpnt->lun, 
-                      SCpnt->pid, spp->target_status, 
-                      SCpnt->sense_buffer[2]);
-
-            HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-
-            if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
-
-            break;
-         case ASST:     /* Selection Time Out */
-         case 0x02:     /* Command Time Out   */
-
-            if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-               status = DID_ERROR << 16;
-            else {
-               status = DID_TIME_OUT << 16;
-               HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-               }
-
-            break;
-
-         /* Perform a limited number of internal retries */
-         case 0x03:     /* SCSI Bus Reset Received */
-         case 0x04:     /* Initial Controller Power-up */
-
-            for (c = 0; c <= sh[j]->max_channel; c++) 
-               for (k = 0; k < sh[j]->max_id; k++) 
-                  HD(j)->target_redo[k][c] = TRUE;
-
-            if (SCpnt->device->type != TYPE_TAPE
-                && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-               status = DID_BUS_BUSY << 16;
-               HD(j)->retries++;
-               HD(j)->last_retried_pid = SCpnt->pid;
-               }
-            else 
-               status = DID_ERROR << 16;
-
-            break;
-         case 0x05:     /* Unexpected Bus Phase */
-         case 0x06:     /* Unexpected Bus Free */
-         case 0x07:     /* Bus Parity Error */
-         case 0x08:     /* SCSI Hung */
-         case 0x09:     /* Unexpected Message Reject */
-         case 0x0a:     /* SCSI Bus Reset Stuck */
-         case 0x0b:     /* Auto Request-Sense Failed */
-         case 0x0c:     /* Controller Ram Parity Error */
-         default:
+         if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
             status = DID_ERROR << 16;
-            break;
-         }
+         else {
+            status = DID_TIME_OUT << 16;
+            HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+            }
+
+         break;
 
-      SCpnt->result = status | spp->target_status;
-      HD(j)->iocount++;
+      /* Perform a limited number of internal retries */
+      case 0x03:     /* SCSI Bus Reset Received */
+      case 0x04:     /* Initial Controller Power-up */
+
+         for (c = 0; c <= sh[j]->max_channel; c++)
+            for (k = 0; k < sh[j]->max_id; k++)
+               HD(j)->target_redo[k][c] = TRUE;
+
+         if (SCpnt->device->type != TYPE_TAPE
+             && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+            status = DID_BUS_BUSY << 16;
+            HD(j)->retries++;
+            HD(j)->last_retried_pid = SCpnt->pid;
+            }
+         else
+            status = DID_ERROR << 16;
+
+         break;
+      case 0x05:     /* Unexpected Bus Phase */
+      case 0x06:     /* Unexpected Bus Free */
+      case 0x07:     /* Bus Parity Error */
+      case 0x08:     /* SCSI Hung */
+      case 0x09:     /* Unexpected Message Reject */
+      case 0x0a:     /* SCSI Bus Reset Stuck */
+      case 0x0b:     /* Auto Request-Sense Failed */
+      case 0x0c:     /* Controller Ram Parity Error */
+      default:
+         status = DID_ERROR << 16;
+         break;
+      }
+
+   SCpnt->result = status | spp->target_status;
 
 #if defined (DEBUG_INTERRUPT)
-      if (SCpnt->result || do_trace)
+   if (SCpnt->result || do_trace)
 #else
-      if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-          (spp->adapter_status != ASOK && 
-          spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-          do_trace || msg_byte(spp->target_status))
+   if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+       (spp->adapter_status != ASOK &&
+        spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+        do_trace || msg_byte(spp->target_status))
 #endif
-         printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-                BN(j), i, spp->adapter_status, spp->target_status,
-                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                reg, HD(j)->iocount);
-
-      /* Set the command state to inactive */
-      SCpnt->host_scribble = NULL;
+      printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+             " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+             BN(j), i, spp->adapter_status, spp->target_status,
+             SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+             reg, HD(j)->iocount);
 
-      SCpnt->scsi_done(SCpnt);
-
-      }   /* Mailbox loop */
+   /* Set the command state to inactive */
+   SCpnt->host_scribble = NULL;
 
-   if (n_ready > 1)
-      printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready);
+   SCpnt->scsi_done(SCpnt);
 
    if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
                         HD(j)->iocount);
@@ -1938,18 +1955,22 @@
 
 static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   unsigned int j;
+
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
 
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   {
    unsigned long flags;
    spin_lock_irqsave(&io_request_lock, flags);
-   ihdlr(irq, shap, regs);
+   ihdlr(irq, j);
    spin_unlock_irqrestore(&io_request_lock, flags);
-
+   }
 #else
-
-   ihdlr(irq, shap, regs);
-
+   ihdlr(irq, j);
 #endif
+
 }
 
 int eata2x_release(struct Scsi_Host *shpnt) {
@@ -1960,11 +1981,11 @@
    cli();
 
    for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
-    
+
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   for (i = 0; i < sh[j]->can_queue; i++) 
+   for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
    free_irq(sh[j]->irq, &sha[j]);
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.1.97/linux/drivers/scsi/eata.h	Fri Apr 10 13:03:49 1998
+++ linux/drivers/scsi/eata.h	Thu Apr 23 15:54:54 1998
@@ -13,7 +13,7 @@
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "4.04.00"
+#define EATA_VERSION "4.20.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.1.97/linux/drivers/scsi/hosts.h	Thu Apr 23 20:21:35 1998
+++ linux/drivers/scsi/hosts.h	Thu Apr 23 15:57:06 1998
@@ -23,6 +23,7 @@
     $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
 */
 
+#include <linux/config.h>
 #include <linux/proc_fs.h>
 
 /* It is senseless to set SG_ALL any higher than this - the performance
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.1.97/linux/drivers/scsi/u14-34f.c	Fri Apr 10 13:03:49 1998
+++ linux/drivers/scsi/u14-34f.c	Thu Apr 23 15:54:54 1998
@@ -1,13 +1,21 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
+ *          Reworked interrupt handler.
+ *
+ *      11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
+ *          Major reliability improvement: when a batch with overlapping
+ *          requests is detected, requests are queued one at a time
+ *          eliminating any possible board or drive reordering.
+ *
  *      10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
  *          Improved SMP support (if linux version >= 2.1.95).
  *
  *       9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94
  *          Performance improvement: when sequential i/o is detected,
  *          always use direct sort instead of reverse sort.
- *   
+ *
  *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
  *          io_port is now unsigned long.
  *
@@ -35,7 +43,7 @@
  *          Fixed data transfer direction for some SCSI opcodes.
  *          Immediate acknowledge to request sense commands.
  *          Linked commands to each disk device are now reordered by elevator
- *          sorting. Rare cases in which reordering of write requests could 
+ *          sorting. Rare cases in which reordering of write requests could
  *          cause wrong results are managed.
  *
  *      18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28
@@ -119,12 +127,12 @@
  *      28 Oct 1994 rev. 1.09 for linux 1.1.58  Final BETA release.
  *      16 Jul 1994 rev. 1.00 for linux 1.1.29  Initial ALPHA release.
  *
- *          This driver is a total replacement of the original UltraStor 
+ *          This driver is a total replacement of the original UltraStor
  *          scsi driver, but it supports ONLY the 14F and 34F boards.
  *          It can be configured in the same kernel in which the original
  *          ultrastor driver is configured to allow the original U24F
  *          support.
- * 
+ *
  *          Multiple U14F and/or U34F host adapters are supported.
  *
  *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
@@ -148,11 +156,11 @@
  *  24F - EISA Bus Master HA with floppy support and WD1003 emulation.
  *  34F - VESA Local-Bus Bus Master HA (no WD1003 emulation).
  *
- *  This code has been tested with up to two U14F boards, using both 
+ *  This code has been tested with up to two U14F boards, using both
  *  firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware
- *  28004-006/38004-005 (BIOS rev. 2.01). 
+ *  28004-006/38004-005 (BIOS rev. 2.01).
  *
- *  The latest firmware is required in order to get reliable operations when 
+ *  The latest firmware is required in order to get reliable operations when
  *  clustering is enabled. ENABLE_CLUSTERING provides a performance increase
  *  up to 50% on sequential access.
  *
@@ -168,24 +176,24 @@
  *  have their BIOS disabled, or enabled to an higher address.
  *  Boards are named Ux4F0, Ux4F1..., according to the port address order in
  *  the io_port[] array.
- *  
+ *
  *  The following facts are based on real testing results (not on
  *  documentation) on the above U14F board.
- *  
- *  - The U14F board should be jumpered for bus on time less or equal to 7 
- *    microseconds, while the default is 11 microseconds. This is order to 
- *    get acceptable performance while using floppy drive and hard disk 
- *    together. The jumpering for 7 microseconds is: JP13 pin 15-16, 
+ *
+ *  - The U14F board should be jumpered for bus on time less or equal to 7
+ *    microseconds, while the default is 11 microseconds. This is order to
+ *    get acceptable performance while using floppy drive and hard disk
+ *    together. The jumpering for 7 microseconds is: JP13 pin 15-16,
  *    JP14 pin 7-8 and pin 9-10.
  *    The reduction has a little impact on scsi performance.
- *  
+ *
  *  - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced
  *    from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8).
  *
  *  - If U14F on board firmware is older than 28004-006/38004-005,
- *    the U14F board is unable to provide reliable operations if the scsi 
+ *    the U14F board is unable to provide reliable operations if the scsi
  *    request length exceeds 16Kbyte. When this length is exceeded the
- *    behavior is: 
+ *    behavior is:
  *    - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94;
  *    - adapter_status equal 0 and target_status equal 2 on for all targets
  *      in the next operation following the reset.
@@ -199,7 +207,7 @@
  *    Any reset of the scsi bus is going to kill tape operations, since
  *    no retry is allowed for tapes. Bus resets are more likely when the
  *    scsi bus is under heavy load.
- *    Requests using scatter/gather have a maximum length of 16 x 1024 bytes 
+ *    Requests using scatter/gather have a maximum length of 16 x 1024 bytes
  *    when DISABLE_CLUSTERING is in effect, but unscattered requests could be
  *    larger than 16Kbyte.
  *
@@ -246,15 +254,15 @@
  *  in the elevator sorting queue. When the active command completes, the
  *  commands in this queue are sorted by sector address. The sort is chosen
  *  between increasing or decreasing by minimizing the seek distance between
- *  the sector of the commands just completed and the sector of the first 
- *  command in the list to be sorted. 
+ *  the sector of the commands just completed and the sector of the first
+ *  command in the list to be sorted.
  *  Trivial math assures that the unsorted average seek distance when doing
  *  random seeks over S sectors is S/3.
  *  When (Q-1) requests are uniformly distributed over S sectors, the average
  *  distance between two adjacent requests is S/((Q-1) + 1), so the sorted
  *  average seek distance for (Q-1) random requests over S sectors is S/Q.
  *  The elevator sorting hence divides the seek distance by a factor Q/3.
- *  The above pure geometric remarks are valid in all cases and the 
+ *  The above pure geometric remarks are valid in all cases and the
  *  driver effectively reduces the seek distance by the predicted factor
  *  when there are Q concurrent read i/o operations on the device, but this
  *  does not necessarily results in a noticeable performance improvement:
@@ -262,7 +270,7 @@
  *
  *  Note: command reordering inside a batch of queued commands could cause
  *        wrong results only if there is at least one write request and the
- *        intersection (sector-wise) of all requests is not empty. 
+ *        intersection (sector-wise) of all requests is not empty.
  *        When the driver detects a batch including overlapping requests
  *        (a really rare event) strict serial (pid) order is enforced.
  *  ----------------------------------------------------------------------------
@@ -300,6 +308,11 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+#include <asm/spinlock.h>
+#endif
+
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -350,7 +363,7 @@
 #undef  DEBUG_RESET
 
 #define MAX_ISA 3
-#define MAX_VESA 1 
+#define MAX_VESA 1
 #define MAX_EISA 0
 #define MAX_PCI 0
 #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
@@ -462,7 +475,7 @@
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
 
-static unsigned long io_port[] __initdata = { 
+static unsigned long io_port[] __initdata = {
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -494,7 +507,7 @@
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
 #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
-static void interrupt_handler(int, void *, struct pt_regs *);
+static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
 static int setup_done = FALSE;
@@ -520,7 +533,7 @@
 
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
-   int j, ntag = 0, nuntag = 0, tqd, utqd; 
+   int j, ntag = 0, nuntag = 0, tqd, utqd;
    unsigned long flags;
 
    save_flags(flags);
@@ -637,23 +650,23 @@
    char *bus_type, dma_name[16];
 
    /* Allowed BIOS base addresses (NULL indicates reserved) */
-   void *bios_segment_table[8] = { 
-      NULL, 
+   void *bios_segment_table[8] = {
+      NULL,
       (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000,
       (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000
       };
-   
+
    /* Allowed IRQs */
    unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
-   
+
    /* Allowed DMA channels for ISA (0 indicates reserved) */
    unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
-   
+
    /* Head/sector mappings */
    struct {
       unsigned char heads;
       unsigned char sectors;
-      } mapping_table[4] = { 
+      } mapping_table[4] = {
            { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
            };
 
@@ -694,7 +707,7 @@
    subversion = (in_byte & 0x0f);
 
    /* Board detected, allocate its IRQ */
-   if (request_irq(irq, interrupt_handler,
+   if (request_irq(irq, do_interrupt_handler,
              SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
              driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
@@ -797,14 +810,14 @@
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
-            sh[j]->sg_tablesize * sizeof(struct sg_list), 
+            sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
          printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
          u14_34f_release(sh[j]);
          return FALSE;
          }
-      
-   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
@@ -834,8 +847,8 @@
 
       if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
 
-      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; 
-   
+      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
+
       io_port[i] = 0;
       setup_done = TRUE;
       }
@@ -884,7 +897,7 @@
       if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
       }
 
-   if (j > 0) 
+   if (j > 0)
       printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
    num_boards = j;
@@ -916,7 +929,7 @@
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
-      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 
+      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
       0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
       };
 
@@ -934,16 +947,16 @@
    if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
 
    if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
-      SCpnt->result = DID_OK << 16; 
+      SCpnt->result = DID_OK << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 0;
       }
 
-   /* i is the mailbox number, look for the first free mailbox 
+   /* i is the mailbox number, look for the first free mailbox
       starting from last_cp_used */
    i = HD(j)->last_cp_used + 1;
 
@@ -960,17 +973,17 @@
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
-      if (HD(j)->in_reset) 
+      if (HD(j)->in_reset)
          printk("%s: qcomm, already in reset.\n", BN(j));
-      else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
-               == SCSI_RESET_SUCCESS) 
+      else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
+               == SCSI_RESET_SUCCESS)
          panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
-      SCpnt->result = DID_BUS_BUSY << 16; 
+      SCpnt->result = DID_BUS_BUSY << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -983,7 +996,7 @@
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-                        BN(j), i, SCpnt->channel, SCpnt->target, 
+                        BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
@@ -1136,7 +1149,7 @@
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
           BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
@@ -1197,10 +1210,10 @@
       if (SCpnt->host_scribble == NULL)
          panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
+      if (*(unsigned int *)SCpnt->host_scribble != i)
          panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
-      if (SCpnt->scsi_done == NULL) 
+      if (SCpnt->scsi_done == NULL)
          panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
@@ -1294,7 +1307,7 @@
    for (i = 0; i < n - 1; i++) {
       k = i;
 
-      for (j = k + 1; j < n; j++) 
+      for (j = k + 1; j < n; j++)
          if (rev) {
             if (sk[j] > sk[k]) k = j;
             }
@@ -1311,7 +1324,7 @@
    return;
    }
 
-static inline void reorder(unsigned int j, unsigned long cursec,
+static inline int reorder(unsigned int j, unsigned long cursec,
                  unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
    Scsi_Cmnd *SCpnt;
    struct mscp *cpp;
@@ -1331,10 +1344,10 @@
       printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
              " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
              ovlcount, readycount, readysorted, sortcount, revcount,
-             seeknosort / (readycount + 1), 
+             seeknosort / (readycount + 1),
              seeksorted / (readycount + 1));
 
-   if (n_ready <= 1) return;
+   if (n_ready <= 1) return FALSE;
 
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
@@ -1351,7 +1364,7 @@
 
       if (sl[n] < sl[n - 1]) s = FALSE;
       if (sl[n] > sl[n - 1]) r = FALSE;
-   
+
       if (link_statistics) {
          if (sl[n] > sl[n - 1])
             seek += sl[n] - sl[n - 1];
@@ -1376,7 +1389,7 @@
       ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
 
       if (!n) continue;
- 
+
       if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
           || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
       }
@@ -1385,9 +1398,9 @@
 
    if (link_statistics) {
       if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
-      batchcount++; readycount += n_ready, seeknosort += seek / 1024; 
+      batchcount++; readycount += n_ready, seeknosort += seek / 1024;
       if (input_only) inputcount++;
-      if (overlap) { ovlcount++; seeksorted += seek / 1024; }
+      if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
       else seeksorted += (iseek + maxsec - minsec) / 1024;
       if (rev && !r)     {  revcount++; readysorted += n_ready; }
       if (!rev && !s)    { sortcount++; readysorted += n_ready; }
@@ -1402,10 +1415,11 @@
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
                 SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
                 SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
-                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), 
+                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->xdir);
          }
 #endif
+   return overlap;
 }
 
 static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
@@ -1427,13 +1441,13 @@
       il[n_ready++] = k;
       }
 
-   reorder(j, cursec, ihdlr, il, n_ready);
-  
+   if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
+
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
 
       if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
-         printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\
+         printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
                 " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
                 SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
          HD(j)->cp_stat[k] = ABORTING;
@@ -1444,33 +1458,43 @@
       outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
       HD(j)->cp_stat[k] = IN_USE;
       }
+
 }
 
-static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
+static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, c, status, tstatus, reg, ret;
-   struct mscp *spp;
-
-   /* Check if the interrupt must be processed by this handler */
-   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+   unsigned int i, k, c, status, tstatus, reg, ret;
+   struct mscp *spp, *cpp;
 
    if (sh[j]->irq != irq)
        panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
 
+   /* Check if this board need to be serviced */
+   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+
+   HD(j)->iocount++;
+
    if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
                         HD(j)->iocount);
 
-   /* Check if this board need to be serviced */
-   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+   /* Check if this board is still busy */
+   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+      printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+      return;
+      }
 
    spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+   cpp = spp;
 
    /* Clear interrupt pending flag */
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
-   i = spp - HD(j)->cp;
+   /* Find the mailbox to be serviced on this board */
+   i = cpp - HD(j)->cp;
 
-   if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
                                      || i >= sh[j]->can_queue)
       panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
             (void *)ret, HD(j)->cp);
@@ -1492,22 +1516,22 @@
       }
    else if (HD(j)->cp_stat[i] == IN_RESET)
       printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-   else if (HD(j)->cp_stat[i] != IN_USE) 
-      panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", 
+   else if (HD(j)->cp_stat[i] != IN_USE)
+      panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n",
             BN(j), i, HD(j)->cp_stat[i]);
 
    HD(j)->cp_stat[i] = FREE;
-   SCpnt = spp->SCpnt;
+   SCpnt = cpp->SCpnt;
 
    if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-   if (SCpnt->host_scribble == NULL) 
+   if (SCpnt->host_scribble == NULL)
       panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
             SCpnt->pid, SCpnt);
 
-   if (*(unsigned int *)SCpnt->host_scribble != i) 
-      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", 
-            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+   if (*(unsigned int *)SCpnt->host_scribble != i)
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
@@ -1519,7 +1543,7 @@
       case ASOK:     /* status OK */
 
          /* Forces a reset if a disk drive keeps returning BUSY */
-         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
             status = DID_ERROR << 16;
 
          /* If there was a bus reset, redo operation on each target */
@@ -1541,7 +1565,7 @@
 
          if (spp->target_status && SCpnt->device->type == TYPE_DISK)
             printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                   "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j),
                    SCpnt->channel, SCpnt->target, SCpnt->lun,
                    SCpnt->pid, spp->target_status,
                    SCpnt->sense_buffer[2]);
@@ -1568,10 +1592,10 @@
       case 0x96:     /* Illegal SCSI command */
       case 0xa3:     /* SCSI bus reset error */
 
-         for (c = 0; c <= sh[j]->max_channel; c++) 
-            for (k = 0; k < sh[j]->max_id; k++) 
+         for (c = 0; c <= sh[j]->max_channel; c++)
+            for (k = 0; k < sh[j]->max_id; k++)
                HD(j)->target_redo[k][c] = TRUE;
-   
+
 
       case 0x92:     /* Data over/under-run */
 
@@ -1581,7 +1605,7 @@
             HD(j)->retries++;
             HD(j)->last_retried_pid = SCpnt->pid;
             }
-         else 
+         else
             status = DID_ERROR << 16;
 
          break;
@@ -1598,13 +1622,12 @@
       }
 
    SCpnt->result = status | spp->target_status;
-   HD(j)->iocount++;
 
 #if defined (DEBUG_INTERRUPT)
-   if (SCpnt->result || do_trace) 
+   if (SCpnt->result || do_trace)
 #else
    if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-       (spp->adapter_status != ASOK && 
+       (spp->adapter_status != ASOK &&
         spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
         do_trace || msg_byte(spp->target_status))
 #endif
@@ -1625,20 +1648,24 @@
    return;
 }
 
-static void interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
+static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   unsigned int j;
 
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   {
    unsigned long flags;
    spin_lock_irqsave(&io_request_lock, flags);
-   ihdlr(irq, shap, regs);
+   ihdlr(irq, j);
    spin_unlock_irqrestore(&io_request_lock, flags);
-
+   }
 #else
-
-   ihdlr(irq, shap, regs);
-
+   ihdlr(irq, j);
 #endif
+
 }
 
 int u14_34f_release(struct Scsi_Host *shpnt) {
@@ -1649,11 +1676,11 @@
    cli();
 
    for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
-    
+
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   for (i = 0; i < sh[j]->can_queue; i++) 
+   for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
    free_irq(sh[j]->irq, &sha[j]);
diff -u --recursive --new-file v2.1.97/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.1.97/linux/drivers/scsi/u14-34f.h	Fri Apr 10 13:03:49 1998
+++ linux/drivers/scsi/u14-34f.h	Thu Apr 23 15:54:54 1998
@@ -13,7 +13,7 @@
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "4.04.00"
+#define U14_34F_VERSION "4.20.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
diff -u --recursive --new-file v2.1.97/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.97/linux/fs/binfmt_elf.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/binfmt_elf.c	Thu Apr 23 18:10:12 1998
@@ -108,6 +108,7 @@
 create_elf_tables(char *p, int argc, int envc,
 		  struct elfhdr * exec,
 		  unsigned long load_addr,
+		  unsigned long load_bias,
 		  unsigned long interp_load_addr, int ibcs)
 {
 	elf_caddr_t *argv;
@@ -173,7 +174,7 @@
 		NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
 		NEW_AUX_ENT(4, AT_BASE, interp_load_addr);
 		NEW_AUX_ENT(5, AT_FLAGS, 0);
-		NEW_AUX_ENT(6, AT_ENTRY, (elf_addr_t) exec->e_entry);
+		NEW_AUX_ENT(6, AT_ENTRY, load_bias + exec->e_entry);
 		NEW_AUX_ENT(7, AT_UID, (elf_addr_t) current->uid);
 		NEW_AUX_ENT(8, AT_EUID, (elf_addr_t) current->euid);
 		NEW_AUX_ENT(9, AT_GID, (elf_addr_t) current->gid);
@@ -584,6 +585,7 @@
 	current->mm->end_data = 0;
 	current->mm->end_code = 0;
 	current->mm->mmap = NULL;
+	current->flags &= ~PF_FORKNOEXEC;
 	elf_entry = (unsigned long) elf_ex.e_entry;
 
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
@@ -712,7 +714,7 @@
 			bprm->argc,
 			bprm->envc,
 			(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
-			load_addr,
+			load_addr, load_bias,
 			interp_load_addr,
 			(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
 	/* N.B. passed_fileno might not be initialized? */
diff -u --recursive --new-file v2.1.97/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v2.1.97/linux/fs/nfs/nfsroot.c	Fri Jan  9 09:28:06 1998
+++ linux/fs/nfs/nfsroot.c	Thu Apr 23 18:12:21 1998
@@ -1,5 +1,5 @@
 /*
- *  $Id: nfsroot.c,v 1.43 1997/10/16 19:55:27 mj Exp $
+ *  $Id: nfsroot.c,v 1.45 1998/03/07 10:44:46 mj Exp $
  *
  *  Copyright (C) 1995, 1996  Gero Kuhlmann <gero@gkminix.han.de>
  *
@@ -59,6 +59,8 @@
  *				host IP address (but host name defaults to IP
  *				address anyway).
  *	Martin Mares	:	Use root_server_addr appropriately during setup.
+ *	Martin Mares	:	Rewrote parameter parsing, now hopefully giving
+ *				correct overriding.
  */
 
 #include <linux/types.h>
@@ -83,11 +85,9 @@
 
 /* Default path we try to mount. "%s" gets replaced by our IP address */
 #define NFS_ROOT		"/tftpboot/%s"
-#define NFS_ROOT_NAME_LEN	256
 
 /* Parameters passed from the kernel command line */
-static char nfs_root_name[NFS_ROOT_NAME_LEN] __initdata = "default";
-static int nfs_params_parsed = 0;
+static char nfs_root_name[256] __initdata = "";
 
 /* Address of NFS server */
 static __u32 servaddr __initdata = 0;
@@ -150,19 +150,15 @@
 
 
 /*
- *  Prepare the NFS data structure and parse any options. This tries to
- *  set as many values in the nfs_data structure as known right now.
+ *  Extract IP address from the parameter string if needed. Note that we
+ *  need to have root_server_addr set _before_ IPConfig gets called as it
+ *  can override it.
  */
-__initfunc(static int root_nfs_name(char *name))
+__initfunc(static void root_nfs_parse_addr(char *name))
 {
-	char buf[NFS_MAXPATHLEN];
-	char *cp, *cq, *options, *val;
 	int octets = 0;
+	char *cp, *cq;
 
-	if (nfs_params_parsed)
-		return nfs_params_parsed;
-
-	/* It is possible to override the server IP number here */
 	cp = cq = name;
 	while (octets < 4) {
 		while (*cp >= '0' && *cp <= '9')
@@ -179,45 +175,20 @@
 		if (*cp == ':')
 			*cp++ = '\0';
 		root_server_addr = in_aton(name);
-		name = cp;
+		strcpy(name, cp);
 	}
+}
 
-	/* Clear the nfs_data structure and setup the server hostname */
-	memset(&nfs_data, 0, sizeof(nfs_data));
-
-	/* Set the name of the directory to mount */
-	if (root_server_path[0] && !strcmp(name, "default"))
-		strncpy(buf, root_server_path, NFS_MAXPATHLEN-1);
-	else
-		strncpy(buf, name, NFS_MAXPATHLEN-1);
-	buf[NFS_MAXPATHLEN-1] = '\0';
-	if ((options = strchr(buf, ',')))
-		*options++ = '\0';
-	if (!strcmp(buf, "default"))
-		strcpy(buf, NFS_ROOT);
-	cp = system_utsname.nodename;
-	if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
-		printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
-		return -1;
-	}
-	sprintf(nfs_path, buf, cp);
 
-	/* Set some default values */
-	nfs_port          = -1;
-	nfs_data.version  = NFS_MOUNT_VERSION;
-	nfs_data.flags    = NFS_MOUNT_NONLM;	/* No lockd in nfs root yet */
-	nfs_data.rsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
-	nfs_data.wsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
-	nfs_data.bsize	  = 0;
-	nfs_data.timeo    = 7;
-	nfs_data.retrans  = 3;
-	nfs_data.acregmin = 3;
-	nfs_data.acregmax = 60;
-	nfs_data.acdirmin = 30;
-	nfs_data.acdirmax = 60;
+/*
+ *  Parse option string.
+ */
+__initfunc(static void root_nfs_parse(char *name, char *buf))
+{
+	char *options, *val, *cp;
 
-	/* Process any options */
-	if (options) {
+	if ((options = strchr(name, ','))) {
+		*options++ = 0;
 		cp = strtok(options, ",");
 		while (cp) {
 			if ((val = strchr(cp, '='))) {
@@ -239,6 +210,50 @@
 			cp = strtok(NULL, ",");
 		}
 	}
+	if (name[0] && strcmp(name, "default")) {
+		strncpy(buf, name, NFS_MAXPATHLEN-1);
+		buf[NFS_MAXPATHLEN-1] = 0;
+	}
+}
+
+
+/*
+ *  Prepare the NFS data structure and parse all options.
+ */
+__initfunc(static int root_nfs_name(char *name))
+{
+	char buf[NFS_MAXPATHLEN];
+	char *cp;
+
+	/* Set some default values */
+	memset(&nfs_data, 0, sizeof(nfs_data));
+	nfs_port          = -1;
+	nfs_data.version  = NFS_MOUNT_VERSION;
+	nfs_data.flags    = NFS_MOUNT_NONLM;	/* No lockd in nfs root yet */
+	nfs_data.rsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
+	nfs_data.wsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
+	nfs_data.bsize	  = 0;
+	nfs_data.timeo    = 7;
+	nfs_data.retrans  = 3;
+	nfs_data.acregmin = 3;
+	nfs_data.acregmax = 60;
+	nfs_data.acdirmin = 30;
+	nfs_data.acdirmax = 60;
+	strcpy(buf, NFS_ROOT);
+
+	/* Process options received from the remote server */
+	root_nfs_parse(root_server_path, buf);
+
+	/* Override them by options set on kernel command-line */
+	root_nfs_parse(name, buf);
+
+	cp = system_utsname.nodename;
+	if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
+		printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
+		return -1;
+	}
+	sprintf(nfs_path, buf, cp);
+
 	return 1;
 }
 
@@ -317,7 +332,7 @@
 			line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
 		sprintf(nfs_root_name, NFS_ROOT, line);
 	}
-	nfs_params_parsed = root_nfs_name(nfs_root_name);
+	root_nfs_parse_addr(nfs_root_name);
 }
 
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-alpha/serial.h linux/include/asm-alpha/serial.h
--- v2.1.97/linux/include/asm-alpha/serial.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-alpha/serial.h	Thu Apr 23 15:57:06 1998
@@ -2,6 +2,8 @@
  * include/asm-alpha/serial.h
  */
 
+#include <linux/config.h>
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
diff -u --recursive --new-file v2.1.97/linux/include/asm-i386/serial.h linux/include/asm-i386/serial.h
--- v2.1.97/linux/include/asm-i386/serial.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-i386/serial.h	Thu Apr 23 15:57:06 1998
@@ -2,6 +2,8 @@
  * include/asm-i386/serial.h
  */
 
+#include <linux/config.h>
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
diff -u --recursive --new-file v2.1.97/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.1.97/linux/include/asm-i386/system.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-i386/system.h	Sat Apr 18 12:13:07 1998
@@ -293,7 +293,7 @@
 	"movb $0,6(%2)\n\t" \
 	"movb %%ah,7(%2)\n\t" \
 	"rorl $16,%%eax" \
-	: "=m"(*(n)) : "a" (addr), "r"(n), "g"(limit), "i"(type))
+	: "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
 
 #define set_tss_desc(n,addr) \
 	_set_tssldt_desc(((char *) (n)),((int)(addr)),235,0x89)
diff -u --recursive --new-file v2.1.97/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.1.97/linux/include/asm-ppc/irq.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/irq.h	Thu Apr 23 15:57:06 1998
@@ -1,3 +1,5 @@
+#include <linux/config.h>
+
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.1.97/linux/include/asm-ppc/mmu_context.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/mmu_context.h	Thu Apr 23 15:57:06 1998
@@ -1,3 +1,5 @@
+#include <linux/config.h>
+
 #ifndef __PPC_MMU_CONTEXT_H
 #define __PPC_MMU_CONTEXT_H
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.1.97/linux/include/asm-ppc/page.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/page.h	Thu Apr 23 15:57:06 1998
@@ -1,3 +1,5 @@
+#include <linux/config.h>
+
 #ifndef _PPC_PAGE_H
 #define _PPC_PAGE_H
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.1.97/linux/include/asm-ppc/pgtable.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/pgtable.h	Thu Apr 23 15:57:06 1998
@@ -1,3 +1,5 @@
+#include <linux/config.h>
+
 #ifndef _PPC_PGTABLE_H
 #define _PPC_PGTABLE_H
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.1.97/linux/include/asm-sparc/system.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/system.h	Thu Apr 23 15:57:06 1998
@@ -1,4 +1,6 @@
 /* $Id: system.h,v 1.68 1998/03/09 14:04:51 jj Exp $ */
+#include <linux/config.h>
+
 #ifndef __SPARC_SYSTEM_H
 #define __SPARC_SYSTEM_H
 
diff -u --recursive --new-file v2.1.97/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h
--- v2.1.97/linux/include/asm-sparc/timer.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/timer.h	Thu Apr 23 15:57:06 1998
@@ -3,6 +3,9 @@
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
+
+#include <linux/config.h>
+
 #ifndef _SPARC_TIMER_H
 #define _SPARC_TIMER_H
 
diff -u --recursive --new-file v2.1.97/linux/include/linux/capability.h linux/include/linux/capability.h
--- v2.1.97/linux/include/linux/capability.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/capability.h	Thu Apr 23 15:56:30 1998
@@ -1,7 +1,7 @@
 /*
  * This is <linux/capability.h>
  *
- * Andrew G. Morgan <morgan@parc.power.net>
+ * Andrew G. Morgan <morgan@transmeta.com>
  * Alexander Kjeldaas <astor@guardian.no>
  * with help from Aleph1, Roland Buresund and Andrew Main.
  */ 
diff -u --recursive --new-file v2.1.97/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.1.97/linux/include/linux/parport.h	Thu Apr 23 20:21:38 1998
+++ linux/include/linux/parport.h	Wed Apr 22 19:01:06 1998
@@ -283,7 +283,6 @@
 	if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
 		return 0;
 	parport_release(dev);
-	schedule();
 	return parport_claim_or_block(dev);
 }
 
diff -u --recursive --new-file v2.1.97/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.1.97/linux/kernel/kmod.c	Tue Apr 14 14:29:26 1998
+++ linux/kernel/kmod.c	Sat Apr 18 19:41:17 1998
@@ -113,7 +113,7 @@
 	 * CLONE_FILES just saves some space (we don't need any
 	 * new file descriptors). Ditto for CLONE_SIGHAND.
 	 */
-	kernel_thread(kmod_thread, NULL, CLONE_FILES | CLONE_FS | CLONE_SIGHAND);
+	kernel_thread(kmod_thread, NULL, CLONE_FILES | CLONE_FS | CLONE_SIGHAND);
 
 	kmod_unload_timer.next = NULL;
 	kmod_unload_timer.prev = NULL;
diff -u --recursive --new-file v2.1.97/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.97/linux/mm/page_alloc.c	Mon Apr  6 17:41:01 1998
+++ linux/mm/page_alloc.c	Thu Apr 23 12:03:49 1998
@@ -273,10 +273,8 @@
 	 * "maxorder" is the highest order number that we're allowed
 	 * to empty in order to find a free page..
 	 */
-	maxorder = order + NR_MEM_LISTS/3;
-	if (gfp_mask & __GFP_MED)
-		maxorder += NR_MEM_LISTS/3;
-	if ((gfp_mask & __GFP_HIGH) || maxorder > NR_MEM_LISTS)
+	maxorder = NR_MEM_LISTS-1;
+	if (gfp_mask & __GFP_HIGH)
 		maxorder = NR_MEM_LISTS;
 
 	if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
@@ -295,6 +293,7 @@
 	if (gfp_mask & __GFP_WAIT) {
 		int freed = try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX);
 		gfp_mask &= ~__GFP_WAIT;	/* go through this only once */
+		maxorder = NR_MEM_LISTS;	/* Allow anything this time */
 		if (freed)
 			goto repeat;
 	}
