## Automatically generated incremental diff
## From:   linux-2.2.19-pre8
## To:     linux-2.2.19-pre9
## Robot:  $Id: make-incremental-diff,v 1.6 2001/12/04 04:41:15 hpa Exp $

diff -urN linux-2.2.19-pre8/CREDITS linux/CREDITS
--- linux-2.2.19-pre8/CREDITS	Mon Dec  3 20:59:32 2001
+++ linux/CREDITS	Mon Dec  3 20:59:57 2001
@@ -1869,7 +1869,7 @@
 S: Germany
 
 N: Stephen Rothwell
-E: sfr@linuxcare.com
+E: sfr@linuxcare.com.au
 W: http://linuxcare.com.au/sfr
 P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
diff -urN linux-2.2.19-pre8/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.19-pre8/Documentation/Configure.help	Mon Dec  3 20:59:32 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 20:59:57 2001
@@ -1530,7 +1530,7 @@
   inserted in and removed from the running kernel whenever you want).
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt. You will get modules called i2o_core.o
-  and i20_config.o. 
+  and i2o_config.o. 
 
   If unsure, say N.
 
@@ -8512,10 +8512,10 @@
   The module is called nfsd.o. If you want to compile it as a module,
   say M here and read Documentation/modules.txt. If unsure, say N.
 
-Provide NFSv3 server support (EXPERIMENTAL)
+Provide NFSv3 server support
 CONFIG_NFSD_V3
   If you would like to include the NFSv3 server as well as the NFSv2
-  server, say Y here.  File locking, via the NLMv4 protocol, is now
+  server, say Y here.  File locking, via the NLMv4 protocol, is also
   supported. If unsure, say N.
 
 OS/2 HPFS filesystem support (read only)
@@ -13616,6 +13616,20 @@
   If you do not have a CompactPCI model CP1400 or CP1500, or 
   another UltraSPARC-IIi-cEngine boardset with digital display,
   you should say N to this option.
+
+CP1XXX Hardware Watchdog support
+CONFIG_WATCHDOG_CP1XXX
+  This is the driver for the hardware watchdog timers present on
+  Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called cpwatchdog.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+ 
+  If you do not have a CompactPCI model CP1400 or CP1500, or
+  another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
+  you should say N to this option. 
    
 #
 # A couple of things I keep forgetting:
diff -urN linux-2.2.19-pre8/Documentation/networking/cs89x0.txt linux/Documentation/networking/cs89x0.txt
--- linux-2.2.19-pre8/Documentation/networking/cs89x0.txt	Wed Aug 25 17:29:45 1999
+++ linux/Documentation/networking/cs89x0.txt	Mon Dec  3 20:59:57 2001
@@ -205,9 +205,8 @@
 * mmode=#####         - specify memory base address
 * dma=#               - specify DMA channel
 * media=rj45          - specify media type
-   or media=2
+   or media=bnc
    or media=aui
-   or medai=auto
 * duplex=f            - specify forced half/full/autonegotiate duplex
    or duplex=h
    or duplex=auto
diff -urN linux-2.2.19-pre8/MAINTAINERS linux/MAINTAINERS
--- linux-2.2.19-pre8/MAINTAINERS	Mon Dec  3 20:59:32 2001
+++ linux/MAINTAINERS	Mon Dec  3 20:59:58 2001
@@ -572,10 +572,12 @@
 S:	Maintained
 
 KERNEL NFSD
-P:	G. Allen Morris III
-M:	gam3@acm.org
+P:	Neil Brown
+M:	neilb@cse.unsw.edu.au
 L:	nfs-devel@linux.kernel.org (Linux NFS)
-W:	http://csua.berkeley.edu/~gam3/knfsd
+L:	nfs@lists.sourceforge.net
+W:	http://nfs.sourceforge.net/
+W:	http://www.cse.unsw.edu.au/~neilb/patches/knfsd-2.2/
 S:	Maintained
 
 LANMEDIA WAN CARD DRIVER
diff -urN linux-2.2.19-pre8/Makefile linux/Makefile
--- linux-2.2.19-pre8/Makefile	Mon Dec  3 20:59:32 2001
+++ linux/Makefile	Mon Dec  3 20:59:58 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 19
-EXTRAVERSION = pre8
+EXTRAVERSION = pre9
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.19-pre8/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- linux-2.2.19-pre8/arch/alpha/kernel/osf_sys.c	Wed May  3 17:16:30 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Mon Dec  3 20:59:58 2001
@@ -78,8 +78,10 @@
 	mm = current->mm;
 	mm->end_code = bss_start + bss_len;
 	mm->brk = bss_start + bss_len;
+#if 0
 	printk("set_program_attributes(%lx %lx %lx %lx)\n",
 		text_start, text_len, bss_start, bss_len);
+#endif
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.2.19-pre8/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/alpha/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/alpha/kernel/ptrace.c	Wed May  3 17:16:30 2000
@@ -543,7 +543,7 @@
 		ret = -EPERM;
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		     (current->uid != child->euid) ||
 		     (current->uid != child->suid) ||
 		     (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c
--- linux-2.2.19-pre8/arch/alpha/kernel/sys_ruffian.c	Sat Jan  9 19:08:27 1999
+++ linux/arch/alpha/kernel/sys_ruffian.c	Mon Dec  3 20:59:58 2001
@@ -163,16 +163,91 @@
 	enable_irq(2);		/* enable 2nd PIC cascade */
 }
 
+/*
+ *  Interrupt routing:
+ *
+ *		Primary bus
+ *	  IdSel		INTA	INTB	INTC	INTD
+ * 21052   13		  -	  -	  -	  -
+ * SIO	   14		 23	  -	  -	  -
+ * 21143   15		 44	  -	  -	  -
+ * Slot 0  17		 43	 42	 41	 40
+ *
+ *		Secondary bus
+ *	  IdSel		INTA	INTB	INTC	INTD
+ * Slot 0   8 (18)	 19	 18	 17	 16
+ * Slot 1   9 (19)	 31	 30	 29	 28
+ * Slot 2  10 (20)	 27	 26	 25	 24
+ * Slot 3  11 (21)	 39	 38	 37	 36
+ * Slot 4  12 (22)	 35	 34	 33	 32
+ * 53c875  13 (23)	 20	  -	  -	  -
+ *
+ */
+
+static int __init
+ruffian_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+        static char irq_tab[11][5] __initdata = {
+	      /*INT  INTA INTB INTC INTD */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 13,  21052	     */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 14,  SIO	     */
+		{44,  44,  44,  44,  44},  /* IdSel 15,  21143	     */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 16,  none	     */
+		{43,  43,  42,  41,  40},  /* IdSel 17,  64-bit slot */
+		/* the next 6 are actually on PCI bus 1, across the bridge */
+		{19,  19,  18,  17,  16},  /* IdSel  8,  slot 0	     */
+		{31,  31,  30,  29,  28},  /* IdSel  9,  slot 1	     */
+		{27,  27,  26,  25,  24},  /* IdSel 10,  slot 2	     */
+		{39,  39,  38,  37,  36},  /* IdSel 11,  slot 3	     */
+		{35,  35,  34,  33,  32},  /* IdSel 12,  slot 4	     */
+		{20,  20,  20,  20,  20},  /* IdSel 13,  53c875	     */
+        };
+	const long min_idsel = 13, max_idsel = 23, irqs_per_slot = 5;
+	return COMMON_TABLE_LOOKUP;
+}
+
+static int __init
+ruffian_swizzle(struct pci_dev *dev, int *pinp)
+{
+	int slot, pin = *pinp;
+
+	if (dev->bus->number == 0) {
+		slot = PCI_SLOT(dev->devfn);
+	}		
+	/* Check for the built-in bridge.  */
+	else if (PCI_SLOT(dev->bus->self->devfn) == 13) {
+		slot = PCI_SLOT(dev->devfn) + 10;
+	}
+	else 
+	{
+		/* Must be a card-based bridge.  */
+		do {
+			if (PCI_SLOT(dev->bus->self->devfn) == 13) {
+				slot = PCI_SLOT(dev->devfn) + 10;
+				break;
+			}
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+			/* Move up the chain of bridges.  */
+			dev = dev->bus->self;
+			/* Slot of the next bridge.  */
+			slot = PCI_SLOT(dev->devfn);
+		} while (dev->bus->self);
+	}
+	*pinp = pin;
+	return slot;
+}
 
 /*
  * For RUFFIAN, we do not want to make any modifications to the PCI
- * setup.  But we may need to do some kind of init.
+ * setup, except IRQ assignment.  But we may need to do some kind of init.
  */
 
 static void __init
 ruffian_pci_fixup(void)
 {
 	/* layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); */
+	common_pci_fixup(ruffian_map_irq, ruffian_swizzle);
 }
 
 
diff -urN linux-2.2.19-pre8/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- linux-2.2.19-pre8/arch/alpha/kernel/traps.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/alpha/kernel/traps.c	Mon Dec  3 20:59:58 2001
@@ -1086,7 +1086,9 @@
 {
 	/* We only get here for OSF system calls, minus #112;
 	   the rest go to sys_ni_syscall.  */
+#if 0
 	printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
+#endif
 	return -ENOSYS;
 }
 
diff -urN linux-2.2.19-pre8/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/arm/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/arm/kernel/ptrace.c	Mon Dec  3 20:59:58 2001
@@ -817,7 +817,7 @@
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- linux-2.2.19-pre8/arch/i386/kernel/apm.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/apm.c	Mon Dec  3 20:59:58 2001
@@ -36,6 +36,7 @@
  * Oct 1999, Version 1.10
  * Nov 1999, Version 1.11
  * Jan 2000, Version 1.12
+ * Feb 2000, Version 1.13
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -55,7 +56,7 @@
  *         The new replacment for it is, but Linux doesn't yet support this.
  *         Alan Cox Linux 2.1.55
  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
- *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by 
+ *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
  *         Dean Gaudet <dgaudet@arctic.org>.
  *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
  *    1.5: Fix segment register reloading (in case of bad segments saved
@@ -127,7 +128,7 @@
  *         scripts that check for it before doing power off
  *         work (Jim Avera <jima@hal.com>).
  *   1.13: Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
- *         is now the way life works). 
+ *         is now the way life works).
  *         Fix thinko in suspend() (wrong return).
  *   1.13ac: Added apm_battery_horked() for Compal boards (Dell 5000e etc)
  *
@@ -242,8 +243,8 @@
 
 /*
  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David 
- * Chen <chen@ctpa04.mit.edu>
+ * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
+ * David Chen <chen@ctpa04.mit.edu>
  */
 #undef INIT_TIMER_AFTER_SUSPEND
 
@@ -326,7 +327,6 @@
 #else
 static int			power_off_enabled = 1;
 #endif
-static int 			dell_crap = 0;	/*Set if we find a 5000e */
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -522,7 +522,7 @@
 			&dummy, &dummy))
 		return (eax >> 8) & 0xff;
 	*event = ebx;
-	if (apm_bios_info.version < 0x0102)
+	if (apm_info.connection_version < 0x0102)
 		*info = ~0; /* indicate info not valid */
 	else
 		*info = ecx;
@@ -554,7 +554,7 @@
 #ifdef ALWAYS_CALL_BUSY
 	clock_slowed = 1;
 #else
-	clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+	clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
 #endif
 	return 1;
 }
@@ -620,7 +620,7 @@
 	 * This may be called on an SMP machine.
 	 */
 #ifdef CONFIG_SMP
-	/* Many bioses don't like being called from CPU != 0 */
+	/* Some bioses don't like being called from CPU != 0 */
 	while (cpu_number_map[smp_processor_id()] != 0) {
 		kernel_thread(apm_magic, NULL,
 			CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
@@ -638,15 +638,15 @@
 {
 	u32	eax;
 
-	if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+	if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
 		return APM_NOT_ENGAGED;
 	if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
 			enable, &eax))
 		return (eax >> 8) & 0xff;
 	if (enable)
-		apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+		apm_info.bios.flags &= ~APM_BIOS_DISABLED;
 	else
-		apm_bios_info.flags |= APM_BIOS_DISABLED;
+		apm_info.bios.flags |= APM_BIOS_DISABLED;
 	return APM_SUCCESS;
 }
 
@@ -658,6 +658,8 @@
 	u32	edx;
 	u32	dummy;
 
+	if (apm_info.get_power_status_broken)
+		return APM_32_UNSUPPORTED;
 	if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
 			&eax, &ebx, &ecx, &edx, &dummy))
 		return (eax >> 8) & 0xff;
@@ -677,7 +679,7 @@
 	u32	edx;
 	u32	esi;
 
-	if (apm_bios_info.version < 0x0102) {
+	if (apm_info.connection_version < 0x0102) {
 		/* pretend we only have one battery. */
 		if (which != 1)
 			return APM_BAD_DEVICE;
@@ -701,15 +703,15 @@
 	u32	eax;
 
 	if ((enable == 0) && (device == APM_DEVICE_ALL)
-	    && (apm_bios_info.flags & APM_BIOS_DISABLED))
+	    && (apm_info.bios.flags & APM_BIOS_DISABLED))
 		return APM_DISABLED;
 	if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
 		return (eax >> 8) & 0xff;
 	if (device == APM_DEVICE_ALL) {
 		if (enable)
-			apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+			apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
 		else
-			apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+			apm_info.bios.flags |= APM_BIOS_DISENGAGED;
 	}
 	return APM_SUCCESS;
 }
@@ -931,7 +933,7 @@
 		if (call->callback(event) && undo) {
 			for (fix = callback_list; fix != call; fix = fix->next)
 				fix->callback(undo);
-			if (apm_bios_info.version > 0x100)
+			if (apm_info.connection_version > 0x100)
 				apm_set_power_state(APM_STATE_REJECT);
 			return 0;
 		}
@@ -974,7 +976,7 @@
 
 		case APM_USER_SUSPEND:
 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
-			if (apm_bios_info.version > 0x100)
+			if (apm_info.connection_version > 0x100)
 				apm_set_power_state(APM_STATE_REJECT);
 			break;
 #endif
@@ -1035,7 +1037,7 @@
 	int		err;
 
 	if ((standbys_pending > 0) || (suspends_pending > 0)) {
-		if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
+		if ((apm_info.connection_version > 0x100) && (pending_count-- <= 0)) {
 			pending_count = 4;
 			if (debug)
 				printk(KERN_DEBUG "apm: setting state busy\n");
@@ -1244,18 +1246,6 @@
 	return 0;
 }
 
-/*
- *	This is called by the DMI code when it finds an Inspiron 5000e
- *	(aka compal reference board). We actually do the check by the BIOS
- *	vendor name, version and serial so we can extend it to try and catch
- *	non Dell stuff later.
- */
- 
-void apm_battery_horked(void)
-{
-	dell_crap = 1;
-}
-
 static int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
 {
 	char *		p;
@@ -1272,14 +1262,14 @@
 
 	p = buf;
 
-	if ((smp_num_cpus == 1) && (!dell_crap) && 
+	if ((smp_num_cpus == 1) &&
 	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
 		ac_line_status = (bx >> 8) & 0xff;
 		battery_status = bx & 0xff;
 		if ((cx & 0xff) != 0xff)
 			percentage = cx & 0xff;
 
-		if (apm_bios_info.version > 0x100) {
+		if (apm_info.connection_version > 0x100) {
 			battery_flag = (cx >> 8) & 0xff;
 			if (dx != 0xffff) {
 				units = (dx & 0x8000) ? "min" : "sec";
@@ -1327,9 +1317,9 @@
 
 	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
 		     driver_version,
-		     (apm_bios_info.version >> 8) & 0xff,
-		     apm_bios_info.version & 0xff,
-		     apm_bios_info.flags,
+		     (apm_info.bios.version >> 8) & 0xff,
+		     apm_info.bios.version & 0xff,
+		     apm_info.bios.flags,
 		     ac_line_status,
 		     battery_status,
 		     battery_flag,
@@ -1349,22 +1339,28 @@
 	char *		power_stat;
 	char *		bat_stat;
 
-	if (apm_bios_info.version > 0x100) {
-		/*
-		 * We only support BIOSs up to version 1.2
-		 */
-		if (apm_bios_info.version > 0x0102)
-			apm_bios_info.version = 0x0102;
-		if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
-			/* Fall back to an APM 1.0 connection. */
-			apm_bios_info.version = 0x100;
+	if (apm_info.connection_version == 0) {
+		apm_info.connection_version = apm_info.bios.version;
+		if (apm_info.connection_version > 0x100) {
+			/*
+			 * We only support BIOSs up to version 1.2
+			 */
+			if (apm_info.connection_version > 0x0102)
+				apm_info.connection_version = 0x0102;
+			error = apm_driver_version(&apm_info.connection_version);
+			if (error != APM_SUCCESS) {
+				apm_error("driver version", error);
+				/* Fall back to an APM 1.0 connection. */
+				apm_info.connection_version = 0x100;
+			}
 		}
 	}
-	if (debug && (smp_num_cpus == 1)) {
+	if (debug)
 		printk(KERN_INFO "apm: Connection version %d.%d\n",
-			(apm_bios_info.version >> 8) & 0xff,
-			apm_bios_info.version & 0xff);
+			(apm_info.connection_version >> 8) & 0xff,
+			apm_info.connection_version & 0xff);
 
+	if (debug && (smp_num_cpus == 1)) {
 		error = apm_get_power_status(&bx, &cx, &dx);
 		if (error)
 			printk(KERN_INFO "apm: power status not available\n");
@@ -1389,7 +1385,7 @@
 				printk("unknown\n");
 			else
 				printk("%d%%\n", cx & 0xff);
-			if (apm_bios_info.version > 0x100) {
+			if (apm_info.connection_version > 0x100) {
 				printk(KERN_INFO
 				       "apm: battery flag 0x%02x, battery life ",
 				       (cx >> 8) & 0xff);
@@ -1404,7 +1400,7 @@
 	}
 
 #ifdef CONFIG_APM_DO_ENABLE
-	if (apm_bios_info.flags & APM_BIOS_DISABLED) {
+	if (apm_info.bios.flags & APM_BIOS_DISABLED) {
 		/*
 		 * This call causes my NEC UltraLite Versa 33/C to hang if it
 		 * is booted with PM disabled but not in the docking station.
@@ -1417,8 +1413,8 @@
 		}
 	}
 #endif
-	if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
-	    && (apm_bios_info.version > 0x0100)) {
+	if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
+	    && (apm_info.connection_version > 0x0100)) {
 		error = apm_engage_power_management(APM_DEVICE_ALL, 1);
 		if (error) {
 			apm_error("engage power management", error);
@@ -1482,17 +1478,17 @@
 
 static int __init apm_init(void)
 {
-	if (apm_bios_info.version == 0) {
+	if (apm_info.bios.version == 0) {
 		printk(KERN_INFO "apm: BIOS not found.\n");
 		return -ENODEV;
 	}
 	printk(KERN_INFO
 		"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
-		((apm_bios_info.version >> 8) & 0xff),
-		(apm_bios_info.version & 0xff),
-		apm_bios_info.flags,
+		((apm_info.bios.version >> 8) & 0xff),
+		(apm_info.bios.version & 0xff),
+		apm_info.bios.flags,
 		driver_version);
-	if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
+	if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
 		printk(KERN_INFO "apm: no 32 bit BIOS support\n");
 		return -ENODEV;
 	}
@@ -1501,23 +1497,23 @@
 	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
 	 * but is reportedly a 1.0 BIOS.
 	 */
-	if (apm_bios_info.version == 0x001)
-		apm_bios_info.version = 0x100;
+	if (apm_info.bios.version == 0x001)
+		apm_info.bios.version = 0x100;
 
 	/* BIOS < 1.2 doesn't set cseg_16_len */
-	if (apm_bios_info.version < 0x102)
-		apm_bios_info.cseg_16_len = 0; /* 64k */
+	if (apm_info.bios.version < 0x102)
+		apm_info.bios.cseg_16_len = 0; /* 64k */
 
 	if (debug) {
 		printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
-			apm_bios_info.cseg, apm_bios_info.offset,
-			apm_bios_info.cseg_16, apm_bios_info.dseg);
-		if (apm_bios_info.version > 0x100)
+			apm_info.bios.cseg, apm_info.bios.offset,
+			apm_info.bios.cseg_16, apm_info.bios.dseg);
+		if (apm_info.bios.version > 0x100)
 			printk(" cseg len %x, dseg len %x",
-				apm_bios_info.cseg_len,
-				apm_bios_info.dseg_len);
-		if (apm_bios_info.version > 0x101)
-			printk(" cseg16 len %x", apm_bios_info.cseg_16_len);
+				apm_info.bios.cseg_len,
+				apm_info.bios.dseg_len);
+		if (apm_info.bios.version > 0x101)
+			printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
 		printk("\n");
 	}
 
@@ -1540,16 +1536,16 @@
 		 __va((unsigned long)0x40 << 4));
 	_set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
 
-	apm_bios_entry.offset = apm_bios_info.offset;
+	apm_bios_entry.offset = apm_info.bios.offset;
 	apm_bios_entry.segment = APM_CS;
 	set_base(gdt[APM_CS >> 3],
-		 __va((unsigned long)apm_bios_info.cseg << 4));
+		 __va((unsigned long)apm_info.bios.cseg << 4));
 	set_base(gdt[APM_CS_16 >> 3],
-		 __va((unsigned long)apm_bios_info.cseg_16 << 4));
+		 __va((unsigned long)apm_info.bios.cseg_16 << 4));
 	set_base(gdt[APM_DS >> 3],
-		 __va((unsigned long)apm_bios_info.dseg << 4));
+		 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
-	if (apm_bios_info.version == 0x100) {
+	if (apm_info.bios.version == 0x100) {
 #endif
 		/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
 		_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
@@ -1560,11 +1556,11 @@
 #ifndef APM_RELAX_SEGMENTS
 	} else {
 		_set_limit((char *)&gdt[APM_CS >> 3],
-			(apm_bios_info.cseg_len - 1) & 0xffff);
+			(apm_info.bios.cseg_len - 1) & 0xffff);
 		_set_limit((char *)&gdt[APM_CS_16 >> 3],
-			(apm_bios_info.cseg_16_len - 1) & 0xffff);
+			(apm_info.bios.cseg_16_len - 1) & 0xffff);
 		_set_limit((char *)&gdt[APM_DS >> 3],
-			(apm_bios_info.dseg_len - 1) & 0xffff);
+			(apm_info.bios.dseg_len - 1) & 0xffff);
 	}
 #endif
 
diff -urN linux-2.2.19-pre8/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- linux-2.2.19-pre8/arch/i386/kernel/dmi_scan.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/i386/kernel/dmi_scan.c	Mon Dec  3 20:59:58 2001
@@ -1,8 +1,8 @@
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/apm_bios.h>
 #include <asm/io.h>
 
 struct dmi_header
@@ -125,17 +125,19 @@
 			 *	< Does it Boot Win98 >-N--
 			 *               |Y
 			 *           [Ship It]
+			 *
+			 *	Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
+			 *	Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
 			 */
 			 
-			if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0 &&
-			   strcmp(dmi_string(dm, data[5]), "A04")==0 &&
-			   strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
+			if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0)
 			{
-#ifdef CONFIG_APM
-				extern void apm_battery_horked(void);
-			   	apm_battery_horked();			   	
-			   	printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling battery reporting.\n");
-#endif			   	
+				if(strcmp(dmi_string(dm, data[5]), "A04")==0 
+					&& strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
+				{
+				   	apm_info.get_power_status_broken = 1;
+					printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
+				}
 			}
 			break;
 #ifdef DUMP_DMI
diff -urN linux-2.2.19-pre8/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/i386/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/i386/kernel/ptrace.c	Wed May  3 17:16:31 2000
@@ -413,7 +413,7 @@
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.2.19-pre8/arch/i386/kernel/setup.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/i386/kernel/setup.c	Mon Dec  3 20:59:58 2001
@@ -99,7 +99,7 @@
  */
 struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info;
-struct apm_bios_info apm_bios_info;
+struct apm_info apm_info;
 struct sys_desc_table_struct {
 	unsigned short length;
 	unsigned char table[0];
@@ -403,7 +403,7 @@
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
-	apm_bios_info = APM_BIOS_INFO;
+	apm_info.bios = APM_BIOS_INFO;
 	if( SYS_DESC_TABLE.length != 0 ) {
 		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
 		machine_id = SYS_DESC_TABLE.table[0];
diff -urN linux-2.2.19-pre8/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/m68k/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/m68k/kernel/ptrace.c	Sun Dec 10 16:49:41 2000
@@ -339,7 +339,7 @@
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/mips/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/mips/kernel/ptrace.c	Mon Aug  9 12:04:38 1999
@@ -292,7 +292,7 @@
 			res = -EPERM;
 			goto out;
 		}
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/ppc/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/ppc/kernel/ptrace.c	Tue Jan  4 10:12:12 2000
@@ -360,7 +360,7 @@
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
diff -urN linux-2.2.19-pre8/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/s390/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/s390/kernel/ptrace.c	Sun Dec 10 16:49:41 2000
@@ -452,7 +452,7 @@
 	{
 		if (child == current)
 			goto out;
-		if ((child->dumpable != 1 ||
+		if ((!child->dumpable ||
 		     (current->uid != child->euid) ||
 		     (current->uid != child->uid) ||
 		     (current->gid != child->egid) ||
diff -urN linux-2.2.19-pre8/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/sparc/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc/kernel/ptrace.c	Tue Jan  4 10:12:12 2000
@@ -567,7 +567,7 @@
 			pt_error_return(regs, EPERM);
 			goto out;
 		}
-		if((child->dumpable != 1 ||
+		if((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->uid) ||
 		    (current->gid != child->egid) ||
diff -urN linux-2.2.19-pre8/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- linux-2.2.19-pre8/arch/sparc/kernel/sys_sunos.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/sparc/kernel/sys_sunos.c	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.94.2.5 2000/09/16 14:15:15 davem Exp $
+/* $Id: sys_sunos.c,v 1.94.2.6 2001/02/02 05:16:11 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -712,7 +712,7 @@
 
 struct sunos_nfs_mount_args {
 	struct sockaddr_in  *addr; /* file server address */
-	struct nfs_fh *fh;     /* File handle to be mounted */
+	struct nfs3_fh *fh;     /* File handle to be mounted */
 	int        flags;      /* flags */
 	int        wsize;      /* write size in bytes */
 	int        rsize;      /* read size in bytes */
diff -urN linux-2.2.19-pre8/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- linux-2.2.19-pre8/arch/sparc/kernel/systbls.S	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc/kernel/systbls.S	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.83.2.3 2001/01/11 15:44:37 davem Exp $
+/* $Id: systbls.S,v 1.83.2.4 2001/01/11 19:12:10 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -48,7 +48,7 @@
 /*135*/	.long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_lfs_syscall
 /*140*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
 /*145*/	.long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
-/*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
+/*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_lfs_syscall
 /*155*/	.long sys_lfs_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 /*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
diff -urN linux-2.2.19-pre8/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux-2.2.19-pre8/arch/sparc64/config.in	Sun Dec 10 16:49:41 2000
+++ linux/arch/sparc64/config.in	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.67.2.13 2000/10/24 21:00:53 davem Exp $
+# $Id: config.in,v 1.67.2.14 2001/01/26 22:26:07 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -92,6 +92,7 @@
   fi
   tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
   tristate '7-Segment Display support' CONFIG_DISPLAY7SEG
+  tristate 'CP1XXX Hardware Watchdog support' CONFIG_WATCHDOG_CP1XXX
 fi
 endmenu
 
diff -urN linux-2.2.19-pre8/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.2.19-pre8/arch/sparc64/defconfig	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc64/defconfig	Mon Dec  3 20:59:58 2001
@@ -100,6 +100,7 @@
 CONFIG_PRINTER_READBACK=y
 CONFIG_ENVCTRL=m
 CONFIG_DISPLAY7SEG=m
+CONFIG_WATCHDOG_CP1XXX=m
 
 #
 # Floppy, IDE, and other block devices
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- linux-2.2.19-pre8/arch/sparc64/kernel/binfmt_aout32.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc64/kernel/binfmt_aout32.c	Mon Aug  9 12:04:38 1999
@@ -101,7 +101,7 @@
 #       define START_DATA(u)    (u.u_tsize)
 #       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
 
-	if (current->dumpable != 1 || atomic_read(&current->mm->count) != 1)
+	if (!current->dumpable || atomic_read(&current->mm->count) != 1)
 		return 0;
 	current->dumpable = 0;
 
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- linux-2.2.19-pre8/arch/sparc64/kernel/ebus.c	Mon Sep  4 10:39:16 2000
+++ linux/arch/sparc64/kernel/ebus.c	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.36.2.5 2000/07/27 01:50:59 davem Exp $
+/* $Id: ebus.c,v 1.36.2.6 2001/01/26 22:26:07 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -46,6 +46,9 @@
 #endif
 #ifdef CONFIG_DISPLAY7SEG
 extern int d7s_init(void);
+#endif
+#ifdef CONFIG_WATCHDOG_CP1XXX
+extern int wd_init(void);
 #endif
 
 static inline unsigned long ebus_alloc(size_t size)
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux-2.2.19-pre8/arch/sparc64/kernel/ioctl32.c	Sun Dec 10 16:49:41 2000
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.62.2.17 2000/11/08 09:43:04 davem Exp $
+/* $Id: ioctl32.c,v 1.62.2.18 2001/01/26 22:26:07 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -63,6 +63,7 @@
 #include <asm/audioio.h>
 #include <asm/ethtool.h>
 #include <asm/display7seg.h>
+#include <asm/watchdog.h>
 
 #include <linux/soundcard.h>
 
@@ -3093,6 +3094,17 @@
 	case AUTOFS_IOC_CATATONIC:
 	case AUTOFS_IOC_PROTOVER:
 	case AUTOFS_IOC_EXPIRE:
+
+	/* Big W for hardware watchdog timers */
+	/* WIOC_GETSUPPORT not yet implemented -E */
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+	case WDIOC_GETTEMP:
+	case WDIOC_SETOPTIONS:
+	case WDIOC_KEEPALIVE:
+	case WIOCSTART:
+	case WIOCSTOP:
+	case WIOCGSTAT:
 	
 	/* Raw devices */
 	case _IO(0xac, 0): /* RAW_SETBIND */
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- linux-2.2.19-pre8/arch/sparc64/kernel/ptrace.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc64/kernel/ptrace.c	Wed May  3 17:16:32 2000
@@ -605,7 +605,7 @@
 			pt_error_return(regs, EPERM);
 			goto out;
 		}
-		if((child->dumpable != 1 ||
+		if((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->uid) ||
 		    (current->gid != child->egid) ||
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.2.19-pre8/arch/sparc64/kernel/sys_sunos32.c	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.22.2.5 2001/01/04 05:35:03 davem Exp $
+/* $Id: sys_sunos32.c,v 1.22.2.6 2001/02/02 01:30:09 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -677,7 +677,7 @@
 
 struct sunos_nfs_mount_args {
 	struct sockaddr_in  *addr; /* file server address */
-	struct nfs_fh *fh;     /* File handle to be mounted */
+	struct nfs3_fh *fh;     /* File handle to be mounted */
 	int        flags;      /* flags */
 	int        wsize;      /* write size in bytes */
 	int        rsize;      /* read size in bytes */
diff -urN linux-2.2.19-pre8/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- linux-2.2.19-pre8/arch/sparc64/kernel/systbls.S	Mon Dec  3 20:59:32 2001
+++ linux/arch/sparc64/kernel/systbls.S	Mon Dec  3 20:59:58 2001
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.53.2.6 2001/01/11 15:44:37 davem Exp $
+/* $Id: systbls.S,v 1.53.2.7 2001/01/11 19:12:10 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -49,7 +49,7 @@
 	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_lfs_syscall
 /*140*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
 	.word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
-/*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
+/*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_lfs_syscall
 	.word sys_lfs_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
 /*160*/	.word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 	.word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
diff -urN linux-2.2.19-pre8/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- linux-2.2.19-pre8/drivers/net/cs89x0.c	Mon Dec  3 20:59:32 2001
+++ linux/drivers/net/cs89x0.c	Mon Dec  3 21:00:01 2001
@@ -1018,16 +1018,15 @@
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(debug, "i");
-MODULE_PARM(media, "s");
+MODULE_PARM(media, "c8");
 MODULE_PARM(duplex, "i");
 
 EXPORT_NO_SYMBOLS;
 
 /*
-* media=t             - specify media type
-   or media=2
+* media=rj45             - specify media type
+   or media=bnc
    or media=aui
-   or medai=auto
 * duplex=0            - specify forced half/full/autonegotiate duplex
 * debug=#             - debug level
 
diff -urN linux-2.2.19-pre8/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile
--- linux-2.2.19-pre8/drivers/sbus/char/Makefile	Mon Sep  4 10:39:20 2000
+++ linux/drivers/sbus/char/Makefile	Mon Dec  3 21:00:03 2001
@@ -45,6 +45,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_WATCHDOG_CP1XXX),y)
+O_OBJS += cpwatchdog.o
+else
+  ifeq ($(CONFIG_WATCHDOG_CP1XXX),m)
+  M_OBJS += cpwatchdog.o
+  endif
+endif
+
 endif # eq($(CONFIG_PCI,y)
 
 ifeq ($(CONFIG_OBP_FLASH),y)
diff -urN linux-2.2.19-pre8/drivers/sbus/char/cpwatchdog.c linux/drivers/sbus/char/cpwatchdog.c
--- linux-2.2.19-pre8/drivers/sbus/char/cpwatchdog.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sbus/char/cpwatchdog.c	Mon Dec  3 21:00:03 2001
@@ -0,0 +1,846 @@
+/* cpwatchdog.c - driver implementation for hardware watchdog
+ * timers found on Sun Microsystems CP1400 and CP1500 boards.
+ *
+ * This device supports both the generic Linux watchdog 
+ * interface and Solaris-compatible ioctls as best it is
+ * able.
+ *
+ * NOTE: 	CP1400 systems appear to have a defective intr_mask
+ * 			register on the PLD, preventing the disabling of
+ * 			timer interrupts.  We use a timer to periodically 
+ * 			reset 'stopped' watchdogs on affected platforms.
+ *
+ * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <asm/irq.h>
+#include <asm/ebus.h>
+#include <asm/oplib.h>
+#include <asm/uaccess.h>
+
+#include <asm/watchdog.h>
+
+#define WD_OBPNAME	"watchdog"
+#define WD_BADMODEL "SUNW,501-5336"
+#define WD_BTIMEOUT	(jiffies + (HZ * 1000))
+#define WD_BLIMIT	0xFFFF
+
+#define WD0_DEVNAME "watchdog0"
+#define WD1_DEVNAME "watchdog1"
+#define WD2_DEVNAME "watchdog2"
+
+#define WD0_MINOR	212
+#define WD1_MINOR	213	
+#define WD2_MINOR	214	
+
+#define WD_DEBUG
+
+/* Internal driver definitions
+ */
+#define WD0_ID			0		/* Watchdog0						*/
+#define WD1_ID			1		/* Watchdog1						*/
+#define WD2_ID			2		/* Watchdog2						*/
+#define WD_NUMDEVS		3		/* Device contains 3 timers			*/
+
+#define WD_INTR_OFF		0		/* Interrupt disable value			*/
+#define WD_INTR_ON		1		/* Interrupt enable value			*/
+
+#define WD_STAT_INIT	0x01	/* Watchdog timer is initialized	*/
+#define WD_STAT_BSTOP	0x02	/* Watchdog timer is brokenstopped	*/
+#define WD_STAT_SVCD	0x04	/* Watchdog interrupt occurred		*/
+
+/* Register value definitions
+ */
+#define WD0_INTR_MASK	0x01	/* Watchdog device interrupt masks	*/
+#define WD1_INTR_MASK	0x02
+#define WD2_INTR_MASK	0x04
+
+#define WD_S_RUNNING	0x01	/* Watchdog device status running	*/
+#define WD_S_EXPIRED	0x02	/* Watchdog device status expired	*/
+
+/* Sun uses Altera PLD EPF8820ATC144-4 
+ * providing three hardware watchdogs:
+ *
+ * 	1) RIC - sends an interrupt when triggered
+ * 	2) XIR - asserts XIR_B_RESET when triggered, resets CPU
+ * 	3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
+ *
+ *** Timer register block definition (struct wd_timer_regblk)
+ *
+ * dcntr and limit registers (halfword access):      
+ * -------------------
+ * | 15 | ...| 1 | 0 |
+ * -------------------
+ * |-  counter val  -|
+ * -------------------
+ * dcntr - 	Current 16-bit downcounter value.
+ * 			When downcounter reaches '0' watchdog expires.
+ * 			Reading this register resets downcounter with 'limit' value.
+ * limit - 	16-bit countdown value in 1/10th second increments.
+ * 			Writing this register begins countdown with input value.
+ * 			Reading from this register does not affect counter.
+ * NOTES:	After watchdog reset, dcntr and limit contain '1'
+ *
+ * status register (byte access):
+ * ---------------------------
+ * | 7 | ... | 2 |  1  |  0  |
+ * --------------+------------
+ * |-   UNUSED  -| EXP | RUN |
+ * ---------------------------
+ * status-	Bit 0 - Watchdog is running
+ * 			Bit 1 - Watchdog has expired
+ *
+ *** PLD register block definition (struct wd_pld_regblk)
+ *
+ * intr_mask register (byte access):
+ * ---------------------------------
+ * | 7 | ... | 3 |  2  |  1  |  0  |
+ * +-------------+------------------
+ * |-   UNUSED  -| WD3 | WD2 | WD1 |
+ * ---------------------------------
+ * WD3 -  1 == Interrupt disabled for watchdog 3
+ * WD2 -  1 == Interrupt disabled for watchdog 2
+ * WD1 -  1 == Interrupt disabled for watchdog 1
+ *
+ * pld_status register (byte access):
+ * UNKNOWN, MAGICAL MYSTERY REGISTER
+ *
+ */
+struct wd_timer_regblk {
+	volatile __u16	dcntr;		/* down counter		- hw	*/
+	volatile __u16	dcntr_pad;
+	volatile __u16	limit;		/* limit register	- hw	*/
+	volatile __u16	limit_pad;
+	volatile __u8	status;		/* status register	- b		*/
+	volatile __u8	status_pad;
+	volatile __u16	status_pad2;
+	volatile __u32	pad32;		/* yet more padding			*/
+};
+
+struct wd_pld_regblk {
+	volatile __u8	intr_mask;	/* interrupt mask	- b		*/
+	volatile __u8	intr_mask_pad;
+	volatile __u16	intr_mask_pad2;
+	volatile __u8	status;		/* device status	- b		*/
+	volatile __u8	status_pad;
+	volatile __u16	status_pad2;
+};
+
+struct wd_regblk {
+	volatile struct wd_timer_regblk		wd0_regs;
+	volatile struct wd_timer_regblk		wd1_regs;
+	volatile struct wd_timer_regblk		wd2_regs;
+	volatile struct wd_pld_regblk		pld_regs;
+};
+
+/* Individual timer structure 
+ */
+struct wd_timer {
+	__u16			timeout;
+	__u8			intr_mask;
+	unsigned char	runstatus;
+	volatile struct wd_timer_regblk* regs;
+};
+
+/* Device structure
+ */
+struct wd_device {
+	int				irq;
+	spinlock_t		lock;
+	unsigned char	isbaddoggie;	/* defective PLD */
+	unsigned char	opt_enable;
+	unsigned char	opt_reboot;
+	unsigned short	opt_timeout;
+	unsigned char	initialized;
+	struct wd_timer	watchdog[WD_NUMDEVS];
+	volatile struct	wd_regblk* regs;
+};
+
+static struct wd_device wd_dev = { 
+		0, SPIN_LOCK_UNLOCKED, 0, 0, 0, 0,
+};
+
+struct timer_list wd_timer;
+
+static int wd0_timeout = 0;
+static int wd1_timeout = 0;
+static int wd2_timeout = 0;
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM		(wd0_timeout, "i");
+MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
+MODULE_PARM 	(wd1_timeout, "i");
+MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
+MODULE_PARM 	(wd2_timeout, "i");
+MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
+
+MODULE_AUTHOR
+	("Eric Brower <ebrower@usa.net>");
+MODULE_DESCRIPTION
+	("Hardware watchdog driver for Sun Microsystems CP1400/1500");
+MODULE_SUPPORTED_DEVICE
+	("watchdog");
+#endif /* ifdef MODULE */
+
+/* Forward declarations of internal methods
+ */
+void wd_dumpregs(void);
+void wd_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void wd_toggleintr(struct wd_timer* pTimer, int enable);
+void wd_pingtimer(struct wd_timer* pTimer);
+void wd_starttimer(struct wd_timer* pTimer);
+void wd_resetbrokentimer(struct wd_timer* pTimer);
+void wd_stoptimer(struct wd_timer* pTimer);
+void wd_brokentimer(unsigned long data);
+int  wd_getstatus(struct wd_timer* pTimer);
+
+#define wd_writew(val, addr)	(addr = val)
+#define wd_writeb(val, addr)	(addr = val)
+#define wd_readw(addr)			(addr)
+#define wd_readb(addr)			(addr)
+
+/* CP1400s seem to have broken PLD implementations--
+ * the interrupt_mask register cannot be written, so
+ * no timer interrupts can be masked within the PLD.
+ */
+static inline int wd_isbroken(void)
+{
+	/* we could test this by read/write/read/restore
+	 * on the interrupt mask register only if OBP
+	 * 'watchdog-enable?' == FALSE, but it seems 
+	 * ubiquitous on CP1400s
+	 */
+	char val[32];
+	prom_getproperty(prom_root_node, "model", val, sizeof(val));
+	return((!strcmp(val, WD_BADMODEL)) ? 1 : 0);
+}
+		
+/* Retrieve watchdog-enable? option from OBP
+ * Returns 0 if false, 1 if true
+ */
+static inline int wd_opt_enable(void)
+{
+	int opt_node;
+
+	opt_node = prom_getchild(prom_root_node);
+	opt_node = prom_searchsiblings(opt_node, "options");
+	return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1);
+}
+
+/* Retrieve watchdog-reboot? option from OBP
+ * Returns 0 if false, 1 if true
+ */
+static inline int wd_opt_reboot(void)
+{
+	int opt_node;
+
+	opt_node = prom_getchild(prom_root_node);
+	opt_node = prom_searchsiblings(opt_node, "options");
+	return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1);
+}
+
+/* Retrieve watchdog-timeout option from OBP
+ * Returns OBP value, or 0 if not located
+ */
+static inline int wd_opt_timeout(void)
+{
+	int opt_node;
+	char value[32];
+	char *p = value;
+
+	opt_node = prom_getchild(prom_root_node);
+	opt_node = prom_searchsiblings(opt_node, "options");
+	opt_node = prom_getproperty(opt_node, 
+								"watchdog-timeout", 
+								value, 
+								sizeof(value));
+	if(-1 != opt_node) {
+		/* atoi implementation */
+		for(opt_node = 0; /* nop */; p++) {
+			if(*p >= '0' && *p <= '9') {
+				opt_node = (10*opt_node)+(*p-'0');
+			}
+			else {
+				break;
+			}
+		}
+	}
+	return((-1 == opt_node) ? (0) : (opt_node)); 
+}
+
+static int wd_open(struct inode *inode, struct file *f)
+{
+	switch(MINOR(inode->i_rdev))
+	{
+		case WD0_MINOR:
+			f->private_data = &wd_dev.watchdog[WD0_ID];
+			break;
+		case WD1_MINOR:
+			f->private_data = &wd_dev.watchdog[WD1_ID];
+			break;
+		case WD2_MINOR:
+			f->private_data = &wd_dev.watchdog[WD2_ID];
+			break;
+		default:
+			return(-ENODEV);
+	}
+
+	/* Register IRQ on first open of device */
+	if(0 == wd_dev.initialized)
+	{	
+		if (request_irq(wd_dev.irq, 
+						&wd_interrupt, 
+						SA_SHIRQ,
+						WD_OBPNAME,
+						(void *)wd_dev.regs)) {
+			printk("%s: Cannot register IRQ %s\n", 
+				WD_OBPNAME, __irq_itoa(wd_dev.irq));
+			return(-EBUSY);
+		}
+		wd_dev.initialized = 1;
+	}
+
+	MOD_INC_USE_COUNT;
+	return(0);
+}
+
+static int wd_release(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int wd_ioctl(struct inode *inode, struct file *file, 
+		     unsigned int cmd, unsigned long arg)
+{
+	int 	setopt 				= 0;
+	struct 	wd_timer* pTimer 	= (struct wd_timer*)file->private_data;
+	struct 	watchdog_info info 	= {
+		0,
+		0,
+		"Altera EPF8820ATC144-4"
+	};
+
+	if(NULL == pTimer) {
+		return(-EINVAL);
+	}
+
+	switch(cmd)
+	{
+		/* Generic Linux IOCTLs */
+		case WDIOC_GETSUPPORT:
+			if(copy_to_user((struct watchdog_info *)arg, 
+							(struct watchdog_info *)&info, 
+							sizeof(struct watchdog_info *))) {
+				return(-EFAULT);
+			}
+			break;
+		case WDIOC_KEEPALIVE:
+			wd_pingtimer(pTimer);
+			break;
+		case WDIOC_SETOPTIONS:
+			if(copy_from_user(&setopt, (void*) arg, sizeof(unsigned int))) {
+				return -EFAULT;
+			}
+			if(setopt & WDIOS_DISABLECARD) {
+				if(wd_dev.opt_enable) {
+					printk(
+						"%s: cannot disable watchdog in ENABLED mode\n",
+						WD_OBPNAME);
+					return(-EINVAL);
+				}
+				wd_stoptimer(pTimer);
+			}
+			else if(setopt & WDIOS_ENABLECARD) {
+				wd_starttimer(pTimer);
+			}
+			else {
+				return(-EINVAL);
+			}	
+			break;
+		/* Solaris-compatible IOCTLs */
+		case WIOCGSTAT:
+			setopt = wd_getstatus(pTimer);
+			if(copy_to_user((void*)arg, &setopt, sizeof(unsigned int))) {
+				return(-EFAULT);
+			}
+			break;
+		case WIOCSTART:
+			wd_starttimer(pTimer);
+			break;
+		case WIOCSTOP:
+			if(wd_dev.opt_enable) {
+				printk("%s: cannot disable watchdog in ENABLED mode\n",
+					WD_OBPNAME);
+				return(-EINVAL);
+			}
+			wd_stoptimer(pTimer);
+			break;
+		default:
+			return(-EINVAL);
+	}
+	return(0);
+}
+
+static ssize_t wd_write(	struct file 	*file, 
+							const char		*buf, 
+							size_t 			count, 
+							loff_t 			*ppos)
+{
+	struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
+
+	if(NULL == pTimer) {
+		return(-EINVAL);
+	}
+
+	wd_pingtimer(pTimer);
+	return(count);
+}
+
+static ssize_t wd_read(struct file * file, char * buffer,
+		        size_t count, loff_t *ppos)
+{
+#ifdef WD_DEBUG
+	wd_dumpregs();
+	return(0);
+#else
+	return(-EINVAL);
+#endif /* ifdef WD_DEBUG */
+}
+
+void wd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* Only WD0 will interrupt-- others are NMI and we won't
+	 * see them here....
+	 */
+	spin_lock_irq(&wd_dev.lock);
+	if((unsigned long)wd_dev.regs == (unsigned long)dev_id)
+	{
+		wd_stoptimer(&wd_dev.watchdog[WD0_ID]);
+		wd_dev.watchdog[WD0_ID].runstatus |=  WD_STAT_SVCD;
+	}
+	spin_unlock_irq(&wd_dev.lock);
+	return;
+}
+
+static struct file_operations wd_fops = {
+	NULL,		/* lseek	*/
+	wd_read,
+	wd_write,
+	NULL,		/* readdir	*/
+	NULL,		/* select	*/
+	wd_ioctl,
+	NULL,		/* mmap		*/
+	wd_open,
+	NULL,		/* flush	*/
+	wd_release,
+	NULL,		/* fsync	*/
+	NULL,		/* fasync	*/
+	NULL,		/* chk media*/
+	NULL,		/* revalid	*/
+	NULL,		/* lock		*/
+};
+
+static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops };
+static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops };
+static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops };
+
+void wd_dumpregs(void)
+{
+	/* Reading from downcounters initiates watchdog countdown--
+	 * Example is included below for illustration purposes.
+	 */
+	int i;
+	printk("%s: dumping register values\n", WD_OBPNAME);
+	for(i = WD0_ID; i < WD_NUMDEVS; ++i) {
+			/* printk("\t%s%i: dcntr  at 0x%lx: 0x%x\n", 
+			  	WD_OBPNAME,
+		 	 	i,
+			 	(unsigned long)(&wd_dev.watchdog[i].regs->dcntr), 
+				wd_readw(wd_dev.watchdog[i].regs->dcntr));
+			*/
+			printk("\t%s%i: limit  at 0x%lx: 0x%x\n", 
+				WD_OBPNAME,
+				i,
+				(unsigned long)(&wd_dev.watchdog[i].regs->limit), 
+				wd_readw(wd_dev.watchdog[i].regs->limit));
+			printk("\t%s%i: status at 0x%lx: 0x%x\n", 
+				WD_OBPNAME,
+				i,
+				(unsigned long)(&wd_dev.watchdog[i].regs->status), 
+				wd_readb(wd_dev.watchdog[i].regs->status));
+			printk("\t%s%i: driver status: 0x%x\n",
+				WD_OBPNAME,
+				i,
+				wd_getstatus(&wd_dev.watchdog[i]));
+	}
+	printk("\tintr_mask  at 0x%lx: 0x%x\n", 
+		(unsigned long)(&wd_dev.regs->pld_regs.intr_mask), 
+		wd_readb(wd_dev.regs->pld_regs.intr_mask));
+	printk("\tpld_status at 0x%lx: 0x%x\n", 
+		(unsigned long)(&wd_dev.regs->pld_regs.status), 
+		wd_readb(wd_dev.regs->pld_regs.status));
+}
+
+/* Enable or disable watchdog interrupts
+ * Because of the CP1400 defect this should only be
+ * called during initialzation or by wd_[start|stop]timer()
+ *
+ * pTimer 	- pointer to timer device, or NULL to indicate all timers 
+ * enable	- non-zero to enable interrupts, zero to disable
+ */
+void wd_toggleintr(struct wd_timer* pTimer, int enable)
+{
+	unsigned char curregs = wd_readb(wd_dev.regs->pld_regs.intr_mask);
+	unsigned char setregs = 
+		(NULL == pTimer) ? 
+			(WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : 
+			(pTimer->intr_mask);
+
+	(WD_INTR_ON == enable) ?
+		(curregs &= ~setregs):
+		(curregs |=  setregs);
+
+	wd_writeb(curregs, wd_dev.regs->pld_regs.intr_mask);
+	return;
+}
+
+/* Reset countdown timer with 'limit' value and continue countdown.
+ * This will not start a stopped timer.
+ *
+ * pTimer	- pointer to timer device
+ */
+void wd_pingtimer(struct wd_timer* pTimer)
+{
+	if(wd_readb(pTimer->regs->status) & WD_S_RUNNING) {
+		wd_readb(pTimer->regs->dcntr);
+	}
+}
+
+/* Stop a running watchdog timer-- the timer actually keeps
+ * running, but the interrupt is masked so that no action is
+ * taken upon expiration.
+ *
+ * pTimer	- pointer to timer device
+ */
+void wd_stoptimer(struct wd_timer* pTimer)
+{
+	if(wd_readb(pTimer->regs->status) & WD_S_RUNNING) {
+		wd_toggleintr(pTimer, WD_INTR_OFF);
+
+		if(wd_dev.isbaddoggie) {
+			pTimer->runstatus |= WD_STAT_BSTOP;
+			wd_brokentimer((unsigned long)&wd_dev);
+		}
+	}
+}
+
+/* Start a watchdog timer with the specified limit value
+ * If the watchdog is running, it will be restarted with
+ * the provided limit value.
+ *
+ * This function will enable interrupts on the specified
+ * watchdog.
+ *
+ * pTimer	- pointer to timer device
+ * limit	- limit (countdown) value in 1/10th seconds
+ */
+void wd_starttimer(struct wd_timer* pTimer)
+{
+	if(wd_dev.isbaddoggie) {
+		pTimer->runstatus &= ~WD_STAT_BSTOP;
+	}
+	pTimer->runstatus &= ~WD_STAT_SVCD;
+	wd_writew(pTimer->timeout, pTimer->regs->limit);
+	wd_toggleintr(pTimer, WD_INTR_ON);
+}
+
+/* Restarts timer with maximum limit value and
+ * does not unset 'brokenstop' value.
+ */
+void wd_resetbrokentimer(struct wd_timer* pTimer)
+{
+	wd_toggleintr(pTimer, WD_INTR_ON);
+	wd_writew(WD_BLIMIT, pTimer->regs->limit);
+}
+
+/* Timer device initialization helper.
+ * Returns 0 on success, other on failure
+ */
+int wd_inittimer(int whichdog)
+{
+	struct miscdevice 				*whichmisc;
+	volatile struct wd_timer_regblk	*whichregs;
+	char 							whichident[8];
+	int								whichmask;
+	__u16							whichlimit;
+
+	switch(whichdog)
+	{
+		case WD0_ID:
+			whichmisc = &wd0_miscdev;
+			strcpy(whichident, "RIC");
+			whichregs = &wd_dev.regs->wd0_regs;
+			whichmask = WD0_INTR_MASK;
+			whichlimit= (0 == wd0_timeout) 	? 
+						(wd_dev.opt_timeout): 
+						(wd0_timeout);
+			break;
+		case WD1_ID:
+			whichmisc = &wd1_miscdev;
+			strcpy(whichident, "XIR");
+			whichregs = &wd_dev.regs->wd1_regs;
+			whichmask = WD1_INTR_MASK;
+			whichlimit= (0 == wd1_timeout) 	? 
+						(wd_dev.opt_timeout): 
+						(wd1_timeout);
+			break;
+		case WD2_ID:
+			whichmisc = &wd2_miscdev;
+			strcpy(whichident, "POR");
+			whichregs = &wd_dev.regs->wd2_regs;
+			whichmask = WD2_INTR_MASK;
+			whichlimit= (0 == wd2_timeout) 	? 
+						(wd_dev.opt_timeout): 
+						(wd2_timeout);
+			break;
+		default:
+			printk("%s: %s: invalid watchdog id: %i\n",
+				WD_OBPNAME, __FUNCTION__, whichdog);
+			return(1);
+	}
+	if(0 != misc_register(whichmisc))
+	{
+		return(1);
+	}
+	wd_dev.watchdog[whichdog].regs			= whichregs;
+	wd_dev.watchdog[whichdog].timeout 		= whichlimit;
+	wd_dev.watchdog[whichdog].intr_mask		= whichmask;
+	wd_dev.watchdog[whichdog].runstatus 	&= ~WD_STAT_BSTOP;
+	wd_dev.watchdog[whichdog].runstatus 	|= WD_STAT_INIT;
+
+	printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n", 
+		WD_OBPNAME, 
+		whichdog, 
+		whichident, 
+		wd_dev.watchdog[whichdog].timeout / 10,
+		wd_dev.watchdog[whichdog].timeout % 10,
+		(0 != wd_dev.opt_enable) ? "in ENABLED mode" : "");
+	return(0);
+}
+
+/* Timer method called to reset stopped watchdogs--
+ * because of the PLD bug on CP1400, we cannot mask
+ * interrupts within the PLD so me must continually
+ * reset the timers ad infinitum.
+ */
+void wd_brokentimer(unsigned long data)
+{
+	struct wd_device* pDev = (struct wd_device*)data;
+	int id, tripped = 0;
+
+	/* kill a running timer instance, in case we
+	 * were called directly instead of by kernel timer
+	 */
+	if(timer_pending(&wd_timer)) {
+		del_timer(&wd_timer);
+	}
+
+	for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+		if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) {
+			++tripped;
+			wd_resetbrokentimer(&pDev->watchdog[id]);
+		}
+	}
+
+	if(tripped) {
+		/* there is at least one timer brokenstopped-- reschedule */
+		wd_timer.expires = WD_BTIMEOUT;
+		add_timer(&wd_timer);
+	}
+}
+
+int wd_getstatus(struct wd_timer* pTimer)
+{
+	unsigned char stat = wd_readb(pTimer->regs->status);
+	unsigned char intr = wd_readb(wd_dev.regs->pld_regs.intr_mask);
+	unsigned char ret  = WD_STOPPED;
+
+	/* determine STOPPED */
+	if(0 == stat ) { 
+		return(ret);
+	}
+	/* determine EXPIRED vs FREERUN vs RUNNING */
+	else if(WD_S_EXPIRED & stat) {
+		ret = WD_EXPIRED;
+	}
+	else if(WD_S_RUNNING & stat) {
+		if(intr & pTimer->intr_mask) {
+			ret = WD_FREERUN;
+		}
+		else {
+			/* Fudge WD_EXPIRED status for defective CP1400--
+			 * IF timer is running 
+			 * 	AND brokenstop is set 
+			 * 	AND an interrupt has been serviced
+			 * we are WD_EXPIRED.
+			 *
+			 * IF timer is running 
+			 * 	AND brokenstop is set 
+			 * 	AND no interrupt has been serviced
+			 * we are WD_FREERUN.
+			 */
+			if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) {
+				if(pTimer->runstatus & WD_STAT_SVCD) {
+					ret = WD_EXPIRED;
+				}
+				else {
+					/* we could as well pretend we are expired */
+					ret = WD_FREERUN;
+				}
+			}
+			else {
+				ret = WD_RUNNING;
+			}
+		}
+	}
+
+	/* determine SERVICED */
+	if(pTimer->runstatus & WD_STAT_SVCD) {
+		ret |= WD_SERVICED;
+	}
+
+	return(ret);
+}
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int wd_init(void))
+#endif
+{
+	int 	id;
+	struct 	linux_ebus *ebus = NULL;
+	struct 	linux_ebus_device *edev = NULL;
+
+	for_each_ebus(ebus) {
+		for_each_ebusdev(edev, ebus) {
+			if (!strcmp(edev->prom_name, WD_OBPNAME))
+				goto ebus_done;
+		}
+	}
+
+ebus_done:
+	if(!edev) {
+		printk("%s: unable to locate device\n", WD_OBPNAME);
+		return -ENODEV;
+	}
+
+	if(check_region(edev->base_address[0], sizeof(*wd_dev.regs)))
+	{
+		printk("%s: Unable to get region %lx, %d\n", 
+			__FUNCTION__, edev->base_address[0], (int)sizeof(*wd_dev.regs));
+	}
+
+	wd_dev.regs = 
+		(struct wd_regblk *)edev->base_address[0];
+	request_region(
+		(unsigned long)wd_dev.regs, sizeof(*wd_dev.regs), WD_OBPNAME);
+
+	if(NULL == wd_dev.regs) {
+		printk("%s: unable to map registers\n", WD_OBPNAME);
+		return(-ENODEV);
+	}
+
+	/* initialize device structure from OBP parameters */
+	wd_dev.irq 			= edev->irqs[0];
+	wd_dev.opt_enable	= wd_opt_enable();
+	wd_dev.opt_reboot	= wd_opt_reboot();
+	wd_dev.opt_timeout	= wd_opt_timeout();
+	wd_dev.isbaddoggie	= wd_isbroken();
+
+	/* disable all interrupts unless watchdog-enabled? == true */
+	if(! wd_dev.opt_enable) {
+		wd_toggleintr(NULL, WD_INTR_OFF);
+	}
+
+	/* register miscellaneous devices */
+	for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+		if(0 != wd_inittimer(id)) {
+			printk("%s%i: unable to initialize\n", WD_OBPNAME, id);
+		}
+	}
+
+	/* warn about possible defective PLD */
+	if(wd_dev.isbaddoggie) {
+		init_timer(&wd_timer);
+		wd_timer.function 	= wd_brokentimer;
+		wd_timer.data		= (unsigned long)&wd_dev;
+		wd_timer.expires	= WD_BTIMEOUT;
+
+		printk("%s: PLD defect workaround enabled for model %s\n",
+			WD_OBPNAME, WD_BADMODEL);
+	}
+	return(0);
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	int id;
+
+	/* if 'watchdog-enable?' == TRUE, timers are not stopped 
+	 * when module is unloaded.  All brokenstopped timers will
+	 * also now eventually trip. 
+	 */
+	for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+		if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs->status)) {
+			if(wd_dev.opt_enable) {
+				printk(KERN_WARNING "%s%i: timer not stopped at release\n",
+					WD_OBPNAME, id);
+			}
+			else {
+				wd_stoptimer(&wd_dev.watchdog[id]);
+				if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) {
+					wd_resetbrokentimer(&wd_dev.watchdog[id]);
+					printk(KERN_WARNING 
+							"%s%i: defect workaround disabled at release, "\
+							"timer expires in ~%01i sec\n",
+							WD_OBPNAME, id, 
+							wd_readw(wd_dev.watchdog[id].regs->limit) / 10);
+				}
+			}
+		}
+	}
+
+	if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) {
+		del_timer(&wd_timer);
+	}
+	if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) {
+		misc_deregister(&wd0_miscdev);
+	}
+	if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) {
+		misc_deregister(&wd1_miscdev);
+	}
+	if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) {
+		misc_deregister(&wd2_miscdev);
+	}
+	if(0 != wd_dev.initialized) {
+		free_irq(wd_dev.irq, (void *)wd_dev.regs);
+	}
+	release_region((unsigned long)wd_dev.regs, sizeof(*wd_dev.regs));
+}
+#endif /* ifdef MODULE */
diff -urN linux-2.2.19-pre8/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- linux-2.2.19-pre8/drivers/scsi/Config.in	Mon Dec  3 20:59:32 2001
+++ linux/drivers/scsi/Config.in	Mon Dec  3 21:00:03 2001
@@ -29,10 +29,9 @@
 dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
 dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
 if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
-    bool '   Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
-    int  '   Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
-    bool '   Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
-    int  '   Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
+    bool '   Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT y
+    int  '   Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 24
+    bool '   Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS y
 fi
 dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI
 dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
diff -urN linux-2.2.19-pre8/drivers/scsi/README.aic7xxx linux/drivers/scsi/README.aic7xxx
--- linux-2.2.19-pre8/drivers/scsi/README.aic7xxx	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/README.aic7xxx	Mon Dec  3 21:00:03 2001
@@ -14,50 +14,17 @@
     Adaptec Cards
     ----------------------------
     AHA-274x
-    AHA-274xT               
-    AHA-2842
-    AHA-2910B               
-    AHA-2920C
-    AHA-2930
-    AHA-2930U
-    AHA-2930CU
-    AHA-2930U2
-    AHA-2940               
-    AHA-2940W              
-    AHA-2940U              
-    AHA-2940UW
-    AHA-2940UW-PRO
-    AHA-2940AU 
-    AHA-2940U2W
-    AHA-2940U2
-    AHA-2940U2B
-    AHA-2940U2BOEM
-    AHA-2944D              
-    AHA-2944WD
-    AHA-2944UD
-    AHA-2944UWD
-    AHA-2950U2
-    AHA-2950U2W
-    AHA-2950U2B
-    AHA-29160M
-    AHA-3940
-    AHA-3940U
-    AHA-3940W
-    AHA-3940UW
-    AHA-3940AUW
-    AHA-3940U2W
-    AHA-3950U2B
-    AHA-3950U2D
-    AHA-3960D
-    AHA-39160M
-    AHA-3985
-    AHA-3985U
-    AHA-3985W
-    AHA-3985UW
+    AHA-274xT
+    AHA-274xW
+    AHA-284x
+    AHA-284xW
+    All PCI based cards using any of the chipsets listed under motherboard
+    chipsets.  In general, this means *all* of the Adaptec SCSI controllers
+    except the ones specifically excluded later on in this document.
 
     Motherboard Chipsets
     ----------------------------
-    AIC-777x   
+    AIC-777x
     AIC-785x
     AIC-786x
     AIC-787x
@@ -71,15 +38,14 @@
         SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
     U - Ultra SCSI, transfer rates up to 40MB/s.
     U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
+    U3- Ultra 3 SCSI, transfer rates up to 160MB/s.
     D - Differential SCSI.
     T - Twin Channel SCSI. Up to 14 SCSI devices.
 
     AHA-274x - EISA SCSI controller
     AHA-284x - VLB SCSI controller
     AHA-29xx - PCI SCSI controller
-    AHA-394x - PCI controllers with two separate SCSI controllers on-board.
-    AHA-398x - PCI RAID controllers with three separate SCSI controllers
-               on-board.
+    AHA-39xx - PCI controllers with multiple separate SCSI channels on-board.
 
   Not Supported Devices
   ------------------------------
@@ -93,7 +59,7 @@
 
     Motherboard Chipsets
     ----------------------------
-    AIC-7810
+    AIC-781x
 
     Bus Types
     ----------------------------
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.h linux/drivers/scsi/aic7xxx/aic7xxx.h
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/aic7xxx/aic7xxx.h	Mon Dec  3 21:00:03 2001
@@ -0,0 +1,114 @@
+/*+M*************************************************************************
+ * Adaptec AIC7xxx device driver for Linux.
+ *
+ * Copyright (c) 1994 John Aycock
+ *   The University of Calgary Department of Computer Science.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $
+ *-M*************************************************************************/
+#ifndef _aic7xxx_h
+#define _aic7xxx_h
+
+#define AIC7XXX_H_VERSION  "3.2.4"
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if defined(__i386__)
+#  define AIC7XXX_BIOSPARAM aic7xxx_biosparam
+#else
+#  define AIC7XXX_BIOSPARAM NULL
+#endif
+
+/*
+ * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
+ * to do with card config are filled in after the card is detected.
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65)
+#define AIC7XXX	{						\
+	next: NULL,						\
+	module: NULL,						\
+	proc_dir: NULL,						\
+	proc_info: aic7xxx_proc_info,				\
+	name: NULL,						\
+	detect: aic7xxx_detect,					\
+	release: aic7xxx_release,				\
+	info: aic7xxx_info,					\
+	command: NULL,						\
+	queuecommand: aic7xxx_queue,				\
+	eh_strategy_handler: NULL,				\
+	eh_abort_handler: NULL,					\
+	eh_device_reset_handler: NULL,				\
+	eh_bus_reset_handler: NULL,				\
+	eh_host_reset_handler: NULL,				\
+	abort: aic7xxx_abort,					\
+	reset: aic7xxx_reset,					\
+	slave_attach: NULL,					\
+	bios_param: AIC7XXX_BIOSPARAM,				\
+	can_queue: 255,		/* max simultaneous cmds      */\
+	this_id: -1,		/* scsi id of host adapter    */\
+	sg_tablesize: 0,	/* max scatter-gather cmds    */\
+	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
+	present: 0,		/* number of 7xxx's present   */\
+	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
+	use_clustering: ENABLE_CLUSTERING,			\
+	use_new_eh_code: 0					\
+}
+#else
+#define AIC7XXX	{						\
+	next: NULL,						\
+	usage_count: NULL,					\
+	proc_dir: NULL, 					\
+	proc_info: aic7xxx_proc_info,				\
+	name: NULL,						\
+	detect: aic7xxx_detect,					\
+	release: aic7xxx_release,				\
+	info: aic7xxx_info,					\
+	command: NULL,						\
+	queuecommand: aic7xxx_queue,				\
+	abort: aic7xxx_abort,					\
+	reset: aic7xxx_reset,					\
+	slave_attach: NULL,					\
+	bios_param: AIC7XXX_BIOSPARAM,				\
+	can_queue: 255,		/* max simultaneous cmds      */\
+	this_id: -1,		/* scsi id of host adapter    */\
+	sg_tablesize: 0,	/* max scatter-gather cmds    */\
+	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
+	present: 0,		/* number of 7xxx's present   */\
+	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
+	use_clustering: ENABLE_CLUSTERING			\
+}
+#endif
+
+extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+extern int aic7xxx_biosparam(Disk *, kdev_t, int[]);
+extern int aic7xxx_detect(Scsi_Host_Template *);
+extern int aic7xxx_command(Scsi_Cmnd *);
+extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int);
+extern int aic7xxx_abort(Scsi_Cmnd *);
+extern int aic7xxx_release(struct Scsi_Host *);
+
+extern const char *aic7xxx_info(struct Scsi_Host *);
+
+extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int);
+
+#endif /* _aic7xxx_h */
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.reg	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx/aic7xxx.reg	Mon Dec  3 21:00:03 2001
@@ -703,7 +703,12 @@
 						 * it that it can fill the
 						 * message buffer.
 						 */
-	mask	TRACEPOINT	0xb0|SEQINT
+	mask	SEQ_SG_FIXUP	0xb0|SEQINT	/* need help with fixing up
+						 * the sg array pointer after
+						 * a phasemis with no valid
+						 * sg elements in the shadow
+						 * pipeline.
+						 */
 	mask	TRACEPOINT2	0xc0|SEQINT
 	mask	MSGIN_PHASEMIS	0xd0|SEQINT	/*
 						 * Target changed phase on us
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx.seq	Mon Sep  4 10:39:20 2000
+++ linux/drivers/scsi/aic7xxx/aic7xxx.seq	Mon Dec  3 21:00:03 2001
@@ -291,7 +291,11 @@
 
 	mov	A, LASTPHASE;
 
-	test	A, ~P_DATAIN	jz p_data;
+	if ((p->features & AHC_ULTRA2) != 0) {
+		test	A, ~P_DATAIN	jz u2_p_data;
+	} else {
+		test	A, ~P_DATAIN	jz p_data;
+	}
 	cmp	A,P_COMMAND	je p_command;
 	cmp	A,P_MESGOUT	je p_mesgout;
 	cmp	A,P_STATUS	je p_status;
@@ -332,133 +336,73 @@
 	/* clear target specific flags */
 	clr	SEQ_FLAGS ret;
 
+ 	if ((p->features & AHC_ULTRA2) != 0) {
+
+
+
+u2_data_phase_reinit:
 /*
  * If we re-enter the data phase after going through another phase, the
  * STCNT may have been cleared, so restore it from the residual field.
+ * On Ultra2, we have to put it into the HCNT field because we have to
+ * drop the data down into the shadow layer via the preload ability.
  */
-data_phase_reinit:
-	if ((p->features & AHC_ULTRA2) != 0) {
 		bmov	HADDR, SHADDR, 4;
 		bmov    HCNT, SCB_RESID_DCNT, 3;
-	}
-	if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
-		bmov    STCNT, SCB_RESID_DCNT, 3;
-	}
-	if ((p->features & AHC_CMD_CHAN) == 0) {
-		mvi	DINDEX, STCNT;
-		mvi	SCB_RESID_DCNT	call bcopy_3;
-	}
-	jmp	data_phase_loop;
-
-p_data:
-	if ((p->features & AHC_ULTRA2) != 0) {
+		jmp	u2_data_phase_loop;
+u2_p_data:
 		mvi	DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
-	} else {
-		mvi	DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
-	}
-	test	LASTPHASE, IOI jnz . + 2;
-	or	DMAPARAMS, DIRECTION;
-	call	assert;			/*
+		test	LASTPHASE, IOI jnz . + 2;
+		or	DMAPARAMS, DIRECTION;
+		call	assert;		/*
 					 * Ensure entering a data
 					 * phase is okay - seen identify, etc.
 					 */
-	if ((p->features & AHC_CMD_CHAN) != 0) {
 		mvi	CCSGADDR, CCSGADDR_MAX;
-	}
-	test	SEQ_FLAGS, DPHASE	jnz data_phase_reinit;
-
-	/* We have seen a data phase */
-	or	SEQ_FLAGS, DPHASE;
-
-	/*
-	 * Initialize the DMA address and counter from the SCB.
-	 * Also set SG_COUNT and SG_NEXT in memory since we cannot
-	 * modify the values in the SCB itself until we see a
-	 * save data pointers message.
-	 */
-	if ((p->features & AHC_CMD_CHAN) != 0) {
+		test	SEQ_FLAGS, DPHASE	jnz u2_data_phase_reinit;
+		or	SEQ_FLAGS, DPHASE;	/* we've seen a data phase */
+		/*
+		 * Initialize the DMA address and counter from the SCB.
+		 * Also set SG_COUNT and SG_NEXT in memory since we cannot
+		 * modify the values in the SCB itself until we see a
+		 * save data pointers message.
+		 */
 		bmov	HADDR, SCB_DATAPTR, 7;
-		bmov    STCNT, HCNT, 3;
 		bmov    SG_COUNT, SCB_SGCOUNT, 5;
-	} else {
-		mvi	DINDEX, HADDR;
-		mvi	SCB_DATAPTR	call bcopy_7;
-		call	set_stcnt_from_hcnt;
-		mvi	DINDEX, SG_COUNT;
-		mvi	SCB_SGCOUNT	call bcopy_5;
-	}
-
-data_phase_loop:
-/* Guard against overruns */
-	test	SG_COUNT, 0xff jnz data_phase_inbounds;
+u2_data_phase_loop:
+		/* Guard against overruns */
+		test	SG_COUNT, 0xff jnz u2_data_phase_inbounds;
 /*
  * Turn on 'Bit Bucket' mode, set the transfer count to
  * 16meg and let the target run until it changes phase.
  * When the transfer completes, notify the host that we
  * had an overrun.
  */
-	or	SXFRCTL1,BITBUCKET;
-	and	DMAPARAMS, ~(HDMAEN|SDMAEN);
-	if ((p->features & AHC_CMD_CHAN) != 0) {
-		if ((p->features & AHC_ULTRA2) != 0) {
-			bmov	HCNT, ALLONES, 3;
-		}
-		bmov	STCNT, ALLONES, 3;
-	} else {
-		mvi	STCNT[0], 0xFF;
-		mvi	STCNT[1], 0xFF;
-		mvi	STCNT[2], 0xFF;
-	}
-data_phase_inbounds:
+		or	SXFRCTL1,BITBUCKET;
+		and	DMAPARAMS, DIRECTION;
+		bmov	HCNT, ALLONES, 3;
+u2_data_phase_inbounds:
 /* If we are the last SG block, tell the hardware. */
-	cmp	SG_COUNT,0x01 jne data_phase_wideodd;
-	if ((p->features & AHC_ULTRA2) == 0) {
-		and	DMAPARAMS, ~WIDEODD;
-	} else {
-		mvi	SG_CACHEPTR, LAST_SEG;
-	}
-data_phase_wideodd:
-	if ((p->features & AHC_ULTRA2) != 0) {
-		mov	SINDEX, ALLONES;
-		mov	DFCNTRL, DMAPARAMS;
-		test	SSTAT0, SDONE jnz .;
-data_phase_dma_loop:
-		test	SSTAT0, SDONE jnz data_phase_dma_done;
-		test	SSTAT1,PHASEMIS	jz data_phase_dma_loop;	/* ie. underrun */
-data_phase_dma_phasemis:
-		test	SSTAT0,SDONE	jnz data_phase_dma_done;
-		clr	SINDEX;			/* Remember the phasemiss */
-	} else {
-		mov	DMAPARAMS  call dma;
-	}
-
-data_phase_dma_done:
-/* Go tell the host about any overruns */
-	test	SXFRCTL1,BITBUCKET jnz data_phase_overrun;
-
-/* Exit if we had an underrun.  dma clears SINDEX in this case. */
-	test	SINDEX,0xff	jz data_phase_finish;
-
+		shl	A, 2, SG_COUNT;
+		cmp	SG_COUNT,0x01 jne u2_data_phase_lastseg;
+		or	A, LAST_SEG;
+u2_data_phase_lastseg:
+		mov	SG_CACHEPTR, A;
+		mov	DFCNTRL, DMAPARAMS; /* start the operation */
+		test	SXFRCTL1, BITBUCKET jnz u2_data_phase_overrun;
+u2_preload_wait:
+		test	SSTAT1, PHASEMIS jnz u2_phasemis;
+		test	DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait;
 /*
- * Advance the scatter-gather pointers if needed 
+ * Advance the scatter-gather pointers 
  */
-sg_advance:
-	dec	SG_COUNT;	/* one less segment to go */
+u2_sg_advance:
+		cmp	SG_COUNT, 0x01	je u2_data_phase_finish;
 
-	test	SG_COUNT, 0xff	jz data_phase_finish; /* Are we done? */
-/*
- * Load a struct scatter and set up the data address and length.
- * If the working value of the SG count is nonzero, then
- * we need to load a new set of values.
- *
- * This, like all DMA's, assumes little-endian host data storage.
- */
-sg_load:
-	if ((p->features & AHC_CMD_CHAN) != 0) {
 		/*
 		 * Do we have any prefetch left???
 		 */
-		cmp	CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
+		cmp	CCSGADDR, CCSGADDR_MAX jne u2_prefetch_avail;
 
 		/*
 		 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
@@ -474,48 +418,263 @@
 		and	CCSGCTL, ~CCSGEN;
 		test	CCSGCTL, CCSGEN jnz .;
 		mvi	CCSGCTL, CCSGRESET;
-prefetched_segs_avail:
-		bmov 	HADDR, CCSGRAM, 8;
-		if ((p->features & AHC_ULTRA2) == 0) {
-			bmov    STCNT, HCNT, 3;
+u2_prefetch_avail:
+		/* Test for a phasemis before we drop the stuff into the
+		 * host regs.  We might have actually missed the phasemis
+		 * while doing the dma of the sg segs.
+		 */
+		test	SSTAT1, PHASEMIS jnz u2_phasemis;
+		dec	SG_COUNT;	      /* one less segment to go */
+		bmov 	HADDR, CCSGRAM, 8;    /* drop the address in place */
+		clr	A;		      /* Advance the SG pointer by */
+		add	SG_NEXT[0],SG_SIZEOF; /* adding SG_SIZEOF to addr0 */
+		adc	SG_NEXT[1],A;         /* and adding any carry to */
+		jmp	u2_data_phase_loop;   /* addr1 */
+
+
+/*
+ * We've loaded all of our segments into the preload layer.  Now, we simply
+ * have to wait for it to finish or for us to get a phasemis.  And, since
+ * we'll get a phasemis if we do finish, all we really need to do is wait
+ * for a phasemis then check if we did actually complete all the segments.
+ */
+u2_data_phase_finish:
+		test	SSTAT1, PHASEMIS jnz u2_phasemis;
+		test	SG_CACHEPTR, LAST_SEG_DONE jz u2_data_phase_finish;
+		clr	SG_COUNT;
+		test	SSTAT1, REQINIT	jz .;
+		test	SSTAT1, PHASEMIS jz u2_data_phase_loop;
+u2_phasemis:
+		call	ultra2_dmafinish;
+		test	SG_CACHEPTR, LAST_SEG_DONE jnz u2_phasemis_end;
+		test	SSTAT2, SHVALID jnz u2_fixup_residual;
+		mvi	INTSTAT, SEQ_SG_FIXUP;
+		jmp	u2_phasemis_end;
+u2_fixup_residual:
+		shr	ARG_1, 2, SG_CACHEPTR;
+u2_phasemis_loop:
+		and	A, 0x3f, SG_COUNT;
+		cmp	ARG_1, A je u2_phasemis_end;
+/*
+ * Subtract SG_SIZEOF from the SG_NEXT pointer and add 1 to the SG_COUNT
+ */
+ 		clr	A;
+		add	SG_NEXT[0], -SG_SIZEOF;
+		adc	SG_NEXT[1], 0xff;
+		inc	SG_COUNT;
+		jmp	u2_phasemis_loop;
+u2_phasemis_end:
+		bmov	SCB_RESID_DCNT, STCNT, 3;
+		mov	SCB_RESID_SGCNT, SG_COUNT;
+		or	SXFRCTL0, CLRSTCNT|CLRCHN;
+		jmp	ITloop;
+
+
+
+/*
+ * Actually turn off the DMA hardware, save our current position into the
+ * proper residual variables, wait for the next REQ signal, then jump to
+ * the ITloop.  Jumping to the ITloop ensures that if we happen to get
+ * brought into the data phase again (or are still in it after our last
+ * segment) that we will properly signal an overrun to the kernel.
+ */
+ultra2_dmafinish:
+		test	DFCNTRL, DIRECTION jnz ultra2_dmahalt;
+		and	DFCNTRL, ~SCSIEN;
+		test	DFCNTRL, SCSIEN jnz .;
+		if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
+			or	DFCNTRL, FIFOFLUSH;
 		}
-	} else {
-		mvi	DINDEX, HADDR;
-		mvi	SG_NEXT	call bcopy_4;
+ultra2_dmafifoflush:
+		if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
+			/*
+			 * hardware bug alert!  This needless set of jumps
+			 * works around a glitch in the silicon.  When the
+			 * PCI DMA fifo goes empty, but there is still SCSI
+			 * data to be flushed into the PCI DMA fifo (and from
+			 * there on into main memory), the FIFOEMP bit will
+			 * come on between the time when the PCI DMA buffer
+			 * went empty and the next bit of data is copied from
+			 * the SCSI fifo into the PCI fifo.  It should only
+			 * come on when both FIFOs (meaning the entire FIFO
+			 * chain) are emtpy.  Since it can take up to 4 cycles
+			 * for new data to be copied from the SCSI fifo into
+			 * the PCI fifo, testing for FIFOEMP status for 4
+			 * extra times gives the needed time for any
+			 * remaining SCSI fifo data to be put in the PCI fifo
+			 * before we declare it *truly* empty.
+			 */
+			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+		}
+		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+		test	DFSTATUS, MREQPEND	jnz .;
+ultra2_dmahalt:
+		and     DFCNTRL, ~(HDMAEN|SCSIEN);
+		test	DFCNTRL, (HDMAEN|SCSIEN) jnz .;
+		ret;
 
-		mvi	HCNT[0],SG_SIZEOF;
-		clr	HCNT[1];
-		clr	HCNT[2];
+u2_data_phase_overrun:
+/*
+ * Wait for the target to quit transferring data on the SCSI bus
+ */
+ 		test	SSTAT1, PHASEMIS jz .;
+		call	ultra2_dmafinish;
+/*
+ * Turn off BITBUCKET mode and notify the host
+ */
+		and	SXFRCTL1, ~BITBUCKET;
+		mvi	INTSTAT,DATA_OVERRUN;
+		jmp	ITloop;
+
+
+
+	} else {  /* NOT Ultra2 */
 
-		or	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
 
-		call	dma_finish;
 
+data_phase_reinit:
+/*
+ * If we re-enter the data phase after going through another phase, the
+ * STCNT may have been cleared, so restore it from the residual field.
+ */
+		if ((p->features & AHC_CMD_CHAN) != 0) {
+			bmov    STCNT, SCB_RESID_DCNT, 3;
+		} else {
+			mvi	DINDEX, STCNT;
+			mvi	SCB_RESID_DCNT	call bcopy_3;
+		}
+		jmp	data_phase_loop;
+p_data:
+		mvi	DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
+		test	LASTPHASE, IOI jnz . + 2;
+		or	DMAPARAMS, DIRECTION;
+		call	assert;		/*
+					 * Ensure entering a data
+					 * phase is okay - seen identify, etc.
+					 */
+		if ((p->features & AHC_CMD_CHAN) != 0) {
+			mvi	CCSGADDR, CCSGADDR_MAX;
+		}
+		test	SEQ_FLAGS, DPHASE	jnz data_phase_reinit;
+		or	SEQ_FLAGS, DPHASE;	/* we've seen a data phase */
 		/*
-		 * Copy data from FIFO into SCB data pointer and data count.
-		 * This assumes that the SG segments are of the form:
-		 * struct ahc_dma_seg {
-		 *	u_int32_t	addr;	four bytes, little-endian order
-		 *	u_int32_t	len;	four bytes, little endian order
-		 * };
+		 * Initialize the DMA address and counter from the SCB.
+		 * Also set SG_COUNT and SG_NEXT in memory since we cannot
+		 * modify the values in the SCB itself until we see a
+		 * save data pointers message.
 		 */
-		mvi	HADDR	call dfdat_in_7;
-		call	set_stcnt_from_hcnt;
-	}
+		if ((p->features & AHC_CMD_CHAN) != 0) {
+			bmov	HADDR, SCB_DATAPTR, 7;
+			bmov    STCNT, HCNT, 3;
+			bmov    SG_COUNT, SCB_SGCOUNT, 5;
+		} else {
+			mvi	DINDEX, HADDR;
+			mvi	SCB_DATAPTR	call bcopy_7;
+			call	set_stcnt_from_hcnt;
+			mvi	DINDEX, SG_COUNT;
+			mvi	SCB_SGCOUNT	call bcopy_5;
+		}
+data_phase_loop:
+		/* Guard against overruns */
+		test	SG_COUNT, 0xff jnz data_phase_inbounds;
+/*
+ * Turn on 'Bit Bucket' mode, set the transfer count to
+ * 16meg and let the target run until it changes phase.
+ * When the transfer completes, notify the host that we
+ * had an overrun.
+ */
+		or	SXFRCTL1,BITBUCKET;
+		and	DMAPARAMS, ~(HDMAEN|SDMAEN);
+		if ((p->features & AHC_CMD_CHAN) != 0) {
+			bmov	STCNT, ALLONES, 3;
+		} else {
+			mvi	STCNT[0], 0xFF;
+			mvi	STCNT[1], 0xFF;
+			mvi	STCNT[2], 0xFF;
+		}
 
-/* Advance the SG pointer */
-	clr	A;			/* add sizeof(struct scatter) */
-	add	SG_NEXT[0],SG_SIZEOF;
-	adc	SG_NEXT[1],A;
+data_phase_inbounds:
+/* If we are the last SG block, tell the hardware. */
+		cmp	SG_COUNT,0x01 jne data_phase_wideodd;
+		and	DMAPARAMS, ~WIDEODD;
+data_phase_wideodd:
+		mov	DMAPARAMS  call dma;
+data_phase_dma_done:
+/* Go tell the host about any overruns */
+		test	SXFRCTL1,BITBUCKET jnz data_phase_overrun;
+
+/* Exit if we had an underrun.  dma clears SINDEX in this case. */
+		test	SINDEX,0xff	jz data_phase_finish;
+/*
+ * Advance the scatter-gather pointers if needed 
+ */
+sg_advance:
+		cmp	SG_COUNT, 0x01	je data_phase_finish; /* Are we done? */
+		dec	SG_COUNT;	/* one less segment to go */
+/*
+ * Load a struct scatter and set up the data address and length.
+ * If the working value of the SG count is nonzero, then
+ * we need to load a new set of values.
+ *
+ * This, like all DMA's, assumes little-endian host data storage.
+ */
+sg_load:
+		if ((p->features & AHC_CMD_CHAN) != 0) {
+			/*
+			 * Do we have any prefetch left???
+			 */
+			cmp	CCSGADDR, CCSGADDR_MAX jne prefetch_avail;
+
+			/*
+			 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
+			 */
+			add	A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
+			mvi	A, CCSGADDR_MAX;
+			jc	. + 2;
+			shl	A, 3, SG_COUNT;
+			mov	CCHCNT, A;
+			bmov	CCHADDR, SG_NEXT, 4;
+			mvi	CCSGCTL, CCSGEN|CCSGRESET;
+			test	CCSGCTL, CCSGDONE jz .;
+			and	CCSGCTL, ~CCSGEN;
+			test	CCSGCTL, CCSGEN jnz .;
+			mvi	CCSGCTL, CCSGRESET;
+prefetch_avail:
+			bmov 	HADDR, CCSGRAM, 8;
+			bmov    STCNT, HCNT, 3;
+		} else {
+			mvi	DINDEX, HADDR;
+			mvi	SG_NEXT	call bcopy_4;
 
-	test    SSTAT1, REQINIT jz .;
-	test	SSTAT1,PHASEMIS	jz data_phase_loop;
+			mvi	HCNT[0],SG_SIZEOF;
+			clr	HCNT[1];
+			clr	HCNT[2];
 
-/* This drops the last SG segment down to the shadow layer for us */
-	if ((p->features & AHC_ULTRA2) != 0) {
-		mov	DFCNTRL, DMAPARAMS;
-		test	SSTAT0, SDONE	jnz .;
-	}
+			or	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
+
+			call	dma_finish;
+
+/*
+ * Copy data from FIFO into SCB data pointer and data count.
+ * This assumes that the SG segments are of the form:
+ * struct ahc_dma_seg {
+ *	u_int32_t	addr;	four bytes, little-endian order
+ *	u_int32_t	len;	four bytes, little endian order
+ * };
+ */
+			mvi	HADDR	call dfdat_in_7;
+			call	set_stcnt_from_hcnt;
+		}
+/* Advance the SG pointer */
+		clr	A;		/* add sizeof(struct scatter) */
+		add	SG_NEXT[0],SG_SIZEOF;
+		adc	SG_NEXT[1],A;
+
+		test    SSTAT1, REQINIT jz .;
+		test	SSTAT1,PHASEMIS	jz data_phase_loop;
 
 data_phase_finish:
 /*
@@ -523,10 +682,7 @@
  * We use STCNT instead of HCNT, since it's a reflection of how many bytes 
  * were transferred on the SCSI (as opposed to the host) bus.
  */
-	if ((p->features & AHC_ULTRA2) != 0) {
-		call	ultra2_dmafinish;
-	}
-	if ((p->features & AHC_ULTRA2) == 0) {
+		clr	SG_COUNT;
 		if ((p->features & AHC_CMD_CHAN) != 0) {
 			bmov    SCB_RESID_DCNT, STCNT, 3;
 			mov	SCB_RESID_SGCNT, SG_COUNT;
@@ -536,52 +692,19 @@
 			mov	SCB_RESID_DCNT[2],STCNT[2];
 			mov	SCB_RESID_SGCNT, SG_COUNT;
 		}
-	}
 
-	jmp	ITloop;
+		jmp	ITloop;
 
 data_phase_overrun:
-	if ((p->features & AHC_ULTRA2) != 0) {
-		call	ultra2_dmafinish;
-	}
 /*
  * Turn off BITBUCKET mode and notify the host
  */
-	and	SXFRCTL1, ~BITBUCKET;
-	mvi	INTSTAT,DATA_OVERRUN;
-	jmp	ITloop;
+		and	SXFRCTL1, ~BITBUCKET;
+		mvi	INTSTAT,DATA_OVERRUN;
+		jmp	ITloop;
+
+
 
-ultra2_dmafinish:
-	if ((p->features & AHC_ULTRA2) != 0) {
-		test	DFCNTRL, DIRECTION jnz ultra2_dmahalt;
-		and	DFCNTRL, ~SCSIEN;
-		test	DFCNTRL, SCSIEN jnz .;
-ultra2_dmafifoflush:
-		or	DFCNTRL, FIFOFLUSH;
-		test	DFSTATUS, FIFOEMP jz . - 1;
-		/*
-		 * hardware bug alert!  This needless set of jumps is to
-		 * protect against a FIFOEMP status bit glitch in the
-		 * silicon.
-		 */
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-		test	DFSTATUS, MREQPEND	jnz .;
-ultra2_dmahalt:
-		test	SCSIOFFSET, 0x7f	jnz ultra2_shutdown;
-ultra2_await_nreq:
-		test	SCSISIGI, REQI	jz ultra2_shutdown;
-		test	SSTAT1, (PHASEMIS|REQINIT)	jz ultra2_await_nreq;
-ultra2_shutdown:
-		and     DFCNTRL, ~(HDMAEN|SCSIEN);
-		test	DFCNTRL, (HDMAEN|SCSIEN) jnz .;
-		bmov	SCB_RESID_DCNT, STCNT, 3;
-		mov	SCB_RESID_SGCNT, SG_COUNT;
-		or	SXFRCTL0, CLRSTCNT|CLRCHN;
-		ret;
 	}
 
 /*
@@ -1021,6 +1144,7 @@
 inb_last:
 	mov	NONE,SCSIDATL ret;		/*dummy read from latch to ACK*/
 
+	
 mesgin_phasemis:
 /*
  * We expected to receive another byte, but the target changed phase
@@ -1080,7 +1204,9 @@
 	 * to drain the data fifo until there is space for the input
 	 * latch to drain and HDMAEN de-asserts.
 	 */
-	mov	NONE, DFDAT;
+	if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
+		mov	NONE, DFDAT;
+	}
 	test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
 }
 return:
@@ -1306,11 +1432,17 @@
 		cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
 		jmp	dma_scb_finish;
 dma_scb_tohost:
-		if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
+		if ((p->features & AHC_ULTRA2) == 0) {
 			mvi	CCSCBCTL, CCSCBRESET;
 			bmov	CCSCBRAM, SCB_CONTROL, 32;
 			or	CCSCBCTL, CCSCBEN|CCSCBRESET;
 			test	CCSCBCTL, CCSCBDONE jz .;
+		} else if ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0) {
+                        mvi     CCSCBCTL, CCARREN|CCSCBRESET;
+			cmp     CCSCBCTL, ARRDONE|CCARREN jne .;
+                        mvi     CCHCNT, 32;
+			mvi     CCSCBCTL, CCSCBEN|CCSCBRESET;
+			cmp     CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
 		} else {
 			mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
 			cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
@@ -1342,17 +1474,81 @@
 		mov	DFDAT,SINDIR;
 		cmp	SINDEX, A jne copy_scb_tofifo_loop;
 		or	DFCNTRL, HDMAEN|FIFOFLUSH;
+		jmp	dma_finish;
 dma_scb_fromhost:
-		call	dma_finish;
-		/* If we were putting the SCB, we are done */
-		test	DMAPARAMS, DIRECTION	jz	return;
-		mvi	SCB_CONTROL  call dfdat_in_7;
-		call	dfdat_in_7_continued;
-		call	dfdat_in_7_continued;
-		jmp	dfdat_in_7_continued;
+		mvi	DINDEX, SCB_CONTROL;
+		if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
+			/*
+			 * Set the A to -24.  It it hits 0, then we let
+			 * our code fall through to dfdat_in_8 to complete
+			 * the last of the copy.
+			 *
+			 * Also, things happen 8 bytes at a time in this
+			 * case, so we may need to drain the fifo at most
+			 * 3 times to keep things flowing
+			 */
+			mvi	A, -24;
+dma_scb_hang_fifo:
+			/* Wait for the first bit of data to hit the fifo */
+			test	DFSTATUS, FIFOEMP jnz .;
+dma_scb_hang_wait:
+			/* OK, now they've started to transfer into the fifo,
+			 * so wait for them to stop trying to transfer any
+			 * more data.
+			 */
+			test	DFSTATUS, MREQPEND jnz .;
+			/*
+			 * OK, they started, then they stopped, now see if they
+			 * managed to complete the job before stopping.  Try
+			 * it multiple times to give the chip a few cycles to
+			 * set the flag if it did complete.
+			 */
+			test	DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
+			test	DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
+			test	DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
+			/*
+			 * Too bad, the chip didn't complete the DMA, but there
+			 * aren't any more memory requests pending, so that
+			 * means it stopped part way through and hung.  That's
+			 * our bug, so now we drain what data there is in the
+			 * fifo in order to get things going again.
+			 */
+dma_scb_hang_empty_fifo:
+			call	dfdat_in_8;
+			add	A, 8;
+			add	SINDEX, A, HCNT;
+			/*
+			 * If there are another 8 bytes of data waiting in the
+			 * fifo, then the carry bit will be set as a result
+			 * of the above add command (unless A is non-negative,
+			 * in which case the carry bit won't be set).
+			 */
+			jc	dma_scb_hang_empty_fifo;
+			/*
+			 * We've emptied the fifo now, but we wouldn't have got
+			 * here if the memory transfer hadn't stopped part way
+			 * through, so go back up to the beginning of the
+			 * loop and start over.  When it succeeds in getting
+			 * all the data down, HDONE will be set and we'll
+			 * jump to the code just below here.
+			 */
+			jmp	dma_scb_hang_fifo;
+dma_scb_hang_dma_done:
+			and	DFCNTRL, ~HDMAEN;
+			test	DFCNTRL, HDMAEN jnz .;
+			call	dfdat_in_8;
+			add	A, 8;
+			cmp	A, 8 jne . - 2;
+			ret;
+		} else {
+			call	dma_finish;
+			call	dfdat_in_8;
+			call	dfdat_in_8;
+			call	dfdat_in_8;
+		}
+dfdat_in_8:
+		mov	DINDIR,DFDAT;
 dfdat_in_7:
-		mov     DINDEX,SINDEX;
-dfdat_in_7_continued:
 		mov	DINDIR,DFDAT;
 		mov	DINDIR,DFDAT;
 		mov	DINDIR,DFDAT;
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_proc.c linux/drivers/scsi/aic7xxx/aic7xxx_proc.c
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_proc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/aic7xxx/aic7xxx_proc.c	Mon Dec  3 21:00:03 2001
@@ -0,0 +1,414 @@
+/*+M*************************************************************************
+ * Adaptec AIC7xxx device driver proc support for Linux.
+ *
+ * Copyright (c) 1995, 1996 Dean W. Gehnert
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ----------------------------------------------------------------
+ *  o Modified from the EATA-DMA /proc support.
+ *  o Additional support for device block statistics provided by
+ *    Matthew Jacob.
+ *  o Correction of overflow by Heinz Mauelshagen
+ *  o Adittional corrections by Doug Ledford
+ *
+ *  Dean W. Gehnert, deang@teleport.com, 05/01/96
+ *
+ *  $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
+ *-M*************************************************************************/
+
+#include <linux/config.h>
+
+#define	BLS	(&aic7xxx_buffer[size])
+#define HDRB \
+"             < 2K      2K+     4K+     8K+    16K+    32K+    64K+   128K+"
+
+#ifdef PROC_DEBUG
+extern int vsprintf(char *, const char *, va_list);
+
+static void
+proc_debug(const char *fmt, ...)
+{
+  va_list ap;
+  char buf[256];
+
+  va_start(ap, fmt);
+  vsprintf(buf, fmt, ap);
+  printk(buf);
+  va_end(ap);
+}
+#else /* PROC_DEBUG */
+#  define proc_debug(fmt, args...)
+#endif /* PROC_DEBUG */
+
+static int aic7xxx_buffer_size = 0;
+static char *aic7xxx_buffer = NULL;
+
+
+/*+F*************************************************************************
+ * Function:
+ *   aic7xxx_set_info
+ *
+ * Description:
+ *   Set parameters for the driver from the /proc filesystem.
+ *-F*************************************************************************/
+int
+aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+  proc_debug("aic7xxx_set_info(): %s\n", buffer);
+  return (-ENOSYS);  /* Currently this is a no-op */
+}
+
+
+/*+F*************************************************************************
+ * Function:
+ *   aic7xxx_proc_info
+ *
+ * Description:
+ *   Return information to handle /proc support for the driver.
+ *-F*************************************************************************/
+int
+aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length, 
+                    int hostno, int inout)
+{
+  struct Scsi_Host *HBAptr;
+  struct aic7xxx_host *p;
+  int    size = 0;
+  unsigned char i;
+  struct aic7xxx_xferstats *sp;
+  unsigned char target;
+
+  HBAptr = NULL;
+
+  for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
+    ;
+
+  if (!p)
+  {
+    size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
+    if (size > length)
+    {
+      return (size);
+    }
+    else
+    {
+      return (length);
+    }
+  }
+
+  HBAptr = p->host;
+
+  if (inout == TRUE) /* Has data been written to the file? */ 
+  {
+    return (aic7xxx_set_info(buffer, length, HBAptr));
+  }
+
+  p = (struct aic7xxx_host *) HBAptr->hostdata;
+
+  /*
+   * It takes roughly 1K of space to hold all relevant card info, not
+   * counting any proc stats, so we start out with a 1.5k buffer size and
+   * if proc_stats is defined, then we sweep the stats structure to see
+   * how many drives we will be printing out for and add 384 bytes per
+   * device with active stats.
+   *
+   * Hmmmm...that 1.5k seems to keep growing as items get added so they
+   * can be easily viewed for debugging purposes.  So, we bumped that
+   * 1.5k to 4k so we can quit having to bump it all the time.
+   */
+
+  size = 4096;
+  for (target = 0; target < MAX_TARGETS; target++)
+  {
+    if (p->dev_flags[target] & DEVICE_PRESENT)
+#ifdef AIC7XXX_PROC_STATS
+      size += 512;
+#else
+      size += 256;
+#endif
+  }
+  if (aic7xxx_buffer_size != size)
+  {
+    if (aic7xxx_buffer != NULL) 
+    {
+      kfree(aic7xxx_buffer);
+      aic7xxx_buffer_size = 0;
+    }
+    aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
+  }
+  if (aic7xxx_buffer == NULL)
+  {
+    size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
+        __LINE__);
+    return size;
+  }
+  aic7xxx_buffer_size = size;
+
+  size = 0;
+  size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
+  size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
+  size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
+  size += sprintf(BLS, "\n");
+  size += sprintf(BLS, "Compile Options:\n");
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+  size += sprintf(BLS, "  TCQ Enabled By Default : Enabled\n");
+#else
+  size += sprintf(BLS, "  TCQ Enabled By Default : Disabled\n");
+#endif
+#ifdef AIC7XXX_PROC_STATS
+  size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Enabled\n");
+#else
+  size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Disabled\n");
+#endif
+  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n", AIC7XXX_RESET_DELAY);
+  size += sprintf(BLS, "\n");
+  size += sprintf(BLS, "Adapter Configuration:\n");
+  size += sprintf(BLS, "           SCSI Adapter: %s\n",
+      board_names[p->board_name_index]);
+  if (p->flags & AHC_TWIN)
+    size += sprintf(BLS, "                         Twin Channel Controller ");
+  else
+  {
+    char *channel = "";
+    char *ultra = "";
+    char *wide = "Narrow ";
+    if (p->flags & AHC_MULTI_CHANNEL)
+    {
+      channel = " Channel A";
+      if (p->flags & (AHC_CHNLB|AHC_CHNLC))
+        channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C";
+    }
+    if (p->features & AHC_WIDE)
+      wide = "Wide ";
+    if (p->features & AHC_ULTRA3)
+    {
+      switch(p->chip & AHC_CHIPID_MASK)
+      {
+        case AHC_AIC7892:
+        case AHC_AIC7899:
+          ultra = "Ultra-160/m LVD/SE ";
+          break;
+        default:
+          ultra = "Ultra-3 LVD/SE ";
+          break;
+      }
+    }
+    else if (p->features & AHC_ULTRA2)
+      ultra = "Ultra-2 LVD/SE ";
+    else if (p->features & AHC_ULTRA)
+      ultra = "Ultra ";
+    size += sprintf(BLS, "                           %s%sController%s ",
+      ultra, wide, channel);
+  }
+  switch(p->chip & ~AHC_CHIPID_MASK)
+  {
+    case AHC_VL:
+      size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+      break;
+    case AHC_EISA:
+      size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+      break;
+    default:
+      size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+        PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
+      break;
+  }
+  if( !(p->maddr) )
+  {
+    size += sprintf(BLS, "    Programmed I/O Base: %lx\n", p->base);
+  }
+  else
+  {
+    size += sprintf(BLS, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
+  }
+  if( (p->chip & (AHC_VL | AHC_EISA)) )
+  {
+    size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
+  }
+  size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
+          (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
+         ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
+           "SEEPROM not found, using leftover BIOS values.") );
+  size += sprintf(BLS, "      Adaptec SCSI BIOS: %s\n",
+          (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
+  size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
+  size += sprintf(BLS, "                   SCBs: Active %d, Max Active %d,\n",
+            p->activescbs, p->max_activescbs);
+  size += sprintf(BLS, "                         Allocated %d, HW %d, "
+            "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
+            p->scb_data->maxscbs);
+  if (p->flags & AHC_EXTERNAL_SRAM)
+    size += sprintf(BLS, "                         Using External SCB SRAM\n");
+  size += sprintf(BLS, "             Interrupts: %ld", p->isr_count);
+  if (p->chip & AHC_EISA)
+  {
+    size += sprintf(BLS, " %s\n",
+        (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
+  }
+  else
+  {
+    size += sprintf(BLS, "\n");
+  }
+  size += sprintf(BLS, "      BIOS Control Word: 0x%04x\n",
+            p->bios_control);
+  size += sprintf(BLS, "   Adapter Control Word: 0x%04x\n",
+            p->adapter_control);
+  size += sprintf(BLS, "   Extended Translation: %sabled\n",
+      (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
+  size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
+  if (p->features & (AHC_ULTRA | AHC_ULTRA2))
+  {
+    size += sprintf(BLS, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
+  }
+  size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
+  size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
+  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE);
+  size += sprintf(BLS, "    Tagged Queue By Device array for aic7xxx host "
+                       "instance %d:\n", p->instance);
+  size += sprintf(BLS, "      {");
+  for(i=0; i < (MAX_TARGETS - 1); i++)
+    size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
+  size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
+  size += sprintf(BLS, "    Actual queue depth per device for aic7xxx host "
+                       "instance %d:\n", p->instance);
+  size += sprintf(BLS, "      {");
+  for(i=0; i < (MAX_TARGETS - 1); i++)
+    size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]);
+  size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]);
+
+  size += sprintf(BLS, "\n");
+  size += sprintf(BLS, "Statistics:\n\n");
+  for (target = 0; target < MAX_TARGETS; target++)
+  {
+    sp = &p->stats[target];
+    if ((p->dev_flags[target] & DEVICE_PRESENT) == 0)
+    {
+      continue;
+    }
+    if (p->features & AHC_TWIN)
+    {
+      size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+          p->host_no, (target >> 3), (target & 0x7), 0);
+    }
+    else
+    {
+      size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+          p->host_no, 0, target, 0);
+    }
+    size += sprintf(BLS, "  Device using %s/%s",
+          (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
+          "Wide" : "Narrow",
+          (p->transinfo[target].cur_offset != 0) ?
+          "Sync transfers at " : "Async transfers.\n" );
+    if (p->transinfo[target].cur_offset != 0)
+    {
+      struct aic7xxx_syncrate *sync_rate;
+      unsigned char options = p->transinfo[target].cur_options;
+      int period = p->transinfo[target].cur_period;
+      int rate = (p->transinfo[target].cur_width ==
+                  MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
+
+      sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
+      if (sync_rate != NULL)
+      {
+        size += sprintf(BLS, "%s MByte/sec, offset %d\n",
+                        sync_rate->rate[rate],
+                        p->transinfo[target].cur_offset );
+      }
+      else
+      {
+        size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
+                        p->transinfo[target].cur_offset );
+      }
+    }
+    size += sprintf(BLS, "  Transinfo settings: ");
+    size += sprintf(BLS, "current(%d/%d/%d/%d), ",
+                    p->transinfo[target].cur_period,
+                    p->transinfo[target].cur_offset,
+                    p->transinfo[target].cur_width,
+                    p->transinfo[target].cur_options);
+    size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
+                    p->transinfo[target].goal_period,
+                    p->transinfo[target].goal_offset,
+                    p->transinfo[target].goal_width,
+                    p->transinfo[target].goal_options);
+    size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
+                    p->transinfo[target].user_period,
+                    p->transinfo[target].user_offset,
+                    p->transinfo[target].user_width,
+                    p->transinfo[target].user_options);
+#ifdef AIC7XXX_PROC_STATS
+    size += sprintf(BLS, "  Total transfers %ld (%ld reads and %ld writes)\n",
+        sp->r_total + sp->w_total, sp->r_total, sp->w_total);
+    size += sprintf(BLS, "%s\n", HDRB);
+    size += sprintf(BLS, "   Reads:");
+    for (i = 0; i < NUMBER(sp->r_bins); i++)
+    {
+      size += sprintf(BLS, " %7ld", sp->r_bins[i]);
+    }
+    size += sprintf(BLS, "\n");
+    size += sprintf(BLS, "  Writes:");
+    for (i = 0; i < NUMBER(sp->w_bins); i++)
+    {
+      size += sprintf(BLS, " %7ld", sp->w_bins[i]);
+    }
+    size += sprintf(BLS, "\n");
+#else
+    size += sprintf(BLS, "  Total transfers %ld (%ld reads and %ld writes)\n",
+        sp->r_total + sp->w_total, sp->r_total, sp->w_total);
+#endif /* AIC7XXX_PROC_STATS */
+    size += sprintf(BLS, "\n\n");
+  }
+
+  if (size >= aic7xxx_buffer_size)
+  {
+    printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
+  }
+
+  if (offset > size - 1)
+  {
+    kfree(aic7xxx_buffer);
+    aic7xxx_buffer = NULL;
+    aic7xxx_buffer_size = length = 0;
+    *start = NULL;
+  }
+  else
+  {
+    *start = buffer;
+    length = MIN(length, size - offset);
+    memcpy(buffer, &aic7xxx_buffer[offset], length);
+  }
+
+  return (length);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_reg.h linux/drivers/scsi/aic7xxx/aic7xxx_reg.h
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_reg.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/aic7xxx/aic7xxx_reg.h	Mon Dec  3 21:00:03 2001
@@ -0,0 +1,629 @@
+/*
+  * DO NOT EDIT - This file is automatically generated.
+  */
+
+#define	SCSISEQ         		0x00
+#define		TEMODE          	0x80
+#define		ENSELO          	0x40
+#define		ENSELI          	0x20
+#define		ENRSELI         	0x10
+#define		ENAUTOATNO      	0x08
+#define		ENAUTOATNI      	0x04
+#define		ENAUTOATNP      	0x02
+#define		SCSIRSTO        	0x01
+
+#define	SXFRCTL0        		0x01
+#define		DFON            	0x80
+#define		DFPEXP          	0x40
+#define		FAST20          	0x20
+#define		CLRSTCNT        	0x10
+#define		SPIOEN          	0x08
+#define		SCAMEN          	0x04
+#define		CLRCHN          	0x02
+
+#define	SXFRCTL1        		0x02
+#define		BITBUCKET       	0x80
+#define		SWRAPEN         	0x40
+#define		ENSPCHK         	0x20
+#define		STIMESEL        	0x18
+#define		ENSTIMER        	0x04
+#define		ACTNEGEN        	0x02
+#define		STPWEN          	0x01
+
+#define	SCSISIGO        		0x03
+#define		CDO             	0x80
+#define		IOO             	0x40
+#define		MSGO            	0x20
+#define		ATNO            	0x10
+#define		SELO            	0x08
+#define		BSYO            	0x04
+#define		REQO            	0x02
+#define		ACKO            	0x01
+
+#define	SCSISIGI        		0x03
+#define		ATNI            	0x10
+#define		SELI            	0x08
+#define		BSYI            	0x04
+#define		REQI            	0x02
+#define		ACKI            	0x01
+
+#define	SCSIRATE        		0x04
+#define		WIDEXFER        	0x80
+#define		SXFR_ULTRA2     	0x7f
+#define		SXFR            	0x70
+#define		SOFS            	0x0f
+
+#define	SCSIID          		0x05
+#define	SCSIOFFSET      		0x05
+#define		SOFS_ULTRA2     	0x7f
+
+#define	SCSIDATL        		0x06
+
+#define	SCSIDATH        		0x07
+
+#define	STCNT           		0x08
+
+#define	OPTIONMODE      		0x08
+#define		AUTORATEEN      	0x80
+#define		AUTOACKEN       	0x40
+#define		ATNMGMNTEN      	0x20
+#define		BUSFREEREV      	0x10
+#define		EXPPHASEDIS     	0x08
+#define		SCSIDATL_IMGEN  	0x04
+#define		AUTO_MSGOUT_DE  	0x02
+#define		DIS_MSGIN_DUALEDGE	0x01
+
+#define	CLRSINT0        		0x0b
+#define		CLRSELDO        	0x40
+#define		CLRSELDI        	0x20
+#define		CLRSELINGO      	0x10
+#define		CLRSWRAP        	0x08
+#define		CLRSPIORDY      	0x02
+
+#define	SSTAT0          		0x0b
+#define		TARGET          	0x80
+#define		SELDO           	0x40
+#define		SELDI           	0x20
+#define		SELINGO         	0x10
+#define		IOERR           	0x08
+#define		SWRAP           	0x08
+#define		SDONE           	0x04
+#define		SPIORDY         	0x02
+#define		DMADONE         	0x01
+
+#define	CLRSINT1        		0x0c
+#define		CLRSELTIMEO     	0x80
+#define		CLRATNO         	0x40
+#define		CLRSCSIRSTI     	0x20
+#define		CLRBUSFREE      	0x08
+#define		CLRSCSIPERR     	0x04
+#define		CLRPHASECHG     	0x02
+#define		CLRREQINIT      	0x01
+
+#define	SSTAT1          		0x0c
+#define		SELTO           	0x80
+#define		ATNTARG         	0x40
+#define		SCSIRSTI        	0x20
+#define		PHASEMIS        	0x10
+#define		BUSFREE         	0x08
+#define		SCSIPERR        	0x04
+#define		PHASECHG        	0x02
+#define		REQINIT         	0x01
+
+#define	SSTAT2          		0x0d
+#define		OVERRUN         	0x80
+#define		SHVALID         	0x40
+#define		WIDE_RES        	0x20
+#define		SFCNT           	0x1f
+#define		EXP_ACTIVE      	0x10
+#define		CRCVALERR       	0x08
+#define		CRCENDERR       	0x04
+#define		CRCREQERR       	0x02
+#define		DUAL_EDGE_ERROR 	0x01
+
+#define	SSTAT3          		0x0e
+#define		SCSICNT         	0xf0
+#define		OFFCNT          	0x0f
+
+#define	SCSIID_ULTRA2   		0x0f
+#define		OID             	0x0f
+
+#define	SIMODE0         		0x10
+#define		ENSELDO         	0x40
+#define		ENSELDI         	0x20
+#define		ENSELINGO       	0x10
+#define		ENIOERR         	0x08
+#define		ENSWRAP         	0x08
+#define		ENSDONE         	0x04
+#define		ENSPIORDY       	0x02
+#define		ENDMADONE       	0x01
+
+#define	SIMODE1         		0x11
+#define		ENSELTIMO       	0x80
+#define		ENATNTARG       	0x40
+#define		ENSCSIRST       	0x20
+#define		ENPHASEMIS      	0x10
+#define		ENBUSFREE       	0x08
+#define		ENSCSIPERR      	0x04
+#define		ENPHASECHG      	0x02
+#define		ENREQINIT       	0x01
+
+#define	SCSIBUSL        		0x12
+
+#define	SCSIBUSH        		0x13
+
+#define	SHADDR          		0x14
+
+#define	SELTIMER        		0x18
+#define		STAGE6          	0x20
+#define		STAGE5          	0x10
+#define		STAGE4          	0x08
+#define		STAGE3          	0x04
+#define		STAGE2          	0x02
+#define		STAGE1          	0x01
+
+#define	SELID           		0x19
+#define		SELID_MASK      	0xf0
+#define		ONEBIT          	0x08
+
+#define	SPIOCAP         		0x1b
+#define		SOFT1           	0x80
+#define		SOFT0           	0x40
+#define		SOFTCMDEN       	0x20
+#define		HAS_BRDCTL      	0x10
+#define		SEEPROM         	0x08
+#define		EEPROM          	0x04
+#define		ROM             	0x02
+#define		SSPIOCPS        	0x01
+
+#define	BRDCTL          		0x1d
+#define		BRDDAT7         	0x80
+#define		BRDDAT6         	0x40
+#define		BRDDAT5         	0x20
+#define		BRDDAT4         	0x10
+#define		BRDSTB          	0x10
+#define		BRDCS           	0x08
+#define		BRDDAT3         	0x08
+#define		BRDDAT2         	0x04
+#define		BRDRW           	0x04
+#define		BRDRW_ULTRA2    	0x02
+#define		BRDCTL1         	0x02
+#define		BRDSTB_ULTRA2   	0x01
+#define		BRDCTL0         	0x01
+
+#define	SEECTL          		0x1e
+#define		EXTARBACK       	0x80
+#define		EXTARBREQ       	0x40
+#define		SEEMS           	0x20
+#define		SEERDY          	0x10
+#define		SEECS           	0x08
+#define		SEECK           	0x04
+#define		SEEDO           	0x02
+#define		SEEDI           	0x01
+
+#define	SBLKCTL         		0x1f
+#define		DIAGLEDEN       	0x80
+#define		DIAGLEDON       	0x40
+#define		AUTOFLUSHDIS    	0x20
+#define		ENAB40          	0x08
+#define		ENAB20          	0x04
+#define		SELWIDE         	0x02
+#define		XCVR            	0x01
+
+#define	SRAM_BASE       		0x20
+
+#define	TARG_SCSIRATE   		0x20
+
+#define	ULTRA_ENB       		0x30
+
+#define	DISC_DSB        		0x32
+
+#define	MSG_OUT         		0x34
+
+#define	DMAPARAMS       		0x35
+#define		PRELOADEN       	0x80
+#define		WIDEODD         	0x40
+#define		SCSIEN          	0x20
+#define		SDMAENACK       	0x10
+#define		SDMAEN          	0x10
+#define		HDMAEN          	0x08
+#define		HDMAENACK       	0x08
+#define		DIRECTION       	0x04
+#define		FIFOFLUSH       	0x02
+#define		FIFORESET       	0x01
+
+#define	SEQ_FLAGS       		0x36
+#define		IDENTIFY_SEEN   	0x80
+#define		SCBPTR_VALID    	0x20
+#define		DPHASE          	0x10
+#define		AMTARGET        	0x08
+#define		WIDE_BUS        	0x02
+#define		TWIN_BUS        	0x01
+
+#define	SAVED_TCL       		0x37
+
+#define	SG_COUNT        		0x38
+
+#define	SG_NEXT         		0x39
+
+#define	LASTPHASE       		0x3d
+#define		P_MESGIN        	0xe0
+#define		PHASE_MASK      	0xe0
+#define		P_STATUS        	0xc0
+#define		P_MESGOUT       	0xa0
+#define		P_COMMAND       	0x80
+#define		CDI             	0x80
+#define		IOI             	0x40
+#define		P_DATAIN        	0x40
+#define		MSGI            	0x20
+#define		P_BUSFREE       	0x01
+#define		P_DATAOUT       	0x00
+
+#define	WAITING_SCBH    		0x3e
+
+#define	DISCONNECTED_SCBH		0x3f
+
+#define	FREE_SCBH       		0x40
+
+#define	HSCB_ADDR       		0x41
+
+#define	SCBID_ADDR      		0x45
+
+#define	TMODE_CMDADDR   		0x49
+
+#define	KERNEL_QINPOS   		0x4d
+
+#define	QINPOS          		0x4e
+
+#define	QOUTPOS         		0x4f
+
+#define	TMODE_CMDADDR_NEXT		0x50
+
+#define	ARG_1           		0x51
+#define	RETURN_1        		0x51
+#define		SEND_MSG        	0x80
+#define		SEND_SENSE      	0x40
+#define		SEND_REJ        	0x20
+#define		MSGOUT_PHASEMIS 	0x10
+
+#define	ARG_2           		0x52
+#define	RETURN_2        		0x52
+
+#define	LAST_MSG        		0x53
+
+#define	PREFETCH_CNT    		0x54
+
+#define	SCSICONF        		0x5a
+#define		TERM_ENB        	0x80
+#define		RESET_SCSI      	0x40
+#define		HWSCSIID        	0x0f
+#define		HSCSIID         	0x07
+
+#define	HOSTCONF        		0x5d
+
+#define	HA_274_BIOSCTRL 		0x5f
+#define		BIOSMODE        	0x30
+#define		BIOSDISABLED    	0x30
+#define		CHANNEL_B_PRIMARY	0x08
+
+#define	SEQCTL          		0x60
+#define		PERRORDIS       	0x80
+#define		PAUSEDIS        	0x40
+#define		FAILDIS         	0x20
+#define		FASTMODE        	0x10
+#define		BRKADRINTEN     	0x08
+#define		STEP            	0x04
+#define		SEQRESET        	0x02
+#define		LOADRAM         	0x01
+
+#define	SEQRAM          		0x61
+
+#define	SEQADDR0        		0x62
+
+#define	SEQADDR1        		0x63
+#define		SEQADDR1_MASK   	0x01
+
+#define	ACCUM           		0x64
+
+#define	SINDEX          		0x65
+
+#define	DINDEX          		0x66
+
+#define	ALLONES         		0x69
+
+#define	ALLZEROS        		0x6a
+
+#define	NONE            		0x6a
+
+#define	FLAGS           		0x6b
+#define		ZERO            	0x02
+#define		CARRY           	0x01
+
+#define	SINDIR          		0x6c
+
+#define	DINDIR          		0x6d
+
+#define	FUNCTION1       		0x6e
+
+#define	STACK           		0x6f
+
+#define	TARG_OFFSET     		0x70
+
+#define	BCTL            		0x84
+#define		ACE             	0x08
+#define		ENABLE          	0x01
+
+#define	DSCOMMAND0      		0x84
+#define		INTSCBRAMSEL    	0x08
+#define		RAMPS           	0x04
+#define		USCBSIZE32      	0x02
+#define		CIOPARCKEN      	0x01
+
+#define	DSCOMMAND       		0x84
+#define		CACHETHEN       	0x80
+#define		DPARCKEN        	0x40
+#define		MPARCKEN        	0x20
+#define		EXTREQLCK       	0x10
+
+#define	BUSTIME         		0x85
+#define		BOFF            	0xf0
+#define		BON             	0x0f
+
+#define	BUSSPD          		0x86
+#define		DFTHRSH         	0xc0
+#define		STBOFF          	0x38
+#define		STBON           	0x07
+
+#define	DSPCISTATUS     		0x86
+#define		DFTHRSH_100     	0xc0
+
+#define	HCNTRL          		0x87
+#define		POWRDN          	0x40
+#define		SWINT           	0x10
+#define		IRQMS           	0x08
+#define		PAUSE           	0x04
+#define		INTEN           	0x02
+#define		CHIPRST         	0x01
+#define		CHIPRSTACK      	0x01
+
+#define	HADDR           		0x88
+
+#define	HCNT            		0x8c
+
+#define	SCBPTR          		0x90
+
+#define	INTSTAT         		0x91
+#define		SEQINT_MASK     	0xf1
+#define		DATA_OVERRUN    	0xe1
+#define		MSGIN_PHASEMIS  	0xd1
+#define		TRACEPOINT2     	0xc1
+#define		SEQ_SG_FIXUP    	0xb1
+#define		AWAITING_MSG    	0xa1
+#define		RESIDUAL        	0x81
+#define		BAD_STATUS      	0x71
+#define		REJECT_MSG      	0x61
+#define		WIDE_RESIDUE    	0x51
+#define		EXTENDED_MSG    	0x41
+#define		NO_MATCH        	0x31
+#define		NO_IDENT        	0x21
+#define		SEND_REJECT     	0x11
+#define		INT_PEND        	0x0f
+#define		BRKADRINT       	0x08
+#define		SCSIINT         	0x04
+#define		CMDCMPLT        	0x02
+#define		BAD_PHASE       	0x01
+#define		SEQINT          	0x01
+
+#define	CLRINT          		0x92
+#define		CLRPARERR       	0x10
+#define		CLRBRKADRINT    	0x08
+#define		CLRSCSIINT      	0x04
+#define		CLRCMDINT       	0x02
+#define		CLRSEQINT       	0x01
+
+#define	ERROR           		0x92
+#define		CIOPARERR       	0x80
+#define		PCIERRSTAT      	0x40
+#define		MPARERR         	0x20
+#define		DPARERR         	0x10
+#define		SQPARERR        	0x08
+#define		ILLOPCODE       	0x04
+#define		DSCTMOUT        	0x02
+#define		ILLSADDR        	0x02
+#define		ILLHADDR        	0x01
+
+#define	DFCNTRL         		0x93
+
+#define	DFSTATUS        		0x94
+#define		PRELOAD_AVAIL   	0x80
+#define		DWORDEMP        	0x20
+#define		MREQPEND        	0x10
+#define		HDONE           	0x08
+#define		DFTHRESH        	0x04
+#define		FIFOFULL        	0x02
+#define		FIFOEMP         	0x01
+
+#define	DFDAT           		0x99
+
+#define	SCBCNT          		0x9a
+#define		SCBAUTO         	0x80
+#define		SCBCNT_MASK     	0x1f
+
+#define	QINFIFO         		0x9b
+
+#define	QINCNT          		0x9c
+
+#define	SCSIDATL_IMG    		0x9c
+
+#define	QOUTFIFO        		0x9d
+
+#define	CRCCONTROL1     		0x9d
+#define		CRCONSEEN       	0x80
+#define		CRCVALCHKEN     	0x40
+#define		CRCENDCHKEN     	0x20
+#define		CRCREQCHKEN     	0x10
+#define		TARGCRCENDEN    	0x08
+#define		TARGCRCCNTEN    	0x04
+
+#define	SCSIPHASE       		0x9e
+#define		SP_STATUS       	0x20
+#define		SP_COMMAND      	0x10
+#define		SP_MSG_IN       	0x08
+#define		SP_MSG_OUT      	0x04
+#define		SP_DATA_IN      	0x02
+#define		SP_DATA_OUT     	0x01
+
+#define	QOUTCNT         		0x9e
+
+#define	SFUNCT          		0x9f
+#define		ALT_MODE        	0x80
+
+#define	SCB_CONTROL     		0xa0
+#define		MK_MESSAGE      	0x80
+#define		DISCENB         	0x40
+#define		TAG_ENB         	0x20
+#define		DISCONNECTED    	0x04
+#define		SCB_TAG_TYPE    	0x03
+
+#define	SCB_BASE        		0xa0
+
+#define	SCB_TCL         		0xa1
+#define		TID             	0xf0
+#define		SELBUSB         	0x08
+#define		LID             	0x07
+
+#define	SCB_TARGET_STATUS		0xa2
+
+#define	SCB_SGCOUNT     		0xa3
+
+#define	SCB_SGPTR       		0xa4
+
+#define	SCB_RESID_SGCNT 		0xa8
+
+#define	SCB_RESID_DCNT  		0xa9
+
+#define	SCB_DATAPTR     		0xac
+
+#define	SCB_DATACNT     		0xb0
+
+#define	SCB_CMDPTR      		0xb4
+
+#define	SCB_CMDLEN      		0xb8
+
+#define	SCB_TAG         		0xb9
+
+#define	SCB_NEXT        		0xba
+
+#define	SCB_PREV        		0xbb
+
+#define	SCB_BUSYTARGETS 		0xbc
+
+#define	SEECTL_2840     		0xc0
+#define		CS_2840         	0x04
+#define		CK_2840         	0x02
+#define		DO_2840         	0x01
+
+#define	STATUS_2840     		0xc1
+#define		EEPROM_TF       	0x80
+#define		BIOS_SEL        	0x60
+#define		ADSEL           	0x1e
+#define		DI_2840         	0x01
+
+#define	CCHADDR         		0xe0
+
+#define	CCHCNT          		0xe8
+
+#define	CCSGRAM         		0xe9
+
+#define	CCSGADDR        		0xea
+
+#define	CCSGCTL         		0xeb
+#define		CCSGDONE        	0x80
+#define		CCSGEN          	0x08
+#define		FLAG            	0x02
+#define		CCSGRESET       	0x01
+
+#define	CCSCBRAM        		0xec
+
+#define	CCSCBADDR       		0xed
+
+#define	CCSCBCTL        		0xee
+#define		CCSCBDONE       	0x80
+#define		ARRDONE         	0x40
+#define		CCARREN         	0x10
+#define		CCSCBEN         	0x08
+#define		CCSCBDIR        	0x04
+#define		CCSCBRESET      	0x01
+
+#define	CCSCBCNT        		0xef
+
+#define	CCSCBPTR        		0xf1
+
+#define	HNSCB_QOFF      		0xf4
+
+#define	HESCB_QOFF      		0xf5
+
+#define	SNSCB_QOFF      		0xf6
+
+#define	SESCB_QOFF      		0xf7
+
+#define	SDSCB_QOFF      		0xf8
+
+#define	QOFF_CTLSTA     		0xfa
+#define		ESTABLISH_SCB_AVAIL	0x80
+#define		SCB_AVAIL       	0x40
+#define		SNSCB_ROLLOVER  	0x20
+#define		SDSCB_ROLLOVER  	0x10
+#define		SESCB_ROLLOVER  	0x08
+#define		SCB_QSIZE       	0x07
+#define		SCB_QSIZE_256   	0x06
+
+#define	DFF_THRSH       		0xfb
+#define		WR_DFTHRSH      	0x70
+#define		WR_DFTHRSH_MAX  	0x70
+#define		WR_DFTHRSH_90   	0x60
+#define		WR_DFTHRSH_85   	0x50
+#define		WR_DFTHRSH_75   	0x40
+#define		WR_DFTHRSH_63   	0x30
+#define		WR_DFTHRSH_50   	0x20
+#define		WR_DFTHRSH_25   	0x10
+#define		RD_DFTHRSH_MAX  	0x07
+#define		RD_DFTHRSH      	0x07
+#define		RD_DFTHRSH_90   	0x06
+#define		RD_DFTHRSH_85   	0x05
+#define		RD_DFTHRSH_75   	0x04
+#define		RD_DFTHRSH_63   	0x03
+#define		RD_DFTHRSH_50   	0x02
+#define		RD_DFTHRSH_25   	0x01
+#define		WR_DFTHRSH_MIN  	0x00
+#define		RD_DFTHRSH_MIN  	0x00
+
+#define	SG_CACHEPTR     		0xfc
+#define		SG_USER_DATA    	0xfc
+#define		LAST_SEG        	0x02
+#define		LAST_SEG_DONE   	0x01
+
+
+#define	CMD_GROUP2_BYTE_DELTA	0xfa
+#define	MAX_OFFSET_8BIT	0x0f
+#define	BUS_16_BIT	0x01
+#define	QINFIFO_OFFSET	0x02
+#define	CMD_GROUP5_BYTE_DELTA	0x0b
+#define	CMD_GROUP_CODE_SHIFT	0x05
+#define	MAX_OFFSET_ULTRA2	0x7f
+#define	MAX_OFFSET_16BIT	0x08
+#define	BUS_8_BIT	0x00
+#define	QOUTFIFO_OFFSET	0x01
+#define	UNTAGGEDSCB_OFFSET	0x00
+#define	CCSGRAM_MAXSEGS	0x10
+#define	SCB_LIST_NULL	0xff
+#define	SG_SIZEOF	0x08
+#define	CMD_GROUP4_BYTE_DELTA	0x04
+#define	CMD_GROUP0_BYTE_DELTA	0xfc
+#define	HOST_MSG	0xff
+#define	BUS_32_BIT	0x02
+#define	CCSGADDR_MAX	0x80
+
+
+/* Downloaded Constant Definitions */
+#define	TMODE_NUMCMDS	0x00
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_seq.c linux/drivers/scsi/aic7xxx/aic7xxx_seq.c
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx/aic7xxx_seq.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/aic7xxx/aic7xxx_seq.c	Mon Dec  3 21:00:03 2001
@@ -0,0 +1,830 @@
+/*
+  * DO NOT EDIT - This file is automatically generated.
+  */
+static unsigned char seqprog[] = {
+	0xff, 0x6a, 0x06, 0x08,
+	0x7f, 0x02, 0x04, 0x08,
+	0x12, 0x6a, 0x00, 0x00,
+	0xff, 0x6a, 0xd6, 0x09,
+	0xff, 0x6a, 0xdc, 0x09,
+	0x00, 0x65, 0xcc, 0x58,
+	0xf7, 0x01, 0x02, 0x08,
+	0xff, 0x4e, 0xc8, 0x08,
+	0xbf, 0x60, 0xc0, 0x08,
+	0x60, 0x0b, 0x86, 0x68,
+	0x40, 0x00, 0x0c, 0x68,
+	0x08, 0x1f, 0x3e, 0x10,
+	0x60, 0x0b, 0x86, 0x68,
+	0x40, 0x00, 0x0c, 0x68,
+	0x08, 0x1f, 0x3e, 0x10,
+	0xff, 0x3e, 0x48, 0x60,
+	0x40, 0xfa, 0x10, 0x78,
+	0xff, 0xf6, 0xd4, 0x08,
+	0x01, 0x4e, 0x9c, 0x18,
+	0x40, 0x60, 0xc0, 0x00,
+	0x00, 0x4d, 0x10, 0x70,
+	0x01, 0x4e, 0x9c, 0x18,
+	0xbf, 0x60, 0xc0, 0x08,
+	0x00, 0x6a, 0xce, 0x5c,
+	0xff, 0x4e, 0xc8, 0x18,
+	0x02, 0x6a, 0xb8, 0x5b,
+	0xff, 0x52, 0x20, 0x09,
+	0x0d, 0x6a, 0x6a, 0x00,
+	0x00, 0x52, 0x2e, 0x5c,
+	0x03, 0xb0, 0x52, 0x31,
+	0xff, 0xb0, 0x52, 0x09,
+	0xff, 0xb1, 0x54, 0x09,
+	0xff, 0xb2, 0x56, 0x09,
+	0xff, 0xa3, 0x50, 0x09,
+	0xff, 0x3e, 0x74, 0x09,
+	0xff, 0x90, 0x7c, 0x08,
+	0xff, 0x3e, 0x20, 0x09,
+	0x00, 0x65, 0x4e, 0x58,
+	0x00, 0x65, 0x0c, 0x40,
+	0xf7, 0x1f, 0xca, 0x08,
+	0x08, 0xa1, 0xc8, 0x08,
+	0x00, 0x65, 0xca, 0x00,
+	0xff, 0x65, 0x3e, 0x08,
+	0xf0, 0xa1, 0xc8, 0x08,
+	0x0f, 0x0f, 0x1e, 0x08,
+	0x00, 0x0f, 0x1e, 0x00,
+	0xf0, 0xa1, 0xc8, 0x08,
+	0x0f, 0x05, 0x0a, 0x08,
+	0x00, 0x05, 0x0a, 0x00,
+	0xff, 0x6a, 0x0c, 0x08,
+	0x5a, 0x6a, 0x00, 0x04,
+	0x12, 0x65, 0x02, 0x00,
+	0x31, 0x6a, 0xca, 0x00,
+	0x80, 0x37, 0x6e, 0x68,
+	0xff, 0x65, 0xca, 0x18,
+	0xff, 0x37, 0xdc, 0x08,
+	0xff, 0x6e, 0xc8, 0x08,
+	0x00, 0x6c, 0x76, 0x78,
+	0x20, 0x01, 0x02, 0x00,
+	0x4c, 0x37, 0xc8, 0x28,
+	0x08, 0x1f, 0x7e, 0x78,
+	0x08, 0x37, 0x6e, 0x00,
+	0x08, 0x64, 0xc8, 0x00,
+	0x70, 0x64, 0xca, 0x18,
+	0xff, 0x6c, 0x0a, 0x08,
+	0x20, 0x64, 0xca, 0x18,
+	0xff, 0x6c, 0x08, 0x0c,
+	0x40, 0x0b, 0x96, 0x68,
+	0x20, 0x6a, 0x16, 0x00,
+	0xf0, 0x19, 0x6e, 0x08,
+	0x08, 0x6a, 0x18, 0x00,
+	0x08, 0x11, 0x22, 0x00,
+	0x08, 0x6a, 0x66, 0x58,
+	0x08, 0x6a, 0x68, 0x00,
+	0x00, 0x65, 0xaa, 0x40,
+	0x12, 0x6a, 0x00, 0x00,
+	0x40, 0x6a, 0x16, 0x00,
+	0xff, 0x3e, 0x20, 0x09,
+	0xff, 0xba, 0x7c, 0x08,
+	0xff, 0xa1, 0x6e, 0x08,
+	0x08, 0x6a, 0x18, 0x00,
+	0x08, 0x11, 0x22, 0x00,
+	0x08, 0x6a, 0x66, 0x58,
+	0x80, 0x6a, 0x68, 0x00,
+	0x80, 0x36, 0x6c, 0x00,
+	0x00, 0x65, 0x02, 0x5c,
+	0xff, 0x3d, 0xc8, 0x08,
+	0xbf, 0x64, 0xde, 0x78,
+	0xbf, 0x64, 0x88, 0x79,
+	0x80, 0x64, 0x10, 0x72,
+	0xa0, 0x64, 0x40, 0x72,
+	0xc0, 0x64, 0x38, 0x72,
+	0xe0, 0x64, 0x80, 0x72,
+	0x01, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xaa, 0x40,
+	0xf7, 0x11, 0x22, 0x08,
+	0x00, 0x65, 0xcc, 0x58,
+	0xff, 0x06, 0xd4, 0x08,
+	0xf7, 0x01, 0x02, 0x08,
+	0x09, 0x0c, 0xc6, 0x78,
+	0x08, 0x0c, 0x0c, 0x68,
+	0x01, 0x6a, 0x22, 0x01,
+	0xff, 0x6a, 0x26, 0x09,
+	0x02, 0x6a, 0x08, 0x30,
+	0xff, 0x6a, 0x08, 0x08,
+	0xdf, 0x01, 0x02, 0x08,
+	0x01, 0x6a, 0x7a, 0x00,
+	0xff, 0x6a, 0x6c, 0x0c,
+	0x04, 0x14, 0x10, 0x31,
+	0x03, 0xa9, 0x18, 0x31,
+	0x00, 0x65, 0xf0, 0x40,
+	0xa8, 0x6a, 0x6a, 0x00,
+	0x40, 0x3d, 0xe4, 0x68,
+	0x04, 0x35, 0x6a, 0x00,
+	0x00, 0x65, 0x72, 0x5b,
+	0x80, 0x6a, 0xd4, 0x01,
+	0x10, 0x36, 0xd8, 0x68,
+	0x10, 0x36, 0x6c, 0x00,
+	0x07, 0xac, 0x10, 0x31,
+	0x05, 0xa3, 0x70, 0x30,
+	0xff, 0x38, 0xf8, 0x68,
+	0x80, 0x02, 0x04, 0x00,
+	0x04, 0x35, 0x6a, 0x08,
+	0x03, 0x69, 0x18, 0x31,
+	0x22, 0x38, 0xc8, 0x28,
+	0x01, 0x38, 0xfe, 0x60,
+	0x02, 0x64, 0xc8, 0x00,
+	0xff, 0x64, 0xf8, 0x09,
+	0xff, 0x35, 0x26, 0x09,
+	0x80, 0x02, 0x76, 0x69,
+	0x10, 0x0c, 0x3a, 0x69,
+	0x80, 0x94, 0x04, 0x79,
+	0x01, 0x38, 0x30, 0x71,
+	0x80, 0xea, 0x22, 0x61,
+	0xef, 0x38, 0xc8, 0x18,
+	0x80, 0x6a, 0xc8, 0x00,
+	0x00, 0x65, 0x14, 0x49,
+	0x33, 0x38, 0xc8, 0x28,
+	0xff, 0x64, 0xd0, 0x09,
+	0x04, 0x39, 0xc0, 0x31,
+	0x09, 0x6a, 0xd6, 0x01,
+	0x80, 0xeb, 0x1a, 0x79,
+	0xf7, 0xeb, 0xd6, 0x09,
+	0x08, 0xeb, 0x1e, 0x69,
+	0x01, 0x6a, 0xd6, 0x01,
+	0x10, 0x0c, 0x3a, 0x69,
+	0xff, 0x38, 0x70, 0x18,
+	0x08, 0xe9, 0x10, 0x31,
+	0xff, 0x6a, 0xc8, 0x08,
+	0x08, 0x39, 0x72, 0x18,
+	0x00, 0x3a, 0x74, 0x20,
+	0x00, 0x65, 0xf0, 0x40,
+	0x10, 0x0c, 0x3a, 0x69,
+	0x01, 0xfc, 0x30, 0x79,
+	0xff, 0x6a, 0x70, 0x08,
+	0x01, 0x0c, 0x36, 0x79,
+	0x10, 0x0c, 0xf0, 0x78,
+	0x00, 0x65, 0x5c, 0x59,
+	0x01, 0xfc, 0x54, 0x69,
+	0x40, 0x0d, 0x44, 0x69,
+	0xb1, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0x54, 0x41,
+	0x2e, 0xfc, 0xa2, 0x28,
+	0x3f, 0x38, 0xc8, 0x08,
+	0x00, 0x51, 0x54, 0x71,
+	0xff, 0x6a, 0xc8, 0x08,
+	0xf8, 0x39, 0x72, 0x18,
+	0xff, 0x3a, 0x74, 0x20,
+	0x01, 0x38, 0x70, 0x18,
+	0x00, 0x65, 0x46, 0x41,
+	0x03, 0x08, 0x52, 0x31,
+	0xff, 0x38, 0x50, 0x09,
+	0x12, 0x01, 0x02, 0x00,
+	0x00, 0x65, 0xaa, 0x40,
+	0x04, 0x93, 0x70, 0x69,
+	0xdf, 0x93, 0x26, 0x09,
+	0x20, 0x93, 0x60, 0x69,
+	0x02, 0x93, 0x26, 0x01,
+	0x01, 0x94, 0x64, 0x79,
+	0x01, 0x94, 0x64, 0x79,
+	0x01, 0x94, 0x64, 0x79,
+	0x01, 0x94, 0x64, 0x79,
+	0x01, 0x94, 0x64, 0x79,
+	0x10, 0x94, 0x6e, 0x69,
+	0xd7, 0x93, 0x26, 0x09,
+	0x28, 0x93, 0x72, 0x69,
+	0xff, 0x6a, 0xd4, 0x0c,
+	0x10, 0x0c, 0x76, 0x79,
+	0x00, 0x65, 0x5c, 0x59,
+	0x7f, 0x02, 0x04, 0x08,
+	0xe1, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xaa, 0x40,
+	0x03, 0xa9, 0x10, 0x30,
+	0x08, 0x6a, 0xcc, 0x00,
+	0xa9, 0x6a, 0x18, 0x5c,
+	0x00, 0x65, 0xa6, 0x41,
+	0x79, 0x6a, 0x6a, 0x00,
+	0x40, 0x3d, 0x8e, 0x69,
+	0x04, 0x35, 0x6a, 0x00,
+	0x00, 0x65, 0x72, 0x5b,
+	0x80, 0x6a, 0xd4, 0x01,
+	0x10, 0x36, 0x80, 0x69,
+	0x10, 0x36, 0x6c, 0x00,
+	0x07, 0xac, 0x10, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
+	0x05, 0xa3, 0x70, 0x30,
+	0x88, 0x6a, 0xcc, 0x00,
+	0xac, 0x6a, 0x10, 0x5c,
+	0x00, 0x65, 0x0a, 0x5c,
+	0x38, 0x6a, 0xcc, 0x00,
+	0xa3, 0x6a, 0x14, 0x5c,
+	0xff, 0x38, 0xb4, 0x69,
+	0x80, 0x02, 0x04, 0x00,
+	0xe7, 0x35, 0x6a, 0x08,
+	0x03, 0x69, 0x10, 0x30,
+	0xff, 0x6a, 0x10, 0x00,
+	0xff, 0x6a, 0x12, 0x00,
+	0xff, 0x6a, 0x14, 0x00,
+	0x01, 0x38, 0xb8, 0x61,
+	0xbf, 0x35, 0x6a, 0x08,
+	0x00, 0x35, 0x52, 0x5b,
+	0x80, 0x02, 0x0a, 0x6a,
+	0xff, 0x65, 0xfa, 0x79,
+	0x01, 0x38, 0xfa, 0x71,
+	0xff, 0x38, 0x70, 0x18,
+	0x80, 0xea, 0xda, 0x61,
+	0xef, 0x38, 0xc8, 0x18,
+	0x80, 0x6a, 0xc8, 0x00,
+	0x00, 0x65, 0xcc, 0x49,
+	0x33, 0x38, 0xc8, 0x28,
+	0xff, 0x64, 0xd0, 0x09,
+	0x04, 0x39, 0xc0, 0x31,
+	0x09, 0x6a, 0xd6, 0x01,
+	0x80, 0xeb, 0xd2, 0x79,
+	0xf7, 0xeb, 0xd6, 0x09,
+	0x08, 0xeb, 0xd6, 0x69,
+	0x01, 0x6a, 0xd6, 0x01,
+	0x08, 0xe9, 0x10, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
+	0x88, 0x6a, 0xcc, 0x00,
+	0x39, 0x6a, 0x16, 0x5c,
+	0x08, 0x6a, 0x18, 0x01,
+	0xff, 0x6a, 0x1a, 0x09,
+	0xff, 0x6a, 0x1c, 0x09,
+	0x0d, 0x93, 0x26, 0x01,
+	0x00, 0x65, 0xc0, 0x5c,
+	0x88, 0x6a, 0xb2, 0x5c,
+	0x00, 0x65, 0x0a, 0x5c,
+	0xff, 0x6a, 0xc8, 0x08,
+	0x08, 0x39, 0x72, 0x18,
+	0x00, 0x3a, 0x74, 0x20,
+	0x01, 0x0c, 0xf6, 0x79,
+	0x10, 0x0c, 0xa6, 0x79,
+	0xff, 0x6a, 0x70, 0x08,
+	0x03, 0x08, 0x52, 0x31,
+	0xff, 0x38, 0x50, 0x09,
+	0xff, 0x08, 0x52, 0x09,
+	0xff, 0x09, 0x54, 0x09,
+	0xff, 0x0a, 0x56, 0x09,
+	0xff, 0x38, 0x50, 0x09,
+	0x00, 0x65, 0xaa, 0x40,
+	0x7f, 0x02, 0x04, 0x08,
+	0xe1, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xaa, 0x40,
+	0x00, 0x65, 0x72, 0x5b,
+	0x05, 0xb4, 0x10, 0x31,
+	0x02, 0x6a, 0x1a, 0x31,
+	0x03, 0x8c, 0x10, 0x30,
+	0x88, 0x6a, 0xcc, 0x00,
+	0xb4, 0x6a, 0x14, 0x5c,
+	0xff, 0x6a, 0x1a, 0x09,
+	0xff, 0x6a, 0x1c, 0x09,
+	0x00, 0x65, 0x0a, 0x5c,
+	0x3d, 0x6a, 0x52, 0x5b,
+	0xac, 0x6a, 0x26, 0x01,
+	0x04, 0x0b, 0x26, 0x6a,
+	0x04, 0x0b, 0x2c, 0x6a,
+	0x10, 0x0c, 0x28, 0x7a,
+	0x02, 0x03, 0x30, 0x7a,
+	0x11, 0x0c, 0x2c, 0x7a,
+	0xd7, 0x93, 0x26, 0x09,
+	0x28, 0x93, 0x32, 0x6a,
+	0x12, 0x01, 0x02, 0x00,
+	0x00, 0x65, 0xaa, 0x40,
+	0x00, 0x65, 0x72, 0x5b,
+	0xff, 0x06, 0x44, 0x09,
+	0x00, 0x65, 0xaa, 0x40,
+	0x10, 0x3d, 0x06, 0x00,
+	0xff, 0x34, 0xca, 0x08,
+	0x80, 0x65, 0x64, 0x62,
+	0x0f, 0xa1, 0xca, 0x08,
+	0x07, 0xa1, 0xca, 0x08,
+	0x40, 0xa0, 0xc8, 0x08,
+	0x00, 0x65, 0xca, 0x00,
+	0x80, 0x65, 0xca, 0x00,
+	0x80, 0xa0, 0x54, 0x7a,
+	0xff, 0x65, 0x0c, 0x08,
+	0x00, 0x65, 0x66, 0x42,
+	0x20, 0xa0, 0x6c, 0x7a,
+	0xff, 0x65, 0x0c, 0x08,
+	0x00, 0x65, 0x02, 0x5c,
+	0xa0, 0x3d, 0x74, 0x62,
+	0x23, 0xa0, 0x0c, 0x08,
+	0x00, 0x65, 0x02, 0x5c,
+	0xa0, 0x3d, 0x74, 0x62,
+	0x00, 0xb9, 0x6c, 0x42,
+	0xff, 0x65, 0x6c, 0x62,
+	0xa1, 0x6a, 0x22, 0x01,
+	0xff, 0x6a, 0xd4, 0x08,
+	0x10, 0x51, 0x74, 0x72,
+	0x40, 0x6a, 0x18, 0x00,
+	0xff, 0x65, 0x0c, 0x08,
+	0x00, 0x65, 0x02, 0x5c,
+	0xa0, 0x3d, 0x3e, 0x72,
+	0x40, 0x6a, 0x18, 0x00,
+	0xff, 0x34, 0xa6, 0x08,
+	0x80, 0x34, 0x7c, 0x62,
+	0x7f, 0xa0, 0x40, 0x09,
+	0x08, 0x6a, 0x68, 0x00,
+	0x00, 0x65, 0xaa, 0x40,
+	0x64, 0x6a, 0x48, 0x5b,
+	0x80, 0x64, 0xf2, 0x6a,
+	0x04, 0x64, 0xd4, 0x72,
+	0x02, 0x64, 0xda, 0x72,
+	0x00, 0x6a, 0x9c, 0x72,
+	0x03, 0x64, 0xee, 0x72,
+	0x01, 0x64, 0xd0, 0x72,
+	0x07, 0x64, 0x30, 0x73,
+	0x08, 0x64, 0x98, 0x72,
+	0x23, 0x64, 0x34, 0x73,
+	0x11, 0x6a, 0x22, 0x01,
+	0x07, 0x6a, 0x3a, 0x5b,
+	0xff, 0x06, 0xd4, 0x08,
+	0x00, 0x65, 0xaa, 0x40,
+	0xff, 0xa8, 0xa0, 0x6a,
+	0xff, 0xa2, 0xb8, 0x7a,
+	0x01, 0x6a, 0x6a, 0x00,
+	0x00, 0xb9, 0x2e, 0x5c,
+	0xff, 0xa2, 0xb8, 0x7a,
+	0x71, 0x6a, 0x22, 0x01,
+	0xff, 0x6a, 0xd4, 0x08,
+	0x40, 0x51, 0xb8, 0x62,
+	0x0d, 0x6a, 0x6a, 0x00,
+	0x00, 0xb9, 0x2e, 0x5c,
+	0xff, 0x3e, 0x74, 0x09,
+	0xff, 0x90, 0x7c, 0x08,
+	0x00, 0x65, 0x4e, 0x58,
+	0x00, 0x65, 0xbe, 0x40,
+	0x20, 0xa0, 0xc0, 0x6a,
+	0xff, 0x37, 0xc8, 0x08,
+	0x00, 0x6a, 0xd8, 0x5b,
+	0xff, 0x6a, 0xee, 0x5b,
+	0xff, 0xf8, 0xc8, 0x08,
+	0xff, 0x4f, 0xc8, 0x08,
+	0x01, 0x6a, 0xd8, 0x5b,
+	0x00, 0xb9, 0xee, 0x5b,
+	0x01, 0x4f, 0x9e, 0x18,
+	0x02, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xc8, 0x5c,
+	0x00, 0x65, 0xbe, 0x40,
+	0x41, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xaa, 0x40,
+	0x04, 0xa0, 0x40, 0x01,
+	0x00, 0x65, 0xe0, 0x5c,
+	0x00, 0x65, 0xbe, 0x40,
+	0x10, 0x36, 0x98, 0x7a,
+	0x05, 0x38, 0x46, 0x31,
+	0x04, 0x14, 0x58, 0x31,
+	0x03, 0xa9, 0x60, 0x31,
+	0xa3, 0x6a, 0xcc, 0x00,
+	0x38, 0x6a, 0x14, 0x5c,
+	0xac, 0x6a, 0xcc, 0x00,
+	0x14, 0x6a, 0x16, 0x5c,
+	0xa9, 0x6a, 0x18, 0x5c,
+	0x00, 0x65, 0x98, 0x42,
+	0xef, 0x36, 0x6c, 0x08,
+	0x00, 0x65, 0x98, 0x42,
+	0x0f, 0x64, 0xc8, 0x08,
+	0x07, 0x64, 0xc8, 0x08,
+	0x00, 0x37, 0x6e, 0x00,
+	0xff, 0x6a, 0xa4, 0x00,
+	0x00, 0x65, 0xa8, 0x5b,
+	0xff, 0x51, 0x04, 0x73,
+	0x20, 0x36, 0x0e, 0x7b,
+	0x00, 0x90, 0x96, 0x5b,
+	0x00, 0x65, 0x10, 0x43,
+	0xff, 0x06, 0xd4, 0x08,
+	0x00, 0x65, 0x02, 0x5c,
+	0xe0, 0x3d, 0x2a, 0x63,
+	0x20, 0x12, 0x2a, 0x63,
+	0x51, 0x6a, 0x3e, 0x5b,
+	0x00, 0x65, 0x90, 0x5b,
+	0xff, 0x37, 0xc8, 0x08,
+	0x00, 0xa1, 0x22, 0x63,
+	0x04, 0xa0, 0x22, 0x7b,
+	0xfb, 0xa0, 0x40, 0x09,
+	0x80, 0x36, 0x6c, 0x00,
+	0x80, 0xa0, 0x98, 0x7a,
+	0x7f, 0xa0, 0x40, 0x09,
+	0xff, 0x6a, 0x3a, 0x5b,
+	0x00, 0x65, 0x98, 0x42,
+	0x04, 0xa0, 0x28, 0x7b,
+	0x00, 0x65, 0xe0, 0x5c,
+	0x00, 0x65, 0x2a, 0x43,
+	0x00, 0x65, 0xc8, 0x5c,
+	0x31, 0x6a, 0x22, 0x01,
+	0x0c, 0x6a, 0x3a, 0x5b,
+	0x00, 0x65, 0x98, 0x42,
+	0x61, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0x98, 0x42,
+	0x51, 0x6a, 0x3e, 0x5b,
+	0x51, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0x98, 0x42,
+	0x10, 0x3d, 0x06, 0x00,
+	0xff, 0x65, 0x68, 0x0c,
+	0xff, 0x06, 0xd4, 0x08,
+	0x01, 0x0c, 0x40, 0x7b,
+	0x04, 0x0c, 0x42, 0x6b,
+	0xe0, 0x03, 0x7a, 0x08,
+	0xe0, 0x3d, 0x4e, 0x63,
+	0xff, 0x65, 0xcc, 0x08,
+	0xff, 0x12, 0xda, 0x0c,
+	0xff, 0x06, 0xd4, 0x0c,
+	0xd1, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xaa, 0x40,
+	0xff, 0x65, 0x26, 0x09,
+	0x01, 0x0b, 0x62, 0x6b,
+	0x10, 0x0c, 0x54, 0x7b,
+	0x04, 0x0b, 0x5c, 0x6b,
+	0xff, 0x6a, 0xca, 0x08,
+	0x04, 0x93, 0x60, 0x6b,
+	0x01, 0x94, 0x5e, 0x7b,
+	0x10, 0x94, 0x60, 0x6b,
+	0x80, 0x3d, 0x66, 0x73,
+	0x0f, 0x04, 0x6a, 0x6b,
+	0x02, 0x03, 0x6a, 0x7b,
+	0x11, 0x0c, 0x66, 0x7b,
+	0xc7, 0x93, 0x26, 0x09,
+	0xff, 0x99, 0xd4, 0x08,
+	0x38, 0x93, 0x6c, 0x6b,
+	0xff, 0x6a, 0xd4, 0x0c,
+	0x80, 0x36, 0x70, 0x6b,
+	0x21, 0x6a, 0x22, 0x05,
+	0xff, 0x65, 0x20, 0x09,
+	0xff, 0x51, 0x7e, 0x63,
+	0xff, 0x37, 0xc8, 0x08,
+	0xa1, 0x6a, 0x8a, 0x43,
+	0xff, 0x51, 0xc8, 0x08,
+	0xb9, 0x6a, 0x8a, 0x43,
+	0xff, 0x90, 0xa4, 0x08,
+	0xff, 0xba, 0x8e, 0x73,
+	0xff, 0xba, 0x20, 0x09,
+	0xff, 0x65, 0xca, 0x18,
+	0x00, 0x6c, 0x82, 0x63,
+	0xff, 0x90, 0xca, 0x0c,
+	0xff, 0x6a, 0xca, 0x04,
+	0x20, 0x36, 0xa2, 0x7b,
+	0x00, 0x90, 0x76, 0x5b,
+	0xff, 0x65, 0xa2, 0x73,
+	0xff, 0x52, 0xa0, 0x73,
+	0xff, 0xba, 0xcc, 0x08,
+	0xff, 0x52, 0x20, 0x09,
+	0xff, 0x66, 0x74, 0x09,
+	0xff, 0x65, 0x20, 0x0d,
+	0xff, 0xba, 0x7e, 0x0c,
+	0x00, 0x6a, 0xce, 0x5c,
+	0x0d, 0x6a, 0x6a, 0x00,
+	0x00, 0x51, 0x2e, 0x44,
+	0xff, 0x3f, 0xfc, 0x73,
+	0xff, 0x6a, 0xa2, 0x00,
+	0x00, 0x3f, 0x76, 0x5b,
+	0xff, 0x65, 0xfc, 0x73,
+	0x20, 0x36, 0x6c, 0x00,
+	0x20, 0xa0, 0xb6, 0x6b,
+	0xff, 0xb9, 0xa2, 0x0c,
+	0xff, 0x6a, 0xa2, 0x04,
+	0xff, 0x65, 0xa4, 0x08,
+	0xe0, 0x6a, 0xcc, 0x00,
+	0x45, 0x6a, 0x22, 0x5c,
+	0x01, 0x6a, 0xd0, 0x01,
+	0x09, 0x6a, 0xd6, 0x01,
+	0x80, 0xeb, 0xc2, 0x7b,
+	0x01, 0x6a, 0xd6, 0x01,
+	0x01, 0xe9, 0xa4, 0x34,
+	0x88, 0x6a, 0xcc, 0x00,
+	0x45, 0x6a, 0x22, 0x5c,
+	0x01, 0x6a, 0x18, 0x01,
+	0xff, 0x6a, 0x1a, 0x09,
+	0xff, 0x6a, 0x1c, 0x09,
+	0x0d, 0x6a, 0x26, 0x01,
+	0x00, 0x65, 0xc0, 0x5c,
+	0xff, 0x99, 0xa4, 0x0c,
+	0xff, 0x65, 0xa4, 0x08,
+	0xe0, 0x6a, 0xcc, 0x00,
+	0x45, 0x6a, 0x22, 0x5c,
+	0x01, 0x6a, 0xd0, 0x01,
+	0x01, 0x6a, 0xdc, 0x05,
+	0x88, 0x6a, 0xcc, 0x00,
+	0x45, 0x6a, 0x22, 0x5c,
+	0x01, 0x6a, 0x18, 0x01,
+	0xff, 0x6a, 0x1a, 0x09,
+	0xff, 0x6a, 0x1c, 0x09,
+	0x01, 0x6a, 0x26, 0x05,
+	0x01, 0x65, 0xd8, 0x31,
+	0x09, 0xee, 0xdc, 0x01,
+	0x80, 0xee, 0xf2, 0x7b,
+	0xff, 0x6a, 0xdc, 0x0d,
+	0xff, 0x65, 0x32, 0x09,
+	0x0a, 0x93, 0x26, 0x01,
+	0x00, 0x65, 0xc0, 0x44,
+	0xff, 0x37, 0xc8, 0x08,
+	0x00, 0x6a, 0xb8, 0x5b,
+	0xff, 0x52, 0xa2, 0x0c,
+	0x01, 0x0c, 0x02, 0x7c,
+	0x04, 0x0c, 0x02, 0x6c,
+	0xe0, 0x03, 0x06, 0x08,
+	0xe0, 0x03, 0x7a, 0x0c,
+	0xff, 0x8c, 0x10, 0x08,
+	0xff, 0x8d, 0x12, 0x08,
+	0xff, 0x8e, 0x14, 0x0c,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x08,
+	0xff, 0x6c, 0xda, 0x0c,
+	0x3d, 0x64, 0xa4, 0x28,
+	0x55, 0x64, 0xc8, 0x28,
+	0x00, 0x6c, 0xda, 0x18,
+	0xff, 0x52, 0xc8, 0x08,
+	0x00, 0x6c, 0xda, 0x20,
+	0xff, 0x6a, 0xc8, 0x08,
+	0x00, 0x6c, 0xda, 0x20,
+	0x00, 0x6c, 0xda, 0x24,
+	0xff, 0x65, 0xc8, 0x08,
+	0xe0, 0x6a, 0xcc, 0x00,
+	0x41, 0x6a, 0x1e, 0x5c,
+	0xff, 0x90, 0xe2, 0x09,
+	0x20, 0x6a, 0xd0, 0x01,
+	0x04, 0x35, 0x40, 0x7c,
+	0x1d, 0x6a, 0xdc, 0x01,
+	0xdc, 0xee, 0x3c, 0x64,
+	0x00, 0x65, 0x56, 0x44,
+	0x01, 0x6a, 0xdc, 0x01,
+	0x20, 0xa0, 0xd8, 0x31,
+	0x09, 0xee, 0xdc, 0x01,
+	0x80, 0xee, 0x46, 0x7c,
+	0x11, 0x6a, 0xdc, 0x01,
+	0x50, 0xee, 0x4a, 0x64,
+	0x20, 0x6a, 0xd0, 0x01,
+	0x09, 0x6a, 0xdc, 0x01,
+	0x88, 0xee, 0x50, 0x64,
+	0x19, 0x6a, 0xdc, 0x01,
+	0xd8, 0xee, 0x54, 0x64,
+	0xff, 0x6a, 0xdc, 0x09,
+	0x18, 0xee, 0x58, 0x6c,
+	0xff, 0x6a, 0xd4, 0x0c,
+	0x88, 0x6a, 0xcc, 0x00,
+	0x41, 0x6a, 0x1e, 0x5c,
+	0x20, 0x6a, 0x18, 0x01,
+	0xff, 0x6a, 0x1a, 0x09,
+	0xff, 0x6a, 0x1c, 0x09,
+	0xff, 0x35, 0x26, 0x09,
+	0x04, 0x35, 0x84, 0x6c,
+	0xa0, 0x6a, 0xca, 0x00,
+	0x20, 0x65, 0xc8, 0x18,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0xff, 0x6c, 0x32, 0x09,
+	0x00, 0x65, 0x6e, 0x64,
+	0x0a, 0x93, 0x26, 0x01,
+	0x00, 0x65, 0xc0, 0x44,
+	0xa0, 0x6a, 0xcc, 0x00,
+	0xe8, 0x6a, 0xc8, 0x00,
+	0x01, 0x94, 0x88, 0x6c,
+	0x10, 0x94, 0x8a, 0x6c,
+	0x08, 0x94, 0x9c, 0x6c,
+	0x08, 0x94, 0x9c, 0x6c,
+	0x08, 0x94, 0x9c, 0x6c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x08, 0x64, 0xc8, 0x18,
+	0x00, 0x8c, 0xca, 0x18,
+	0x00, 0x65, 0x92, 0x4c,
+	0x00, 0x65, 0x88, 0x44,
+	0xf7, 0x93, 0x26, 0x09,
+	0x08, 0x93, 0x9e, 0x6c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x08, 0x64, 0xc8, 0x18,
+	0x08, 0x64, 0xa0, 0x64,
+	0xff, 0x6a, 0xd4, 0x0c,
+	0x00, 0x65, 0xc0, 0x5c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x08,
+	0xff, 0x99, 0xda, 0x0c,
+	0x08, 0x94, 0xc0, 0x7c,
+	0xf7, 0x93, 0x26, 0x09,
+	0x08, 0x93, 0xc4, 0x6c,
+	0xff, 0x6a, 0xd4, 0x0c,
+	0xff, 0x40, 0x74, 0x09,
+	0xff, 0x90, 0x80, 0x08,
+	0xff, 0x6a, 0x72, 0x05,
+	0xff, 0x40, 0xdc, 0x64,
+	0xff, 0x3f, 0xd4, 0x64,
+	0xff, 0x6a, 0xca, 0x04,
+	0xff, 0x3f, 0x20, 0x09,
+	0x01, 0x6a, 0x6a, 0x00,
+	0x00, 0xb9, 0x2e, 0x5c,
+	0xff, 0xba, 0x7e, 0x0c,
+	0xff, 0x40, 0x20, 0x09,
+	0xff, 0xba, 0x80, 0x0c,
+	0xff, 0x3f, 0x74, 0x09,
+	0xff, 0x90, 0x7e, 0x0c,
+};
+
+static int aic7xxx_patch14_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch14_func(struct aic7xxx_host *p)
+{
+	return ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0);
+}
+
+static int aic7xxx_patch13_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch13_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_CMD_CHAN) == 0);
+}
+
+static int aic7xxx_patch12_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch12_func(struct aic7xxx_host *p)
+{
+	return ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0);
+}
+
+static int aic7xxx_patch11_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch11_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_WIDE) != 0);
+}
+
+static int aic7xxx_patch10_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch10_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_ULTRA2) == 0);
+}
+
+static int aic7xxx_patch9_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch9_func(struct aic7xxx_host *p)
+{
+	return ((p->bugs & AHC_BUG_AUTOFLUSH) != 0);
+}
+
+static int aic7xxx_patch8_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch8_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_ULTRA) != 0);
+}
+
+static int aic7xxx_patch7_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch7_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_ULTRA2) != 0);
+}
+
+static int aic7xxx_patch6_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch6_func(struct aic7xxx_host *p)
+{
+	return ((p->flags & AHC_PAGESCBS) == 0);
+}
+
+static int aic7xxx_patch5_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch5_func(struct aic7xxx_host *p)
+{
+	return ((p->flags & AHC_PAGESCBS) != 0);
+}
+
+static int aic7xxx_patch4_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch4_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_QUEUE_REGS) != 0);
+}
+
+static int aic7xxx_patch3_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch3_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_TWIN) != 0);
+}
+
+static int aic7xxx_patch2_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch2_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_QUEUE_REGS) == 0);
+}
+
+static int aic7xxx_patch1_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch1_func(struct aic7xxx_host *p)
+{
+	return ((p->features & AHC_CMD_CHAN) != 0);
+}
+
+static int aic7xxx_patch0_func(struct aic7xxx_host *p);
+
+static int
+aic7xxx_patch0_func(struct aic7xxx_host *p)
+{
+	return (0);
+}
+
+struct sequencer_patch {
+	int		(*patch_func)(struct aic7xxx_host *);
+	unsigned int	begin	   :10,
+			skip_instr :10,
+			skip_patch :12;
+} sequencer_patches[] = {
+	{ aic7xxx_patch1_func, 3, 2, 1 },
+	{ aic7xxx_patch2_func, 7, 1, 1 },
+	{ aic7xxx_patch2_func, 8, 1, 1 },
+	{ aic7xxx_patch3_func, 11, 4, 1 },
+	{ aic7xxx_patch4_func, 16, 3, 2 },
+	{ aic7xxx_patch0_func, 19, 4, 1 },
+	{ aic7xxx_patch5_func, 23, 1, 1 },
+	{ aic7xxx_patch6_func, 26, 1, 1 },
+	{ aic7xxx_patch1_func, 29, 1, 2 },
+	{ aic7xxx_patch0_func, 30, 3, 1 },
+	{ aic7xxx_patch3_func, 39, 4, 1 },
+	{ aic7xxx_patch7_func, 43, 3, 2 },
+	{ aic7xxx_patch0_func, 46, 3, 1 },
+	{ aic7xxx_patch8_func, 52, 7, 1 },
+	{ aic7xxx_patch3_func, 60, 3, 1 },
+	{ aic7xxx_patch7_func, 63, 2, 1 },
+	{ aic7xxx_patch7_func, 87, 1, 2 },
+	{ aic7xxx_patch0_func, 88, 1, 1 },
+	{ aic7xxx_patch7_func, 103, 1, 2 },
+	{ aic7xxx_patch0_func, 104, 2, 1 },
+	{ aic7xxx_patch7_func, 108, 84, 15 },
+	{ aic7xxx_patch9_func, 177, 1, 1 },
+	{ aic7xxx_patch9_func, 178, 4, 1 },
+	{ aic7xxx_patch0_func, 192, 72, 12 },
+	{ aic7xxx_patch1_func, 192, 1, 2 },
+	{ aic7xxx_patch0_func, 193, 2, 1 },
+	{ aic7xxx_patch1_func, 200, 1, 1 },
+	{ aic7xxx_patch1_func, 203, 3, 2 },
+	{ aic7xxx_patch0_func, 206, 5, 1 },
+	{ aic7xxx_patch1_func, 214, 1, 2 },
+	{ aic7xxx_patch0_func, 215, 3, 1 },
+	{ aic7xxx_patch1_func, 225, 14, 2 },
+	{ aic7xxx_patch0_func, 239, 9, 1 },
+	{ aic7xxx_patch1_func, 254, 2, 2 },
+	{ aic7xxx_patch0_func, 256, 4, 1 },
+	{ aic7xxx_patch1_func, 265, 3, 3 },
+	{ aic7xxx_patch10_func, 267, 1, 1 },
+	{ aic7xxx_patch0_func, 268, 5, 1 },
+	{ aic7xxx_patch10_func, 273, 1, 2 },
+	{ aic7xxx_patch0_func, 274, 9, 1 },
+	{ aic7xxx_patch11_func, 290, 1, 2 },
+	{ aic7xxx_patch0_func, 291, 1, 1 },
+	{ aic7xxx_patch4_func, 352, 1, 2 },
+	{ aic7xxx_patch0_func, 353, 1, 1 },
+	{ aic7xxx_patch2_func, 356, 1, 1 },
+	{ aic7xxx_patch1_func, 366, 3, 2 },
+	{ aic7xxx_patch0_func, 369, 5, 1 },
+	{ aic7xxx_patch11_func, 377, 1, 2 },
+	{ aic7xxx_patch0_func, 378, 1, 1 },
+	{ aic7xxx_patch5_func, 383, 1, 1 },
+	{ aic7xxx_patch10_func, 425, 15, 2 },
+	{ aic7xxx_patch12_func, 438, 1, 1 },
+	{ aic7xxx_patch1_func, 477, 7, 2 },
+	{ aic7xxx_patch0_func, 484, 8, 1 },
+	{ aic7xxx_patch1_func, 493, 4, 2 },
+	{ aic7xxx_patch0_func, 497, 6, 1 },
+	{ aic7xxx_patch1_func, 503, 4, 2 },
+	{ aic7xxx_patch0_func, 507, 3, 1 },
+	{ aic7xxx_patch13_func, 517, 10, 1 },
+	{ aic7xxx_patch1_func, 536, 22, 8 },
+	{ aic7xxx_patch10_func, 544, 4, 4 },
+	{ aic7xxx_patch0_func, 548, 7, 3 },
+	{ aic7xxx_patch14_func, 548, 5, 2 },
+	{ aic7xxx_patch0_func, 553, 2, 1 },
+	{ aic7xxx_patch0_func, 558, 50, 3 },
+	{ aic7xxx_patch12_func, 579, 17, 2 },
+	{ aic7xxx_patch0_func, 596, 4, 1 },
+	{ aic7xxx_patch13_func, 608, 4, 1 },
+	{ aic7xxx_patch5_func, 612, 2, 1 },
+	{ aic7xxx_patch5_func, 615, 9, 1 },
+
+};
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx.c	Mon Sep  4 10:39:21 2000
+++ linux/drivers/scsi/aic7xxx.c	Mon Dec  3 21:00:03 2001
@@ -246,11 +246,11 @@
 #include "sd.h"
 #include "scsi.h"
 #include "hosts.h"
-#include "aic7xxx.h"
+#include "aic7xxx/aic7xxx.h"
 
 #include "aic7xxx/sequencer.h"
 #include "aic7xxx/scsi_message.h"
-#include "aic7xxx_reg.h"
+#include "aic7xxx/aic7xxx_reg.h"
 #include <scsi/scsicam.h>
 
 #include <linux/stat.h>
@@ -270,7 +270,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.31"
+#define AIC7XXX_C_VERSION  "5.1.32"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -790,6 +790,7 @@
 
 typedef enum {
         SCB_FREE                = 0x0000,
+        SCB_DTR_SCB             = 0x0001,
         SCB_WAITINGQ            = 0x0002,
         SCB_ACTIVE              = 0x0004,
         SCB_SENSE               = 0x0008,
@@ -896,6 +897,17 @@
   AHC_AIC7899_FE       = AHC_AIC7890_FE|AHC_ULTRA3,
 } ahc_feature;
 
+typedef enum {
+  AHC_BUG_NONE            = 0x0000,
+  AHC_BUG_TMODE_WIDEODD   = 0x0001,
+  AHC_BUG_AUTOFLUSH       = 0x0002,
+  AHC_BUG_CACHETHEN       = 0x0004,
+  AHC_BUG_CACHETHEN_DIS   = 0x0008,
+  AHC_BUG_PCI_2_1_RETRY   = 0x0010,
+  AHC_BUG_PCI_MWI         = 0x0020,
+  AHC_BUG_SCBCHAN_UPLOAD  = 0x0040,
+} ahc_bugs;
+
 struct aic7xxx_scb {
         struct aic7xxx_hwscb  *hscb;          /* corresponding hardware scb */
         Scsi_Cmnd             *cmd;              /* Scsi_Cmnd for this scb */
@@ -1004,7 +1016,6 @@
   unsigned long            isr_count;        /* Interrupt count */
   unsigned long            spurious_int;
   scb_data_type           *scb_data;
-  volatile unsigned short  needdv;
   volatile unsigned short  needppr;
   volatile unsigned short  needsdtr;
   volatile unsigned short  needwdtr;
@@ -1032,10 +1043,9 @@
 #define  BUS_DEVICE_RESET_PENDING       0x02
 #define  DEVICE_RESET_DELAY             0x04
 #define  DEVICE_PRINT_DTR               0x08
-#define  DEVICE_PARITY_ERROR            0x10
-#define  DEVICE_WAS_BUSY                0x20
-#define  DEVICE_SCSI_3                  0x40
-#define  DEVICE_SCANNED                 0x80
+#define  DEVICE_WAS_BUSY                0x10
+#define  DEVICE_SCSI_3                  0x20
+#define  DEVICE_DTR_SCANNED             0x40
   volatile unsigned char   dev_flags[MAX_TARGETS];
   volatile unsigned char   dev_active_cmds[MAX_TARGETS];
   volatile unsigned char   dev_temp_queue_depth[MAX_TARGETS];
@@ -1051,10 +1061,6 @@
 #endif
 
 
-  Scsi_Cmnd               *dev_dtr_cmnd[MAX_TARGETS];
-
-  unsigned int             dev_checksum[MAX_TARGETS];
-  
   unsigned char            dev_last_queue_full[MAX_TARGETS];
   unsigned char            dev_last_queue_full_count[MAX_TARGETS];
   unsigned char            dev_max_queue_depth[MAX_TARGETS];
@@ -1111,6 +1117,7 @@
   int                      host_no;          /* SCSI host number */
   unsigned long            mbase;            /* I/O memory address */
   ahc_chip                 chip;             /* chip type */
+  ahc_bugs                 bugs;             /* hardware bugs this chip has */
 
   /*
    * Statistics Kept:
@@ -1712,7 +1719,7 @@
  * prototype, our code has to be ordered that way, it's a left-over from
  * the original driver days.....I should fix it some time DL).
  */
-#include "aic7xxx_seq.c"
+#include "aic7xxx/aic7xxx_seq.c"
 
 /*+F*************************************************************************
  * Function:
@@ -2876,138 +2883,98 @@
   {
     p->flags &= ~AHC_ABORT_PENDING;
   }
-  if (scb->flags & SCB_RESET)
+  if (scb->flags & (SCB_RESET|SCB_ABORT))
   {
-      cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff);
+    cmd->result |= (DID_RESET << 16);
   }
-  else if (scb->flags & SCB_ABORT)
-  {
-      cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff);
-  }
-  else if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+
+  if (!(p->dev_flags[tindex] & DEVICE_PRESENT))
   {
     if ( (cmd->cmnd[0] == INQUIRY) && (cmd->result == DID_OK) )
     {
-      char *buffer;
-      
+    
       p->dev_flags[tindex] |= DEVICE_PRESENT;
-      if(cmd->use_sg)
-      {
-        struct scatterlist *sg;
-
-        sg = (struct scatterlist *)cmd->request_buffer;
-        buffer = (char *)sg[0].address;
-      }
-      else
-      {
-        buffer = (char *)cmd->request_buffer;
-      }
 #define WIDE_INQUIRY_BITS 0x60
 #define SYNC_INQUIRY_BITS 0x10
 #define SCSI_VERSION_BITS 0x07
 #define SCSI_DT_BIT       0x04
-      if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
-           (p->features & AHC_WIDE) )
-      {
-        p->needwdtr |= (1<<tindex);
-        p->needwdtr_copy |= (1<<tindex);
-        p->transinfo[tindex].goal_width = p->transinfo[tindex].user_width;
-      }
-      else
-      {
-        p->needwdtr &= ~(1<<tindex);
-        p->needwdtr_copy &= ~(1<<tindex);
-        pause_sequencer(p);
-        aic7xxx_set_width(p, cmd->target, cmd->channel, cmd->lun,
-                          MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE |
-                                                   AHC_TRANS_GOAL |
-                                                   AHC_TRANS_CUR) );
-        unpause_sequencer(p, FALSE);
-      }
-      if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
-            p->transinfo[tindex].user_offset )
-      {
-        p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
-        p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
-        if (p->features & AHC_ULTRA2)
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-        else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+      if(!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED)) {
+        char *buffer;
+
+        if(cmd->use_sg)
+        {
+          struct scatterlist *sg;
+
+          sg = (struct scatterlist *)cmd->request_buffer;
+          buffer = (char *)sg[0].address;
+        }
+        else
+        {
+          buffer = (char *)cmd->request_buffer;
+        }
+
+
+        if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
+             (p->features & AHC_WIDE) )
+        {
+          p->needwdtr |= (1<<tindex);
+          p->needwdtr_copy |= (1<<tindex);
+          p->transinfo[tindex].goal_width = p->transinfo[tindex].user_width;
+        }
         else
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
-        if ( (((buffer[2] & SCSI_VERSION_BITS) == 3) ||
-               (buffer[56] & SCSI_DT_BIT) ||
-	       (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
-               (p->transinfo[tindex].user_period <= 9) &&
-               (p->transinfo[tindex].user_options) )
         {
-          p->needppr |= (1<<tindex);
-          p->needppr_copy |= (1<<tindex);
-          p->needsdtr &= ~(1<<tindex);
-          p->needsdtr_copy &= ~(1<<tindex);
           p->needwdtr &= ~(1<<tindex);
           p->needwdtr_copy &= ~(1<<tindex);
-          p->dev_flags[tindex] |= DEVICE_SCSI_3;
+          pause_sequencer(p);
+          aic7xxx_set_width(p, cmd->target, cmd->channel, cmd->lun,
+                            MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE |
+                                                     AHC_TRANS_GOAL |
+                                                     AHC_TRANS_CUR) );
+          unpause_sequencer(p, FALSE);
         }
-        else
+        if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
+              p->transinfo[tindex].user_offset )
         {
-          p->needsdtr |= (1<<tindex);
-          p->needsdtr_copy |= (1<<tindex);
-          p->transinfo[tindex].goal_period = 
-            MAX(10, p->transinfo[tindex].goal_period);
-          p->transinfo[tindex].goal_options = 0;
+          p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
+          p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
+          if (p->features & AHC_ULTRA2)
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+          else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+          else
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+          if ( (((buffer[2] & SCSI_VERSION_BITS) >= 3) ||
+                 (buffer[56] & SCSI_DT_BIT) ||
+                 (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
+                 (p->transinfo[tindex].user_period <= 9) &&
+                 (p->transinfo[tindex].user_options) )
+          {
+            p->needppr |= (1<<tindex);
+            p->needppr_copy |= (1<<tindex);
+            p->needsdtr &= ~(1<<tindex);
+            p->needsdtr_copy &= ~(1<<tindex);
+            p->needwdtr &= ~(1<<tindex);
+            p->needwdtr_copy &= ~(1<<tindex);
+            p->dev_flags[tindex] |= DEVICE_SCSI_3;
+          }
+          else
+          {
+            p->needsdtr |= (1<<tindex);
+            p->needsdtr_copy |= (1<<tindex);
+            p->transinfo[tindex].goal_period = 
+              MAX(10, p->transinfo[tindex].goal_period);
+            p->transinfo[tindex].goal_options = 0;
+          }
         }
-      }
-      else
-      {
-        p->needsdtr &= ~(1<<tindex);
-        p->needsdtr_copy &= ~(1<<tindex);
-        p->transinfo[tindex].goal_period = 255;
-        p->transinfo[tindex].goal_offset = 0;
-        p->transinfo[tindex].goal_options = 0;
-      }
-      /*
-       * This is needed to work around a sequencer bug for now.  Regardless
-       * of the controller in use, if we have a Quantum drive, we need to
-       * limit the speed to 80MByte/sec.  As soon as I get a fixed version
-       * of the sequencer, this code will get yanked.
-       */
-      if(!strncmp(buffer + 8, "QUANTUM", 7) &&
-         p->transinfo[tindex].goal_options )
-      {
-        p->transinfo[tindex].goal_period = 
-          MAX(p->transinfo[tindex].goal_period, 10);
-        p->transinfo[tindex].goal_options = 0;
-        p->needppr &= ~(1<<tindex);
-        p->needppr_copy &= ~(1<<tindex);
-        p->needsdtr |= (1<<tindex);
-        p->needsdtr_copy |= (1<<tindex);
-        p->needwdtr |= (1<<tindex);
-        p->needwdtr_copy |= (1<<tindex);
-      }
-      /*
-       * Get the INQUIRY checksum.  We use this on Ultra 160/m
-       * and older devices both.  It allows us to drop speed on any bus type
-       * while at the same time giving us the needed domain validation for
-       * Ultra 160/m
-       *
-       * Note: We only get the checksum and set the SCANNED bit if this is
-       * one of our dtr commands.  If we don't do this, then we end up
-       * getting bad checksum results on the mid-level SCSI code's INQUIRY
-       * commands.
-       */
-      if(p->dev_dtr_cmnd[tindex] == cmd) {
-        unsigned int checksum = 0;
-        int *ibuffer;
-        int i=0;
-
-        ibuffer = (int *)buffer;
-        for( i = 0; i < (cmd->request_bufflen >> 2); i++)
+        else
         {
-          checksum += ibuffer[i];
+          p->needsdtr &= ~(1<<tindex);
+          p->needsdtr_copy &= ~(1<<tindex);
+          p->transinfo[tindex].goal_period = 255;
+          p->transinfo[tindex].goal_offset = 0;
+          p->transinfo[tindex].goal_options = 0;
         }
-        p->dev_checksum[tindex] = checksum;
-        p->dev_flags[tindex] |= DEVICE_SCANNED;
+        p->dev_flags[tindex] |= DEVICE_DTR_SCANNED;
         p->dev_flags[tindex] |= DEVICE_PRINT_DTR;
       }
 #undef WIDE_INQUIRY_BITS
@@ -3016,7 +2983,8 @@
 #undef SCSI_DT_BIT
     }
   }
-  else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
+
+  if ((scb->flags & SCB_MSGOUT_BITS) != 0)
   {
     unsigned short mask;
     int message_error = FALSE;
@@ -3036,7 +3004,6 @@
 
     if (scb->flags & SCB_MSGOUT_WDTR)
     {
-      p->dtr_pending &= ~mask;
       if (message_error)
       {
         if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
@@ -3055,7 +3022,6 @@
     }
     if (scb->flags & SCB_MSGOUT_SDTR)
     {
-      p->dtr_pending &= ~mask;
       if (message_error)
       {
         if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
@@ -3075,7 +3041,6 @@
     }
     if (scb->flags & SCB_MSGOUT_PPR)
     {
-      p->dtr_pending &= ~mask;
       if(message_error)
       {
         if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
@@ -3100,6 +3065,7 @@
       }
     }
   }
+
   queue_depth = p->dev_temp_queue_depth[tindex];
   if (queue_depth >= p->dev_active_cmds[tindex])
   {
@@ -3133,9 +3099,18 @@
       }
     }
   }
-  if ( !(scb->tag_action) && (p->tagenable & (1<<tindex)) )
+  if (!(scb->tag_action))
+  {
+    aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun,
+                              /* unbusy */ TRUE);
+    if (p->tagenable & (1<<tindex))
+    {
+      p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex];
+    }
+  }
+  if(scb->flags & SCB_DTR_SCB)
   {
-    p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex];
+    p->dtr_pending &= ~(1 << tindex);
   }
   p->dev_active_cmds[tindex]--;
   p->activescbs--;
@@ -3244,6 +3219,14 @@
         printk(INFO_LEAD "Aborting scb %d\n",
              p->host_no, CTL_OF_SCB(scb), scb->hscb->tag);
       found++;
+      /*
+       * Clear any residual information since the normal aic7xxx_done() path
+       * doesn't touch the residuals.
+       */
+      scb->hscb->residual_SG_segment_count = 0;
+      scb->hscb->residual_data_count[0] = 0;
+      scb->hscb->residual_data_count[1] = 0;
+      scb->hscb->residual_data_count[2] = 0;
       aic7xxx_done(p, scb);
     }
   }
@@ -3456,8 +3439,22 @@
   active_scb = aic_inb(p, SCBPTR);
 
   if (aic7xxx_verbose & (VERBOSE_RESET_PROCESS | VERBOSE_ABORT_PROCESS))
+  {
     printk(INFO_LEAD "Reset device, active_scb %d\n",
          p->host_no, channel, target, lun, active_scb);
+    printk(INFO_LEAD "Current scb_tag %d, SEQADDR 0x%x, LASTPHASE "
+           "0x%x\n",
+         p->host_no, channel, target, lun, aic_inb(p, SCB_TAG),
+         aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
+         aic_inb(p, LASTPHASE));
+    printk(INFO_LEAD "SG_CACHEPTR 0x%x, SG_COUNT %d, SCSISIGI 0x%x\n",
+         p->host_no, channel, target, lun,
+         (p->features & AHC_ULTRA2) ?  aic_inb(p, SG_CACHEPTR) : 0,
+         aic_inb(p, SG_COUNT), aic_inb(p, SCSISIGI));
+    printk(INFO_LEAD "SSTAT0 0x%x, SSTAT1 0x%x, SSTAT2 0x%x\n",
+         p->host_no, channel, target, lun, aic_inb(p, SSTAT0),
+         aic_inb(p, SSTAT1), aic_inb(p, SSTAT2));
+  }
   /*
    * Deal with the busy target and linked next issues.
    */
@@ -3501,11 +3498,11 @@
       if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
         printk(INFO_LEAD "Cleaning up status information "
           "and delayed_scbs.\n", p->host_no, channel, i, lun);
-      p->dev_flags[i] &= ~(BUS_DEVICE_RESET_PENDING | DEVICE_PARITY_ERROR);
+      p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
       if ( tag == SCB_LIST_NULL )
       {
         p->dev_flags[i] |= DEVICE_PRINT_DTR | DEVICE_RESET_DELAY;
-        p->dev_expires[i] = jiffies + (4 * HZ);
+        p->dev_expires[i] = jiffies + (1 * HZ);
         p->dev_timer_active |= (0x01 << i);
         p->dev_last_queue_full_count[i] = 0;
         p->dev_last_queue_full[i] = 0;
@@ -3550,7 +3547,7 @@
           prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
         }
       }
-      if ( j > (p->scb_data->maxscbs + 1) )
+      if ( j > (p->scb_data->numscbs + 1) )
       {
         if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET))
           printk(WARN_LEAD "Yikes!! There's a loop in the "
@@ -3611,7 +3608,7 @@
         prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
       }
     }
-    if ( j > (p->scb_data->maxscbs + 1) )
+    if ( j > (p->scb_data->numscbs + 1) )
     {
       if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET))
         printk(WARN_LEAD "Yikes!! There's a loop in the "
@@ -4375,11 +4372,25 @@
     if (actual < cmd->underflow)
     {
       if (aic7xxx_verbose & VERBOSE_MINOR_ERROR)
+      {
         printk(INFO_LEAD "Underflow - Wanted %u, %s %u, residual SG "
           "count %d.\n", p->host_no, CTL_OF_SCB(scb), cmd->underflow,
           (cmd->request.cmd == WRITE) ? "wrote" : "read", actual,
           hscb->residual_SG_segment_count);
+        printk(INFO_LEAD "status 0x%x.\n", p->host_no, CTL_OF_SCB(scb),
+          hscb->target_status);
+      }
+      /*
+       * In 2.4, only send back the residual information, don't flag this
+       * as an error.  Before 2.4 we had to flag this as an error because
+       * the mid layer didn't check residual data counts to see if the
+       * command needs retried.
+       */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+      cmd->resid = scb->sg_length - actual;
+#else
       aic7xxx_error(cmd) = DID_RETRY_COMMAND;
+#endif
       aic7xxx_status(cmd) = hscb->target_status;
     }
   }
@@ -4698,7 +4709,6 @@
            */
           p->needwdtr &= ~target_mask;
           p->needwdtr_copy &= ~target_mask;
-          p->dtr_pending &= ~target_mask;
           scb->flags &= ~SCB_MSGOUT_BITS;
           aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
             (AHC_TRANS_ACTIVE|AHC_TRANS_GOAL|AHC_TRANS_CUR));
@@ -4718,8 +4728,7 @@
           */
           p->needsdtr &= ~target_mask;
           p->needsdtr_copy &= ~target_mask;
-          p->dtr_pending &= ~target_mask;
-          scb->flags &= ~SCB_MSGOUT_SDTR;
+          scb->flags &= ~SCB_MSGOUT_BITS;
           aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
             (AHC_TRANS_CUR|AHC_TRANS_ACTIVE|AHC_TRANS_GOAL));
           if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
@@ -4852,6 +4861,8 @@
                 aic7xxx_error(cmd) = DID_OK;
                 break;
               }  /* first time sense, no errors */
+              printk(INFO_LEAD "CHECK_CONDITION on REQUEST_SENSE, returning "
+                     "an error.\n", p->host_no, CTL_OF_SCB(scb));
               aic7xxx_error(cmd) = DID_ERROR;
               scb->flags &= ~SCB_SENSE;
               break;
@@ -5214,12 +5225,21 @@
           printk(KERN_WARNING "  %s seen Data Phase. Length=%d, NumSGs=%d.\n",
             (aic_inb(p, SEQ_FLAGS) & DPHASE) ? "Have" : "Haven't",
             scb->sg_length, scb->sg_count);
-          for (i = 0; i < scb->sg_count; i++)
+          printk(KERN_WARNING "  Raw SCSI Command: 0x");
+          for (i = 0; i < scb->hscb->SCSI_cmd_length; i++)
+          {
+            printk("%02x ", scb->cmd->cmnd[i]);
+          }
+          printk("\n");
+          if(aic7xxx_verbose > 0xffff)
           {
-            printk(KERN_WARNING "     sg[%d] - Addr 0x%x : Length %d\n",
+            for (i = 0; i < scb->sg_count; i++)
+            {
+              printk(KERN_WARNING "     sg[%d] - Addr 0x%x : Length %d\n",
                  i, 
                  le32_to_cpu(scb->sg_list[i].address),
                  le32_to_cpu(scb->sg_list[i].length) );
+            }
           }
           aic7xxx_error(scb->cmd) = DID_ERROR;
         }
@@ -5234,7 +5254,7 @@
         unsigned char resid_sgcnt, index;
         unsigned char scb_index = aic_inb(p, SCB_TAG);
         unsigned int cur_addr, resid_dcnt;
-        unsigned int native_addr, native_length;
+        unsigned int native_addr, native_length, sg_addr;
         int i;
 
         if(scb_index > p->scb_data->numscbs)
@@ -5254,6 +5274,9 @@
                  scb->flags, (unsigned int)scb->cmd);
           break;
         }
+        if(aic7xxx_verbose & VERBOSE_MINOR_ERROR)
+          printk(INFO_LEAD "Got WIDE_RESIDUE message, patching up data "
+                 "pointer.\n", p->host_no, CTL_OF_SCB(scb));
 
         /*
          * We have a valid scb to use on this WIDE_RESIDUE message, so
@@ -5266,132 +5289,87 @@
          */
         cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) |
           (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 24);
+        sg_addr = aic_inb(p, SG_COUNT + 1) | (aic_inb(p, SG_COUNT + 2) << 8) |
+          (aic_inb(p, SG_COUNT + 3) << 16) | (aic_inb(p, SG_COUNT + 4) << 24);
         resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
         resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
           (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
           (aic_inb(p, SCB_RESID_DCNT + 2) << 16);
-        index = scb->sg_count - (resid_sgcnt + 1);
+        index = scb->sg_count - ((resid_sgcnt) ? resid_sgcnt : 1);
         native_addr = le32_to_cpu(scb->sg_list[index].address);
         native_length = le32_to_cpu(scb->sg_list[index].length);
         /*
-         * Make sure this is a valid sg_seg for the given pointer
+         * If resid_dcnt == native_length, then we just loaded this SG
+         * segment and we need to back it up one...
          */
-        if(cur_addr < native_addr ||
-           cur_addr > (native_addr + native_length + 1))
-        {
-          printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
-                 p->host_no, CTL_OF_SCB(scb), cur_addr);
-          if(index > 0)
-            printk(WARN_LEAD "  sg_address[-1]:0x%x sg_length[-1]:%d\n",
-                   p->host_no, CTL_OF_SCB(scb),
-                   le32_to_cpu(scb->sg_list[index - 1].address),
-                   le32_to_cpu(scb->sg_list[index - 1].length));
-          printk(WARN_LEAD "  sg_address:0x%x sg_length:%d\n",
-                 p->host_no, CTL_OF_SCB(scb),
-                 native_addr, native_length);
-          if(resid_sgcnt > 1)
-            printk(WARN_LEAD "  sg_address[1]:0x%x sg_length[1]:%d\n",
-                   p->host_no, CTL_OF_SCB(scb),
-                   le32_to_cpu(scb->sg_list[index + 1].address),
-                   le32_to_cpu(scb->sg_list[index + 1].length));
-          printk(WARN_LEAD "  cur_address:0x%x resid_dcnt:0x%06x\n",
-                 p->host_no, CTL_OF_SCB(scb),
-                 cur_addr, resid_dcnt);
-          break;
-        }
-
-        if( (resid_sgcnt == 0) &&
-            ((resid_dcnt == 0) || (resid_dcnt == 0xffffff)))
+        if(resid_dcnt == native_length)
         {
-          /*
-           * We are at the end of the transfer and this is about a byte
-           * we ignored already (because the sequencer knew this was
-           * the last segment and set the adapter to ignore any wide
-           * residue bytes that might come through, which is only done
-           * on the last scatter gather segment of transfers).
-           */
-          break;
-        }
-        else if(cur_addr == native_addr)
-        {
-          /*
-           * If our current address matches the sg_seg->address then we
-           * have to back up the sg array to the previous segment and set
-           * it up to have only one byte of transfer left to go.
-           */
           if(index == 0)
           {
-            printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
-                   "transferred.\n", p->host_no, CTL_OF_SCB(scb));
+            /*
+             * Oops, this isn't right, we can't back up to before the
+             * beginning.  This must be a bogus message, ignore it.
+             */
             break;
           }
-          resid_sgcnt++;
-          index--;
-          cur_addr = le32_to_cpu(scb->sg_list[index].address) + 
-            le32_to_cpu(scb->sg_list[index].length) - 1;
-          native_addr = aic_inb(p, SG_NEXT) | (aic_inb(p, SG_NEXT + 1) << 8)
-            | (aic_inb(p, SG_NEXT + 2) << 16) | (aic_inb(p, SG_NEXT + 3) << 24);
-          native_addr -= SG_SIZEOF;
-          aic_outb(p, resid_sgcnt, SG_COUNT);
-          aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT);
-          aic_outb(p, native_addr & 0xff, SG_NEXT);
-          aic_outb(p, (native_addr >> 8) & 0xff, SG_NEXT + 1);
-          aic_outb(p, (native_addr >> 16) & 0xff, SG_NEXT + 2);
-          aic_outb(p, (native_addr >> 24) & 0xff, SG_NEXT + 3);
-          aic_outb(p, 1, SCB_RESID_DCNT); 
-          aic_outb(p, 0, SCB_RESID_DCNT + 1); 
-          aic_outb(p, 0, SCB_RESID_DCNT + 2); 
-          aic_outb(p, 1, HCNT); 
-          aic_outb(p, 0, HCNT + 1); 
-          aic_outb(p, 0, HCNT + 2); 
-          aic_outb(p, cur_addr & 0xff, HADDR);
-          aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
-          aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
-          aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+          resid_dcnt = 1;
+          resid_sgcnt += 1;
+          native_addr = le32_to_cpu(scb->sg_list[index - 1].address);
+          native_length = le32_to_cpu(scb->sg_list[index - 1].length);
+          cur_addr = native_addr + (native_length - 1);
+          sg_addr -= sizeof(struct hw_scatterlist);
         }
         else
         {
           /*
-           * Back the data pointer up by one and add one to the remaining
-           * byte count.  Then store that in the HCNT and HADDR registers.
+           * resid_dcnt != native_length, so we are in the middle of a SG
+           * element.  Back it up one byte and leave the rest alone.
            */
-          cur_addr--;
-          resid_dcnt++;
-          aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT); 
-          aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1); 
-          aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2); 
-          aic_outb(p, resid_dcnt & 0xff, HCNT); 
-          aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1); 
-          aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2); 
-          aic_outb(p, cur_addr & 0xff, HADDR);
-          aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
-          aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
-          aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+          resid_dcnt += 1;
+          cur_addr -= 1;
         }
+        
+        /*
+         * Output the new addresses and counts to the right places on the
+         * card.
+         */
+        aic_outb(p, resid_sgcnt, SG_COUNT);
+        aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT);
+        aic_outb(p, sg_addr & 0xff, SG_COUNT + 1);
+        aic_outb(p, (sg_addr >> 8) & 0xff, SG_COUNT + 2);
+        aic_outb(p, (sg_addr >> 16) & 0xff, SG_COUNT + 3);
+        aic_outb(p, (sg_addr >> 24) & 0xff, SG_COUNT + 4);
+        aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT);
+        aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1);
+        aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2);
+
         /*
-         * The sequencer actually wants to find the new address and byte
-         * count in the SHCNT and SHADDR register sets.  These registers
-         * are a shadow of the regular HCNT and HADDR registers.  On the
-         * Ultra2 controllers, these registers are read only and the way
-         * we have to set their values is to put the values we want into
-         * the HCNT and HADDR registers and then output PRELOADEN into
-         * the DFCNTRL register which causes the card to latch the current
-         * values in the HADDR and HCNT registers and drop it through to
-         * the shadow registers.  On older cards we copy them directly
-         * across by hand.
+         * The sequencer actually wants to find the new address
+         * in the SHADDR register set.  On the Ultra2 and later controllers
+         * this register set is readonly.  In order to get the right number
+         * into the register, you actually have to enter it in HADDR and then
+         * use the PRELOADEN bit of DFCNTRL to drop it through from the
+         * HADDR register to the SHADDR register.  On non-Ultra2 controllers,
+         * we simply write it direct.
          */
         if(p->features & AHC_ULTRA2)
         {
-          aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-          i=0;
+          /*
+           * We might as well be accurate and drop both the resid_dcnt and
+           * cur_addr into HCNT and HADDR and have both of them drop
+           * through to the shadow layer together.
+           */
+          aic_outb(p, resid_dcnt & 0xff, HCNT);
+          aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1);
+          aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2);
+          aic_outb(p, cur_addr & 0xff, HADDR);
+          aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+          aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+          aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+          aic_outb(p, aic_inb(p, DMAPARAMS) | PRELOADEN, DFCNTRL);
           udelay(1);
-          while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
-          {
-            udelay(1);
-          }
           aic_outb(p, aic_inb(p, DMAPARAMS) & ~(SCSIEN|HDMAEN), DFCNTRL);
           i=0;
-          udelay(1);
           while(((aic_inb(p, DFCNTRL) & (SCSIEN|HDMAEN)) != 0) && (i++ < 1000))
           {
             udelay(1);
@@ -5399,9 +5377,6 @@
         }
         else
         {
-          aic_outb(p, resid_dcnt & 0xff, STCNT); 
-          aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
-          aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
           aic_outb(p, cur_addr & 0xff, SHADDR);
           aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
           aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
@@ -5410,15 +5385,82 @@
       }
       break;
 
-        
-#if AIC7XXX_NOT_YET 
-    case TRACEPOINT:
+    case SEQ_SG_FIXUP:
+    {
+      unsigned char scb_index, tmp;
+      int sg_addr, sg_length;
+
+      scb_index = aic_inb(p, SCB_TAG);
+
+      if(scb_index > p->scb_data->numscbs)
       {
-        printk(INFO_LEAD "Tracepoint #1 reached.\n", p->host_no,
-               channel, target, lun);
+        printk(WARN_LEAD "invalid scb_index during SEQ_SG_FIXUP.\n",
+          p->host_no, -1, -1, -1);
+        printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 "
+           "0x%x\n", p->host_no, -1, -1, -1,
+           aic_inb(p, SCSISIGI),
+           aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
+           aic_inb(p, SSTAT0), aic_inb(p, SSTAT1));
+        printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n",
+           p->host_no, -1, -1, -1, aic_inb(p, SG_CACHEPTR),
+           aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 |
+           aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT));
+        /*
+         * XXX: Add error handling here
+         */
+        break;
       }
-      break;
+      scb = p->scb_data->scb_array[scb_index];
+      if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+      {
+        printk(WARN_LEAD "invalid scb during SEQ_SG_FIXUP flags:0x%x "
+               "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb),
+               scb->flags, (unsigned int)scb->cmd);
+        printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 "
+           "0x%x\n", p->host_no, CTL_OF_SCB(scb),
+           aic_inb(p, SCSISIGI),
+           aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
+           aic_inb(p, SSTAT0), aic_inb(p, SSTAT1));
+        printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n",
+           p->host_no, CTL_OF_SCB(scb), aic_inb(p, SG_CACHEPTR),
+           aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 |
+           aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT));
+        break;
+      }
+      if(aic7xxx_verbose & VERBOSE_MINOR_ERROR)
+        printk(INFO_LEAD "Fixing up SG address for sequencer.\n", p->host_no,
+               CTL_OF_SCB(scb));
+      /*
+       * Advance the SG pointer to the next element in the list
+       */
+      tmp = aic_inb(p, SG_NEXT);
+      tmp += SG_SIZEOF;
+      aic_outb(p, tmp, SG_NEXT);
+      if( tmp < SG_SIZEOF )
+        aic_outb(p, aic_inb(p, SG_NEXT + 1) + 1, SG_NEXT + 1);
+      tmp = aic_inb(p, SG_COUNT) - 1;
+      aic_outb(p, tmp, SG_COUNT);
+      sg_addr = le32_to_cpu(scb->sg_list[scb->sg_count - tmp].address);
+      sg_length = le32_to_cpu(scb->sg_list[scb->sg_count - tmp].length);
+      /*
+       * Now stuff the element we just advanced past down onto the
+       * card so it can be stored in the residual area.
+       */
+      aic_outb(p, sg_addr & 0xff, HADDR);
+      aic_outb(p, (sg_addr >> 8) & 0xff, HADDR + 1);
+      aic_outb(p, (sg_addr >> 16) & 0xff, HADDR + 2);
+      aic_outb(p, (sg_addr >> 24) & 0xff, HADDR + 3);
+      aic_outb(p, sg_length & 0xff, HCNT);
+      aic_outb(p, (sg_length >> 8) & 0xff, HCNT + 1);
+      aic_outb(p, (sg_length >> 16) & 0xff, HCNT + 2);
+      aic_outb(p, (tmp << 2) | ((tmp == 1) ? LAST_SEG : 0), SG_CACHEPTR);
+      aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+      while(aic_inb(p, SSTAT0) & SDONE) udelay(1);
+      while(aic_inb(p, DFCNTRL) & (HDMAEN|SCSIEN)) aic_outb(p, 0, DFCNTRL);
+    }
+    break;
 
+#if AIC7XXX_NOT_YET 
     case TRACEPOINT2:
       {
         printk(INFO_LEAD "Tracepoint #2 reached.\n", p->host_no,
@@ -5463,6 +5505,10 @@
   unsigned char target_scsirate, tindex;
   unsigned short target_mask;
   unsigned char target, channel, lun;
+  unsigned char bus_width, new_bus_width;
+  unsigned char trans_options, new_trans_options;
+  unsigned int period, new_period, offset, new_offset, maxsync;
+  struct aic7xxx_syncrate *syncrate;
 
   target = scb->cmd->target;
   channel = scb->cmd->channel;
@@ -5486,6 +5532,35 @@
   }
 
   /*
+   * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when
+   * using the SDTR messages.  We need the PPR messages to enable the
+   * higher speeds that include things like Dual Edge clocking.
+   */
+  if (p->features & AHC_ULTRA2)
+  {
+    if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
+         !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
+    {
+      if (p->features & AHC_ULTRA3)
+        maxsync = AHC_SYNCRATE_ULTRA3;
+      else
+        maxsync = AHC_SYNCRATE_ULTRA2;
+    }
+    else
+    {
+      maxsync = AHC_SYNCRATE_ULTRA;
+    }
+  }
+  else if (p->features & AHC_ULTRA)
+  {
+    maxsync = AHC_SYNCRATE_ULTRA;
+  }
+  else
+  {
+    maxsync = AHC_SYNCRATE_FAST;
+  }
+
+  /*
    * Just accept the length byte outright and perform
    * more checking once we know the message type.
    */
@@ -5496,9 +5571,6 @@
     {
       case MSG_EXT_SDTR:
       {
-        unsigned int period, offset;
-        unsigned char maxsync, saved_offset, options;
-        struct aic7xxx_syncrate *syncrate;
         
         if (p->msg_buf[1] != MSG_EXT_SDTR_LEN)
         {
@@ -5511,35 +5583,18 @@
           break;
         }
 
-        period = p->msg_buf[3];
-        saved_offset = offset = p->msg_buf[4];
-        options = 0;
+        period = new_period = p->msg_buf[3];
+        offset = new_offset = p->msg_buf[4];
+        trans_options = new_trans_options = 0;
+        bus_width = new_bus_width = target_scsirate & WIDEXFER;
 
         /*
-         * Even if we are an Ultra3 card, don't allow Ultra3 sync rates when
-         * using the SDTR messages.  We need the PPR messages to enable the
-         * higher speeds that include things like Dual Edge clocking.
+         * If our current max syncrate is in the Ultra3 range, bump it back
+         * down to Ultra2 since we can't negotiate DT transfers using SDTR
          */
-        if (p->features & AHC_ULTRA2)
-        {
-          if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
-               !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
-          {
-            maxsync = AHC_SYNCRATE_ULTRA2;
-          }
-          else
-          {
-            maxsync = AHC_SYNCRATE_ULTRA;
-          }
-        }
-        else if (p->features & AHC_ULTRA)
-        {
-          maxsync = AHC_SYNCRATE_ULTRA;
-        }
-        else
-        {
-          maxsync = AHC_SYNCRATE_FAST;
-        }
+        if(maxsync == AHC_SYNCRATE_ULTRA3)
+          maxsync = AHC_SYNCRATE_ULTRA2;
+
         /*
          * We might have a device that is starting negotiation with us
          * before we can start up negotiation with it....be prepared to
@@ -5549,88 +5604,116 @@
         if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
         {
-          if (!(p->dev_flags[tindex] & DEVICE_SCANNED) &&
-              !(p->needsdtr_copy & target_mask) &&
-               (p->transinfo[tindex].user_offset) )
+          if (!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED))
           {
             /*
-             * Not only is the device starting this up, but it also hasn't
-             * been scanned yet, so this would likely be our TUR or our
-             * INQUIRY command at scan time, so we need to use the
-             * settings from the SEEPROM if they existed.  Of course, even
-             * if we didn't find a SEEPROM, we stuffed default values into
-             * the user settings anyway, so use those in all cases.
+             * We shouldn't get here unless this is a narrow drive, wide
+             * devices should trigger this same section of code in the WDTR
+             * handler first instead.
              */
-            p->transinfo[tindex].goal_period =
-              p->transinfo[tindex].user_period;
-            if(p->features & AHC_ULTRA2)
-            {
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-            }
-            else if (p->transinfo[tindex].cur_width)
+            p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
+            p->transinfo[tindex].goal_options = 0;
+            if(p->transinfo[tindex].user_offset)
             {
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+              p->needsdtr_copy |= target_mask;
+              p->transinfo[tindex].goal_period =
+                MAX(10,p->transinfo[tindex].user_period);
+              if(p->features & AHC_ULTRA2)
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+              }
+              else
+              {
+                p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+              }
             }
             else
             {
-              p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+              p->needsdtr_copy &= ~target_mask;
+              p->transinfo[tindex].goal_period = 255;
+              p->transinfo[tindex].goal_offset = 0;
             }
-            p->needsdtr_copy |= target_mask;
+            p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR;
+          }
+          else if ((p->needsdtr_copy & target_mask) == 0)
+          {
+            /*
+             * This is a preemptive message from the target, we've already
+             * scanned this target and set our options for it, and we
+             * don't need a WDTR with this target (for whatever reason),
+             * so reject this incoming WDTR
+             */
+            reject = TRUE;
+            break;
           }
+
+          /* The device is sending this message first and we have to reply */
+          reply = TRUE;
+          
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Received pre-emptive SDTR message from "
                    "target.\n", p->host_no, CTL_OF_SCB(scb));
           }
-          if ( !p->transinfo[tindex].goal_offset )
-            period = 255;
-          if ( p->transinfo[tindex].goal_period > period )
-            period = p->transinfo[tindex].goal_period;
+          /*
+           * Validate the values the device passed to us against our SEEPROM
+           * settings.  We don't have to do this if we aren't replying since
+           * the device isn't allowed to send values greater than the ones
+           * we first sent to it.
+           */
+          new_period = MAX(period, p->transinfo[tindex].goal_period);
+          new_offset = MIN(offset, p->transinfo[tindex].goal_offset);
         }
-  
-        syncrate = aic7xxx_find_syncrate(p, &period, maxsync, &options);
-        aic7xxx_validate_offset(p, syncrate, &offset,
-                                target_scsirate & WIDEXFER);
-        aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                             offset, options, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+ 
+        /*
+         * Use our new_period, new_offset, bus_width, and card options
+         * to determine the actual syncrate settings
+         */
+        syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync,
+                                         &trans_options);
+        aic7xxx_validate_offset(p, syncrate, &new_offset, bus_width);
 
         /*
-         * Did we drop to async?  Or are we sending a reply?  If we are,
-         * then we have to make sure that the reply value reflects the proper
-         * settings so we need to set the goal values according to what
-         * we need to send.
+         * Did we drop to async?  If so, send a reply regardless of whether
+         * or not we initiated this negotiation.
          */
-        if ( (offset != saved_offset) ||
-             ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
-              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
+        if ((new_offset == 0) && (new_offset != offset))
         {
-          aic7xxx_set_syncrate(p, syncrate, target, channel, period, offset,
-                               options, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+          p->needsdtr_copy &= ~target_mask;
+          reply = TRUE;
         }
         
         /*
-         * Did we start this, if not, or if we went to low and had to
+         * Did we start this, if not, or if we went too low and had to
          * go async, then send an SDTR back to the target
          */
-        p->needsdtr &= ~target_mask;
-        p->dtr_pending &= ~target_mask;
-        if ( ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
-              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) ||
-             (offset != saved_offset) )
+        if(reply)
         {
-          reply = TRUE;
-          p->dtr_pending |= target_mask;
+          /* when sending a reply, make sure that the goal settings are
+           * updated along with current and active since the code that
+           * will actually build the message for the sequencer uses the
+           * goal settings as its guidelines.
+           */
+          aic7xxx_set_syncrate(p, syncrate, target, channel, new_period,
+                               new_offset, trans_options,
+                               AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_SDTR;
           aic_outb(p, HOST_MSG, MSG_OUT);
           aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
         }
+        else
+        {
+          aic7xxx_set_syncrate(p, syncrate, target, channel, new_period,
+                               new_offset, trans_options,
+                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          p->needsdtr &= ~target_mask;
+        }
         done = TRUE;
         break;
       }
       case MSG_EXT_WDTR:
       {
-        unsigned char bus_width;
           
         if (p->msg_buf[1] != MSG_EXT_WDTR_LEN)
         {
@@ -5643,7 +5726,8 @@
           break;
         }
 
-        bus_width = p->msg_buf[3];
+        bus_width = new_bus_width = p->msg_buf[3];
+
         if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_WDTR)) ==
              (SCB_MSGOUT_SENT|SCB_MSGOUT_WDTR) )
         {
@@ -5662,7 +5746,7 @@
             } /* We fall through on purpose */
             case MSG_EXT_WDTR_BUS_8_BIT:
             {
-              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+              p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
               p->needwdtr_copy &= ~target_mask;
               break;
             }
@@ -5671,29 +5755,40 @@
               break;
             }
           }
-          p->dtr_pending &= ~target_mask;
           p->needwdtr &= ~target_mask;
+          aic7xxx_set_width(p, target, channel, lun, new_bus_width,
+                            AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
         }
         else
         {
-          if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
+          if ( !(p->dev_flags[tindex] & DEVICE_DTR_SCANNED) )
           {
             /* 
              * Well, we now know the WDTR and SYNC caps of this device since
              * it contacted us first, mark it as such and copy the user stuff
              * over to the goal stuff.
              */
-            p->transinfo[tindex].goal_period =
-              p->transinfo[tindex].user_period;
+            if( (p->features & AHC_WIDE) && p->transinfo[tindex].user_width )
+            {
+              p->transinfo[tindex].goal_width = MSG_EXT_WDTR_BUS_16_BIT;
+              p->needwdtr_copy |= target_mask;
+            }
+            
+            /*
+             * Devices that support DT transfers don't start WDTR requests
+             */
+            p->transinfo[tindex].goal_options = 0;
+
             if(p->transinfo[tindex].user_offset)
             {
+              p->needsdtr_copy |= target_mask;
+              p->transinfo[tindex].goal_period =
+                MAX(10,p->transinfo[tindex].user_period);
               if(p->features & AHC_ULTRA2)
               {
                 p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
               }
-              else if( p->transinfo[tindex].user_width &&
-                       (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
-                       p->features & AHC_WIDE )
+              else if( p->transinfo[tindex].goal_width )
               {
                 p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
               }
@@ -5701,48 +5796,76 @@
               {
                 p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
               }
+            } else {
+              p->needsdtr_copy &= ~target_mask;
+              p->transinfo[tindex].goal_period = 255;
+              p->transinfo[tindex].goal_offset = 0;
             }
-            p->transinfo[tindex].goal_width =
-              p->transinfo[tindex].user_width;
-            p->needwdtr_copy |= target_mask;
-            p->needsdtr_copy |= target_mask;
+            
+            p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR;
           }
-          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          else if ((p->needwdtr_copy & target_mask) == 0)
           {
-            printk(INFO_LEAD "Received pre-emptive WDTR message from "
-                   "target.\n", p->host_no, CTL_OF_SCB(scb));
-          }
+            /*
+             * This is a preemptive message from the target, we've already
+             * scanned this target and set our options for it, and we
+             * don't need a WDTR with this target (for whatever reason),
+             * so reject this incoming WDTR
+             */
+            reject = TRUE;
+            break;
+          }
+
+          /* The device is sending this message first and we have to reply */
+          reply = TRUE;
+
+          if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+          {
+            printk(INFO_LEAD "Received pre-emptive WDTR message from "
+                   "target.\n", p->host_no, CTL_OF_SCB(scb));
+          }
           switch(bus_width)
           {
-            default:
+            case MSG_EXT_WDTR_BUS_16_BIT:
             {
               if ( (p->features & AHC_WIDE) &&
                    (p->transinfo[tindex].goal_width ==
                     MSG_EXT_WDTR_BUS_16_BIT) )
               {
-                bus_width = MSG_EXT_WDTR_BUS_16_BIT;
+                new_bus_width = MSG_EXT_WDTR_BUS_16_BIT;
                 break;
               }
             } /* Fall through if we aren't a wide card */
+            default:
             case MSG_EXT_WDTR_BUS_8_BIT:
             {
               p->needwdtr_copy &= ~target_mask;
-              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
-              aic7xxx_set_width(p, target, channel, lun, bus_width,
-                                AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+              new_bus_width = MSG_EXT_WDTR_BUS_8_BIT;
               break;
             }
           }
-          reply = TRUE;
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_WDTR;
           p->needwdtr &= ~target_mask;
-          p->dtr_pending |= target_mask;
+          if((p->dtr_pending & target_mask) == 0)
+          {
+            /* there is no other command with SCB_DTR_SCB already set that will
+             * trigger the release of the dtr_pending bit.  Both set the bit
+             * and set scb->flags |= SCB_DTR_SCB
+             */
+            p->dtr_pending |= target_mask;
+            scb->flags |= SCB_DTR_SCB;
+          }
           aic_outb(p, HOST_MSG, MSG_OUT);
           aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
+          /* when sending a reply, make sure that the goal settings are
+           * updated along with current and active since the code that
+           * will actually build the message for the sequencer uses the
+           * goal settings as its guidelines.
+           */
+          aic7xxx_set_width(p, target, channel, lun, new_bus_width,
+                          AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
         }
-        aic7xxx_set_width(p, target, channel, lun, bus_width,
-                          AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
         
         /*
          * By virtue of the SCSI spec, a WDTR message negates any existing
@@ -5759,10 +5882,6 @@
       }
       case MSG_EXT_PPR:
       {
-        unsigned char bus_width, trans_options, new_trans_options;
-        unsigned int period, offset;
-        unsigned char maxsync, saved_offset;
-        struct aic7xxx_syncrate *syncrate;
         
         if (p->msg_buf[1] != MSG_EXT_PPR_LEN)
         {
@@ -5775,9 +5894,9 @@
           break;
         }
 
-        period = p->msg_buf[3];
-        offset = saved_offset = p->msg_buf[5];
-        bus_width = p->msg_buf[6];
+        period = new_period = p->msg_buf[3];
+        offset = new_offset = p->msg_buf[5];
+        bus_width = new_bus_width = p->msg_buf[6];
         trans_options = new_trans_options = p->msg_buf[7] & 0xf;
 
         if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
@@ -5787,22 +5906,6 @@
                  trans_options);
         }
 
-        if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
-            !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
-        {
-          if(p->features & AHC_ULTRA3)
-          {
-            maxsync = AHC_SYNCRATE_ULTRA3;
-          }
-          else
-          {
-            maxsync = AHC_SYNCRATE_ULTRA2;
-          }
-        }
-        else
-        {
-          maxsync = AHC_SYNCRATE_ULTRA;
-        }
         /*
          * We might have a device that is starting negotiation with us
          * before we can start up negotiation with it....be prepared to
@@ -5811,13 +5914,22 @@
          */
         if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
              (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR) )
-        {
-          reply = TRUE;
-          scb->flags &= ~SCB_MSGOUT_BITS;
-          scb->flags |= SCB_MSGOUT_PPR;
-	  p->dev_flags[tindex] |= DEVICE_SCSI_3;
-          if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
-          {
+        { 
+          /* Have we scanned the device yet? */
+          if (!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED))
+          {
+            /* The device is electing to use PPR messages, so we will too until
+             * we know better */
+            p->needppr |= target_mask;
+            p->needppr_copy |= target_mask;
+            p->needsdtr &= ~target_mask;
+            p->needsdtr_copy &= ~target_mask;
+            p->needwdtr &= ~target_mask;
+            p->needwdtr_copy &= ~target_mask;
+          
+            /* We know the device is SCSI-3 compliant due to PPR */
+            p->dev_flags[tindex] |= DEVICE_SCSI_3;
+          
             /*
              * Not only is the device starting this up, but it also hasn't
              * been scanned yet, so this would likely be our TUR or our
@@ -5826,15 +5938,19 @@
              * if we didn't find a SEEPROM, we stuffed default values into
              * the user settings anyway, so use those in all cases.
              */
-            p->transinfo[tindex].goal_period =
-              p->transinfo[tindex].user_period;
+            p->transinfo[tindex].goal_width =
+              p->transinfo[tindex].user_width;
             if(p->transinfo[tindex].user_offset)
             {
+              p->transinfo[tindex].goal_period =
+                p->transinfo[tindex].user_period;
+              p->transinfo[tindex].goal_options =
+                p->transinfo[tindex].user_options;
               if(p->features & AHC_ULTRA2)
               {
                 p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
               }
-              else if( p->transinfo[tindex].user_width &&
+              else if( p->transinfo[tindex].goal_width &&
                        (bus_width == MSG_EXT_WDTR_BUS_16_BIT) &&
                        p->features & AHC_WIDE )
               {
@@ -5845,117 +5961,142 @@
                 p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
               }
             }
-            p->transinfo[tindex].goal_width =
-              p->transinfo[tindex].user_width;
-            p->transinfo[tindex].goal_options =
-              p->transinfo[tindex].user_options;
+            else
+            {
+              p->transinfo[tindex].goal_period = 255;
+              p->transinfo[tindex].goal_offset = 0;
+              p->transinfo[tindex].goal_options = 0;
+            }
+            p->dev_flags[tindex] |= DEVICE_DTR_SCANNED | DEVICE_PRINT_DTR;
+          }
+          else if ((p->needppr_copy & target_mask) == 0)
+          {
+            /*
+             * This is a preemptive message from the target, we've already
+             * scanned this target and set our options for it, and we
+             * don't need a PPR with this target (for whatever reason),
+             * so reject this incoming PPR
+             */
+            reject = TRUE;
+            break;
           }
+
+          /* The device is sending this message first and we have to reply */
+          reply = TRUE;
+          
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Received pre-emptive PPR message from "
                    "target.\n", p->host_no, CTL_OF_SCB(scb));
           }
-          if ( !p->transinfo[tindex].goal_offset )
-            period = 255;
-          if ( p->transinfo[tindex].goal_period > period )
-            period = p->transinfo[tindex].goal_period;
-          if ( p->transinfo[tindex].goal_options == 0 )
-            new_trans_options = 0;
-          switch(bus_width)
+
+        }
+
+        switch(bus_width)
+        {
+          case MSG_EXT_WDTR_BUS_16_BIT:
           {
-            default:
-            {
-              if ( (p->features & AHC_WIDE) &&
-                   (p->transinfo[tindex].goal_width ==
-                    MSG_EXT_WDTR_BUS_16_BIT) )
-              {
-                bus_width = MSG_EXT_WDTR_BUS_16_BIT;
-                break;
-              }
-            } /* Fall through if we aren't a wide card */
-            case MSG_EXT_WDTR_BUS_8_BIT:
+            if ( (p->transinfo[tindex].goal_width ==
+                  MSG_EXT_WDTR_BUS_16_BIT) && p->features & AHC_WIDE)
             {
-              p->needwdtr_copy &= ~target_mask;
-              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
-              aic7xxx_set_width(p, target, channel, lun, bus_width,
-                                AHC_TRANS_GOAL|AHC_TRANS_QUITE);
               break;
             }
           }
-          if ( (p->transinfo[tindex].goal_period > 9) ||
-               (p->transinfo[tindex].goal_options == 0) )
+          default:
           {
-            scb->flags &= ~SCB_MSGOUT_BITS;
-            reject = TRUE;
-            reply = FALSE;
-            p->needppr &= ~(1 << tindex);
-            p->needppr_copy &= ~(1 << tindex);
-            if ( p->transinfo[tindex].goal_offset )
-            {
-              p->needsdtr |= (1 << tindex);
-              p->needsdtr_copy |= (1 << tindex);
-            }
-            if ( p->transinfo[tindex].goal_width )
-            {
-              p->needwdtr |= (1 << tindex);
-              p->needwdtr_copy |= (1 << tindex);
+            if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+                 ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
+                  (aic7xxx_verbose > 0xffff)) )
+            {
+              reply = TRUE;
+              printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
+                p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
             }
+          } /* We fall through on purpose */
+          case MSG_EXT_WDTR_BUS_8_BIT:
+          {
+            /*
+             * According to the spec, if we aren't wide, we also can't be
+             * Dual Edge so clear the options byte
+             */
+            new_trans_options = 0;
+            new_bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+            break;
           }
         }
+
+        if(reply)
+        {
+          /* when sending a reply, make sure that the goal settings are
+           * updated along with current and active since the code that
+           * will actually build the message for the sequencer uses the
+           * goal settings as its guidelines.
+           */
+          aic7xxx_set_width(p, target, channel, lun, new_bus_width,
+                            AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync,
+                                           &new_trans_options);
+          aic7xxx_validate_offset(p, syncrate, &new_offset, new_bus_width);
+          aic7xxx_set_syncrate(p, syncrate, target, channel, new_period,
+                               new_offset, new_trans_options,
+                               AHC_TRANS_GOAL|AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+        }
         else
         {
-          switch(bus_width)
+          aic7xxx_set_width(p, target, channel, lun, new_bus_width,
+                            AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          syncrate = aic7xxx_find_syncrate(p, &new_period, maxsync,
+                                           &new_trans_options);
+          aic7xxx_validate_offset(p, syncrate, &new_offset, new_bus_width);
+          aic7xxx_set_syncrate(p, syncrate, target, channel, new_period,
+                               new_offset, new_trans_options,
+                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+        }
+
+        /*
+         * As it turns out, if we don't *have* to have PPR messages, then
+         * configure ourselves not to use them since that makes some
+         * external drive chassis work (those chassis can't parse PPR
+         * messages and they mangle the SCSI bus until you send a WDTR
+         * and SDTR that they can understand).
+         */
+        if(new_trans_options == 0)
+        {
+          p->needppr &= ~target_mask;
+          p->needppr_copy &= ~target_mask;
+          if(new_offset)
           {
-            default:
-            {
-              reject = TRUE;
-              if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
-                   ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
-                    (aic7xxx_verbose > 0xffff)) )
-              {
-                printk(INFO_LEAD "Requesting %d bit transfers, rejecting.\n",
-                  p->host_no, CTL_OF_SCB(scb), 8 * (0x01 << bus_width));
-              }
-            } /* We fall through on purpose */
-            case MSG_EXT_WDTR_BUS_8_BIT:
-            {
-              /*
-               * According to the spec, if we aren't wide, we also can't be
-               * Dual Edge so clear the options byte
-               */
-              new_trans_options = 0;
-              bus_width = MSG_EXT_WDTR_BUS_8_BIT;
-              break;
-            }
-            case MSG_EXT_WDTR_BUS_16_BIT:
-            {
-              break;
-            }
+            p->needsdtr |= target_mask;
+            p->needsdtr_copy |= target_mask;
+          }
+          if (new_bus_width)
+          {
+            p->needwdtr |= target_mask;
+            p->needwdtr_copy |= target_mask;
           }
         }
 
-        if ( !reject )
+        if((new_offset == 0) && (offset != 0))
         {
-          aic7xxx_set_width(p, target, channel, lun, bus_width,
-                            AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-          syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
-                                           &new_trans_options);
-          aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
-          aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                               offset, new_trans_options,
-                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          /*
+           * Oops, the syncrate went to low for this card and we fell off
+           * to async (should never happen with a device that uses PPR
+           * messages, but have to be complete)
+           */
+          reply = TRUE;
         }
 
-        p->dtr_pending &= ~target_mask;
-        p->needppr &= ~target_mask;
         if(reply)
         {
-          p->dtr_pending |= target_mask;
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_PPR;
           aic_outb(p, HOST_MSG, MSG_OUT);
           aic_outb(p, aic_inb(p, SCSISIGO) | ATNO, SCSISIGO);
         }
+        else
+        {
+          p->needppr &= ~target_mask;
+        }
         done = TRUE;
         break;
       }
@@ -6193,16 +6334,14 @@
         printerror = 0;
       }
     }
-    if ( (scb != NULL) &&
-         (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)]) )
+    if ( (scb != NULL) && (scb->flags & SCB_DTR_SCB) ) 
     {
       /*
-       * This might be a SCSI-3 device that is dropping the bus due to
-       * errors and signalling that we should reduce the transfer speed.
-       * All we have to do is complete this command (since it's a negotiation
-       * command already) and the checksum routine should flag an error and
-       * reduce the speed setting and renegotiate.  We call the reset routing
-       * just to clean out the hardware from this scb.
+       * Hmmm...error during a negotiation command.  Either we have a
+       * borken bus, or the device doesn't like our negotiation message.
+       * Since we check the INQUIRY data of a device before sending it
+       * negotiation messages, assume the bus is borken for whatever
+       * reason.  Complete the command.
        */
       printerror = 0;
       aic7xxx_reset_device(p, target, channel, ALL_LUNS, scb->hscb->tag);
@@ -6334,19 +6473,6 @@
         cmd->result = 0;
         scb = NULL;
       }
-      else if (scb->cmd == p->dev_dtr_cmnd[TARGET_INDEX(scb->cmd)])
-      {
-        /*
-         * Turn off the needsdtr, needwdtr, and needppr bits since this device
-         * doesn't seem to exist.
-         */
-        p->needppr &= ~(0x01 << TARGET_INDEX(scb->cmd));
-        p->needppr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
-        p->needsdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
-        p->needsdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
-        p->needwdtr &= ~(0x01 << TARGET_INDEX(scb->cmd));
-        p->needwdtr_copy &= ~(0x01 << TARGET_INDEX(scb->cmd));
-      }
     }
     /*
      * Keep the sequencer from trying to restart any selections
@@ -6469,7 +6595,6 @@
       }
     }
     else if( (lastphase == P_MESGOUT) &&
-             (cmd == p->dev_dtr_cmnd[tindex]) &&
              (scb->flags & SCB_MSGOUT_PPR) )
     {
       /*
@@ -6488,7 +6613,6 @@
       aic7xxx_set_syncrate(p, NULL, scb->cmd->target, scb->cmd->channel, 0, 0,
                            0, AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
       p->transinfo[tindex].goal_options = 0;
-      p->dtr_pending &= ~(1 << tindex);
       scb->flags &= ~SCB_MSGOUT_BITS;
       if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
       {
@@ -6511,87 +6635,6 @@
       }
       scb = NULL;
     }
-    else if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
-    {
-      struct aic7xxx_syncrate *syncrate;
-      unsigned int period = p->transinfo[tindex].cur_period;
-      unsigned char options = p->transinfo[tindex].cur_options;
-      /*
-       * oops, we had a failure, lower the transfer rate and try again.  It's
-       * worth noting here that it might be wise to also check for typical
-       * wide setting on narrow cable type problems and try disabling wide
-       * instead of slowing down if those exist.  That's hard to do with simple
-       * checksums though.
-       */
-      printk(WARN_LEAD "Parity error during %s phase.\n",
-             p->host_no, CTL_OF_SCB(scb), phase);
-      if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
-      {
-        syncrate++;
-        if( (syncrate->rate[0] != NULL) &&
-            (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
-        {
-          p->transinfo[tindex].goal_period = syncrate->period;
-          if( p->transinfo[tindex].goal_period > 9 )
-          {
-            p->transinfo[tindex].goal_options = 0;
-            p->needppr &= ~(1<<tindex);
-            p->needsdtr |= (1<<tindex);
-            p->needppr_copy &= ~(1<<tindex);
-            p->needsdtr_copy |= (1<<tindex);
-            if (p->transinfo[tindex].goal_width)
-            {
-              p->needwdtr |= (1<<tindex);
-              p->needwdtr_copy |= (1<<tindex);
-            }
-          }
-        }
-        else if (p->transinfo[tindex].goal_width)
-        {
-          p->transinfo[tindex].goal_width = 0;
-          p->needwdtr &= ~(1<<tindex);
-          p->needwdtr_copy &= ~(1<<tindex);
-          p->transinfo[tindex].goal_offset =
-            p->transinfo[tindex].user_offset;
-          p->transinfo[tindex].goal_period =
-            p->transinfo[tindex].user_period;
-          p->transinfo[tindex].goal_options =
-            p->transinfo[tindex].user_options;
-          if( p->transinfo[tindex].goal_period <= 9 )
-          {
-            p->needppr |= (1<<tindex);
-            p->needsdtr &= ~(1<<tindex);
-            p->needppr_copy |= (1<<tindex);
-            p->needsdtr_copy &= ~(1<<tindex);
-          }
-          else
-          {
-            p->needppr &= ~(1<<tindex);
-            p->needsdtr |= (1<<tindex);
-            p->needppr_copy &= ~(1<<tindex);
-            p->needsdtr_copy |= (1<<tindex);
-          }
-        }
-        else
-        {
-          p->transinfo[tindex].goal_offset = 0;
-          p->transinfo[tindex].goal_period = 255;
-          p->transinfo[tindex].goal_options = 0;
-          p->transinfo[tindex].goal_width = 0;
-          p->needppr &= ~(1<<tindex);
-          p->needsdtr &= ~(1<<tindex);
-          p->needwdtr &= ~(1<<tindex);
-          p->needppr_copy &= ~(1<<tindex);
-          p->needsdtr_copy &= ~(1<<tindex);
-          p->needwdtr_copy &= ~(1<<tindex);
-        }
-      }
-      p->dev_flags[tindex] &= ~DEVICE_PARITY_ERROR;
-    }
-    else
-    {
-      p->dev_flags[tindex] |= DEVICE_PARITY_ERROR;
-    }
 
     /*
      * We've set the hardware to assert ATN if we get a parity
@@ -6860,34 +6903,11 @@
     else if (scb->flags & SCB_SENSE)
     {
       char *buffer = &scb->cmd->sense_buffer[0];
-      if (scb->cmd == p->dev_dtr_cmnd[tindex])
-      {
-        struct aic7xxx_scb *old_scb;
-        /*
-         * We have valid sense data, send it back immediately.
-         */
-        old_scb = p->scb_data->scb_array[scb->cmd->next->tag];
-        *old_scb->cmd->sense_buffer = *scb->cmd->sense_buffer;
-        old_scb->hscb->target_status = scb->hscb->target_status;
-        old_scb->cmd->result = scb->hscb->target_status;
-        old_scb->cmd->result |= (DID_ERROR << 16);
-        aic7xxx_status(old_scb->cmd) = scb->hscb->target_status;
-        scbq_remove(&p->waiting_scbs, old_scb);
-        scbq_remove(&p->delayed_scbs[tindex], old_scb);
-        scb->cmd->next = NULL;
-	aic7xxx_done(p, scb);
-        aic7xxx_done(p, old_scb);
-	continue;
-      } 
-      else if (buffer[12] == 0x47 || buffer[12] == 0x54)
+
+      if (buffer[12] == 0x47 || buffer[12] == 0x54)
       {
         /*
-         * SCSI errors, run domain validation and re-run negotiation
-         */
-        p->needdv |= (1<<tindex);
-        /*
-         * Signal that we need to re-negotiate things, this also gets us our
-         * INQUIRY command to re-checksum off of.
+         * Signal that we need to re-negotiate things.
          */
         p->needppr |= (p->needppr_copy & (1<<tindex));
         p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
@@ -6900,7 +6920,18 @@
       case BUSY:
         scb->hscb->target_status = 0;
         scb->cmd->result = 0;
+        scb->hscb->residual_SG_segment_count = 0;
+        scb->hscb->residual_data_count[0] = 0;
+        scb->hscb->residual_data_count[1] = 0;
+        scb->hscb->residual_data_count[2] = 0;
         aic7xxx_error(scb->cmd) = DID_OK;
+        aic7xxx_status(scb->cmd) = 0;
+        /*
+         * The QUEUE_FULL/BUSY handler in aic7xxx_seqint takes care of putting
+         * this command on a timer and allowing us to retry it.  Here, we
+         * just 0 out a few values so that they don't carry through to when
+         * the command finally does complete.
+         */
         break;
       default:
         cmd = scb->cmd;
@@ -7065,33 +7096,27 @@
   if(!p)
     return;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
-  if(test_and_set_bit(AHC_IN_ISR_BIT, &p->flags))
-  {
-    return;
-  }
   spin_lock_irqsave(&io_request_lock, cpu_flags);
+  p->flags |= AHC_IN_ISR;
   do
   {
     aic7xxx_isr(irq, dev_id, regs);
   } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
   aic7xxx_done_cmds_complete(p);
   aic7xxx_run_waiting_queues(p);
-  clear_bit(AHC_IN_ISR_BIT, &p->flags);
+  p->flags &= ~AHC_IN_ISR;
   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
 #else
-  if(set_bit(AHC_IN_ISR_BIT, (int *)&p->flags))
-  {
-    return;
-  }
   DRIVER_LOCK
+  p->flags |= AHC_IN_ISR;
   do
   {
     aic7xxx_isr(irq, dev_id, regs);
   } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
+  p->flags &= ~AHC_IN_ISR;
   DRIVER_UNLOCK
   aic7xxx_done_cmds_complete(p);
   aic7xxx_run_waiting_queues(p);
-  clear_bit(AHC_IN_ISR_BIT, (int *)&p->flags);
 #endif
 }
 
@@ -9012,22 +9037,6 @@
     kfree(p->scb_data);
   }
 
-  /*
-   * Free any alloced Scsi_Cmnd structures that might be around for
-   * negotiation purposes....
-   */
-  for (i = 0; i < MAX_TARGETS; i++)
-  {
-    if(p->dev_dtr_cmnd[i])
-    {
-      if(p->dev_dtr_cmnd[i]->request_buffer)
-      {
-        kfree(p->dev_dtr_cmnd[i]->request_buffer);
-      }
-      kfree(p->dev_dtr_cmnd[i]);
-    }
-  }
-
 }
 
 /*+F*************************************************************************
@@ -9413,7 +9422,7 @@
   }
   aic_outb(p, ~(p->discenable & 0xFF), DISC_DSB);
   aic_outb(p, ~((p->discenable >> 8) & 0xFF), DISC_DSB + 1);
-  p->needppr = p->needppr_copy = p->needdv = 0;
+  p->needppr = p->needppr_copy = 0;
   p->needwdtr = p->needwdtr_copy;
   p->needsdtr = p->needsdtr_copy;
   p->dtr_pending = 0;
@@ -9471,53 +9480,165 @@
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_detect
+ *   aic7xxx_configure_bugs
  *
  * Description:
- *   Try to detect and register an Adaptec 7770 or 7870 SCSI controller.
- *
- * XXX - This should really be called aic7xxx_probe().  A sequence of
- *       probe(), attach()/detach(), and init() makes more sense than
- *       one do-it-all function.  This may be useful when (and if) the
- *       mid-level SCSI code is overhauled.
+ *   Take the card passed in and set the appropriate bug flags based upon
+ *   the card model.  Also make any changes needed to device registers or
+ *   PCI registers while we are here.
  *-F*************************************************************************/
-int
-aic7xxx_detect(Scsi_Host_Template *template)
+static void
+aic7xxx_configure_bugs(struct aic7xxx_host *p)
 {
-  struct aic7xxx_host *temp_p = NULL;
-  struct aic7xxx_host *current_p = NULL;
-  struct aic7xxx_host *list_p = NULL;
-  int found = 0;
-#if defined(__i386__) || defined(__alpha__)
-  ahc_flag_type flags = 0;
-  int type;
-#endif
-  unsigned char sxfrctl1;
-#if defined(__i386__) || defined(__alpha__)
-  unsigned char hcntrl, hostconf;
-  unsigned int slot, base;
-#endif
-
-#ifdef MODULE
-  /*
-   * If we are called as a module, the aic7xxx pointer may not be null
-   * and it would point to our bootup string, just like on the lilo
-   * command line.  IF not NULL, then process this config string with
-   * aic7xxx_setup
-   */
-  if(aic7xxx)
-    aic7xxx_setup(aic7xxx, NULL);
-  if(dummy_buffer[0] != 'P')
-    printk(KERN_WARNING "aic7xxx: Please read the file /usr/src/linux/drivers"
-      "/scsi/README.aic7xxx\n"
-      "aic7xxx: to see the proper way to specify options to the aic7xxx "
-      "module\n"
-      "aic7xxx: Specifically, don't use any commas when passing arguments to\n"
-      "aic7xxx: insmod or else it might trash certain memory areas.\n");
+  unsigned char pci_rev;
+  unsigned short tmp_word;
+ 
+  if((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI)
+  {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92)
+      pcibios_read_config_byte(p->pci_bus, p->pci_device_fn,
+            PCI_REVISION_ID, &pci_rev);
+#else
+      pci_read_config_byte(p->pdev, PCI_REVISION_ID, &pci_rev);
 #endif
+  }
 
-  template->proc_dir = &proc_scsi_aic7xxx;
-  template->sg_tablesize = AIC7XXX_MAX_SG;
+  switch(p->chip & AHC_CHIPID_MASK)
+  {
+    case AHC_AIC7860:
+      if(pci_rev >= 1)
+      {
+        p->bugs |= AHC_BUG_PCI_2_1_RETRY;
+      }
+      /* fall through */
+    case AHC_AIC7850:
+    case AHC_AIC7870:
+      p->bugs |= AHC_BUG_TMODE_WIDEODD | AHC_BUG_CACHETHEN | AHC_BUG_PCI_MWI;
+      break;
+    case AHC_AIC7880:
+      p->bugs |= AHC_BUG_TMODE_WIDEODD;
+      if(pci_rev >= 1)
+      {
+        p->bugs |= AHC_BUG_PCI_2_1_RETRY;
+      }
+      else
+      {
+        p->bugs |= AHC_BUG_CACHETHEN | AHC_BUG_PCI_MWI;
+      }
+      break;
+    case AHC_AIC7890:
+      if(pci_rev == 0)
+      {
+        p->bugs |= AHC_BUG_AUTOFLUSH | AHC_BUG_CACHETHEN;
+      }
+      break;
+    case AHC_AIC7892:
+      p->bugs |= AHC_BUG_SCBCHAN_UPLOAD;
+      break;
+    case AHC_AIC7895:
+      p->bugs |= AHC_BUG_TMODE_WIDEODD | AHC_BUG_PCI_2_1_RETRY |
+                 AHC_BUG_CACHETHEN;
+      if(pci_rev <= 3)
+      {
+        p->bugs |= AHC_BUG_PCI_MWI;
+      }
+      break;
+    case AHC_AIC7896:
+      p->bugs |= AHC_BUG_CACHETHEN_DIS;
+      break;
+    case AHC_AIC7899:
+      p->bugs |= AHC_BUG_SCBCHAN_UPLOAD;
+      break;
+    default:
+      /* Nothing to do */
+      break;
+  }
+
+  /*
+   * Now handle the bugs that require PCI register or card register tweaks
+   */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92)
+  pcibios_read_config_word(p->pci_bus, p->pci_device_fn,
+            PCI_COMMAND, &tmp_word);
+#else
+  pci_read_config_word(p->pdev, PCI_COMMAND, &tmp_word);
+#endif
+  if(p->bugs & AHC_BUG_PCI_MWI)
+  {
+    tmp_word &= ~PCI_COMMAND_INVALIDATE;
+  }
+  else
+  {
+    tmp_word |= PCI_COMMAND_INVALIDATE;
+  }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,92)
+  pcibios_write_config_word(p->pci_bus, p->pci_device_fn,
+            PCI_COMMAND, tmp_word);
+#else
+  pci_write_config_word(p->pdev, PCI_COMMAND, tmp_word);
+#endif
+
+  if(p->bugs & AHC_BUG_CACHETHEN)
+  {
+    aic_outb(p, aic_inb(p, DSCOMMAND0) & ~CACHETHEN, DSCOMMAND0);
+  }
+  else if (p->bugs & AHC_BUG_CACHETHEN_DIS)
+  {
+    aic_outb(p, aic_inb(p, DSCOMMAND0) | CACHETHEN, DSCOMMAND0);
+  }
+
+  return;
+}
+
+/*+F*************************************************************************
+ * Function:
+ *   aic7xxx_detect
+ *
+ * Description:
+ *   Try to detect and register an Adaptec 7770 or 7870 SCSI controller.
+ *
+ * XXX - This should really be called aic7xxx_probe().  A sequence of
+ *       probe(), attach()/detach(), and init() makes more sense than
+ *       one do-it-all function.  This may be useful when (and if) the
+ *       mid-level SCSI code is overhauled.
+ *-F*************************************************************************/
+int
+aic7xxx_detect(Scsi_Host_Template *template)
+{
+  struct aic7xxx_host *temp_p = NULL;
+  struct aic7xxx_host *current_p = NULL;
+  struct aic7xxx_host *list_p = NULL;
+  int found = 0;
+#if defined(__i386__) || defined(__alpha__)
+  ahc_flag_type flags = 0;
+  int type;
+#endif
+  unsigned char sxfrctl1;
+#if defined(__i386__) || defined(__alpha__)
+  unsigned char hcntrl, hostconf;
+  unsigned int slot, base;
+#endif
+
+#ifdef MODULE
+  /*
+   * If we are called as a module, the aic7xxx pointer may not be null
+   * and it would point to our bootup string, just like on the lilo
+   * command line.  IF not NULL, then process this config string with
+   * aic7xxx_setup
+   */
+  if(aic7xxx)
+    aic7xxx_setup(aic7xxx, NULL);
+  if(dummy_buffer[0] != 'P')
+    printk(KERN_WARNING "aic7xxx: Please read the file /usr/src/linux/drivers"
+      "/scsi/README.aic7xxx\n"
+      "aic7xxx: to see the proper way to specify options to the aic7xxx "
+      "module\n"
+      "aic7xxx: Specifically, don't use any commas when passing arguments to\n"
+      "aic7xxx: insmod or else it might trash certain memory areas.\n");
+#endif
+
+  template->proc_dir = &proc_scsi_aic7xxx;
+  template->sg_tablesize = AIC7XXX_MAX_SG;
 
 
 #ifdef CONFIG_PCI
@@ -10290,6 +10411,14 @@
             aic_outb(temp_p, DFTHRSH_100, DSPCISTATUS);
           }
 
+          /*
+           * Call our function to fixup any bugs that exist on this chipset.
+           * This may muck with PCI settings and other device settings, so
+           * make sure it's after all the other PCI and device register
+           * tweaks so it can back out bad settings on specific broken cards.
+           */
+          aic7xxx_configure_bugs(temp_p);
+
           if ( list_p == NULL )
           {
             list_p = current_p = temp_p;
@@ -10533,6 +10662,11 @@
     }
 
     /*
+     * All the 7770 based chipsets have this bug
+     */
+    temp_p->bugs |= AHC_BUG_TMODE_WIDEODD;
+
+    /*
      * Set the FIFO threshold and the bus off time.
      */
     hostconf = aic_inb(temp_p, HOSTCONF);
@@ -10751,297 +10885,6 @@
   return (found);
 }
 
-static void aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p,
-                                           Scsi_Cmnd *old_cmd, int tindex);
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_allocate_negotiation_command
- *
- * Description:
- *   allocate the actual command struct and fill in the gaps...
- *-F*************************************************************************/
-static Scsi_Cmnd *
-aic7xxx_allocate_negotiation_command(struct aic7xxx_host *p,
-                                     Scsi_Cmnd *old_cmd, int tindex)
-{
-  Scsi_Cmnd *cmd;
-  char *buffer;
-
-  if (!(p->dev_dtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
-  {
-    return(NULL);
-  }
-  if (!(buffer = kmalloc(256, GFP_ATOMIC)))
-  {
-    kfree(p->dev_dtr_cmnd[tindex]);
-    p->dev_dtr_cmnd[tindex] = NULL;
-    return(NULL);
-  }
-  cmd = p->dev_dtr_cmnd[tindex];
-  memset(cmd, 0, sizeof(Scsi_Cmnd));
-  memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
-  memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
-  memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
-  cmd->lun = 0;
-  cmd->request_bufflen = 255;
-  cmd->request_buffer = buffer;
-  cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
-  cmd->bufflen = 0;
-  cmd->buffer = NULL;
-  cmd->underflow = 0;
-  cmd->cmd_len = 6;
-  cmd->cmnd[0] = cmd->data_cmnd[0] = INQUIRY;
-  cmd->cmnd[1] = cmd->data_cmnd[1] = 0;
-  cmd->cmnd[2] = cmd->data_cmnd[2] = 0;
-  cmd->cmnd[3] = cmd->data_cmnd[3] = 0;
-  cmd->cmnd[4] = cmd->data_cmnd[4] = 255; /* match what scsi.c does here */
-  cmd->cmnd[5] = cmd->data_cmnd[5] = 0;
-  return(cmd);
-}
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_negotiation_complete
- *
- * Description:
- *   Handle completion events for our Negotiation commands.  Clear out the
- *   struct and get it ready for its next use.
- *-F*************************************************************************/
-static void
-aic7xxx_negotiation_complete(Scsi_Cmnd *cmd)
-{
-  unsigned int checksum;
-  int i;
-  int *ibuffer;
-  struct aic7xxx_host *p = (struct aic7xxx_host *)cmd->host->hostdata;
-  int tindex = TARGET_INDEX(cmd);
-  struct aic7xxx_syncrate *syncrate;
-
-  /*
-   * perform our minimalistic domain validation
-   */
-  if(p->dev_flags[tindex] & DEVICE_SCANNED)
-  {
-    ibuffer = (int *)cmd->request_buffer;
-    checksum = 0;
-    for(i = 0; i < (cmd->request_bufflen >> 2); i++)
-    {
-      checksum += ibuffer[i];
-    }
-    if( (checksum != p->dev_checksum[tindex]) &&
-        (p->transinfo[tindex].cur_offset != 0) )
-    {
-      unsigned int period = p->transinfo[tindex].cur_period;
-      unsigned char options = p->transinfo[tindex].cur_options;
-
-      if (p->needdv & (1<<tindex))
-      {
-        /*
-         * oops, we had a failure, lower the transfer rate and try again.  It's
-         * worth noting here that it might be wise to also check for typical
-         * wide setting on narrow cable type problems and try disabling wide
-         * instead of slowing down if those exist.  That's hard to do with simple
-         * checksums though.
-         */
-        if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) 
-        {
-          printk(INFO_LEAD "reducing SCSI transfer speed due to Domain "
-                 "validation failure.\n", p->host_no, CTL_OF_CMD(cmd));
-        }
-        if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
-        {
-          syncrate++;
-          if( (syncrate->rate[0] != NULL) &&
-              (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
-          {
-            p->transinfo[tindex].goal_period = syncrate->period;
-            if( p->transinfo[tindex].goal_period > 9 )
-            {
-              p->transinfo[tindex].goal_options = 0;
-              p->needppr &= ~(1<<tindex);
-              p->needsdtr |= (1<<tindex);
-              p->needppr_copy &= ~(1<<tindex);
-              p->needsdtr_copy |= (1<<tindex);
-              if (p->transinfo[tindex].goal_width)
-              {
-                p->needwdtr |= (1<<tindex);
-                p->needwdtr_copy |= (1<<tindex);
-              }
-            }
-          }
-          else if (p->transinfo[tindex].goal_width)
-          {
-            p->transinfo[tindex].goal_width = 0;
-            p->needwdtr &= ~(1<<tindex);
-            p->needwdtr_copy &= ~(1<<tindex);
-            p->transinfo[tindex].goal_offset =
-              p->transinfo[tindex].user_offset;
-            p->transinfo[tindex].goal_period =
-              p->transinfo[tindex].user_period;
-            p->transinfo[tindex].goal_options =
-              p->transinfo[tindex].user_options;
-            if( p->transinfo[tindex].goal_period <= 9 )
-            {
-              p->needppr |= (1<<tindex);
-              p->needsdtr &= ~(1<<tindex);
-              p->needppr_copy |= (1<<tindex);
-              p->needsdtr_copy &= ~(1<<tindex);
-            }
-            else
-            {
-              p->needppr &= ~(1<<tindex);
-              p->needsdtr |= (1<<tindex);
-              p->needppr_copy &= ~(1<<tindex);
-              p->needsdtr_copy |= (1<<tindex);
-            }
-          }
-          else
-          {
-            p->transinfo[tindex].goal_offset = 0;
-            p->transinfo[tindex].goal_period = 255;
-            p->transinfo[tindex].goal_options = 0;
-            p->transinfo[tindex].goal_width = 0;
-            p->needppr &= ~(1<<tindex);
-            p->needsdtr &= ~(1<<tindex);
-            p->needwdtr &= ~(1<<tindex);
-            p->needppr_copy &= ~(1<<tindex);
-            p->needsdtr_copy &= ~(1<<tindex);
-            p->needwdtr_copy &= ~(1<<tindex);
-          }
-        }
-        p->needdv &= ~(1<<tindex);
-      }
-      else
-      {
-        if(aic7xxx_verbose & VERBOSE_NEGOTIATION2) 
-        {
-          printk(INFO_LEAD "Performing Domain validation.\n",
-                 p->host_no, CTL_OF_CMD(cmd));
-        }
-        /*
-         * Update the checksum in case the INQUIRY data has changed, maybe
-         * in relation to a change in the mode pages, or whatever.
-         */
-        p->dev_checksum[tindex] = checksum;
-        /*
-         * Signal that we are trying out the domain validation
-         */
-        p->needdv |= (1<<tindex);
-        /*
-         * Signal that we need to re-negotiate things, this also gets us our
-         * INQUIRY command to re-checksum off of.
-         */
-        p->needppr |= (p->needppr_copy & (1<<tindex));
-        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
-        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
-      }
-    } 
-    else
-    {
-      if( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
-          (p->needdv & (1<<tindex)) )
-      {
-        printk(INFO_LEAD "Successfully completed Domain validation.\n",
-               p->host_no, CTL_OF_CMD(cmd));
-      }
-      /*
-       * We successfully did our checksum, so don't leave the needdv flag set
-       * in case we might have set it last time through.
-       */
-      p->needdv &= ~(1<<tindex);
-    }
-  }
-
-  p->dtr_pending &= ~(0x01 << tindex);
-  /*
-   * This looks recursive in the extreme, but if this was a WDTR negotiation
-   * and we didn't follow up with SDTR yet, then this will get it started.
-   * For all other cases, this should work out to be a no-op, unless we are
-   * doing domain validation and happen to need a new negotiation command.
-   *
-   * In case we don't want this to go any further, the cmdcmplt interrupt
-   * handler will NULL out the cmd->next entry so that the real SCSI command
-   * can be sent back to the mid layer code with SENSE data intact.  We'll
-   * finish things up when the cmd gets sent back down to us, so no worries.
-   */
-  if(cmd->next)
-  {
-    aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
-  }
-  return;
-}
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_build_negotiation_command
- *
- * Description:
- *   Build a Scsi_Cmnd structure to perform negotiation with or else send
- *   a pre-built command specifically for this purpose.
- *-F*************************************************************************/
-static void
-aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, Scsi_Cmnd *old_cmd,
-  int tindex)
-{
-
-  if ( !(p->dtr_pending & (1<<tindex)) &&
-       ( (p->needppr & (1<<tindex)) ||
-         (p->needwdtr & (1<<tindex)) ||
-         (p->needsdtr & (1<<tindex)) ) )
-  {
-    if ( (p->dev_dtr_cmnd[tindex] == NULL) &&
-         (aic7xxx_allocate_negotiation_command(p, old_cmd, tindex) == NULL) )
-    {
-      return;
-    }
-    /*
-     * Before sending this thing out, we also make the cmd->next pointer
-     * point to the real command so we can stuff any possible SENSE data
-     * into the real command instead of this fake command.  This has to be
-     * done each time the command is built, not just the first time, hence
-     * it's outside of the above if()...
-     */
-    p->dev_dtr_cmnd[tindex]->next = old_cmd;
-    /*
-     * Clear the buffer so checksums come out right....
-     */
-    memset(p->dev_dtr_cmnd[tindex]->request_buffer, 0,
-           p->dev_dtr_cmnd[tindex]->request_bufflen);
-    /*
-     * Remove any commands for this particular device that might be on the
-     * waiting_scbs queue or qinfifo so that this command goes out first.
-     * This is vital for our implementation of domain validation.
-     */
-    pause_sequencer(p);
-    aic7xxx_search_qinfifo(p, old_cmd->target, old_cmd->channel, ALL_LUNS,
-                SCB_LIST_NULL, 0, TRUE, &p->delayed_scbs[tindex]);
-    unpause_sequencer(p, FALSE);
-    {
-      struct aic7xxx_scb *scb, *next;
-
-      scb = p->waiting_scbs.head;
-      while(scb != NULL)
-      {
-        if( aic7xxx_match_scb(p, scb, old_cmd->target, old_cmd->channel,
-                              ALL_LUNS, SCB_LIST_NULL) )
-        {
-          next = scb->q_next;
-          scbq_remove(&p->waiting_scbs, scb);
-          scbq_insert_tail(&p->delayed_scbs[tindex], scb);
-          scb = next;
-        }
-        else
-        {
-          scb = scb->q_next;
-        }
-      }
-    }
-    aic7xxx_queue(p->dev_dtr_cmnd[tindex], 
-                  aic7xxx_negotiation_complete);
-  }
-}
-
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
 /*+F*************************************************************************
  * Function:
@@ -11090,7 +10933,7 @@
    */
   hscb->control = 0;
   scb->tag_action = 0;
-  cmd->tag = hscb->tag;
+
   if (p->discenable & mask)
   {
     hscb->control |= DISCENB;
@@ -11119,34 +10962,29 @@
       }
     }
   }
-  if ( cmd == p->dev_dtr_cmnd[tindex] )
+  if ( !(p->dtr_pending & mask) &&
+        ( (p->needppr & mask) ||
+          (p->needwdtr & mask) ||
+          (p->needsdtr & mask) ) &&
+        (p->dev_flags[tindex] & DEVICE_DTR_SCANNED) )
   {
     p->dtr_pending |= mask;
     scb->tag_action = 0;
-    if (p->dev_flags[tindex] & DEVICE_SCANNED)
+    hscb->control &= DISCENB;
+    hscb->control |= MK_MESSAGE;
+    if(p->needppr & mask)
     {
-      hscb->control &= DISCENB;
-      hscb->control |= MK_MESSAGE;
-      if(p->needppr & mask)
-      {
-        scb->flags |= SCB_MSGOUT_PPR;
-      }
-      else if(p->needwdtr & mask)
-      {
-        scb->flags |= SCB_MSGOUT_WDTR;
-      }
-      else if(p->needsdtr & mask)
-      {
-        scb->flags |= SCB_MSGOUT_SDTR;
-      }
+      scb->flags |= SCB_MSGOUT_PPR;
     }
-  }
-  if ( !(p->dtr_pending & mask) &&
-        ( (p->needppr & mask) ||
-          (p->needwdtr & mask) ||
-          (p->needsdtr & mask) ) )
-  {
-    aic7xxx_build_negotiation_cmnd(p, cmd, tindex);
+    else if(p->needwdtr & mask)
+    {
+      scb->flags |= SCB_MSGOUT_WDTR;
+    }
+    else if(p->needsdtr & mask)
+    {
+      scb->flags |= SCB_MSGOUT_SDTR;
+    }
+    scb->flags |= SCB_DTR_SCB;
   }
   hscb->target_channel_lun = ((cmd->target << 4) & 0xF0) |
         ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07);
@@ -11285,50 +11123,58 @@
     aic7xxx_allocate_scb(p);
     DRIVER_UNLOCK
     scb = scbq_remove_head(&p->scb_data->free_scbs);
-  }
-  if (scb == NULL)
-  {
-    printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no,
-           CTL_OF_CMD(cmd));
-    cmd->result = (DID_BUS_BUSY << 16);
+    if(scb == NULL)
+      printk(WARN_LEAD "Couldn't get a free SCB.\n", p->host_no,
+             CTL_OF_CMD(cmd));
+  }
+  while (scb == NULL)
+  {
+    /*
+     * Well, all SCBs are currently active on the bus.  So, we spin here
+     * running the interrupt handler until one completes and becomes free.
+     * We can do this safely because we either A) hold the driver lock (in
+     * 2.0 kernels) or we have the io_request_lock held (in 2.2 and later
+     * kernels) and so either way, we won't take any other interrupts and
+     * the queue path will block until we release it.  Also, we would worry
+     * about running the completion queues, but obviously there are plenty
+     * of commands outstanding to trigger a later interrupt that will do
+     * that for us, so skip it here.
+     */
     DRIVER_LOCK
-    aic7xxx_queue_cmd_complete(p, cmd);
+    aic7xxx_isr(p->irq, p, NULL);
     DRIVER_UNLOCK
-    return 0;
+    scb = scbq_remove_head(&p->scb_data->free_scbs);
   }
-  else
-  {
-    scb->cmd = cmd;
-    aic7xxx_position(cmd) = scb->hscb->tag;
+  scb->cmd = cmd;
+  aic7xxx_position(cmd) = scb->hscb->tag;
 
-    /*
-     * Construct the SCB beforehand, so the sequencer is
-     * paused a minimal amount of time.
-     */
-    aic7xxx_buildscb(p, cmd, scb);
+  /*
+   * Make sure the Scsi_Cmnd pointer is saved, the struct it points to
+   * is set up properly, and the parity error flag is reset, then send
+   * the SCB to the sequencer and watch the fun begin.
+   */
+  cmd->scsi_done = fn;
+  cmd->result = DID_OK;
+  memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+  aic7xxx_error(cmd) = DID_OK;
+  aic7xxx_status(cmd) = 0;
+  cmd->host_scribble = NULL;
 
-    /*
-     * Make sure the Scsi_Cmnd pointer is saved, the struct it points to
-     * is set up properly, and the parity error flag is reset, then send
-     * the SCB to the sequencer and watch the fun begin.
-     */
-    cmd->scsi_done = fn;
-    cmd->result = DID_OK;
-    memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-    aic7xxx_error(cmd) = DID_OK;
-    aic7xxx_status(cmd) = 0;
-    cmd->host_scribble = NULL;
+  /*
+   * Construct the SCB beforehand, so the sequencer is
+   * paused a minimal amount of time.
+   */
+  aic7xxx_buildscb(p, cmd, scb);
 
-    scb->flags |= SCB_ACTIVE | SCB_WAITINGQ;
+  scb->flags |= SCB_ACTIVE | SCB_WAITINGQ;
 
-    DRIVER_LOCK
-    scbq_insert_tail(&p->waiting_scbs, scb);
-    if ( (p->flags & (AHC_IN_ISR | AHC_IN_ABORT | AHC_IN_RESET)) == 0)
-    {
-      aic7xxx_run_waiting_queues(p);
-    }
-    DRIVER_UNLOCK
+  DRIVER_LOCK
+  scbq_insert_tail(&p->waiting_scbs, scb);
+  if ( (p->flags & (AHC_IN_ISR | AHC_IN_ABORT | AHC_IN_RESET)) == 0)
+  {
+    aic7xxx_run_waiting_queues(p);
   }
+  DRIVER_UNLOCK
   return (0);
 }
 
@@ -11394,6 +11240,12 @@
          aic_inb(p, SCSISIGI),
          aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
          aic_inb(p, SSTAT0), aic_inb(p, SSTAT1));
+    printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n", p->host_no,
+         CTL_OF_SCB(scb),
+         (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0,
+         aic_inb(p, SSTAT2),
+         aic_inb(p, STCNT + 2) << 16 | aic_inb(p, STCNT + 1) << 8 |
+         aic_inb(p, STCNT));
   }
 
   channel = cmd->channel;
@@ -11687,7 +11539,6 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
   unsigned long cpu_flags = 0;
 #endif
-  Scsi_Cmnd *cmd_next, *cmd_prev;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
   scb = (p->scb_data->scb_array[aic7xxx_position(cmd)]);
@@ -11718,13 +11569,11 @@
   {
     aic7xxx_isr(p->irq, p, (void *)NULL);
     pause_sequencer(p);
-    aic7xxx_done_cmds_complete(p);
   }
+  aic7xxx_done_cmds_complete(p);
 
-  if ((scb == NULL) || (cmd->serial_number != cmd->serial_number_at_timeout))
-                      /*  Totally bogus cmd since it points beyond our  */
-  {                   /*  valid SCB range or doesn't even match it's own*/
-                      /*  timeout serial number.                        */
+  if (scb == NULL)
+  {
     if (aic7xxx_verbose & VERBOSE_ABORT_MID)
       printk(INFO_LEAD "Abort called with bogus Scsi_Cmnd "
         "pointer.\n", p->host_no, CTL_OF_CMD(cmd));
@@ -11743,28 +11592,6 @@
                         /*  finish successfully, or to indicate that we     */
                         /*  don't have this cmd any more and the mid level  */
                         /*  code needs to find it.                          */
-    cmd_next = p->completeq.head;
-    cmd_prev = NULL;
-    while (cmd_next != NULL) 
-    {
-      if (cmd_next == cmd) 
-      {
-        if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
-          printk(INFO_LEAD "Abort called for command "
-          "on completeq, completing.\n", p->host_no, CTL_OF_CMD(cmd));
-        if ( cmd_prev == NULL )
-          p->completeq.head = (Scsi_Cmnd *)cmd_next->host_scribble;
-        else
-          cmd_prev->host_scribble = cmd_next->host_scribble;
-        cmd_next->scsi_done(cmd_next);
-        unpause_sequencer(p, FALSE);
-        DRIVER_UNLOCK
-        return(SCSI_ABORT_NOT_RUNNING); /* It's already back as a successful
-                                         * completion */
-      }                                  
-      cmd_prev = cmd_next;
-      cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble;
-    }
     if (aic7xxx_verbose & VERBOSE_ABORT_MID)
       printk(INFO_LEAD "Abort called for already completed"
         " command.\n", p->host_no, CTL_OF_CMD(cmd));
@@ -11822,8 +11649,20 @@
   found = 0;
   p->flags |= AHC_IN_ABORT;
   if (aic7xxx_verbose & VERBOSE_ABORT)
-    printk(INFO_LEAD "Aborting scb %d, flags 0x%x\n",
-         p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags);
+  {
+    printk(INFO_LEAD "Aborting scb %d, flags 0x%x, SEQADDR 0x%x, LASTPHASE "
+           "0x%x\n",
+         p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags,
+         aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
+         aic_inb(p, LASTPHASE));
+    printk(INFO_LEAD "SG_CACHEPTR 0x%x, SG_COUNT %d, SCSISIGI 0x%x\n",
+         p->host_no, CTL_OF_SCB(scb), (p->features & AHC_ULTRA2) ?
+         aic_inb(p, SG_CACHEPTR) : 0, aic_inb(p, SG_COUNT),
+         aic_inb(p, SCSISIGI));
+    printk(INFO_LEAD "SSTAT0 0x%x, SSTAT1 0x%x, SSTAT2 0x%x\n",
+         p->host_no, CTL_OF_SCB(scb), aic_inb(p, SSTAT0),
+         aic_inb(p, SSTAT1), aic_inb(p, SSTAT2));
+  }
 
 /*
  *   First, let's check to see if the currently running command is our target
@@ -11851,6 +11690,16 @@
         if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS)
           printk(INFO_LEAD "SCB is currently active.  "
                 "Waiting on completion.\n", p->host_no, CTL_OF_SCB(scb));
+        printk(INFO_LEAD "SCSISIGI 0x%x, SEQADDR 0x%x, SSTAT0 0x%x, SSTAT1 "
+           "0x%x\n", p->host_no, CTL_OF_SCB(scb),
+           aic_inb(p, SCSISIGI),
+           aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
+           aic_inb(p, SSTAT0), aic_inb(p, SSTAT1));
+        printk(INFO_LEAD "SG_CACHEPTR 0x%x, SSTAT2 0x%x, STCNT 0x%x\n",
+           p->host_no, CTL_OF_SCB(scb),
+           (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0,
+           aic_inb(p, SSTAT2), aic_inb(p, STCNT + 2) << 16 |
+           aic_inb(p, STCNT + 1) << 8 | aic_inb(p, STCNT));
         unpause_sequencer(p, FALSE);
         p->flags &= ~AHC_IN_ABORT;
         scb->flags |= SCB_RECOVERY_SCB; /*  Note the fact that we've been  */
@@ -11866,35 +11715,7 @@
   if ((found == 0) && (scb->flags & SCB_WAITINGQ))
   {
     int tindex = TARGET_INDEX(cmd);
-    unsigned short mask;
-
-    mask = (1 << tindex);
 
-    if (p->dtr_pending & mask)
-    {
-      if (p->dev_dtr_cmnd[tindex]->next != cmd)
-        found = 1;
-      else
-        found = 0;
-    }
-    else
-    {
-      found = 1;
-    }
-    if (found == 0)
-    {
-      /*
-       * OK..this means the command we are currently getting an abort
-       * for has an outstanding negotiation command in front of it.
-       * We don't really have a way to tie back into the negotiation
-       * commands, so we just send this back as pending, then it
-       * will get reset in 2 seconds.
-       */
-      unpause_sequencer(p, TRUE);
-      scb->flags |= SCB_ABORT;
-      DRIVER_UNLOCK
-      return(SCSI_ABORT_PENDING);
-    }
     if (aic7xxx_verbose & VERBOSE_ABORT_PROCESS) 
       printk(INFO_LEAD "SCB found on waiting list and "
           "aborted.\n", p->host_no, CTL_OF_SCB(scb));
@@ -12051,10 +11872,8 @@
 #define DEVICE_RESET 0x01
 #define BUS_RESET    0x02
 #define HOST_RESET   0x04
-#define FAIL         0x08
-#define RESET_DELAY  0x10
+#define RESET_DELAY  0x08
   int        action;
-  Scsi_Cmnd *cmd_prev, *cmd_next;
 
 
   if ( cmd == NULL )
@@ -12082,86 +11901,32 @@
   DRIVER_LOCK
 
   pause_sequencer(p);
-  while ( (aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR))
-  {
-    aic7xxx_isr(p->irq, p, (void *)NULL );
-    pause_sequencer(p);
-    aic7xxx_done_cmds_complete(p);
-  }
 
-  if (scb == NULL)
+  if(flags & SCSI_RESET_SYNCHRONOUS)
   {
     if (aic7xxx_verbose & VERBOSE_RESET_MID)
-      printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd"
-           "->SCB mapping, improvising.\n", p->host_no, CTL_OF_CMD(cmd));
-    if ( flags & SCSI_RESET_SUGGEST_HOST_RESET )
-    {
-      action = HOST_RESET;
-    }
-    else
-    {
-      action = BUS_RESET;
-    }
+      printk(INFO_LEAD "Reset called for a SYNCHRONOUS reset, flags 0x%x, "
+           "cmd->result 0x%x.\n", p->host_no, CTL_OF_CMD(cmd), flags,
+           cmd->result);
+    scb = NULL;
+    action = HOST_RESET;
   }
-  else if (scb->cmd != cmd) 
+  else if ((scb == NULL) || (scb->cmd != cmd))
   {
     if (aic7xxx_verbose & VERBOSE_RESET_MID)
-    printk(INFO_LEAD "Reset called with recycled SCB "
-        "for cmd.\n", p->host_no, CTL_OF_CMD(cmd));
-    cmd_prev = NULL;
-    cmd_next = p->completeq.head;
-    while ( cmd_next != NULL )
-    {
-      if (cmd_next == cmd)
-      {
-        if (aic7xxx_verbose & VERBOSE_RESET_RETURN)
-          printk(INFO_LEAD "Reset, found cmd on completeq"
-          ", completing.\n", p->host_no, CTL_OF_CMD(cmd));
-        unpause_sequencer(p, FALSE);
-        DRIVER_UNLOCK
-        return(SCSI_RESET_NOT_RUNNING);
-      }
-      cmd_prev = cmd_next;
-      cmd_next = (Scsi_Cmnd *)cmd_next->host_scribble;
-    }
-    if ( !(flags & SCSI_RESET_SYNCHRONOUS) )
-    {
-      if (aic7xxx_verbose & VERBOSE_RESET_RETURN)
-        printk(INFO_LEAD "Reset, cmd not found,"
-          " failing.\n", p->host_no, CTL_OF_CMD(cmd));
-      unpause_sequencer(p, FALSE);
-      DRIVER_UNLOCK
-      return(SCSI_RESET_NOT_RUNNING);
-    }
-    else
-    {
-      if (aic7xxx_verbose & VERBOSE_RESET_MID)
-        printk(INFO_LEAD "Reset called, no scb, "
-          "flags 0x%x\n", p->host_no, CTL_OF_CMD(cmd), flags);
-      scb = NULL;
-      action = HOST_RESET;
-    }
+      printk(INFO_LEAD "Reset called with bogus Scsi_Cmnd"
+           "->SCB mapping, failing.\n", p->host_no, CTL_OF_CMD(cmd));
+    aic7xxx_done_cmds_complete(p);
+    aic7xxx_run_waiting_queues(p);
+    unpause_sequencer(p, FALSE);
+    DRIVER_UNLOCK
+    return(SCSI_RESET_NOT_RUNNING);
   }
   else
   {
     if (aic7xxx_verbose & VERBOSE_RESET_MID)
       printk(INFO_LEAD "Reset called, scb %d, flags "
         "0x%x\n", p->host_no, CTL_OF_SCB(scb), scb->hscb->tag, scb->flags);
-    if ( aic7xxx_scb_on_qoutfifo(p, scb) )
-    {
-      if(aic7xxx_verbose & VERBOSE_RESET_RETURN)
-        printk(INFO_LEAD "SCB on qoutfifo, completing.\n", p->host_no,
-          CTL_OF_SCB(scb));
-      if ((aic_inb(p,INTSTAT) & CMDCMPLT) == 0)
-        printk(INFO_LEAD "missed CMDCMPLT interrupt!\n", p->host_no,
-          CTL_OF_SCB(scb));
-      aic7xxx_handle_command_completion_intr(p);
-      aic7xxx_done_cmds_complete(p);
-      aic7xxx_run_waiting_queues(p);
-      unpause_sequencer(p, FALSE);
-      DRIVER_UNLOCK
-      return(SCSI_RESET_SUCCESS);
-    }
     if ( flags & SCSI_RESET_SUGGEST_HOST_RESET )
     {
       action = HOST_RESET;
@@ -12175,6 +11940,26 @@
       action = DEVICE_RESET;
     }
   }
+
+  while((aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR))
+  {
+    aic7xxx_isr(p->irq, p, (void *)NULL );
+    pause_sequencer(p);
+  }
+  aic7xxx_done_cmds_complete(p);
+
+  if(scb && (scb->cmd == NULL))
+  {
+    /*
+     * We just completed the command when we ran the isr stuff, so we no
+     * longer have it.
+     */
+    aic7xxx_run_waiting_queues(p);
+    unpause_sequencer(p, FALSE);
+    DRIVER_UNLOCK
+    return(SCSI_RESET_SUCCESS);
+  }
+    
   if ( (action & DEVICE_RESET) && 
         (p->dev_flags[tindex] & BUS_DEVICE_RESET_PENDING) )
   {
@@ -12234,14 +12019,13 @@
   switch (action)
   {
     case RESET_DELAY:
+      aic7xxx_run_waiting_queues(p);
       unpause_sequencer(p, FALSE);
       DRIVER_UNLOCK
-      return(SCSI_RESET_PENDING);
-      break;
-    case FAIL:
-      unpause_sequencer(p, FALSE);
-      DRIVER_UNLOCK
-      return(SCSI_RESET_ERROR);
+      if(scb == NULL)
+        return(SCSI_RESET_PUNT);
+      else
+        return(SCSI_RESET_PENDING);
       break;
     case DEVICE_RESET:
       p->flags |= AHC_IN_RESET;
@@ -12259,7 +12043,7 @@
     case HOST_RESET:
     default:
       p->flags |= AHC_IN_RESET | AHC_RESET_DELAY;
-      p->dev_expires[p->scsi_id] = jiffies + (3 * HZ);
+      p->dev_expires[p->scsi_id] = jiffies + (1 * HZ);
       p->dev_timer_active |= (0x01 << p->scsi_id);
       if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) ||
             time_after_eq(p->dev_timer.expires, p->dev_expires[p->scsi_id]) )
@@ -12288,21 +12072,14 @@
         p->msg_index = 0;
         p->msg_len = 0;
       }
-      aic7xxx_run_done_queue(p, TRUE);
-      /*
-       * If this a SCSI_RESET_SYNCHRONOUS then the command we were given is
-       * in need of being re-started, so send it on through to aic7xxx_queue
-       * and let it set until the delay is over.  This keeps it from dying
-       * entirely and avoids getting a bogus dead command back through the
-       * mid-level code due to too many retries.
-       */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
-      if ( flags & SCSI_RESET_SYNCHRONOUS )
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+      if(flags & SCSI_RESET_SYNCHRONOUS)
       {
-        cmd->result = DID_BUS_BUSY << 16;
+        cmd->result = DID_RESET << 16;
         cmd->done(cmd);
       }
 #endif
+      aic7xxx_run_done_queue(p, TRUE);
       p->flags &= ~AHC_IN_RESET;
       /*
        * We can't rely on run_waiting_queues to unpause the sequencer for
@@ -12313,7 +12090,10 @@
       aic7xxx_run_waiting_queues(p);
       unpause_sequencer(p, FALSE);
       DRIVER_UNLOCK
-      return(result);
+      if(scb == NULL)
+        return(SCSI_RESET_SUCCESS|SCSI_RESET_HOST_RESET);
+      else
+        return(result);
       break;
   }
 }
@@ -12623,7 +12403,7 @@
 }
 
 
-#include "aic7xxx_proc.c"
+#include "aic7xxx/aic7xxx_proc.c"
 
 #ifdef MODULE
 /* Eventually this will go into an include file, but this will be later */
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx.h	Tue May 11 10:36:28 1999
+++ linux/drivers/scsi/aic7xxx.h	Wed Dec 31 16:00:00 1969
@@ -1,114 +0,0 @@
-/*+M*************************************************************************
- * Adaptec AIC7xxx device driver for Linux.
- *
- * Copyright (c) 1994 John Aycock
- *   The University of Calgary Department of Computer Science.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * 
- * $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $
- *-M*************************************************************************/
-#ifndef _aic7xxx_h
-#define _aic7xxx_h
-
-#define AIC7XXX_H_VERSION  "3.2.4"
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
-#endif
-
-#if defined(__i386__)
-#  define AIC7XXX_BIOSPARAM aic7xxx_biosparam
-#else
-#  define AIC7XXX_BIOSPARAM NULL
-#endif
-
-/*
- * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
- * to do with card config are filled in after the card is detected.
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65)
-#define AIC7XXX	{						\
-	next: NULL,						\
-	module: NULL,						\
-	proc_dir: NULL,						\
-	proc_info: aic7xxx_proc_info,				\
-	name: NULL,						\
-	detect: aic7xxx_detect,					\
-	release: aic7xxx_release,				\
-	info: aic7xxx_info,					\
-	command: NULL,						\
-	queuecommand: aic7xxx_queue,				\
-	eh_strategy_handler: NULL,				\
-	eh_abort_handler: NULL,					\
-	eh_device_reset_handler: NULL,				\
-	eh_bus_reset_handler: NULL,				\
-	eh_host_reset_handler: NULL,				\
-	abort: aic7xxx_abort,					\
-	reset: aic7xxx_reset,					\
-	slave_attach: NULL,					\
-	bios_param: AIC7XXX_BIOSPARAM,				\
-	can_queue: 255,		/* max simultaneous cmds      */\
-	this_id: -1,		/* scsi id of host adapter    */\
-	sg_tablesize: 0,	/* max scatter-gather cmds    */\
-	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
-	present: 0,		/* number of 7xxx's present   */\
-	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
-	use_clustering: ENABLE_CLUSTERING,			\
-	use_new_eh_code: 0					\
-}
-#else
-#define AIC7XXX	{						\
-	next: NULL,						\
-	usage_count: NULL,					\
-	proc_dir: NULL, 					\
-	proc_info: aic7xxx_proc_info,				\
-	name: NULL,						\
-	detect: aic7xxx_detect,					\
-	release: aic7xxx_release,				\
-	info: aic7xxx_info,					\
-	command: NULL,						\
-	queuecommand: aic7xxx_queue,				\
-	abort: aic7xxx_abort,					\
-	reset: aic7xxx_reset,					\
-	slave_attach: NULL,					\
-	bios_param: AIC7XXX_BIOSPARAM,				\
-	can_queue: 255,		/* max simultaneous cmds      */\
-	this_id: -1,		/* scsi id of host adapter    */\
-	sg_tablesize: 0,	/* max scatter-gather cmds    */\
-	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
-	present: 0,		/* number of 7xxx's present   */\
-	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
-	use_clustering: ENABLE_CLUSTERING			\
-}
-#endif
-
-extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-extern int aic7xxx_biosparam(Disk *, kdev_t, int[]);
-extern int aic7xxx_detect(Scsi_Host_Template *);
-extern int aic7xxx_command(Scsi_Cmnd *);
-extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int);
-extern int aic7xxx_abort(Scsi_Cmnd *);
-extern int aic7xxx_release(struct Scsi_Host *);
-
-extern const char *aic7xxx_info(struct Scsi_Host *);
-
-extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int);
-
-#endif /* _aic7xxx_h */
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx_proc.c	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx_proc.c	Wed Dec 31 16:00:00 1969
@@ -1,414 +0,0 @@
-/*+M*************************************************************************
- * Adaptec AIC7xxx device driver proc support for Linux.
- *
- * Copyright (c) 1995, 1996 Dean W. Gehnert
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * ----------------------------------------------------------------
- *  o Modified from the EATA-DMA /proc support.
- *  o Additional support for device block statistics provided by
- *    Matthew Jacob.
- *  o Correction of overflow by Heinz Mauelshagen
- *  o Adittional corrections by Doug Ledford
- *
- *  Dean W. Gehnert, deang@teleport.com, 05/01/96
- *
- *  $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
- *-M*************************************************************************/
-
-#include <linux/config.h>
-
-#define	BLS	(&aic7xxx_buffer[size])
-#define HDRB \
-"             < 2K      2K+     4K+     8K+    16K+    32K+    64K+   128K+"
-
-#ifdef PROC_DEBUG
-extern int vsprintf(char *, const char *, va_list);
-
-static void
-proc_debug(const char *fmt, ...)
-{
-  va_list ap;
-  char buf[256];
-
-  va_start(ap, fmt);
-  vsprintf(buf, fmt, ap);
-  printk(buf);
-  va_end(ap);
-}
-#else /* PROC_DEBUG */
-#  define proc_debug(fmt, args...)
-#endif /* PROC_DEBUG */
-
-static int aic7xxx_buffer_size = 0;
-static char *aic7xxx_buffer = NULL;
-
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_set_info
- *
- * Description:
- *   Set parameters for the driver from the /proc filesystem.
- *-F*************************************************************************/
-int
-aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
-{
-  proc_debug("aic7xxx_set_info(): %s\n", buffer);
-  return (-ENOSYS);  /* Currently this is a no-op */
-}
-
-
-/*+F*************************************************************************
- * Function:
- *   aic7xxx_proc_info
- *
- * Description:
- *   Return information to handle /proc support for the driver.
- *-F*************************************************************************/
-int
-aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length, 
-                    int hostno, int inout)
-{
-  struct Scsi_Host *HBAptr;
-  struct aic7xxx_host *p;
-  int    size = 0;
-  unsigned char i;
-  struct aic7xxx_xferstats *sp;
-  unsigned char target;
-
-  HBAptr = NULL;
-
-  for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
-    ;
-
-  if (!p)
-  {
-    size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
-    if (size > length)
-    {
-      return (size);
-    }
-    else
-    {
-      return (length);
-    }
-  }
-
-  HBAptr = p->host;
-
-  if (inout == TRUE) /* Has data been written to the file? */ 
-  {
-    return (aic7xxx_set_info(buffer, length, HBAptr));
-  }
-
-  p = (struct aic7xxx_host *) HBAptr->hostdata;
-
-  /*
-   * It takes roughly 1K of space to hold all relevant card info, not
-   * counting any proc stats, so we start out with a 1.5k buffer size and
-   * if proc_stats is defined, then we sweep the stats structure to see
-   * how many drives we will be printing out for and add 384 bytes per
-   * device with active stats.
-   *
-   * Hmmmm...that 1.5k seems to keep growing as items get added so they
-   * can be easily viewed for debugging purposes.  So, we bumped that
-   * 1.5k to 4k so we can quit having to bump it all the time.
-   */
-
-  size = 4096;
-  for (target = 0; target < MAX_TARGETS; target++)
-  {
-    if (p->dev_flags[target] & DEVICE_PRESENT)
-#ifdef AIC7XXX_PROC_STATS
-      size += 512;
-#else
-      size += 256;
-#endif
-  }
-  if (aic7xxx_buffer_size != size)
-  {
-    if (aic7xxx_buffer != NULL) 
-    {
-      kfree(aic7xxx_buffer);
-      aic7xxx_buffer_size = 0;
-    }
-    aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
-  }
-  if (aic7xxx_buffer == NULL)
-  {
-    size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
-        __LINE__);
-    return size;
-  }
-  aic7xxx_buffer_size = size;
-
-  size = 0;
-  size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
-  size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
-  size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Compile Options:\n");
-#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
-  size += sprintf(BLS, "  TCQ Enabled By Default : Enabled\n");
-#else
-  size += sprintf(BLS, "  TCQ Enabled By Default : Disabled\n");
-#endif
-#ifdef AIC7XXX_PROC_STATS
-  size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Enabled\n");
-#else
-  size += sprintf(BLS, "  AIC7XXX_PROC_STATS     : Disabled\n");
-#endif
-  size += sprintf(BLS, "  AIC7XXX_RESET_DELAY    : %d\n", AIC7XXX_RESET_DELAY);
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Adapter Configuration:\n");
-  size += sprintf(BLS, "           SCSI Adapter: %s\n",
-      board_names[p->board_name_index]);
-  if (p->flags & AHC_TWIN)
-    size += sprintf(BLS, "                         Twin Channel Controller ");
-  else
-  {
-    char *channel = "";
-    char *ultra = "";
-    char *wide = "Narrow ";
-    if (p->flags & AHC_MULTI_CHANNEL)
-    {
-      channel = " Channel A";
-      if (p->flags & (AHC_CHNLB|AHC_CHNLC))
-        channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C";
-    }
-    if (p->features & AHC_WIDE)
-      wide = "Wide ";
-    if (p->features & AHC_ULTRA3)
-    {
-      switch(p->chip & AHC_CHIPID_MASK)
-      {
-        case AHC_AIC7892:
-        case AHC_AIC7899:
-          ultra = "Ultra-160/m LVD/SE ";
-          break;
-        default:
-          ultra = "Ultra-3 LVD/SE ";
-          break;
-      }
-    }
-    else if (p->features & AHC_ULTRA2)
-      ultra = "Ultra-2 LVD/SE ";
-    else if (p->features & AHC_ULTRA)
-      ultra = "Ultra ";
-    size += sprintf(BLS, "                           %s%sController%s ",
-      ultra, wide, channel);
-  }
-  switch(p->chip & ~AHC_CHIPID_MASK)
-  {
-    case AHC_VL:
-      size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
-      break;
-    case AHC_EISA:
-      size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
-      break;
-    default:
-      size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
-        PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
-      break;
-  }
-  if( !(p->maddr) )
-  {
-    size += sprintf(BLS, "    Programmed I/O Base: %lx\n", p->base);
-  }
-  else
-  {
-    size += sprintf(BLS, "    PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
-  }
-  if( (p->chip & (AHC_VL | AHC_EISA)) )
-  {
-    size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
-  }
-  size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
-          (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
-         ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
-           "SEEPROM not found, using leftover BIOS values.") );
-  size += sprintf(BLS, "      Adaptec SCSI BIOS: %s\n",
-          (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
-  size += sprintf(BLS, "                    IRQ: %d\n", HBAptr->irq);
-  size += sprintf(BLS, "                   SCBs: Active %d, Max Active %d,\n",
-            p->activescbs, p->max_activescbs);
-  size += sprintf(BLS, "                         Allocated %d, HW %d, "
-            "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
-            p->scb_data->maxscbs);
-  if (p->flags & AHC_EXTERNAL_SRAM)
-    size += sprintf(BLS, "                         Using External SCB SRAM\n");
-  size += sprintf(BLS, "             Interrupts: %ld", p->isr_count);
-  if (p->chip & AHC_EISA)
-  {
-    size += sprintf(BLS, " %s\n",
-        (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
-  }
-  else
-  {
-    size += sprintf(BLS, "\n");
-  }
-  size += sprintf(BLS, "      BIOS Control Word: 0x%04x\n",
-            p->bios_control);
-  size += sprintf(BLS, "   Adapter Control Word: 0x%04x\n",
-            p->adapter_control);
-  size += sprintf(BLS, "   Extended Translation: %sabled\n",
-      (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
-  size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
-  if (p->features & (AHC_ULTRA | AHC_ULTRA2))
-  {
-    size += sprintf(BLS, "     Ultra Enable Flags: 0x%04x\n", p->ultraenb);
-  }
-  size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
-  size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
-  size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE);
-  size += sprintf(BLS, "    Tagged Queue By Device array for aic7xxx host "
-                       "instance %d:\n", p->instance);
-  size += sprintf(BLS, "      {");
-  for(i=0; i < (MAX_TARGETS - 1); i++)
-    size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
-  size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
-  size += sprintf(BLS, "    Actual queue depth per device for aic7xxx host "
-                       "instance %d:\n", p->instance);
-  size += sprintf(BLS, "      {");
-  for(i=0; i < (MAX_TARGETS - 1); i++)
-    size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]);
-  size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]);
-
-  size += sprintf(BLS, "\n");
-  size += sprintf(BLS, "Statistics:\n\n");
-  for (target = 0; target < MAX_TARGETS; target++)
-  {
-    sp = &p->stats[target];
-    if ((p->dev_flags[target] & DEVICE_PRESENT) == 0)
-    {
-      continue;
-    }
-    if (p->features & AHC_TWIN)
-    {
-      size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
-          p->host_no, (target >> 3), (target & 0x7), 0);
-    }
-    else
-    {
-      size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
-          p->host_no, 0, target, 0);
-    }
-    size += sprintf(BLS, "  Device using %s/%s",
-          (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
-          "Wide" : "Narrow",
-          (p->transinfo[target].cur_offset != 0) ?
-          "Sync transfers at " : "Async transfers.\n" );
-    if (p->transinfo[target].cur_offset != 0)
-    {
-      struct aic7xxx_syncrate *sync_rate;
-      unsigned char options = p->transinfo[target].cur_options;
-      int period = p->transinfo[target].cur_period;
-      int rate = (p->transinfo[target].cur_width ==
-                  MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
-
-      sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
-      if (sync_rate != NULL)
-      {
-        size += sprintf(BLS, "%s MByte/sec, offset %d\n",
-                        sync_rate->rate[rate],
-                        p->transinfo[target].cur_offset );
-      }
-      else
-      {
-        size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
-                        p->transinfo[target].cur_offset );
-      }
-    }
-    size += sprintf(BLS, "  Transinfo settings: ");
-    size += sprintf(BLS, "current(%d/%d/%d/%d), ",
-                    p->transinfo[target].cur_period,
-                    p->transinfo[target].cur_offset,
-                    p->transinfo[target].cur_width,
-                    p->transinfo[target].cur_options);
-    size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
-                    p->transinfo[target].goal_period,
-                    p->transinfo[target].goal_offset,
-                    p->transinfo[target].goal_width,
-                    p->transinfo[target].goal_options);
-    size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
-                    p->transinfo[target].user_period,
-                    p->transinfo[target].user_offset,
-                    p->transinfo[target].user_width,
-                    p->transinfo[target].user_options);
-#ifdef AIC7XXX_PROC_STATS
-    size += sprintf(BLS, "  Total transfers %ld (%ld reads and %ld writes)\n",
-        sp->r_total + sp->w_total, sp->r_total, sp->w_total);
-    size += sprintf(BLS, "%s\n", HDRB);
-    size += sprintf(BLS, "   Reads:");
-    for (i = 0; i < NUMBER(sp->r_bins); i++)
-    {
-      size += sprintf(BLS, " %7ld", sp->r_bins[i]);
-    }
-    size += sprintf(BLS, "\n");
-    size += sprintf(BLS, "  Writes:");
-    for (i = 0; i < NUMBER(sp->w_bins); i++)
-    {
-      size += sprintf(BLS, " %7ld", sp->w_bins[i]);
-    }
-    size += sprintf(BLS, "\n");
-#else
-    size += sprintf(BLS, "  Total transfers %ld (%ld reads and %ld writes)\n",
-        sp->r_total + sp->w_total, sp->r_total, sp->w_total);
-#endif /* AIC7XXX_PROC_STATS */
-    size += sprintf(BLS, "\n\n");
-  }
-
-  if (size >= aic7xxx_buffer_size)
-  {
-    printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
-  }
-
-  if (offset > size - 1)
-  {
-    kfree(aic7xxx_buffer);
-    aic7xxx_buffer = NULL;
-    aic7xxx_buffer_size = length = 0;
-    *start = NULL;
-  }
-  else
-  {
-    *start = buffer;
-    length = MIN(length, size - offset);
-    memcpy(buffer, &aic7xxx_buffer[offset], length);
-  }
-
-  return (length);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 2
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -2
- * c-argdecl-indent: 2
- * c-label-offset: -2
- * c-continued-statement-offset: 2
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx_reg.h	Wed May  3 17:16:44 2000
+++ linux/drivers/scsi/aic7xxx_reg.h	Wed Dec 31 16:00:00 1969
@@ -1,629 +0,0 @@
-/*
-  * DO NOT EDIT - This file is automatically generated.
-  */
-
-#define	SCSISEQ         		0x00
-#define		TEMODE          	0x80
-#define		ENSELO          	0x40
-#define		ENSELI          	0x20
-#define		ENRSELI         	0x10
-#define		ENAUTOATNO      	0x08
-#define		ENAUTOATNI      	0x04
-#define		ENAUTOATNP      	0x02
-#define		SCSIRSTO        	0x01
-
-#define	SXFRCTL0        		0x01
-#define		DFON            	0x80
-#define		DFPEXP          	0x40
-#define		FAST20          	0x20
-#define		CLRSTCNT        	0x10
-#define		SPIOEN          	0x08
-#define		SCAMEN          	0x04
-#define		CLRCHN          	0x02
-
-#define	SXFRCTL1        		0x02
-#define		BITBUCKET       	0x80
-#define		SWRAPEN         	0x40
-#define		ENSPCHK         	0x20
-#define		STIMESEL        	0x18
-#define		ENSTIMER        	0x04
-#define		ACTNEGEN        	0x02
-#define		STPWEN          	0x01
-
-#define	SCSISIGO        		0x03
-#define		CDO             	0x80
-#define		IOO             	0x40
-#define		MSGO            	0x20
-#define		ATNO            	0x10
-#define		SELO            	0x08
-#define		BSYO            	0x04
-#define		REQO            	0x02
-#define		ACKO            	0x01
-
-#define	SCSISIGI        		0x03
-#define		ATNI            	0x10
-#define		SELI            	0x08
-#define		BSYI            	0x04
-#define		REQI            	0x02
-#define		ACKI            	0x01
-
-#define	SCSIRATE        		0x04
-#define		WIDEXFER        	0x80
-#define		SXFR_ULTRA2     	0x7f
-#define		SXFR            	0x70
-#define		SOFS            	0x0f
-
-#define	SCSIID          		0x05
-#define	SCSIOFFSET      		0x05
-#define		SOFS_ULTRA2     	0x7f
-
-#define	SCSIDATL        		0x06
-
-#define	SCSIDATH        		0x07
-
-#define	STCNT           		0x08
-
-#define	OPTIONMODE      		0x08
-#define		AUTORATEEN      	0x80
-#define		AUTOACKEN       	0x40
-#define		ATNMGMNTEN      	0x20
-#define		BUSFREEREV      	0x10
-#define		EXPPHASEDIS     	0x08
-#define		SCSIDATL_IMGEN  	0x04
-#define		AUTO_MSGOUT_DE  	0x02
-#define		DIS_MSGIN_DUALEDGE	0x01
-
-#define	CLRSINT0        		0x0b
-#define		CLRSELDO        	0x40
-#define		CLRSELDI        	0x20
-#define		CLRSELINGO      	0x10
-#define		CLRSWRAP        	0x08
-#define		CLRSPIORDY      	0x02
-
-#define	SSTAT0          		0x0b
-#define		TARGET          	0x80
-#define		SELDO           	0x40
-#define		SELDI           	0x20
-#define		SELINGO         	0x10
-#define		IOERR           	0x08
-#define		SWRAP           	0x08
-#define		SDONE           	0x04
-#define		SPIORDY         	0x02
-#define		DMADONE         	0x01
-
-#define	CLRSINT1        		0x0c
-#define		CLRSELTIMEO     	0x80
-#define		CLRATNO         	0x40
-#define		CLRSCSIRSTI     	0x20
-#define		CLRBUSFREE      	0x08
-#define		CLRSCSIPERR     	0x04
-#define		CLRPHASECHG     	0x02
-#define		CLRREQINIT      	0x01
-
-#define	SSTAT1          		0x0c
-#define		SELTO           	0x80
-#define		ATNTARG         	0x40
-#define		SCSIRSTI        	0x20
-#define		PHASEMIS        	0x10
-#define		BUSFREE         	0x08
-#define		SCSIPERR        	0x04
-#define		PHASECHG        	0x02
-#define		REQINIT         	0x01
-
-#define	SSTAT2          		0x0d
-#define		OVERRUN         	0x80
-#define		SHVALID         	0x40
-#define		WIDE_RES        	0x20
-#define		SFCNT           	0x1f
-#define		EXP_ACTIVE      	0x10
-#define		CRCVALERR       	0x08
-#define		CRCENDERR       	0x04
-#define		CRCREQERR       	0x02
-#define		DUAL_EDGE_ERROR 	0x01
-
-#define	SSTAT3          		0x0e
-#define		SCSICNT         	0xf0
-#define		OFFCNT          	0x0f
-
-#define	SCSIID_ULTRA2   		0x0f
-#define		OID             	0x0f
-
-#define	SIMODE0         		0x10
-#define		ENSELDO         	0x40
-#define		ENSELDI         	0x20
-#define		ENSELINGO       	0x10
-#define		ENIOERR         	0x08
-#define		ENSWRAP         	0x08
-#define		ENSDONE         	0x04
-#define		ENSPIORDY       	0x02
-#define		ENDMADONE       	0x01
-
-#define	SIMODE1         		0x11
-#define		ENSELTIMO       	0x80
-#define		ENATNTARG       	0x40
-#define		ENSCSIRST       	0x20
-#define		ENPHASEMIS      	0x10
-#define		ENBUSFREE       	0x08
-#define		ENSCSIPERR      	0x04
-#define		ENPHASECHG      	0x02
-#define		ENREQINIT       	0x01
-
-#define	SCSIBUSL        		0x12
-
-#define	SCSIBUSH        		0x13
-
-#define	SHADDR          		0x14
-
-#define	SELTIMER        		0x18
-#define		STAGE6          	0x20
-#define		STAGE5          	0x10
-#define		STAGE4          	0x08
-#define		STAGE3          	0x04
-#define		STAGE2          	0x02
-#define		STAGE1          	0x01
-
-#define	SELID           		0x19
-#define		SELID_MASK      	0xf0
-#define		ONEBIT          	0x08
-
-#define	SPIOCAP         		0x1b
-#define		SOFT1           	0x80
-#define		SOFT0           	0x40
-#define		SOFTCMDEN       	0x20
-#define		HAS_BRDCTL      	0x10
-#define		SEEPROM         	0x08
-#define		EEPROM          	0x04
-#define		ROM             	0x02
-#define		SSPIOCPS        	0x01
-
-#define	BRDCTL          		0x1d
-#define		BRDDAT7         	0x80
-#define		BRDDAT6         	0x40
-#define		BRDDAT5         	0x20
-#define		BRDDAT4         	0x10
-#define		BRDSTB          	0x10
-#define		BRDCS           	0x08
-#define		BRDDAT3         	0x08
-#define		BRDDAT2         	0x04
-#define		BRDRW           	0x04
-#define		BRDRW_ULTRA2    	0x02
-#define		BRDCTL1         	0x02
-#define		BRDCTL0         	0x01
-#define		BRDSTB_ULTRA2   	0x01
-
-#define	SEECTL          		0x1e
-#define		EXTARBACK       	0x80
-#define		EXTARBREQ       	0x40
-#define		SEEMS           	0x20
-#define		SEERDY          	0x10
-#define		SEECS           	0x08
-#define		SEECK           	0x04
-#define		SEEDO           	0x02
-#define		SEEDI           	0x01
-
-#define	SBLKCTL         		0x1f
-#define		DIAGLEDEN       	0x80
-#define		DIAGLEDON       	0x40
-#define		AUTOFLUSHDIS    	0x20
-#define		ENAB40          	0x08
-#define		ENAB20          	0x04
-#define		SELWIDE         	0x02
-#define		XCVR            	0x01
-
-#define	SRAM_BASE       		0x20
-
-#define	TARG_SCSIRATE   		0x20
-
-#define	ULTRA_ENB       		0x30
-
-#define	DISC_DSB        		0x32
-
-#define	MSG_OUT         		0x34
-
-#define	DMAPARAMS       		0x35
-#define		PRELOADEN       	0x80
-#define		WIDEODD         	0x40
-#define		SCSIEN          	0x20
-#define		SDMAENACK       	0x10
-#define		SDMAEN          	0x10
-#define		HDMAEN          	0x08
-#define		HDMAENACK       	0x08
-#define		DIRECTION       	0x04
-#define		FIFOFLUSH       	0x02
-#define		FIFORESET       	0x01
-
-#define	SEQ_FLAGS       		0x36
-#define		IDENTIFY_SEEN   	0x80
-#define		SCBPTR_VALID    	0x20
-#define		DPHASE          	0x10
-#define		AMTARGET        	0x08
-#define		WIDE_BUS        	0x02
-#define		TWIN_BUS        	0x01
-
-#define	SAVED_TCL       		0x37
-
-#define	SG_COUNT        		0x38
-
-#define	SG_NEXT         		0x39
-
-#define	LASTPHASE       		0x3d
-#define		P_MESGIN        	0xe0
-#define		PHASE_MASK      	0xe0
-#define		P_STATUS        	0xc0
-#define		P_MESGOUT       	0xa0
-#define		P_COMMAND       	0x80
-#define		CDI             	0x80
-#define		IOI             	0x40
-#define		P_DATAIN        	0x40
-#define		MSGI            	0x20
-#define		P_BUSFREE       	0x01
-#define		P_DATAOUT       	0x00
-
-#define	WAITING_SCBH    		0x3e
-
-#define	DISCONNECTED_SCBH		0x3f
-
-#define	FREE_SCBH       		0x40
-
-#define	HSCB_ADDR       		0x41
-
-#define	SCBID_ADDR      		0x45
-
-#define	TMODE_CMDADDR   		0x49
-
-#define	KERNEL_QINPOS   		0x4d
-
-#define	QINPOS          		0x4e
-
-#define	QOUTPOS         		0x4f
-
-#define	TMODE_CMDADDR_NEXT		0x50
-
-#define	ARG_1           		0x51
-#define	RETURN_1        		0x51
-#define		SEND_MSG        	0x80
-#define		SEND_SENSE      	0x40
-#define		SEND_REJ        	0x20
-#define		MSGOUT_PHASEMIS 	0x10
-
-#define	ARG_2           		0x52
-#define	RETURN_2        		0x52
-
-#define	LAST_MSG        		0x53
-
-#define	PREFETCH_CNT    		0x54
-
-#define	SCSICONF        		0x5a
-#define		TERM_ENB        	0x80
-#define		RESET_SCSI      	0x40
-#define		HWSCSIID        	0x0f
-#define		HSCSIID         	0x07
-
-#define	HOSTCONF        		0x5d
-
-#define	HA_274_BIOSCTRL 		0x5f
-#define		BIOSMODE        	0x30
-#define		BIOSDISABLED    	0x30
-#define		CHANNEL_B_PRIMARY	0x08
-
-#define	SEQCTL          		0x60
-#define		PERRORDIS       	0x80
-#define		PAUSEDIS        	0x40
-#define		FAILDIS         	0x20
-#define		FASTMODE        	0x10
-#define		BRKADRINTEN     	0x08
-#define		STEP            	0x04
-#define		SEQRESET        	0x02
-#define		LOADRAM         	0x01
-
-#define	SEQRAM          		0x61
-
-#define	SEQADDR0        		0x62
-
-#define	SEQADDR1        		0x63
-#define		SEQADDR1_MASK   	0x01
-
-#define	ACCUM           		0x64
-
-#define	SINDEX          		0x65
-
-#define	DINDEX          		0x66
-
-#define	ALLONES         		0x69
-
-#define	ALLZEROS        		0x6a
-
-#define	NONE            		0x6a
-
-#define	FLAGS           		0x6b
-#define		ZERO            	0x02
-#define		CARRY           	0x01
-
-#define	SINDIR          		0x6c
-
-#define	DINDIR          		0x6d
-
-#define	FUNCTION1       		0x6e
-
-#define	STACK           		0x6f
-
-#define	TARG_OFFSET     		0x70
-
-#define	BCTL            		0x84
-#define		ACE             	0x08
-#define		ENABLE          	0x01
-
-#define	DSCOMMAND0      		0x84
-#define		INTSCBRAMSEL    	0x08
-#define		RAMPS           	0x04
-#define		USCBSIZE32      	0x02
-#define		CIOPARCKEN      	0x01
-
-#define	DSCOMMAND       		0x84
-#define		CACHETHEN       	0x80
-#define		DPARCKEN        	0x40
-#define		MPARCKEN        	0x20
-#define		EXTREQLCK       	0x10
-
-#define	BUSTIME         		0x85
-#define		BOFF            	0xf0
-#define		BON             	0x0f
-
-#define	BUSSPD          		0x86
-#define		DFTHRSH         	0xc0
-#define		STBOFF          	0x38
-#define		STBON           	0x07
-
-#define	DSPCISTATUS     		0x86
-#define		DFTHRSH_100     	0xc0
-
-#define	HCNTRL          		0x87
-#define		POWRDN          	0x40
-#define		SWINT           	0x10
-#define		IRQMS           	0x08
-#define		PAUSE           	0x04
-#define		INTEN           	0x02
-#define		CHIPRST         	0x01
-#define		CHIPRSTACK      	0x01
-
-#define	HADDR           		0x88
-
-#define	HCNT            		0x8c
-
-#define	SCBPTR          		0x90
-
-#define	INTSTAT         		0x91
-#define		SEQINT_MASK     	0xf1
-#define		DATA_OVERRUN    	0xe1
-#define		MSGIN_PHASEMIS  	0xd1
-#define		TRACEPOINT2     	0xc1
-#define		TRACEPOINT      	0xb1
-#define		AWAITING_MSG    	0xa1
-#define		RESIDUAL        	0x81
-#define		BAD_STATUS      	0x71
-#define		REJECT_MSG      	0x61
-#define		WIDE_RESIDUE    	0x51
-#define		EXTENDED_MSG    	0x41
-#define		NO_MATCH        	0x31
-#define		NO_IDENT        	0x21
-#define		SEND_REJECT     	0x11
-#define		INT_PEND        	0x0f
-#define		BRKADRINT       	0x08
-#define		SCSIINT         	0x04
-#define		CMDCMPLT        	0x02
-#define		BAD_PHASE       	0x01
-#define		SEQINT          	0x01
-
-#define	CLRINT          		0x92
-#define		CLRPARERR       	0x10
-#define		CLRBRKADRINT    	0x08
-#define		CLRSCSIINT      	0x04
-#define		CLRCMDINT       	0x02
-#define		CLRSEQINT       	0x01
-
-#define	ERROR           		0x92
-#define		CIOPARERR       	0x80
-#define		PCIERRSTAT      	0x40
-#define		MPARERR         	0x20
-#define		DPARERR         	0x10
-#define		SQPARERR        	0x08
-#define		ILLOPCODE       	0x04
-#define		DSCTMOUT        	0x02
-#define		ILLSADDR        	0x02
-#define		ILLHADDR        	0x01
-
-#define	DFCNTRL         		0x93
-
-#define	DFSTATUS        		0x94
-#define		PRELOAD_AVAIL   	0x80
-#define		DWORDEMP        	0x20
-#define		MREQPEND        	0x10
-#define		HDONE           	0x08
-#define		DFTHRESH        	0x04
-#define		FIFOFULL        	0x02
-#define		FIFOEMP         	0x01
-
-#define	DFDAT           		0x99
-
-#define	SCBCNT          		0x9a
-#define		SCBAUTO         	0x80
-#define		SCBCNT_MASK     	0x1f
-
-#define	QINFIFO         		0x9b
-
-#define	QINCNT          		0x9c
-
-#define	SCSIDATL_IMG    		0x9c
-
-#define	QOUTFIFO        		0x9d
-
-#define	CRCCONTROL1     		0x9d
-#define		CRCONSEEN       	0x80
-#define		CRCVALCHKEN     	0x40
-#define		CRCENDCHKEN     	0x20
-#define		CRCREQCHKEN     	0x10
-#define		TARGCRCENDEN    	0x08
-#define		TARGCRCCNTEN    	0x04
-
-#define	QOUTCNT         		0x9e
-
-#define	SCSIPHASE       		0x9e
-#define		SP_STATUS       	0x20
-#define		SP_COMMAND      	0x10
-#define		SP_MSG_IN       	0x08
-#define		SP_MSG_OUT      	0x04
-#define		SP_DATA_IN      	0x02
-#define		SP_DATA_OUT     	0x01
-
-#define	SFUNCT          		0x9f
-#define		ALT_MODE        	0x80
-
-#define	SCB_CONTROL     		0xa0
-#define		MK_MESSAGE      	0x80
-#define		DISCENB         	0x40
-#define		TAG_ENB         	0x20
-#define		DISCONNECTED    	0x04
-#define		SCB_TAG_TYPE    	0x03
-
-#define	SCB_BASE        		0xa0
-
-#define	SCB_TCL         		0xa1
-#define		TID             	0xf0
-#define		SELBUSB         	0x08
-#define		LID             	0x07
-
-#define	SCB_TARGET_STATUS		0xa2
-
-#define	SCB_SGCOUNT     		0xa3
-
-#define	SCB_SGPTR       		0xa4
-
-#define	SCB_RESID_SGCNT 		0xa8
-
-#define	SCB_RESID_DCNT  		0xa9
-
-#define	SCB_DATAPTR     		0xac
-
-#define	SCB_DATACNT     		0xb0
-
-#define	SCB_CMDPTR      		0xb4
-
-#define	SCB_CMDLEN      		0xb8
-
-#define	SCB_TAG         		0xb9
-
-#define	SCB_NEXT        		0xba
-
-#define	SCB_PREV        		0xbb
-
-#define	SCB_BUSYTARGETS 		0xbc
-
-#define	SEECTL_2840     		0xc0
-#define		CS_2840         	0x04
-#define		CK_2840         	0x02
-#define		DO_2840         	0x01
-
-#define	STATUS_2840     		0xc1
-#define		EEPROM_TF       	0x80
-#define		BIOS_SEL        	0x60
-#define		ADSEL           	0x1e
-#define		DI_2840         	0x01
-
-#define	CCHADDR         		0xe0
-
-#define	CCHCNT          		0xe8
-
-#define	CCSGRAM         		0xe9
-
-#define	CCSGADDR        		0xea
-
-#define	CCSGCTL         		0xeb
-#define		CCSGDONE        	0x80
-#define		CCSGEN          	0x08
-#define		FLAG            	0x02
-#define		CCSGRESET       	0x01
-
-#define	CCSCBRAM        		0xec
-
-#define	CCSCBADDR       		0xed
-
-#define	CCSCBCTL        		0xee
-#define		CCSCBDONE       	0x80
-#define		ARRDONE         	0x40
-#define		CCARREN         	0x10
-#define		CCSCBEN         	0x08
-#define		CCSCBDIR        	0x04
-#define		CCSCBRESET      	0x01
-
-#define	CCSCBCNT        		0xef
-
-#define	CCSCBPTR        		0xf1
-
-#define	HNSCB_QOFF      		0xf4
-
-#define	HESCB_QOFF      		0xf5
-
-#define	SNSCB_QOFF      		0xf6
-
-#define	SESCB_QOFF      		0xf7
-
-#define	SDSCB_QOFF      		0xf8
-
-#define	QOFF_CTLSTA     		0xfa
-#define		ESTABLISH_SCB_AVAIL	0x80
-#define		SCB_AVAIL       	0x40
-#define		SNSCB_ROLLOVER  	0x20
-#define		SDSCB_ROLLOVER  	0x10
-#define		SESCB_ROLLOVER  	0x08
-#define		SCB_QSIZE       	0x07
-#define		SCB_QSIZE_256   	0x06
-
-#define	DFF_THRSH       		0xfb
-#define		WR_DFTHRSH      	0x70
-#define		WR_DFTHRSH_MAX  	0x70
-#define		WR_DFTHRSH_90   	0x60
-#define		WR_DFTHRSH_85   	0x50
-#define		WR_DFTHRSH_75   	0x40
-#define		WR_DFTHRSH_63   	0x30
-#define		WR_DFTHRSH_50   	0x20
-#define		WR_DFTHRSH_25   	0x10
-#define		RD_DFTHRSH_MAX  	0x07
-#define		RD_DFTHRSH      	0x07
-#define		RD_DFTHRSH_90   	0x06
-#define		RD_DFTHRSH_85   	0x05
-#define		RD_DFTHRSH_75   	0x04
-#define		RD_DFTHRSH_63   	0x03
-#define		RD_DFTHRSH_50   	0x02
-#define		RD_DFTHRSH_25   	0x01
-#define		RD_DFTHRSH_MIN  	0x00
-#define		WR_DFTHRSH_MIN  	0x00
-
-#define	SG_CACHEPTR     		0xfc
-#define		SG_USER_DATA    	0xfc
-#define		LAST_SEG        	0x02
-#define		LAST_SEG_DONE   	0x01
-
-
-#define	CMD_GROUP_CODE_SHIFT	0x05
-#define	BUS_8_BIT	0x00
-#define	QOUTFIFO_OFFSET	0x01
-#define	CCSGRAM_MAXSEGS	0x10
-#define	CMD_GROUP2_BYTE_DELTA	0xfa
-#define	MAX_OFFSET_8BIT	0x0f
-#define	BUS_16_BIT	0x01
-#define	QINFIFO_OFFSET	0x02
-#define	CMD_GROUP5_BYTE_DELTA	0x0b
-#define	MAX_OFFSET_ULTRA2	0x7f
-#define	MAX_OFFSET_16BIT	0x08
-#define	UNTAGGEDSCB_OFFSET	0x00
-#define	SCB_LIST_NULL	0xff
-#define	SG_SIZEOF	0x08
-#define	CMD_GROUP4_BYTE_DELTA	0x04
-#define	CMD_GROUP0_BYTE_DELTA	0xfc
-#define	HOST_MSG	0xff
-#define	BUS_32_BIT	0x02
-#define	CCSGADDR_MAX	0x80
-
-
-/* Downloaded Constant Definitions */
-#define	TMODE_NUMCMDS	0x00
diff -urN linux-2.2.19-pre8/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c
--- linux-2.2.19-pre8/drivers/scsi/aic7xxx_seq.c	Mon Sep  4 10:39:21 2000
+++ linux/drivers/scsi/aic7xxx_seq.c	Wed Dec 31 16:00:00 1969
@@ -1,745 +0,0 @@
-/*
-  * DO NOT EDIT - This file is automatically generated.
-  */
-static unsigned char seqprog[] = {
-	0xff, 0x6a, 0x06, 0x08,
-	0x7f, 0x02, 0x04, 0x08,
-	0x12, 0x6a, 0x00, 0x00,
-	0xff, 0x6a, 0xd6, 0x09,
-	0xff, 0x6a, 0xdc, 0x09,
-	0x00, 0x65, 0xca, 0x58,
-	0xf7, 0x01, 0x02, 0x08,
-	0xff, 0x4e, 0xc8, 0x08,
-	0xbf, 0x60, 0xc0, 0x08,
-	0x60, 0x0b, 0x86, 0x68,
-	0x40, 0x00, 0x0c, 0x68,
-	0x08, 0x1f, 0x3e, 0x10,
-	0x60, 0x0b, 0x86, 0x68,
-	0x40, 0x00, 0x0c, 0x68,
-	0x08, 0x1f, 0x3e, 0x10,
-	0xff, 0x3e, 0x48, 0x60,
-	0x40, 0xfa, 0x10, 0x78,
-	0xff, 0xf6, 0xd4, 0x08,
-	0x01, 0x4e, 0x9c, 0x18,
-	0x40, 0x60, 0xc0, 0x00,
-	0x00, 0x4d, 0x10, 0x70,
-	0x01, 0x4e, 0x9c, 0x18,
-	0xbf, 0x60, 0xc0, 0x08,
-	0x00, 0x6a, 0x3e, 0x5c,
-	0xff, 0x4e, 0xc8, 0x18,
-	0x02, 0x6a, 0x54, 0x5b,
-	0xff, 0x52, 0x20, 0x09,
-	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x52, 0xca, 0x5b,
-	0x03, 0xb0, 0x52, 0x31,
-	0xff, 0xb0, 0x52, 0x09,
-	0xff, 0xb1, 0x54, 0x09,
-	0xff, 0xb2, 0x56, 0x09,
-	0xff, 0xa3, 0x50, 0x09,
-	0xff, 0x3e, 0x74, 0x09,
-	0xff, 0x90, 0x7c, 0x08,
-	0xff, 0x3e, 0x20, 0x09,
-	0x00, 0x65, 0x4e, 0x58,
-	0x00, 0x65, 0x0c, 0x40,
-	0xf7, 0x1f, 0xca, 0x08,
-	0x08, 0xa1, 0xc8, 0x08,
-	0x00, 0x65, 0xca, 0x00,
-	0xff, 0x65, 0x3e, 0x08,
-	0xf0, 0xa1, 0xc8, 0x08,
-	0x0f, 0x0f, 0x1e, 0x08,
-	0x00, 0x0f, 0x1e, 0x00,
-	0xf0, 0xa1, 0xc8, 0x08,
-	0x0f, 0x05, 0x0a, 0x08,
-	0x00, 0x05, 0x0a, 0x00,
-	0xff, 0x6a, 0x0c, 0x08,
-	0x5a, 0x6a, 0x00, 0x04,
-	0x12, 0x65, 0x02, 0x00,
-	0x31, 0x6a, 0xca, 0x00,
-	0x80, 0x37, 0x6e, 0x68,
-	0xff, 0x65, 0xca, 0x18,
-	0xff, 0x37, 0xdc, 0x08,
-	0xff, 0x6e, 0xc8, 0x08,
-	0x00, 0x6c, 0x76, 0x78,
-	0x20, 0x01, 0x02, 0x00,
-	0x4c, 0x37, 0xc8, 0x28,
-	0x08, 0x1f, 0x7e, 0x78,
-	0x08, 0x37, 0x6e, 0x00,
-	0x08, 0x64, 0xc8, 0x00,
-	0x70, 0x64, 0xca, 0x18,
-	0xff, 0x6c, 0x0a, 0x08,
-	0x20, 0x64, 0xca, 0x18,
-	0xff, 0x6c, 0x08, 0x0c,
-	0x40, 0x0b, 0x96, 0x68,
-	0x20, 0x6a, 0x16, 0x00,
-	0xf0, 0x19, 0x6e, 0x08,
-	0x08, 0x6a, 0x18, 0x00,
-	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x66, 0x58,
-	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0xaa, 0x40,
-	0x12, 0x6a, 0x00, 0x00,
-	0x40, 0x6a, 0x16, 0x00,
-	0xff, 0x3e, 0x20, 0x09,
-	0xff, 0xba, 0x7c, 0x08,
-	0xff, 0xa1, 0x6e, 0x08,
-	0x08, 0x6a, 0x18, 0x00,
-	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x66, 0x58,
-	0x80, 0x6a, 0x68, 0x00,
-	0x80, 0x36, 0x6c, 0x00,
-	0x00, 0x65, 0x9e, 0x5b,
-	0xff, 0x3d, 0xc8, 0x08,
-	0xbf, 0x64, 0xe2, 0x78,
-	0x80, 0x64, 0xac, 0x71,
-	0xa0, 0x64, 0xdc, 0x71,
-	0xc0, 0x64, 0xd4, 0x71,
-	0xe0, 0x64, 0x1c, 0x72,
-	0x01, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xaa, 0x40,
-	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0xca, 0x58,
-	0xff, 0x06, 0xd4, 0x08,
-	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0xc4, 0x78,
-	0x08, 0x0c, 0x0c, 0x68,
-	0x01, 0x6a, 0x22, 0x01,
-	0xff, 0x6a, 0x26, 0x09,
-	0x02, 0x6a, 0x08, 0x30,
-	0xff, 0x6a, 0x08, 0x08,
-	0xdf, 0x01, 0x02, 0x08,
-	0x01, 0x6a, 0x7a, 0x00,
-	0xff, 0x6a, 0x6c, 0x0c,
-	0x04, 0x14, 0x10, 0x31,
-	0x03, 0xa9, 0x18, 0x31,
-	0x03, 0xa9, 0x10, 0x30,
-	0x08, 0x6a, 0xcc, 0x00,
-	0xa9, 0x6a, 0xb4, 0x5b,
-	0x00, 0x65, 0x02, 0x41,
-	0xa8, 0x6a, 0x6a, 0x00,
-	0x79, 0x6a, 0x6a, 0x00,
-	0x40, 0x3d, 0xea, 0x68,
-	0x04, 0x35, 0x6a, 0x00,
-	0x00, 0x65, 0x0e, 0x5b,
-	0x80, 0x6a, 0xd4, 0x01,
-	0x10, 0x36, 0xd6, 0x68,
-	0x10, 0x36, 0x6c, 0x00,
-	0x07, 0xac, 0x10, 0x31,
-	0x03, 0x8c, 0x10, 0x30,
-	0x05, 0xa3, 0x70, 0x30,
-	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0xac, 0x5b,
-	0x00, 0x65, 0xa6, 0x5b,
-	0x38, 0x6a, 0xcc, 0x00,
-	0xa3, 0x6a, 0xb0, 0x5b,
-	0xff, 0x38, 0x12, 0x69,
-	0x80, 0x02, 0x04, 0x00,
-	0xe7, 0x35, 0x6a, 0x08,
-	0x03, 0x69, 0x18, 0x31,
-	0x03, 0x69, 0x10, 0x30,
-	0xff, 0x6a, 0x10, 0x00,
-	0xff, 0x6a, 0x12, 0x00,
-	0xff, 0x6a, 0x14, 0x00,
-	0x01, 0x38, 0x18, 0x61,
-	0xbf, 0x35, 0x6a, 0x08,
-	0x02, 0x6a, 0xf8, 0x01,
-	0xff, 0x69, 0xca, 0x08,
-	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0x1c, 0x69,
-	0x04, 0x0b, 0x28, 0x69,
-	0x10, 0x0c, 0x1e, 0x79,
-	0x04, 0x0b, 0x28, 0x69,
-	0xff, 0x6a, 0xca, 0x08,
-	0x00, 0x35, 0xee, 0x5a,
-	0x80, 0x02, 0x7c, 0x69,
-	0xff, 0x65, 0x6c, 0x79,
-	0xff, 0x38, 0x70, 0x18,
-	0xff, 0x38, 0x6c, 0x79,
-	0x80, 0xea, 0x48, 0x61,
-	0xef, 0x38, 0xc8, 0x18,
-	0x80, 0x6a, 0xc8, 0x00,
-	0x00, 0x65, 0x3a, 0x49,
-	0x33, 0x38, 0xc8, 0x28,
-	0xff, 0x64, 0xd0, 0x09,
-	0x04, 0x39, 0xc0, 0x31,
-	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0x40, 0x79,
-	0xf7, 0xeb, 0xd6, 0x09,
-	0x08, 0xeb, 0x44, 0x69,
-	0x01, 0x6a, 0xd6, 0x01,
-	0x08, 0xe9, 0x10, 0x31,
-	0x03, 0x8c, 0x10, 0x30,
-	0x88, 0x6a, 0xcc, 0x00,
-	0x39, 0x6a, 0xb2, 0x5b,
-	0x08, 0x6a, 0x18, 0x01,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x30, 0x5c,
-	0x88, 0x6a, 0x20, 0x5c,
-	0x00, 0x65, 0xa6, 0x5b,
-	0xff, 0x6a, 0xc8, 0x08,
-	0x08, 0x39, 0x72, 0x18,
-	0x00, 0x3a, 0x74, 0x20,
-	0x01, 0x0c, 0x64, 0x79,
-	0x10, 0x0c, 0x02, 0x79,
-	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0x6a, 0x69,
-	0x00, 0x65, 0x84, 0x59,
-	0x03, 0x08, 0x52, 0x31,
-	0xff, 0x38, 0x50, 0x09,
-	0xff, 0x08, 0x52, 0x09,
-	0xff, 0x09, 0x54, 0x09,
-	0xff, 0x0a, 0x56, 0x09,
-	0xff, 0x38, 0x50, 0x09,
-	0x00, 0x65, 0xaa, 0x40,
-	0x00, 0x65, 0x84, 0x59,
-	0x7f, 0x02, 0x04, 0x08,
-	0xe1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xaa, 0x40,
-	0x04, 0x93, 0x9a, 0x69,
-	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x88, 0x69,
-	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0x8a, 0x79,
-	0x01, 0x94, 0x8a, 0x79,
-	0x01, 0x94, 0x8a, 0x79,
-	0x01, 0x94, 0x8a, 0x79,
-	0x01, 0x94, 0x8a, 0x79,
-	0x01, 0x94, 0x8a, 0x79,
-	0x10, 0x94, 0x98, 0x69,
-	0x7f, 0x05, 0xa0, 0x69,
-	0x02, 0x03, 0xa0, 0x79,
-	0x11, 0x0c, 0x9c, 0x79,
-	0xd7, 0x93, 0x26, 0x09,
-	0x28, 0x93, 0xa2, 0x69,
-	0x03, 0x08, 0x52, 0x31,
-	0xff, 0x38, 0x50, 0x09,
-	0x12, 0x01, 0x02, 0x00,
-	0xff, 0x6a, 0xd4, 0x0c,
-	0x00, 0x65, 0x0e, 0x5b,
-	0x05, 0xb4, 0x10, 0x31,
-	0x02, 0x6a, 0x1a, 0x31,
-	0x03, 0x8c, 0x10, 0x30,
-	0x88, 0x6a, 0xcc, 0x00,
-	0xb4, 0x6a, 0xb0, 0x5b,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0x00, 0x65, 0xa6, 0x5b,
-	0x3d, 0x6a, 0xee, 0x5a,
-	0xac, 0x6a, 0x26, 0x01,
-	0x04, 0x0b, 0xc2, 0x69,
-	0x04, 0x0b, 0xc8, 0x69,
-	0x10, 0x0c, 0xc4, 0x79,
-	0x02, 0x03, 0xcc, 0x79,
-	0x11, 0x0c, 0xc8, 0x79,
-	0xd7, 0x93, 0x26, 0x09,
-	0x28, 0x93, 0xce, 0x69,
-	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0xaa, 0x40,
-	0x00, 0x65, 0x0e, 0x5b,
-	0xff, 0x06, 0x44, 0x09,
-	0x00, 0x65, 0xaa, 0x40,
-	0x10, 0x3d, 0x06, 0x00,
-	0xff, 0x34, 0xca, 0x08,
-	0x80, 0x65, 0x00, 0x62,
-	0x0f, 0xa1, 0xca, 0x08,
-	0x07, 0xa1, 0xca, 0x08,
-	0x40, 0xa0, 0xc8, 0x08,
-	0x00, 0x65, 0xca, 0x00,
-	0x80, 0x65, 0xca, 0x00,
-	0x80, 0xa0, 0xf0, 0x79,
-	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x02, 0x42,
-	0x20, 0xa0, 0x08, 0x7a,
-	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x9e, 0x5b,
-	0xa0, 0x3d, 0x10, 0x62,
-	0x23, 0xa0, 0x0c, 0x08,
-	0x00, 0x65, 0x9e, 0x5b,
-	0xa0, 0x3d, 0x10, 0x62,
-	0x00, 0xb9, 0x08, 0x42,
-	0xff, 0x65, 0x08, 0x62,
-	0xa1, 0x6a, 0x22, 0x01,
-	0xff, 0x6a, 0xd4, 0x08,
-	0x10, 0x51, 0x10, 0x72,
-	0x40, 0x6a, 0x18, 0x00,
-	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x9e, 0x5b,
-	0xa0, 0x3d, 0xda, 0x71,
-	0x40, 0x6a, 0x18, 0x00,
-	0xff, 0x34, 0xa6, 0x08,
-	0x80, 0x34, 0x18, 0x62,
-	0x7f, 0xa0, 0x40, 0x09,
-	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0xaa, 0x40,
-	0x64, 0x6a, 0xe4, 0x5a,
-	0x80, 0x64, 0x8e, 0x6a,
-	0x04, 0x64, 0x70, 0x72,
-	0x02, 0x64, 0x76, 0x72,
-	0x00, 0x6a, 0x38, 0x72,
-	0x03, 0x64, 0x8a, 0x72,
-	0x01, 0x64, 0x6c, 0x72,
-	0x07, 0x64, 0xcc, 0x72,
-	0x08, 0x64, 0x34, 0x72,
-	0x23, 0x64, 0xd0, 0x72,
-	0x11, 0x6a, 0x22, 0x01,
-	0x07, 0x6a, 0xd6, 0x5a,
-	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0xaa, 0x40,
-	0xff, 0xa8, 0x3c, 0x6a,
-	0xff, 0xa2, 0x54, 0x7a,
-	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xca, 0x5b,
-	0xff, 0xa2, 0x54, 0x7a,
-	0x71, 0x6a, 0x22, 0x01,
-	0xff, 0x6a, 0xd4, 0x08,
-	0x40, 0x51, 0x54, 0x62,
-	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xca, 0x5b,
-	0xff, 0x3e, 0x74, 0x09,
-	0xff, 0x90, 0x7c, 0x08,
-	0x00, 0x65, 0x4e, 0x58,
-	0x00, 0x65, 0xbc, 0x40,
-	0x20, 0xa0, 0x5c, 0x6a,
-	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0x74, 0x5b,
-	0xff, 0x6a, 0x8a, 0x5b,
-	0xff, 0xf8, 0xc8, 0x08,
-	0xff, 0x4f, 0xc8, 0x08,
-	0x01, 0x6a, 0x74, 0x5b,
-	0x00, 0xb9, 0x8a, 0x5b,
-	0x01, 0x4f, 0x9e, 0x18,
-	0x02, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x38, 0x5c,
-	0x00, 0x65, 0xbc, 0x40,
-	0x41, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xaa, 0x40,
-	0x04, 0xa0, 0x40, 0x01,
-	0x00, 0x65, 0x50, 0x5c,
-	0x00, 0x65, 0xbc, 0x40,
-	0x10, 0x36, 0x34, 0x7a,
-	0x05, 0x38, 0x46, 0x31,
-	0x04, 0x14, 0x58, 0x31,
-	0x03, 0xa9, 0x60, 0x31,
-	0xa3, 0x6a, 0xcc, 0x00,
-	0x38, 0x6a, 0xb0, 0x5b,
-	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xb2, 0x5b,
-	0xa9, 0x6a, 0xb4, 0x5b,
-	0x00, 0x65, 0x34, 0x42,
-	0xef, 0x36, 0x6c, 0x08,
-	0x00, 0x65, 0x34, 0x42,
-	0x0f, 0x64, 0xc8, 0x08,
-	0x07, 0x64, 0xc8, 0x08,
-	0x00, 0x37, 0x6e, 0x00,
-	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0x44, 0x5b,
-	0xff, 0x51, 0xa0, 0x72,
-	0x20, 0x36, 0xaa, 0x7a,
-	0x00, 0x90, 0x32, 0x5b,
-	0x00, 0x65, 0xac, 0x42,
-	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x9e, 0x5b,
-	0xe0, 0x3d, 0xc6, 0x62,
-	0x20, 0x12, 0xc6, 0x62,
-	0x51, 0x6a, 0xda, 0x5a,
-	0x00, 0x65, 0x2c, 0x5b,
-	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0xa1, 0xbe, 0x62,
-	0x04, 0xa0, 0xbe, 0x7a,
-	0xfb, 0xa0, 0x40, 0x09,
-	0x80, 0x36, 0x6c, 0x00,
-	0x80, 0xa0, 0x34, 0x7a,
-	0x7f, 0xa0, 0x40, 0x09,
-	0xff, 0x6a, 0xd6, 0x5a,
-	0x00, 0x65, 0x34, 0x42,
-	0x04, 0xa0, 0xc4, 0x7a,
-	0x00, 0x65, 0x50, 0x5c,
-	0x00, 0x65, 0xc6, 0x42,
-	0x00, 0x65, 0x38, 0x5c,
-	0x31, 0x6a, 0x22, 0x01,
-	0x0c, 0x6a, 0xd6, 0x5a,
-	0x00, 0x65, 0x34, 0x42,
-	0x61, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x34, 0x42,
-	0x51, 0x6a, 0xda, 0x5a,
-	0x51, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x34, 0x42,
-	0x10, 0x3d, 0x06, 0x00,
-	0xff, 0x65, 0x68, 0x0c,
-	0xff, 0x06, 0xd4, 0x08,
-	0x01, 0x0c, 0xdc, 0x7a,
-	0x04, 0x0c, 0xde, 0x6a,
-	0xe0, 0x03, 0x7a, 0x08,
-	0xe0, 0x3d, 0xea, 0x62,
-	0xff, 0x65, 0xcc, 0x08,
-	0xff, 0x12, 0xda, 0x0c,
-	0xff, 0x06, 0xd4, 0x0c,
-	0xd1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xaa, 0x40,
-	0xff, 0x65, 0x26, 0x09,
-	0x01, 0x0b, 0xfe, 0x6a,
-	0x10, 0x0c, 0xf0, 0x7a,
-	0x04, 0x0b, 0xf8, 0x6a,
-	0xff, 0x6a, 0xca, 0x08,
-	0x04, 0x93, 0xfc, 0x6a,
-	0x01, 0x94, 0xfa, 0x7a,
-	0x10, 0x94, 0xfc, 0x6a,
-	0x80, 0x3d, 0x02, 0x73,
-	0x0f, 0x04, 0x06, 0x6b,
-	0x02, 0x03, 0x06, 0x7b,
-	0x11, 0x0c, 0x02, 0x7b,
-	0xc7, 0x93, 0x26, 0x09,
-	0xff, 0x99, 0xd4, 0x08,
-	0x38, 0x93, 0x08, 0x6b,
-	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0x36, 0x0c, 0x6b,
-	0x21, 0x6a, 0x22, 0x05,
-	0xff, 0x65, 0x20, 0x09,
-	0xff, 0x51, 0x1a, 0x63,
-	0xff, 0x37, 0xc8, 0x08,
-	0xa1, 0x6a, 0x26, 0x43,
-	0xff, 0x51, 0xc8, 0x08,
-	0xb9, 0x6a, 0x26, 0x43,
-	0xff, 0x90, 0xa4, 0x08,
-	0xff, 0xba, 0x2a, 0x73,
-	0xff, 0xba, 0x20, 0x09,
-	0xff, 0x65, 0xca, 0x18,
-	0x00, 0x6c, 0x1e, 0x63,
-	0xff, 0x90, 0xca, 0x0c,
-	0xff, 0x6a, 0xca, 0x04,
-	0x20, 0x36, 0x3e, 0x7b,
-	0x00, 0x90, 0x12, 0x5b,
-	0xff, 0x65, 0x3e, 0x73,
-	0xff, 0x52, 0x3c, 0x73,
-	0xff, 0xba, 0xcc, 0x08,
-	0xff, 0x52, 0x20, 0x09,
-	0xff, 0x66, 0x74, 0x09,
-	0xff, 0x65, 0x20, 0x0d,
-	0xff, 0xba, 0x7e, 0x0c,
-	0x00, 0x6a, 0x3e, 0x5c,
-	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x51, 0xca, 0x43,
-	0xff, 0x3f, 0x98, 0x73,
-	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3f, 0x12, 0x5b,
-	0xff, 0x65, 0x98, 0x73,
-	0x20, 0x36, 0x6c, 0x00,
-	0x20, 0xa0, 0x52, 0x6b,
-	0xff, 0xb9, 0xa2, 0x0c,
-	0xff, 0x6a, 0xa2, 0x04,
-	0xff, 0x65, 0xa4, 0x08,
-	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xbe, 0x5b,
-	0x01, 0x6a, 0xd0, 0x01,
-	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0x5e, 0x7b,
-	0x01, 0x6a, 0xd6, 0x01,
-	0x01, 0xe9, 0xa4, 0x34,
-	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xbe, 0x5b,
-	0x01, 0x6a, 0x18, 0x01,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0x0d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x30, 0x5c,
-	0xff, 0x99, 0xa4, 0x0c,
-	0xff, 0x65, 0xa4, 0x08,
-	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xbe, 0x5b,
-	0x01, 0x6a, 0xd0, 0x01,
-	0x01, 0x6a, 0xdc, 0x05,
-	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0xbe, 0x5b,
-	0x01, 0x6a, 0x18, 0x01,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0x01, 0x6a, 0x26, 0x05,
-	0x01, 0x65, 0xd8, 0x31,
-	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x8e, 0x7b,
-	0xff, 0x6a, 0xdc, 0x0d,
-	0xff, 0x65, 0x32, 0x09,
-	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x30, 0x44,
-	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0x54, 0x5b,
-	0xff, 0x52, 0xa2, 0x0c,
-	0x01, 0x0c, 0x9e, 0x7b,
-	0x04, 0x0c, 0x9e, 0x6b,
-	0xe0, 0x03, 0x06, 0x08,
-	0xe0, 0x03, 0x7a, 0x0c,
-	0xff, 0x8c, 0x10, 0x08,
-	0xff, 0x8d, 0x12, 0x08,
-	0xff, 0x8e, 0x14, 0x0c,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x08,
-	0xff, 0x6c, 0xda, 0x0c,
-	0x3d, 0x64, 0xa4, 0x28,
-	0x55, 0x64, 0xc8, 0x28,
-	0x00, 0x6c, 0xda, 0x18,
-	0xff, 0x52, 0xc8, 0x08,
-	0x00, 0x6c, 0xda, 0x20,
-	0xff, 0x6a, 0xc8, 0x08,
-	0x00, 0x6c, 0xda, 0x20,
-	0x00, 0x6c, 0xda, 0x24,
-	0xff, 0x65, 0xc8, 0x08,
-	0xe0, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0xba, 0x5b,
-	0xff, 0x90, 0xe2, 0x09,
-	0x20, 0x6a, 0xd0, 0x01,
-	0x04, 0x35, 0xdc, 0x7b,
-	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0xd8, 0x63,
-	0x00, 0x65, 0xe8, 0x43,
-	0x01, 0x6a, 0xdc, 0x01,
-	0x20, 0xa0, 0xd8, 0x31,
-	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xe2, 0x7b,
-	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0xe6, 0x63,
-	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0xea, 0x6b,
-	0xff, 0x6a, 0xd4, 0x0c,
-	0x88, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0xba, 0x5b,
-	0x20, 0x6a, 0x18, 0x01,
-	0xff, 0x6a, 0x1a, 0x09,
-	0xff, 0x6a, 0x1c, 0x09,
-	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x35, 0x14, 0x6c,
-	0xa0, 0x6a, 0xca, 0x00,
-	0x20, 0x65, 0xc8, 0x18,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0xff, 0x6c, 0x32, 0x09,
-	0x00, 0x65, 0x00, 0x64,
-	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x30, 0x5c,
-	0x04, 0x35, 0x0c, 0x7b,
-	0xa0, 0x6a, 0x20, 0x5c,
-	0x00, 0x65, 0x22, 0x5c,
-	0x00, 0x65, 0x22, 0x5c,
-	0x00, 0x65, 0x22, 0x44,
-	0xff, 0x65, 0xcc, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x08,
-	0xff, 0x99, 0xda, 0x0c,
-	0x08, 0x94, 0x30, 0x7c,
-	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x34, 0x6c,
-	0xff, 0x6a, 0xd4, 0x0c,
-	0xff, 0x40, 0x74, 0x09,
-	0xff, 0x90, 0x80, 0x08,
-	0xff, 0x6a, 0x72, 0x05,
-	0xff, 0x40, 0x4c, 0x64,
-	0xff, 0x3f, 0x44, 0x64,
-	0xff, 0x6a, 0xca, 0x04,
-	0xff, 0x3f, 0x20, 0x09,
-	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0xca, 0x5b,
-	0xff, 0xba, 0x7e, 0x0c,
-	0xff, 0x40, 0x20, 0x09,
-	0xff, 0xba, 0x80, 0x0c,
-	0xff, 0x3f, 0x74, 0x09,
-	0xff, 0x90, 0x7e, 0x0c,
-};
-
-static int aic7xxx_patch12_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch12_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_WIDE) != 0);
-}
-
-static int aic7xxx_patch11_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch11_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_ULTRA2) == 0);
-}
-
-static int aic7xxx_patch10_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch10_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_CMD_CHAN) == 0);
-}
-
-static int aic7xxx_patch9_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch9_func(struct aic7xxx_host *p)
-{
-	return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
-}
-
-static int aic7xxx_patch8_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch8_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_ULTRA) != 0);
-}
-
-static int aic7xxx_patch7_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch7_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_ULTRA2) != 0);
-}
-
-static int aic7xxx_patch6_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch6_func(struct aic7xxx_host *p)
-{
-	return ((p->flags & AHC_PAGESCBS) == 0);
-}
-
-static int aic7xxx_patch5_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch5_func(struct aic7xxx_host *p)
-{
-	return ((p->flags & AHC_PAGESCBS) != 0);
-}
-
-static int aic7xxx_patch4_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch4_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_QUEUE_REGS) != 0);
-}
-
-static int aic7xxx_patch3_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch3_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_TWIN) != 0);
-}
-
-static int aic7xxx_patch2_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch2_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_QUEUE_REGS) == 0);
-}
-
-static int aic7xxx_patch1_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch1_func(struct aic7xxx_host *p)
-{
-	return ((p->features & AHC_CMD_CHAN) != 0);
-}
-
-static int aic7xxx_patch0_func(struct aic7xxx_host *p);
-
-static int
-aic7xxx_patch0_func(struct aic7xxx_host *p)
-{
-	return (0);
-}
-
-struct sequencer_patch {
-	int		(*patch_func)(struct aic7xxx_host *);
-	unsigned int	begin	   :10,
-			skip_instr :10,
-			skip_patch :12;
-} sequencer_patches[] = {
-	{ aic7xxx_patch1_func, 3, 2, 1 },
-	{ aic7xxx_patch2_func, 7, 1, 1 },
-	{ aic7xxx_patch2_func, 8, 1, 1 },
-	{ aic7xxx_patch3_func, 11, 4, 1 },
-	{ aic7xxx_patch4_func, 16, 3, 2 },
-	{ aic7xxx_patch0_func, 19, 4, 1 },
-	{ aic7xxx_patch5_func, 23, 1, 1 },
-	{ aic7xxx_patch6_func, 26, 1, 1 },
-	{ aic7xxx_patch1_func, 29, 1, 2 },
-	{ aic7xxx_patch0_func, 30, 3, 1 },
-	{ aic7xxx_patch3_func, 39, 4, 1 },
-	{ aic7xxx_patch7_func, 43, 3, 2 },
-	{ aic7xxx_patch0_func, 46, 3, 1 },
-	{ aic7xxx_patch8_func, 52, 7, 1 },
-	{ aic7xxx_patch3_func, 60, 3, 1 },
-	{ aic7xxx_patch7_func, 63, 2, 1 },
-	{ aic7xxx_patch7_func, 102, 1, 2 },
-	{ aic7xxx_patch0_func, 103, 2, 1 },
-	{ aic7xxx_patch7_func, 107, 2, 1 },
-	{ aic7xxx_patch9_func, 109, 1, 1 },
-	{ aic7xxx_patch10_func, 110, 2, 1 },
-	{ aic7xxx_patch7_func, 113, 1, 2 },
-	{ aic7xxx_patch0_func, 114, 1, 1 },
-	{ aic7xxx_patch1_func, 118, 1, 1 },
-	{ aic7xxx_patch1_func, 121, 3, 2 },
-	{ aic7xxx_patch0_func, 124, 5, 1 },
-	{ aic7xxx_patch1_func, 132, 2, 3 },
-	{ aic7xxx_patch7_func, 132, 1, 1 },
-	{ aic7xxx_patch0_func, 134, 3, 1 },
-	{ aic7xxx_patch11_func, 138, 1, 2 },
-	{ aic7xxx_patch0_func, 139, 1, 1 },
-	{ aic7xxx_patch7_func, 140, 7, 2 },
-	{ aic7xxx_patch0_func, 147, 1, 1 },
-	{ aic7xxx_patch1_func, 152, 14, 3 },
-	{ aic7xxx_patch11_func, 165, 1, 1 },
-	{ aic7xxx_patch0_func, 166, 9, 1 },
-	{ aic7xxx_patch7_func, 180, 2, 1 },
-	{ aic7xxx_patch7_func, 182, 1, 1 },
-	{ aic7xxx_patch11_func, 183, 6, 3 },
-	{ aic7xxx_patch1_func, 183, 2, 2 },
-	{ aic7xxx_patch0_func, 185, 4, 1 },
-	{ aic7xxx_patch7_func, 190, 1, 1 },
-	{ aic7xxx_patch7_func, 194, 20, 1 },
-	{ aic7xxx_patch1_func, 215, 3, 3 },
-	{ aic7xxx_patch11_func, 217, 1, 1 },
-	{ aic7xxx_patch0_func, 218, 5, 1 },
-	{ aic7xxx_patch11_func, 223, 1, 2 },
-	{ aic7xxx_patch0_func, 224, 9, 1 },
-	{ aic7xxx_patch12_func, 240, 1, 2 },
-	{ aic7xxx_patch0_func, 241, 1, 1 },
-	{ aic7xxx_patch4_func, 302, 1, 2 },
-	{ aic7xxx_patch0_func, 303, 1, 1 },
-	{ aic7xxx_patch2_func, 306, 1, 1 },
-	{ aic7xxx_patch1_func, 316, 3, 2 },
-	{ aic7xxx_patch0_func, 319, 5, 1 },
-	{ aic7xxx_patch12_func, 327, 1, 2 },
-	{ aic7xxx_patch0_func, 328, 1, 1 },
-	{ aic7xxx_patch5_func, 333, 1, 1 },
-	{ aic7xxx_patch11_func, 375, 15, 1 },
-	{ aic7xxx_patch1_func, 427, 7, 2 },
-	{ aic7xxx_patch0_func, 434, 8, 1 },
-	{ aic7xxx_patch1_func, 443, 4, 2 },
-	{ aic7xxx_patch0_func, 447, 6, 1 },
-	{ aic7xxx_patch1_func, 453, 4, 2 },
-	{ aic7xxx_patch0_func, 457, 3, 1 },
-	{ aic7xxx_patch10_func, 467, 10, 1 },
-	{ aic7xxx_patch1_func, 486, 17, 4 },
-	{ aic7xxx_patch9_func, 494, 4, 2 },
-	{ aic7xxx_patch0_func, 498, 2, 1 },
-	{ aic7xxx_patch0_func, 503, 33, 1 },
-	{ aic7xxx_patch10_func, 536, 4, 1 },
-	{ aic7xxx_patch5_func, 540, 2, 1 },
-	{ aic7xxx_patch5_func, 543, 9, 1 },
-
-};
diff -urN linux-2.2.19-pre8/fs/Config.in linux/fs/Config.in
--- linux-2.2.19-pre8/fs/Config.in	Mon Dec  3 20:59:33 2001
+++ linux/fs/Config.in	Mon Dec  3 21:00:04 2001
@@ -76,9 +76,11 @@
     bool '   Root file system on NFS' CONFIG_ROOT_NFS
   fi
   tristate 'NFS server support' CONFIG_NFSD
-  if [ "$CONFIG_NFSD" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    bool '   NFS Version 3 server support (EXPERIMENTAL)' CONFIG_NFSD_V3
-    bool '   NFS server TCP support (VERY EXPERIMENTAL)' CONFIG_NFSD_TCP
+  if [ "$CONFIG_NFSD" != "n" ]; then
+    bool '   NFS Version 3 server support' CONFIG_NFSD_V3
+    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool '   NFS server TCP support (VERY EXPERIMENTAL)' CONFIG_NFSD_TCP
+    fi
   fi
   if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
     define_bool CONFIG_SUNRPC y
diff -urN linux-2.2.19-pre8/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- linux-2.2.19-pre8/fs/binfmt_aout.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/binfmt_aout.c	Mon Dec  3 21:00:04 2001
@@ -112,7 +112,7 @@
 #       define START_STACK(u)   (u.start_stack)
 #endif
 
-	if (current->dumpable != 1 || atomic_read(&current->mm->count) != 1)
+	if (!current->dumpable || atomic_read(&current->mm->count) != 1)
 		return 0;
 	current->dumpable = 0;
 
diff -urN linux-2.2.19-pre8/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.2.19-pre8/fs/binfmt_elf.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/binfmt_elf.c	Mon Dec  3 21:00:04 2001
@@ -1089,7 +1089,7 @@
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
 	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
 
-	if (current->dumpable != 1 ||
+	if (!current->dumpable ||
 	    limit < ELF_EXEC_PAGESIZE ||
 	    atomic_read(&current->mm->count) != 1)
 		return 0;
diff -urN linux-2.2.19-pre8/fs/exec.c linux/fs/exec.c
--- linux-2.2.19-pre8/fs/exec.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/exec.c	Mon Dec  3 21:00:04 2001
@@ -517,8 +517,10 @@
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
+	current->dumpable = 0;
+	bprm->dumpable = 0;
 	if (current->euid == current->uid && current->egid == current->gid)
-		current->dumpable = 2;
+		bprm->dumpable = !bprm->priv_change;
 	name = bprm->filename;
 	for (i=0; (ch = *(name++)) != '\0';) {
 		if (ch == '/')
@@ -531,10 +533,10 @@
 
 	flush_thread();
 
-	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    permission(bprm->dentry->d_inode,MAY_READ))
-		current->dumpable = 0;
-		
+	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
+	    permission(bprm->dentry->d_inode, MAY_READ))
+		bprm->dumpable = 0;
+
 	current->self_exec_id++;
 
 	flush_signal_handlers(current);
@@ -646,7 +648,8 @@
 		}
 	}
 
-	if (id_change || cap_raised) {
+	bprm->priv_change = id_change || cap_raised;
+	if (bprm->priv_change) {
 		/* We can't suid-execute if we're sharing parts of the executable */
 		/* or if we're being traced (or if suid execs are not allowed)    */
 		/* (current->mm->count > 1 is ok, as we'll get a new mm anyway)   */
@@ -704,7 +707,7 @@
         current->sgid = current->egid = current->fsgid = bprm->e_gid;
         if (current->euid != current->uid || current->egid != current->gid ||
 	    !cap_issubset(new_permitted, current->cap_permitted))
-                current->dumpable = 0;
+                bprm->dumpable = 0;
 
         current->keep_capabilities = 0;
 }
@@ -865,9 +868,8 @@
 	if (retval >= 0)
 		retval = search_binary_handler(&bprm,regs);
 
-	if(current->dumpable == 2)
-		current->dumpable = 1;
-		
+	current->dumpable = bprm.dumpable;
+
 	if (retval >= 0)
 		/* execve success */
 		return retval;
@@ -879,6 +881,5 @@
 	for (i=0 ; i<MAX_ARG_PAGES ; i++)
 		free_page(bprm.page[i]);
 
-		
 	return retval;
 }
diff -urN linux-2.2.19-pre8/fs/nfsd/auth.c linux/fs/nfsd/auth.c
--- linux-2.2.19-pre8/fs/nfsd/auth.c	Tue Dec 29 11:42:25 1998
+++ linux/fs/nfsd/auth.c	Mon Dec  3 21:00:04 2001
@@ -10,6 +10,7 @@
 #include <linux/sunrpc/svcauth.h>
 #include <linux/nfsd/nfsd.h>
 
+#define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
 void
 nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
@@ -50,10 +51,10 @@
 	current->ngroups = i;
 
 	if ((cred->cr_uid)) {
-		cap_t(current->cap_effective) &= ~CAP_FS_MASK;
+		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
 	} else {
-		cap_t(current->cap_effective) |= (CAP_FS_MASK &
-		                                  current->cap_permitted);
+		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
+						  current->cap_permitted);
 	}
 
 	rqstp->rq_userset = 1;
diff -urN linux-2.2.19-pre8/fs/nfsd/export.c linux/fs/nfsd/export.c
--- linux-2.2.19-pre8/fs/nfsd/export.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/export.c	Mon Dec  3 21:00:04 2001
@@ -9,8 +9,6 @@
  * creates a client control block and adds it to the hash
  * table. Then, you call NFSCTL_EXPORT for each fs.
  *
- * You cannot currently read the export information from the
- * kernel. It would be nice to have a /proc file though.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
  */
@@ -447,7 +445,7 @@
 	if (path) {
 		if (!(dentry = lookup_dentry(path, NULL, 0))) {
 			printk("nfsd: exp_rootfh path not found %s", path);
-			return -EPERM;
+			return err;
 		}
 		dev = dentry->d_inode->i_dev;
 		ino = dentry->d_inode->i_ino;
@@ -611,7 +609,7 @@
 	{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
 	{ NFSEXP_CROSSMNT, {"nohide", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
-	{ NFSEXP_NOAUTHNLM, {"no_auth_nlm", ""}},
+	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
 	{ 0, {"", ""}}
 };
 
diff -urN linux-2.2.19-pre8/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c
--- linux-2.2.19-pre8/fs/nfsd/nfs3proc.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfs3proc.c	Mon Dec  3 21:00:04 2001
@@ -29,7 +29,7 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-#define RETURN(st)	{ resp->status = (st); return (st); }
+#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
 
 static int	nfs3_ftypes[] = {
 	0,			/* NF3NON */
@@ -76,7 +76,7 @@
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -94,7 +94,7 @@
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -116,7 +116,7 @@
 				    argp->name,
 				    argp->len,
 				    &resp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -136,7 +136,7 @@
 	fh_copy(&resp->fh, &argp->fh);
 	resp->access = argp->access;
 	nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -161,7 +161,7 @@
 	fh_copy(&resp->fh, &argp->fh);
 	resp->len = NFS3_MAXPATHLEN;
 	nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -202,7 +202,7 @@
 		resp->eof = (argp->offset + resp->count) >= inode->i_size;
 	}
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -222,14 +222,14 @@
 				argp->stable? " stable" : "");
 
 	fh_copy(&resp->fh, &argp->fh);
+	resp->committed = argp->stable;
 	nfserr = nfsd_write(rqstp, &resp->fh,
 				   argp->offset,
 				   argp->data,
 				   argp->len,
-				   argp->stable);
-	resp->committed = argp->stable;
+				   &resp->committed);
 	resp->count = argp->count;
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -257,7 +257,7 @@
 	/* Get the directory inode */
 	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
 	if (nfserr)
-		RETURN(nfserr);
+		RETURN_STATUS(nfserr);
 
 	/* Unfudge the mode bits */
 	attr->ia_mode &= ~S_IFMT;
@@ -273,7 +273,7 @@
 				attr, newfhp,
 				argp->createmode, argp->verf);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -296,7 +296,7 @@
 	nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 				    &argp->attrs, S_IFDIR, 0, &resp->fh);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -315,7 +315,7 @@
 	nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
 						   argp->tname, argp->tlen,
 						   &resp->fh, &argp->attrs);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -337,22 +337,22 @@
 	fh_init(&resp->fh);
 
 	if (argp->ftype == 0 || argp->ftype >= NF3BAD)
-		return nfserr_inval;
+		RETURN_STATUS(nfserr_inval);
 	if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
 		if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV)
 		    || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
 		    || argp->minor > 0xFF)
-			return nfserr_inval;
+			RETURN_STATUS(nfserr_inval);
 		rdev = ((argp->major) << 8) | (argp->minor);
 	} else
 		if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
-			return nfserr_inval;
+			RETURN_STATUS(nfserr_inval);
 
 	type = nfs3_ftypes[argp->ftype];
 	nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 				    &argp->attrs, type, rdev, &resp->fh);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -372,7 +372,7 @@
 	/* Unlink. -S_IFDIR means file must not be a directory */
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -391,7 +391,7 @@
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -412,7 +412,7 @@
 	fh_copy(&resp->tfh, &argp->tfh);
 	nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
 				    &resp->tfh, argp->tname, argp->tlen);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -432,7 +432,7 @@
 	fh_copy(&resp->tfh, &argp->tfh);
 	nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
 				  &resp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -468,7 +468,7 @@
 	memcpy(resp->verf, argp->verf, 8);
 	resp->count = count;
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -504,7 +504,7 @@
 	memcpy(resp->verf, argp->verf, 8);
 	resp->count = count;
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -522,7 +522,7 @@
 
 	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -563,7 +563,7 @@
 	}
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -606,7 +606,7 @@
 	}
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 
@@ -626,12 +626,12 @@
 				(unsigned long) argp->offset);
 
 	if (argp->offset > NFS_OFFSET_MAX)
-		return nfserr_inval;
+		RETURN_STATUS(nfserr_inval);
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 
diff -urN linux-2.2.19-pre8/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- linux-2.2.19-pre8/fs/nfsd/nfs3xdr.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfs3xdr.c	Mon Dec  3 21:00:04 2001
@@ -36,17 +36,6 @@
 	NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
 };
 
-/*
- * XDR functions for basic NFS types
- */
-static inline u32 *
-dec64(u32 *p, u64 *valp)
-{
-	*valp  = ((u64) ntohl(*p++)) << 32;
-	*valp |= ntohl(*p++);
-	return p;
-}
-
 static inline u32 *
 encode_time3(u32 *p, time_t secs)
 {
@@ -140,7 +129,7 @@
 		u64	newsize;
 
 		iap->ia_valid |= ATTR_SIZE;
-		p = dec64(p, &newsize);
+		p = xdr_decode_hyper(p, &newsize);
 		if (newsize <= NFS_OFFSET_MAX)
 			iap->ia_size = (u32) newsize;
 		else
@@ -177,24 +166,24 @@
 	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
 	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
 	if (S_ISLNK(inode->i_mode) && inode->i_size > NFS3_MAXPATHLEN) {
-		p = enc64(p, (u64) NFS3_MAXPATHLEN);
+		p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
 	} else {
-		p = enc64(p, (u64) inode->i_size);
+		p = xdr_encode_hyper(p, (u64) inode->i_size);
 	}
 	/*
 	 *  For the 'used' member, we take i_blocks if set; assuming 512-byte
 	 *  units.  Some FSs don't set this, so all we can do then is
 	 *  use the size.
 	 */
-	if (inode->i_blocks) {
-		p = enc64(p,  ((u64)inode->i_blocks)<<9 );
-	} else {
-		p = enc64(p, (u64) inode->i_size);
-	}
+	if (inode->i_blocks)
+		p = xdr_encode_hyper(p,  ((u64)inode->i_blocks)<<9 );
+	else
+		p = xdr_encode_hyper(p, (u64) inode->i_size);
+
 	*p++ = htonl((u32) MAJOR(inode->i_rdev));
 	*p++ = htonl((u32) MINOR(inode->i_rdev));
-	p = enc64(p, (u64) inode->i_dev);
-	p = enc64(p, (u64) inode->i_ino);
+	p = xdr_encode_hyper(p, (u64) inode->i_dev);
+	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, inode->i_atime);
 	p = encode_time3(p, inode->i_mtime);
 	p = encode_time3(p, inode->i_ctime);
@@ -216,19 +205,19 @@
 	*p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
 	*p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
 	if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
-		p = enc64(p, (u64) NFS3_MAXPATHLEN);
+		p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
 	} else {
-		p = enc64(p, (u64) fhp->fh_post_size);
+		p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
 	}
 	if (fhp->fh_post_blocks) {
-		p = enc64(p, ((u64)fhp->fh_post_blocks)<<9);
+		p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks)<<9);
 	} else {
-		p = enc64(p, (u64) fhp->fh_post_size);
+		p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
 	}
 	*p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
 	*p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
-	p = enc64(p, (u64) inode->i_dev);
-	p = enc64(p, (u64) inode->i_ino);
+	p = xdr_encode_hyper(p, (u64) inode->i_dev);
+	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, fhp->fh_post_atime);
 	p = encode_time3(p, fhp->fh_post_mtime);
 	p = encode_time3(p, fhp->fh_post_ctime);
@@ -263,7 +252,7 @@
 	if (dentry && dentry->d_inode && fhp->fh_post_saved) {
 		if (fhp->fh_pre_saved) {
 			*p++ = xdr_one;
-			p = enc64(p, (u64) fhp->fh_pre_size);
+			p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
 			p = encode_time3(p, fhp->fh_pre_mtime);
 			p = encode_time3(p, fhp->fh_pre_ctime);
 		} else {
@@ -350,7 +339,7 @@
 					struct nfsd3_readargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = dec64(p, &args->offset)))
+	 || !(p = xdr_decode_hyper(p, &args->offset)))
 		return 0;
 
 	args->count = ntohl(*p++);
@@ -362,7 +351,7 @@
 					struct nfsd3_writeargs *args)
 {
 	if (!(p = decode_fh(p, &args->fh))
-	 || !(p = dec64(p, &args->offset)))
+	 || !(p = xdr_decode_hyper(p, &args->offset)))
 		return 0;
 
 	args->count = ntohl(*p++);
@@ -478,7 +467,7 @@
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
-	p = dec64(p, &args->cookie);
+	p = xdr_decode_hyper(p, &args->cookie);
 	args->verf   = p; p += 2;
 	args->dircount = ~0;
 	args->count  = ntohl(*p++);
@@ -492,7 +481,7 @@
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
-	p = dec64(p, &args->cookie);
+	p = xdr_decode_hyper(p, &args->cookie);
 	args->verf     = p; p += 2;
 	args->dircount = ntohl(*p++);
 	args->count    = ntohl(*p++);
@@ -506,7 +495,7 @@
 {
 	if (!(p = decode_fh(p, &args->fh)))
 		return 0;
-	p = dec64(p, &args->offset);
+	p = xdr_decode_hyper(p, &args->offset);
 	args->count = ntohl(*p++);
 
 	return xdr_argsize_check(rqstp, p);
@@ -682,7 +671,7 @@
 	int		buflen, slen, elen;
 
 	if (cd->offset)
-		enc64(cd->offset, (u64) offset);
+		xdr_encode_hyper(cd->offset, (u64) offset);
 
 	/* nfsd_readdir calls us with name == 0 when it wants us to
 	 * set the last offset entry. */
@@ -705,20 +694,12 @@
 		cd->eob = 1;
 		return -EINVAL;
 	}
-	*p++ = xdr_one;				   /* mark entry present */
-	p    = enc64(p, ino);			   /* file id */
-#ifdef XDR_ENCODE_STRING_TAKES_LENGTH
-	p    = xdr_encode_string(p, name, namlen); /* name length & name */
-#else
-	/* just like nfsproc.c */
-	*p++ = htonl((u32) namlen);
-	p[slen - 1] = 0;		/* don't leak kernel data */
-	memcpy(p, name, namlen);
-	p += slen;
-#endif
+	*p++ = xdr_one;				  /* mark entry present */
+	p    = xdr_encode_hyper(p, ino);	  /* file id */
+	p    = xdr_encode_string(p, name, namlen);/* name length & name */
 
 	cd->offset = p;			/* remember pointer */
-	p = enc64(p, NFS_OFFSET_MAX);	/* offset of next entry */
+	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);	/* offset of next entry */
 
 	/* throw in readdirplus baggage */
 	if (plus) {
@@ -769,12 +750,12 @@
 	*p++ = xdr_zero;	/* no post_op_attr */
 
 	if (resp->status == 0) {
-		p = enc64(p, bs * s->f_blocks);	/* total bytes */
-		p = enc64(p, bs * s->f_bfree);	/* free bytes */
-		p = enc64(p, bs * s->f_bavail);	/* user available bytes */
-		p = enc64(p, s->f_files);	/* total inodes */
-		p = enc64(p, s->f_ffree);	/* free inodes */
-		p = enc64(p, s->f_ffree);	/* user available inodes */
+		p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
+		p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
+		p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
+		p = xdr_encode_hyper(p, s->f_files);	/* total inodes */
+		p = xdr_encode_hyper(p, s->f_ffree);	/* free inodes */
+		p = xdr_encode_hyper(p, s->f_ffree);	/* user available inodes */
 		*p++ = htonl(resp->invarsec);	/* mean unchanged time */
 	}
 	return xdr_ressize_check(rqstp, p);
@@ -795,7 +776,7 @@
 		*p++ = htonl(resp->f_wtpref);
 		*p++ = htonl(resp->f_wtmult);
 		*p++ = htonl(resp->f_dtpref);
-		p = enc64(p, resp->f_maxfilesize);
+		p = xdr_encode_hyper(p, resp->f_maxfilesize);
 		*p++ = xdr_one;
 		*p++ = xdr_zero;
 		*p++ = htonl(resp->f_properties);
diff -urN linux-2.2.19-pre8/fs/nfsd/nfscache.c linux/fs/nfsd/nfscache.c
--- linux-2.2.19-pre8/fs/nfsd/nfscache.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfscache.c	Mon Dec  3 21:00:04 2001
@@ -217,13 +217,12 @@
 found_entry:
 	/* We found a matching entry which is either in progress or done. */
 	age = jiffies - rp->c_timestamp;
+	rp->c_timestamp = jiffies;
+	lru_put_front(rp);
 
 	/* Request being processed or excessive rexmits */
 	if (rp->c_state == RC_INPROG || age < RC_DELAY)
 		return RC_DROPIT;
-
-	rp->c_timestamp = jiffies;
-	lru_put_front(rp);
 
 	/* From the hall of fame of impractical attacks:
 	 * Is this a user who tries to snoop on the cache? */
diff -urN linux-2.2.19-pre8/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- linux-2.2.19-pre8/fs/nfsd/nfsctl.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfsctl.c	Mon Dec  3 21:00:04 2001
@@ -131,7 +131,6 @@
 static void
 nfsd_init(void)
 {
-	nfsd_xdr_init();	/* XDR */
 	nfsd_stat_init();	/* Statistics */
 	nfsd_cache_init();	/* RPC reply cache */
 	nfsd_export_init();	/* Exports table */
diff -urN linux-2.2.19-pre8/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- linux-2.2.19-pre8/fs/nfsd/nfsfh.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfsfh.c	Mon Dec  3 21:00:04 2001
@@ -183,7 +183,6 @@
 	if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
 		printk("nfsd: d_splice with non-DISCONNECTED target: %s/%s\n", parent->d_name.name, name->name);
 #endif
-	name->hash = full_name_hash(name->name, name->len);
 	tdentry = d_alloc(parent, name);
 	if (tdentry == NULL)
 		return -ENOMEM;
@@ -275,7 +274,6 @@
 	struct qstr qs;
 	char namebuf[256];
 	struct list_head *lp;
-	struct dentry *tmp;
 	/* child is an IS_ROOT (anonymous) dentry, but it is hypothesised that
 	 * it should be a child of parent.
 	 * We see if we can find a name and, if we can - splice it in.
@@ -295,8 +293,8 @@
 	 * parent by a lookup.  In this case return that dentry. 
 	 * caller must notice and act accordingly
 	 */
-	for (lp = child->d_inode->i_dentry.next; lp != &child->d_inode->i_dentry ; lp=lp->next) {
-		tmp = list_entry(lp,struct dentry, d_alias);
+	list_for_each(lp, &child->d_inode->i_dentry) {
+		struct dentry *tmp = list_entry(lp,struct dentry, d_alias);
 		if (tmp->d_parent == parent) {
 			child = dget(tmp);
 			goto out;
@@ -308,12 +306,12 @@
 	err = get_ino_name(parent, &qs, child->d_inode->i_ino);
 	if (err)
 		goto out;
-	tmp = d_lookup(parent, &qs);
-	if (tmp) {
+
+	/* find_inode_number calculates the name hash as a side effect */
+	if (find_inode_number(parent, &qs) != 0) {
 		/* Now that IS odd.  I wonder what it means... */
 		err = -EEXIST;
 		printk("nfsd-fh: found a name that I didn't expect: %s/%s\n", parent->d_name.name, qs.name);
-		dput(tmp);
 		goto out;
 	}
 	err = d_splice(child, parent, &qs);
@@ -339,7 +337,7 @@
 	struct dentry *dentry, *result = NULL;
 	struct dentry *tmp;
 	int  found =0;
-	int err;
+	int err = -ESTALE;
 	/* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free)
 	 * dcache path ever exists, as otherwise two partial paths might get
 	 * joined together, which would be very confusing.
@@ -353,23 +351,21 @@
 	 * Attempt to find the inode.
 	 */
  retry:
+	down(&sb->s_nfsd_free_path_sem);
 	result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
-	err = PTR_ERR(result);
-	if (IS_ERR(result))
-		goto err_out;
-	err = -ESTALE;
-	if (!result) {
-		dprintk("find_fh_dentry: No inode found.\n");
-		goto err_out;
-	}
-	if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED))
-		return result;
-
-	/* result is now an anonymous dentry, which may be adequate as it 
-	 * stands, or else will get spliced into the dcache tree */
-
-	if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) {
-		nfsdstats.fh_anon++;
+	if (!result || IS_ERR(result)
+	    || !(result->d_flags & DCACHE_NFSD_DISCONNECTED)
+	    || (!S_ISDIR(result->d_inode->i_mode) && !needpath)) {
+		up(&sb->s_nfsd_free_path_sem);
+		if (!result) {
+			dprintk("find_fh_dentry: No inode found.\n");
+			goto err_out;
+		}
+		err = PTR_ERR(result);
+		if (IS_ERR(result))
+			goto err_out;
+		if ( (result->d_flags & DCACHE_NFSD_DISCONNECTED))
+			nfsdstats.fh_anon++;
 		return result;
 	}
 
@@ -377,14 +373,6 @@
 	 * location in the tree.
 	 */
 	dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
-	down(&sb->s_nfsd_free_path_sem);
-
-	/* claiming the semaphore might have allow things to get fixed up */
-	if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-		up(&sb->s_nfsd_free_path_sem);
-		return result;
-	}
-
 
 	found = 0;
 	if (!S_ISDIR(result->d_inode->i_mode)) {
@@ -466,6 +454,7 @@
 		if (tmp != dentry) {
 			/* we lost a race,  try again
 			 */
+			dput(pdentry);
 			dput(tmp);
 			dput(dentry);
 			dput(result);	/* this will discard the whole free path, so we can up the semaphore */
@@ -563,7 +552,7 @@
 					!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
 
 		if (IS_ERR(dentry)) {
-			error = nfserrno(-PTR_ERR(dentry));
+			error = nfserrno(PTR_ERR(dentry));
 			goto out;
 		}
 #ifdef NFSD_PARANOIA
diff -urN linux-2.2.19-pre8/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- linux-2.2.19-pre8/fs/nfsd/nfsproc.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfsproc.c	Mon Dec  3 21:00:04 2001
@@ -30,10 +30,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-/* Check for dir entries '.' and '..' */
-#define isdotent(n, l)	(l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
-
-#define RETURN(st)	return st
 
 static void
 svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
@@ -45,7 +41,7 @@
 static int
 nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
-	RETURN(nfs_ok);
+	return nfs_ok;
 }
 
 /*
@@ -60,7 +56,7 @@
 		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
-	RETURN(fh_verify(rqstp, &resp->fh, 0, MAY_NOP));
+	return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
 }
 
 /*
@@ -76,7 +72,7 @@
 		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
 
 	fh_copy(&resp->fh, &argp->fh);
-	RETURN(nfsd_setattr(rqstp, &resp->fh, &argp->attrs));
+	return nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
 }
 
 /*
@@ -98,7 +94,7 @@
 				 &resp->fh);
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -121,7 +117,7 @@
 	nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -159,7 +155,7 @@
 				  (char *) buffer,
 				  &resp->count);
 
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -171,6 +167,7 @@
 					struct nfsd_attrstat  *resp)
 {
 	int	nfserr;
+	int	stable = 1;
 
 	dprintk("nfsd: WRITE    %d/%d %d bytes at %d\n",
 		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
@@ -180,8 +177,8 @@
 				   argp->offset,
 				   argp->data,
 				   argp->len,
-				   0);
-	RETURN(nfserr);
+				   &stable);
+	return nfserr;
 }
 
 /*
@@ -257,8 +254,19 @@
 	if (attr->ia_valid & ATTR_MODE) { 
 		type = attr->ia_mode & S_IFMT;
 		mode = attr->ia_mode & ~S_IFMT;
-		if (!type)	/* HP weirdness */
-			type = S_IFREG;
+		if (!type) {
+			/* no type, so if target exists, assume same as that,
+			 * else assume a file */
+			if (inode) {
+				type = inode->i_mode & S_IFMT;
+				if (type == S_IFCHR || type == S_IFBLK) {
+					/* reserve rdev for later checking */
+					attr->ia_size = inode->i_rdev;
+					attr->ia_valid |= ATTR_SIZE;
+				}
+			} else
+				type = S_IFREG;
+		}
 	} else if (inode) {
 		type = inode->i_mode & S_IFMT;
 		mode = inode->i_mode & ~S_IFMT;
@@ -331,7 +339,7 @@
 
 done:
 	fh_put(dirfhp);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -345,7 +353,7 @@
 	/* Unlink. -SIFDIR means file must not be a directory */
 	nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -362,7 +370,7 @@
 				    &argp->tfh, argp->tname, argp->tlen);
 	fh_put(&argp->ffh);
 	fh_put(&argp->tfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -380,7 +388,7 @@
 				  &argp->ffh);
 	fh_put(&argp->ffh);
 	fh_put(&argp->tfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -404,7 +412,7 @@
 
 	fh_put(&argp->ffh);
 	fh_put(&newfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -428,7 +436,7 @@
 	nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
 				    &argp->attrs, S_IFDIR, 0, &resp->fh);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -444,7 +452,7 @@
 
 	nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -480,7 +488,7 @@
 	resp->count = count;
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -496,7 +504,7 @@
 
 	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -549,36 +557,36 @@
 		int	nfserr;
 		int	syserr;
 	} nfs_errtbl[] = {
-		{ NFS_OK, 0 },
-		{ NFSERR_PERM, EPERM },
-		{ NFSERR_NOENT, ENOENT },
-		{ NFSERR_IO, EIO },
-		{ NFSERR_NXIO, ENXIO },
-		{ NFSERR_ACCES, EACCES },
-		{ NFSERR_EXIST, EEXIST },
-		{ NFSERR_XDEV, EXDEV },
-		{ NFSERR_MLINK, EMLINK },
-		{ NFSERR_NODEV, ENODEV },
-		{ NFSERR_NOTDIR, ENOTDIR },
-		{ NFSERR_ISDIR, EISDIR },
-		{ NFSERR_INVAL, EINVAL },
-		{ NFSERR_FBIG, EFBIG },
-		{ NFSERR_NOSPC, ENOSPC },
-		{ NFSERR_ROFS, EROFS },
-		{ NFSERR_MLINK, EMLINK },
-		{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
-		{ NFSERR_NOTEMPTY, ENOTEMPTY },
+		{ nfs_ok, 0 },
+		{ nfserr_perm, -EPERM },
+		{ nfserr_noent, -ENOENT },
+		{ nfserr_io, -EIO },
+		{ nfserr_nxio, -ENXIO },
+		{ nfserr_acces, -EACCES },
+		{ nfserr_exist, -EEXIST },
+		{ nfserr_xdev, -EXDEV },
+		{ nfserr_mlink, -EMLINK },
+		{ nfserr_nodev, -ENODEV },
+		{ nfserr_notdir, -ENOTDIR },
+		{ nfserr_isdir, -EISDIR },
+		{ nfserr_inval, -EINVAL },
+		{ nfserr_fbig, -EFBIG },
+		{ nfserr_nospc, -ENOSPC },
+		{ nfserr_rofs, -EROFS },
+		{ nfserr_mlink, -EMLINK },
+		{ nfserr_nametoolong, -ENAMETOOLONG },
+		{ nfserr_notempty, -ENOTEMPTY },
 #ifdef EDQUOT
-		{ NFSERR_DQUOT, EDQUOT },
+		{ nfserr_dquot, -EDQUOT },
 #endif
-		{ NFSERR_STALE, ESTALE },
-		{ -1, EIO }
+		{ nfserr_stale, -ESTALE },
+		{ -1, -EIO }
 	};
 	int	i;
 
 	for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
 		if (nfs_errtbl[i].syserr == errno)
-			return htonl(nfs_errtbl[i].nfserr);
+			return nfs_errtbl[i].nfserr;
 	}
 	printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
 	return nfserr_io;
diff -urN linux-2.2.19-pre8/fs/nfsd/nfsxdr.c linux/fs/nfsd/nfsxdr.c
--- linux-2.2.19-pre8/fs/nfsd/nfsxdr.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/nfsxdr.c	Mon Dec  3 21:00:04 2001
@@ -17,15 +17,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
-u32	nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
-	nfserr_acces, nfserr_exist, nfserr_xdev, nfserr_nodev,
-	nfserr_notdir, nfserr_isdir, nfserr_inval, nfserr_fbig,
-	nfserr_nospc, nfserr_rofs, nfserr_mlink,
-	nfserr_nametoolong, nfserr_notempty, nfserr_dquot, nfserr_stale,
-	nfserr_remote, nfserr_badhandle, nfserr_notsync,
-	nfserr_badcookie, nfserr_notsupp, nfserr_toosmall,
-	nfserr_serverfault, nfserr_badtype, nfserr_jukebox;
-
 
 #ifdef NFSD_OPTIMIZE_SPACE
 # define inline
@@ -35,57 +26,12 @@
  * Mapping of S_IF* types to NFS file types
  */
 static u32	nfs_ftypes[] = {
-	NFNON,  NFFIFO, NFCHR, NFBAD,
+	NFNON,  NFCHR,  NFCHR, NFBAD,
 	NFDIR,  NFBAD,  NFBLK, NFBAD,
 	NFREG,  NFBAD,  NFLNK, NFBAD,
 	NFSOCK, NFBAD,  NFLNK, NFBAD,
 };
 
-/*
- * Initialization of NFS status variables
- */
-void
-nfsd_xdr_init(void)
-{
-	static int	inited = 0;
-
-	if (inited)
-		return;
-
-	nfs_ok		= htonl(NFS_OK);
-	nfserr_perm	= htonl(NFSERR_PERM);
-	nfserr_noent	= htonl(NFSERR_NOENT);
-	nfserr_io	= htonl(NFSERR_IO);
-	nfserr_inval	= htonl(NFSERR_INVAL);
-	nfserr_nxio	= htonl(NFSERR_NXIO);
-	nfserr_acces	= htonl(NFSERR_ACCES);
-	nfserr_exist	= htonl(NFSERR_EXIST);
-	nfserr_xdev	= htonl(NFSERR_XDEV);
-	nfserr_nodev	= htonl(NFSERR_NODEV);
-	nfserr_notdir	= htonl(NFSERR_NOTDIR);
-	nfserr_isdir	= htonl(NFSERR_ISDIR);
-	nfserr_inval	= htonl(NFSERR_INVAL);
-	nfserr_fbig	= htonl(NFSERR_FBIG);
-	nfserr_nospc	= htonl(NFSERR_NOSPC);
-	nfserr_rofs	= htonl(NFSERR_ROFS);
-	nfserr_mlink	= htonl(NFSERR_MLINK);
-	nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
-	nfserr_notempty	= htonl(NFSERR_NOTEMPTY);
-	nfserr_dquot	= htonl(NFSERR_DQUOT);
-	nfserr_stale	= htonl(NFSERR_STALE);
-	nfserr_remote	= htonl(NFSERR_REMOTE);
-	nfserr_badhandle = htonl(NFSERR_BADHANDLE);
-	nfserr_notsync	= htonl(NFSERR_NOT_SYNC);
-	nfserr_badcookie = htonl(NFSERR_BAD_COOKIE);
-	nfserr_notsupp	= htonl(NFSERR_NOTSUPP);
-	nfserr_toosmall	= htonl(NFSERR_TOOSMALL);
-	nfserr_serverfault = htonl(NFSERR_SERVERFAULT);
-	nfserr_badtype	= htonl(NFSERR_BADTYPE);
-	nfserr_jukebox	= htonl(NFSERR_JUKEBOX);
-
-
-	inited = 1;
-}
 
 /*
  * XDR functions for basic NFS types
@@ -189,20 +135,25 @@
 static inline u32 *
 encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
 {
+	int type = (inode->i_mode & S_IFMT);
 	if (!inode)
 		return 0;
-	*p++ = htonl(nfs_ftypes[(inode->i_mode & S_IFMT) >> 12]);
+	*p++ = htonl(nfs_ftypes[type >> 12]);
 	*p++ = htonl((u32) inode->i_mode);
 	*p++ = htonl((u32) inode->i_nlink);
 	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
 	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
-	if (S_ISLNK(inode->i_mode) && inode->i_size > NFS_MAXPATHLEN) {
+
+	if (S_ISLNK(type) && inode->i_size > NFS_MAXPATHLEN) {
 		*p++ = htonl(NFS_MAXPATHLEN);
 	} else {
 		*p++ = htonl((u32) inode->i_size);
 	}
 	*p++ = htonl((u32) inode->i_blksize);
-	*p++ = htonl((u32) inode->i_rdev);
+	if (S_ISCHR(type) || S_ISBLK(type))
+		*p++ = htonl((u32) inode->i_rdev);
+	else
+		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) inode->i_blocks);
 	*p++ = htonl((u32) inode->i_dev);
 	*p++ = htonl((u32) inode->i_ino);
@@ -465,11 +416,9 @@
 		cd->eob = 1;
 		return -EINVAL;
 	}
-	*p++ = xdr_one;			/* mark entry present */
-	*p++ = htonl((u32) ino);	/* file id */
-	*p++ = htonl((u32) namlen);	/* name length & name */
-	memcpy(p, name, namlen);
-	p += slen;
+	*p++ = xdr_one;				/* mark entry present */
+	*p++ = htonl((u32) ino);		/* file id */
+	p    = xdr_encode_string(p, name, namlen);/* name length & name */
 	cd->offset = p;			/* remember pointer */
 	*p++ = ~(u32) 0;		/* offset of next entry */
 
diff -urN linux-2.2.19-pre8/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- linux-2.2.19-pre8/fs/nfsd/vfs.c	Sun Dec 10 16:49:44 2000
+++ linux/fs/nfsd/vfs.c	Mon Dec  3 21:00:04 2001
@@ -59,9 +59,6 @@
  */
 extern long nfsd_time_diff_margin;
 
-/* Check for dir entries '.' and '..' */
-#define isdotent(n, l)	(l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
-
 /*
  * This is a cache of readahead params that help us choose the proper
  * readahead strategy. Initially, we set all readahead parameters to 0
@@ -157,15 +154,12 @@
 	dparent = fhp->fh_dentry;
 	exp  = fhp->fh_export;
 
-#if 0
-	err = nfsd_permission(exp, dparent, MAY_EXEC);
-	if (err)
-		goto out;
-#endif
 	err = nfserr_acces;
 
 	/* Lookup the name, but don't follow links */
-	if (strcmp(name, "..")==0) {
+	if (strcmp(name, ".")==0) {
+		dchild = dget(dparent);
+	} else if (strcmp(name, "..")==0) {
 		/* checking mountpoint crossing is very different when stepping up */
 		if (dparent == exp->ex_dentry) {
 			if (!EX_CROSSMNT(exp))
@@ -230,7 +224,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-PTR_ERR(dchild));
+	err = nfserrno(PTR_ERR(dchild));
 	goto out;
 }
 
@@ -283,11 +277,11 @@
 	    if (delta<0) delta = -delta;
 	    if (delta < MAX_TOUCH_TIME_ERROR) {
 		/* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
-		 * this will cause notify_change to setthese times to "now"
+		 * this will cause notify_change to set these times to "now"
 		 */
 		iap->ia_valid &= ~BOTH_TIME_SET;
 		err = inode_change_ok(inode, iap);
-		}
+	    }
 	}
 
 	if (err)
@@ -295,8 +289,6 @@
 
 	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
-if (!S_ISREG(inode->i_mode))
-printk("nfsd_setattr: size change??\n");
 		if (iap->ia_size < inode->i_size) {
 			err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC);
 			if (err)
@@ -380,7 +372,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -412,8 +404,16 @@
 };
 
 static struct accessmap	nfs3_anyaccess[] = {
-    /* XXX: should we try to cover read/write here for clients that
-     * rely on us to do their access checking for special files? */
+	/* Some clients - Solaris 2.6 at least, make an access call
+	 * to the server to check for access for things like /dev/null
+	 * (which really, the server doesn't care about).  So
+	 * We provide simple access checking for them, looking
+	 * mainly at mode bits
+	 */
+    {	NFS3_ACCESS_READ,	MAY_READ			},
+    {	NFS3_ACCESS_EXECUTE,	MAY_EXEC			},
+    {	NFS3_ACCESS_MODIFY,	MAY_WRITE			},
+    {	NFS3_ACCESS_EXTEND,	MAY_WRITE			},
 
     {	0,			0				}
 };
@@ -425,7 +425,7 @@
 	struct svc_export	*export;
 	struct dentry		*dentry;
 	u32			query, result = 0;
-	int			error;
+	unsigned int		error;
 
 	error = fh_verify(rqstp, fhp, 0, MAY_NOP);
 	if (error)
@@ -434,41 +434,45 @@
 	export = fhp->fh_export;
 	dentry = fhp->fh_dentry;
 
-	if (S_ISREG(dentry->d_inode->i_mode)) {
+	if (S_ISREG(dentry->d_inode->i_mode))
 		map = nfs3_regaccess;
-	} else if (S_ISDIR(dentry->d_inode->i_mode)) {
+	else if (S_ISDIR(dentry->d_inode->i_mode))
 		map = nfs3_diraccess;
-	} else {
+	else
 		map = nfs3_anyaccess;
-	}
+
 
 	query = *access;
-	while (map->access) {
+	for  (; map->access; map++) {
 		if (map->access & query) {
 			error = nfsd_permission(export, dentry, (map->how | NO_OWNER_OVERRIDE));
-			if (error == 0)
+			switch(error) {
+			case 0:
 				result |= map->access;
-			else if ((error == nfserr_perm) || (error == nfserr_acces)) {
+				break;
+			case nfserr_perm:
+			case nfserr_acces:
+			case nfserr_rofs:
 				/*
 				 *  This access type is denyed; but the 
 				 *  access query itself succeeds.
 				 */
 				error = 0;
-			} else {
+				break;
+			default:
 				/*
 				 *  Some fatal error.  Fail the query.
 				 */
 				goto out;
 			}
 		}
-		map++;
 	}
 	*access = result;
 
 out:
 	return error;
 }
-#endif
+#endif /* CONFIG_NFSD_V3 */
 
 
 
@@ -532,7 +536,7 @@
 	}
 out_nfserr:
 	if (err)
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out:
 	return err;
 }
@@ -553,9 +557,8 @@
 			dentry->d_parent->d_name.name, dentry->d_name.name);
 	if (filp->f_op && filp->f_op->release)
 		filp->f_op->release(inode, filp);
-	if (filp->f_mode & FMODE_WRITE) {
+	if (filp->f_mode & FMODE_WRITE) 
 		put_write_access(inode);
-	}
 }
 
 /*
@@ -638,7 +641,7 @@
 		goto out_close;
 
 	/* Get readahead parameters */
-	ra = nfsd_get_raparms(fhp->fh_handle.fh_dev, fhp->fh_handle.fh_ino);
+	ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
 	if (ra) {
 		file.f_reada = ra->p_reada;
 		file.f_ramax = ra->p_ramax;
@@ -669,7 +672,7 @@
 		*count = err;
 		err = 0;
 	} else 
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out_close:
 	nfsd_close(&file);
 out:
@@ -683,7 +686,7 @@
  */
 int
 nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
-				char *buf, unsigned long cnt, int stable)
+				char *buf, unsigned long cnt, int *stablep)
 {
 	struct svc_export	*exp;
 	struct file		file;
@@ -691,6 +694,7 @@
 	struct inode		*inode;
 	mm_segment_t		oldfs;
 	int			err = 0;
+	int			stable = *stablep;
 #ifdef CONFIG_QUOTA
 	uid_t			saved_euid;
 #endif
@@ -716,17 +720,16 @@
 	 * When gathered writes have been configured for this volume,
 	 * flushing the data to disk is handled separately below.
 	 */
-#ifdef CONFIG_NFSD_V3
-	if (rqstp->rq_vers == 2)
-		stable = EX_ISSYNC(exp);
-	else if (file.f_op->fsync == 0)
-	       stable = 1;
+
+	if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+	       stable = 2;
+	       *stablep = 2; /* FILE_SYNC */
+	}
+
+	if (!EX_ISSYNC(exp))
+		stable = 0;
 	if (stable && !EX_WGATHER(exp))
 		file.f_flags |= O_SYNC;
-#else
-	if ((stable || (stable = EX_ISSYNC(exp))) && !EX_WGATHER(exp))
-		file.f_flags |= O_SYNC;
-#endif /* CONFIG_NFSD_V3 */
 
 	fh_lock(fhp);			/* lock inode */
 	file.f_pos = offset;		/* set write offset */
@@ -787,7 +790,7 @@
 			dprintk("nfsd: write resume %d\n", current->pid);
 		}
 
-		if (inode->i_state & I_DIRTY) {
+		if (EX_WGATHER(exp) && (inode->i_state & I_DIRTY)) {
 			dprintk("nfsd: write sync %d\n", current->pid);
 			nfsd_sync(&file);
 		}
@@ -802,7 +805,7 @@
 	if (err >= 0)
 		err = 0;
 	else 
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out_close:
 	nfsd_close(&file);
 out:
@@ -812,8 +815,8 @@
 
 #ifdef CONFIG_NFSD_V3
 /*
- * Commit all pendig writes to stable storage.
- * Strictly speaking, we could sync just indicated the file region here,
+ * Commit all pending writes to stable storage.
+ * Strictly speaking, we could sync just the indicated file region here,
  * but there's currently no way we can ask the VFS to do so.
  *
  * We lock the file to make sure we return full WCC data to the client.
@@ -827,14 +830,15 @@
 
 	if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
 		return err;
-
-	fh_lock(fhp);
-	if (file.f_op && file.f_op->fsync) {
-		file.f_op->fsync(&file, file.f_dentry);
-	} else {
-		err = nfserr_notsupp;
+	if (EX_ISSYNC(fhp->fh_export)) {
+		fh_lock(fhp);
+		if (file.f_op && file.f_op->fsync) {
+			file.f_op->fsync(&file, file.f_dentry);
+		} else {
+			err = nfserr_notsupp;
+		}
+		fh_unlock(fhp);
 	}
-	fh_unlock(fhp);
 
 	nfsd_close(&file);
 	return err;
@@ -862,6 +866,9 @@
 	err = nfserr_perm;
 	if (!flen)
 		goto out;
+	err = nfserr_exist;
+	if (isdotent(fname, flen))
+		goto out;
 
 	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
 	if (err)
@@ -873,10 +880,6 @@
 	err = nfserr_notdir;
 	if(!dirp->i_op || !dirp->i_op->lookup)
 		goto out;
-
-	err = nfserr_exist;
-	if (isdotent(fname, flen))
-		goto out;
 	/*
 	 * Check whether the response file handle has been verified yet.
 	 * If it has, the parent directory should already be locked.
@@ -901,7 +904,7 @@
 				dentry->d_name.name);
 			err = -EIO;
 			goto out;
-	}
+		}
 	}
 	/*
 	 * Make sure the child dentry is still negative ...
@@ -959,10 +962,6 @@
 		write_inode_now(dchild->d_inode);
 	}
 
-	/*
-	 * Update the file handle to get the new inode info.
-	 */
-	fh_update(resfhp);
 
 	/* Set file attributes. Mode has already been set and
 	 * setting uid/gid works only for root. Irix appears to
@@ -972,11 +971,15 @@
 	err = 0;
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
 		err = nfsd_setattr(rqstp, resfhp, iap);
+	/*
+	 * Update the file handle to get the new inode info.
+	 */
+	fh_update(resfhp);
 out:
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -992,10 +995,15 @@
 	struct dentry	*dentry, *dchild;
 	struct inode	*dirp;
 	int		err;
+	__u32		v_mtime=0, v_atime=0;
+	int		v_mode=0;
 
 	err = nfserr_perm;
 	if (!flen)
 		goto out;
+	err = nfserr_exist;
+	if (isdotent(fname, flen))
+		goto out;
 	if (!(iap->ia_valid & ATTR_MODE))
 		iap->ia_mode = 0;
 	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
@@ -1014,9 +1022,6 @@
 	if(!dirp->i_op->create)
 		goto out;
 
-	err = nfserr_exist;
-	if (isdotent(fname, flen))
-		goto out;
 	/*
 	 * Compose the response file handle.
 	 */
@@ -1033,6 +1038,19 @@
 	if (err)
 	    goto out;
 
+	if (createmode == NFS3_CREATE_EXCLUSIVE) {
+		/* while the verifier would fit in mtime+atime,
+		 * solaris7 gets confused (bugid 4218508) if these have
+		 * the high bit set, so we use the mode as well
+		 */
+		v_mtime = verifier[0]&0x7fffffff;
+		v_atime = verifier[1]&0x7fffffff;
+		v_mode  = S_IFREG
+			| ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
+			| ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
+			;
+	}
+	
 	if (dchild->d_inode) {
 		err = 0;
 
@@ -1050,10 +1068,10 @@
 			}
 			break;
 		case NFS3_CREATE_EXCLUSIVE:
-			if (   dchild->d_inode->i_mtime == verifier[0]
-			    && dchild->d_inode->i_atime == verifier[1]
-			    && dchild->d_inode->i_mode == S_IFREG
-			    && dchild->d_inode->i_size == 0 )
+			if (   dchild->d_inode->i_mtime == v_mtime
+			    && dchild->d_inode->i_atime == v_atime
+			    && dchild->d_inode->i_mode  == v_mode
+			    && dchild->d_inode->i_size  == 0 )
 				break;
 			 /* fallthru */
 		case NFS3_CREATE_GUARDED:
@@ -1078,19 +1096,23 @@
 	err = 0;
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
-		/* Cram the verifier into atime/mtime */
-		iap->ia_valid = ATTR_MTIME|ATTR_ATIME|ATTR_MTIME_SET|ATTR_ATIME_SET;
-		iap->ia_mtime = verifier[0];
-		iap->ia_atime = verifier[1];
+		/* Cram the verifier into atime/mtime/mode */
+		iap->ia_valid = ATTR_MTIME|ATTR_ATIME
+			| ATTR_MTIME_SET|ATTR_ATIME_SET
+			| ATTR_MODE;
+		iap->ia_mtime = v_mtime;
+		iap->ia_atime = v_atime;
+		iap->ia_mode  = v_mode;
 	}
 
-	/* Set file attributes. Mode has already been set and
-	 * setting uid/gid works only for root. Irix appears to
-	 * send along the gid when it tries to implement setgid
-	 * directories via NFS. Clear out all that cruft.
+	/* Set file attributes.
+	 * Mode has already been set but we might need to reset it
+	 * for CREATE_EXCLUSIVE
+	 * Irix appears to send along the gid when it tries to
+	 * implement setgid directories via NFS. Clear out all that cruft.
 	 */
  set_attr:
-	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
+	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
  		err = nfsd_setattr(rqstp, resfhp, iap);
 
  out:
@@ -1098,68 +1120,12 @@
  	return err;
  
  out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 #endif /* CONFIG_NFSD_V3 */
 
 /*
- * Truncate a file.
- * The calling routines must make sure to update the ctime
- * field and call notify_change.
- *
- * XXX Nobody calls this thing? -DaveM
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
-{
-	struct dentry	*dentry;
-	struct inode	*inode;
-	struct iattr	newattrs;
-	int		err;
-	kernel_cap_t	saved_cap = 0;
-
-	err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC);
-	if (err)
-		goto out;
-
-	dentry = fhp->fh_dentry;
-	inode = dentry->d_inode;
-
-	err = get_write_access(inode);
-	if (err)
-		goto out_nfserr;
-
-	/* Things look sane, lock and do it. */
-	fh_lock(fhp);
-	DQUOT_INIT(inode);
-	newattrs.ia_size = size;
-	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-	if (current->fsuid != 0) {
-		saved_cap = current->cap_effective;
-		cap_clear(current->cap_effective);
-	}
-	err = notify_change(dentry, &newattrs);
-	if (!err) {
-		vmtruncate(inode, size);
-		if (inode->i_op && inode->i_op->truncate)
-			inode->i_op->truncate(inode);
-	}
-	if (current->fsuid != 0)
-		current->cap_effective = saved_cap;
-	put_write_access(inode);
-	if (EX_ISSYNC(fhp->fh_export))
-		nfsd_sync_dir(dentry);
-	fh_unlock(fhp);
-out_nfserr:
-	if (err)
-		err = nfserrno(-err);
-out:
-	return err;
-}
-
-/*
  * Read a symlink. On entry, *lenp must contain the maximum path length that
  * fits into the buffer. On return, it contains the true length.
  * N.B. After this call fhp needs an fh_put
@@ -1172,7 +1138,7 @@
 	mm_segment_t	oldfs;
 	int		err;
 
-	err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ);
+	err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP);
 	if (err)
 		goto out;
 
@@ -1200,7 +1166,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1223,15 +1189,15 @@
 	if (!flen || !plen)
 		goto out;
 
+	err = nfserr_exist;
+	if (isdotent(fname, flen))
+		goto out;
+
 	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
 	if (err)
 		goto out;
 	dentry = fhp->fh_dentry;
 
-	err = nfserr_exist;
-	if (isdotent(fname, flen))
-		goto out;
-
 	err = nfserr_perm;
 	dirp = dentry->d_inode;
 	if (!dirp->i_op	|| !dirp->i_op->symlink)
@@ -1268,7 +1234,7 @@
 			       }
 			}
 		} else
-			err = nfserrno(-err);
+			err = nfserrno(err);
 	}
 	fh_unlock(fhp);
 
@@ -1280,7 +1246,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1299,6 +1265,11 @@
 	err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
 	if (err)
 		goto out;
+
+	err = nfserr_exist;
+	if (isdotent(fname, flen))
+		goto out;
+
 	err = fh_verify(rqstp, tfhp, -S_IFDIR, MAY_NOP);
 	if (err)
 		goto out;
@@ -1307,10 +1278,6 @@
 	if (!flen)
 		goto out;
 
-	err = nfserr_exist;
-	if (isdotent(fname, flen))
-		goto out;
-
 	ddir = ffhp->fh_dentry;
 	dirp = ddir->d_inode;
 
@@ -1350,7 +1317,7 @@
 			write_inode_now(dest);
 		}
 	} else
-		err = nfserrno(-err);
+		err = nfserrno(err);
 
 out_unlock:
 	fh_unlock(ffhp);
@@ -1360,7 +1327,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1478,7 +1445,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1494,13 +1461,14 @@
 	struct inode	*dirp;
 	int		err;
 
-	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
-	if (err)
-		goto out;
 	err = nfserr_acces;
 	if (!flen || isdotent(fname, flen))
 		goto out;
 
+	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
+	if (err)
+		goto out;
+
 	dentry = fhp->fh_dentry;
 	dirp = dentry->d_inode;
 
@@ -1520,8 +1488,10 @@
 		/* It's UNLINK */
 
 		err = fh_lock_parent(fhp, rdentry);
-		if (err)
+		if (err) {
+			dput(rdentry);
 			goto out;
+		}
 
 		err = vfs_unlink(dirp, rdentry);
 
@@ -1568,7 +1538,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1610,6 +1580,7 @@
 	 * may choose to do less.
 	 */
 	inode = file.f_dentry->d_inode;
+	down(&inode->i_sem);
 	while (1) {
 		oldlen = cd.buflen;
 
@@ -1618,9 +1589,7 @@
 			file.f_inode->i_dev, file.f_inode->i_ino,
 			(int) file.f_pos, (int) oldlen, (int) cd.buflen);
 		 */
-		down(&inode->i_sem);
 		err = file.f_op->readdir(&file, &cd, (filldir_t) func);
-		up(&inode->i_sem);
 		if (err < 0)
 			goto out_nfserr;
 		if (oldlen == cd.buflen)
@@ -1628,16 +1597,15 @@
 		if (cd.eob)
 			break;
 	}
+	up(&inode->i_sem);
 
 	/* If we didn't fill the buffer completely, we're at EOF */
 	eof = !cd.eob;
 
 	if (cd.offset) {
-#ifdef CONFIG_NFSD_V3
 		if (rqstp->rq_vers == 3)
-			(void)enc64(cd.offset, file.f_pos);
+			(void)xdr_encode_hyper(cd.offset, file.f_pos);
 		else
-#endif /* CONFIG_NFSD_V3 */
 			*cd.offset = htonl(file.f_pos);
 	}
 
@@ -1656,7 +1624,8 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	up(&inode->i_sem);
+	err = nfserrno(err);
 	goto out_close;
 }
 
@@ -1737,12 +1706,17 @@
 		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
 #endif
 
-	if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
-		if (EX_RDONLY(exp) || IS_RDONLY(inode))
-			return nfserr_rofs;
-		if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
-			return nfserr_perm;
-	}
+	/* only care about readonly exports for files and
+	 * directories. links don't have meaningful write access,
+	 * and all else is local to the client
+	 */
+	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) 
+		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
+			if (EX_RDONLY(exp) || IS_RDONLY(inode))
+				return nfserr_rofs;
+			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
+				return nfserr_perm;
+		}
 	if ((acc & MAY_TRUNC) && IS_APPEND(inode))
 		return nfserr_perm;
 
@@ -1786,7 +1760,7 @@
 	if (current->fsuid != 0)
 		current->cap_effective = saved_cap;
 
-	return err? nfserrno(-err) : 0;
+	return err? nfserrno(err) : 0;
 }
 
 void
diff -urN linux-2.2.19-pre8/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.2.19-pre8/fs/proc/array.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/proc/array.c	Sun Dec 10 16:49:44 2000
@@ -951,7 +951,7 @@
 			vsize += vma->vm_end - vma->vm_start;
 			vma = vma->vm_next;
 		}
-		if ((current->fsuid == tsk->euid && tsk->dumpable == 1 &&
+		if ((current->fsuid == tsk->euid && tsk->dumpable &&
 		    cap_issubset(tsk->cap_permitted, current->cap_permitted)) ||
 		    capable(CAP_DAC_OVERRIDE)) {
 			eip = KSTK_EIP(tsk);
@@ -1482,7 +1482,7 @@
 		case PROC_PID_CPU:
 			return 0;	
 	}
-	if((current->fsuid == euid && ok == 1) || capable(CAP_DAC_OVERRIDE))
+	if((current->fsuid == euid && ok) || capable(CAP_DAC_OVERRIDE))
 		return 0;
 	return 1;
 }
diff -urN linux-2.2.19-pre8/fs/proc/base.c linux/fs/proc/base.c
--- linux-2.2.19-pre8/fs/proc/base.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/proc/base.c	Mon Aug 24 13:02:43 1998
@@ -66,7 +66,7 @@
 	if (fill && (p = find_task_by_pid(pid)) != NULL) {
 		uid_t uid = 0;
 		gid_t gid = 0;
-		if (p->dumpable == 1 || ino == PROC_PID_INO) {
+		if (p->dumpable || ino == PROC_PID_INO) {
 			uid = p->euid;
 			gid = p->egid;
 		}
diff -urN linux-2.2.19-pre8/fs/proc/inode.c linux/fs/proc/inode.c
--- linux-2.2.19-pre8/fs/proc/inode.c	Mon Dec  3 20:59:33 2001
+++ linux/fs/proc/inode.c	Mon Sep  4 10:39:27 2000
@@ -378,7 +378,7 @@
 		goto out_unlock;
 
 	ino &= 0x0000ffff;
-	if (ino == PROC_PID_INO || p->dumpable == 1) {
+	if (ino == PROC_PID_INO || p->dumpable) {
 		inode->i_uid = p->euid;
 		inode->i_gid = p->egid;
 	}
diff -urN linux-2.2.19-pre8/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- linux-2.2.19-pre8/include/asm-sparc/unistd.h	Mon Dec  3 20:59:33 2001
+++ linux/include/asm-sparc/unistd.h	Mon Dec  3 21:00:04 2001
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.55.2.1 2001/01/11 15:44:37 davem Exp $ */
+/* $Id: unistd.h,v 1.55.2.2 2001/01/11 19:12:10 davem Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -169,7 +169,7 @@
 /* #define __NR_getmsg          151    SunOS Specific                              */
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
-/* #define __NR_ni_syscall      154    ENOSYS under SunOS                          */
+/* #define __NR_getdents64      154    Linux Sparc32 Specific                      */
 /* #define __NR_fcntl64         155    Linux Sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
diff -urN linux-2.2.19-pre8/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- linux-2.2.19-pre8/include/asm-sparc64/unistd.h	Mon Dec  3 20:59:33 2001
+++ linux/include/asm-sparc64/unistd.h	Mon Dec  3 21:00:04 2001
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.28.2.1 2001/01/11 15:44:37 davem Exp $ */
+/* $Id: unistd.h,v 1.28.2.2 2001/01/11 19:12:11 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -169,7 +169,7 @@
 /* #define __NR_getmsg          151    SunOS Specific                              */
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
-/* #define __NR_ni_syscall      154    ENOSYS under SunOS                          */
+/* #define __NR_getdents64      154    Linux Sparc32 Specific                      */
 /* #define __NR_fcntl64         155    Linux Sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
diff -urN linux-2.2.19-pre8/include/asm-sparc64/watchdog.h linux/include/asm-sparc64/watchdog.h
--- linux-2.2.19-pre8/include/asm-sparc64/watchdog.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/watchdog.h	Mon Dec  3 21:00:04 2001
@@ -0,0 +1,31 @@
+/* $Id: watchdog.h,v 1.1.2.1 2001/01/26 22:26:07 davem Exp $
+ *
+ * watchdog - Driver interface for the hardware watchdog timers
+ * present on Sun Microsystems boardsets
+ *
+ * Copyright (c) 2000 Eric Brower <ebrower@usa.net>
+ *
+ */
+
+#ifndef _SPARC64_WATCHDOG_H
+#define _SPARC64_WATCHDOG_H
+
+#include <linux/watchdog.h>
+
+/* Solaris compatibility ioctls--
+ * Ref. <linux/watchdog.h> for standard linux watchdog ioctls
+ */
+#define WIOCSTART _IO (WATCHDOG_IOCTL_BASE, 10)		/* Start Timer		*/
+#define WIOCSTOP  _IO (WATCHDOG_IOCTL_BASE, 11)		/* Stop Timer		*/
+#define WIOCGSTAT _IOR(WATCHDOG_IOCTL_BASE, 12, int)/* Get Timer Status	*/
+
+/* Status flags from WIOCGSTAT ioctl
+ */
+#define WD_FREERUN	0x01	/* timer is running, interrupts disabled	*/
+#define WD_EXPIRED	0x02	/* timer has expired						*/
+#define WD_RUNNING	0x04	/* timer is running, interrupts enabled		*/
+#define WD_STOPPED	0x08	/* timer has not been started				*/
+#define WD_SERVICED 0x10	/* timer interrupt was serviced				*/
+
+#endif /* ifndef _SPARC64_WATCHDOG_H */
+
diff -urN linux-2.2.19-pre8/include/linux/apm_bios.h linux/include/linux/apm_bios.h
--- linux-2.2.19-pre8/include/linux/apm_bios.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/apm_bios.h	Mon Dec  3 21:00:04 2001
@@ -38,7 +38,7 @@
 	unsigned short	dseg_len;
 };
 
-				/* Results of APM Installation Check */
+/* Results of APM Installation Check */
 #define APM_16_BIT_SUPPORT	0x0001
 #define APM_32_BIT_SUPPORT	0x0002
 #define APM_IDLE_SLOWS_CLOCK	0x0004
@@ -46,6 +46,15 @@
 #define APM_BIOS_DISENGAGED     0x0010
 
 /*
+ * Data for APM that is persistant across module unload/load
+ */
+struct apm_info {
+	struct apm_bios_info	bios;
+	unsigned short		connection_version;
+	int			get_power_status_broken;
+};
+
+/*
  * The APM function codes
  */
 #define	APM_FUNC_INST_CHECK	0x5300
@@ -91,9 +100,9 @@
 #define	APM_FUNC_TIMER_GET	2
 
 /*
- * in init/main.c
+ * in arch/i386/kernel/setup.c
  */
-extern struct apm_bios_info	apm_bios_info;
+extern struct apm_info	apm_info;
 
 extern int		apm_register_callback(int (*callback)(apm_event_t));
 extern void		apm_unregister_callback(int (*callback)(apm_event_t));
@@ -176,7 +185,7 @@
 /*
  * This is the "All Devices" ID communicated to the BIOS
  */
-#define APM_DEVICE_BALL		((apm_bios_info.version > 0x0100) ? \
+#define APM_DEVICE_BALL		((apm_info.connection_version > 0x0100) ? \
 				 APM_DEVICE_ALL : APM_DEVICE_OLD_ALL)
 #endif
 
diff -urN linux-2.2.19-pre8/include/linux/binfmts.h linux/include/linux/binfmts.h
--- linux-2.2.19-pre8/include/linux/binfmts.h	Mon Aug  9 12:04:41 1999
+++ linux/include/linux/binfmts.h	Mon Dec  3 21:00:04 2001
@@ -28,6 +28,8 @@
 	int argc, envc;
 	char * filename;	/* Name of binary */
 	unsigned long loader, exec;
+	int dumpable;
+	int priv_change;
 };
 
 /*
diff -urN linux-2.2.19-pre8/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h
--- linux-2.2.19-pre8/include/linux/nfsd/nfsd.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/nfsd/nfsd.h	Mon Dec  3 21:00:04 2001
@@ -100,7 +100,7 @@
 int		nfsd_read(struct svc_rqst *, struct svc_fh *,
 				loff_t, char *, unsigned long *);
 int		nfsd_write(struct svc_rqst *, struct svc_fh *,
-				loff_t, char *, unsigned long, int);
+				loff_t, char *, unsigned long, int *);
 int		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
 				char *, int *);
 int		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
@@ -145,38 +145,41 @@
 #endif
 
 /*
- * These variables contain pre-xdr'ed values for faster operation.
- * FIXME: should be replaced by macros for big-endian machines.
+ * These macros provide pre-xdr'ed values for faster operation.
  */
-extern u32	nfs_ok,
-		nfserr_perm,
-		nfserr_noent,
-		nfserr_io,
-		nfserr_nxio,
-		nfserr_acces,
-		nfserr_exist,
-		nfserr_xdev,
-		nfserr_nodev,
-		nfserr_notdir,
-		nfserr_isdir,
-		nfserr_inval,
-		nfserr_fbig,
-		nfserr_nospc,
-		nfserr_rofs,
-		nfserr_mlink,
-		nfserr_nametoolong,
-		nfserr_notempty,
-		nfserr_dquot,
-		nfserr_stale,
-		nfserr_remote,
-		nfserr_badhandle,
-		nfserr_notsync,
-		nfserr_badcookie,
-		nfserr_notsupp,
-		nfserr_toosmall,
-		nfserr_serverfault,
-		nfserr_badtype,
-		nfserr_jukebox;
+#define	nfs_ok			__constant_htonl(NFS_OK)
+#define	nfserr_perm		__constant_htonl(NFSERR_PERM)
+#define	nfserr_noent		__constant_htonl(NFSERR_NOENT)
+#define	nfserr_io		__constant_htonl(NFSERR_IO)
+#define	nfserr_nxio		__constant_htonl(NFSERR_NXIO)
+#define	nfserr_acces		__constant_htonl(NFSERR_ACCES)
+#define	nfserr_exist		__constant_htonl(NFSERR_EXIST)
+#define	nfserr_xdev		__constant_htonl(NFSERR_XDEV)
+#define	nfserr_nodev		__constant_htonl(NFSERR_NODEV)
+#define	nfserr_notdir		__constant_htonl(NFSERR_NOTDIR)
+#define	nfserr_isdir		__constant_htonl(NFSERR_ISDIR)
+#define	nfserr_inval		__constant_htonl(NFSERR_INVAL)
+#define	nfserr_fbig		__constant_htonl(NFSERR_FBIG)
+#define	nfserr_nospc		__constant_htonl(NFSERR_NOSPC)
+#define	nfserr_rofs		__constant_htonl(NFSERR_ROFS)
+#define	nfserr_mlink		__constant_htonl(NFSERR_MLINK)
+#define	nfserr_opnotsupp	__constant_htonl(NFSERR_OPNOTSUPP)
+#define	nfserr_nametoolong	__constant_htonl(NFSERR_NAMETOOLONG)
+#define	nfserr_notempty		__constant_htonl(NFSERR_NOTEMPTY)
+#define	nfserr_dquot		__constant_htonl(NFSERR_DQUOT)
+#define	nfserr_stale		__constant_htonl(NFSERR_STALE)
+#define	nfserr_remote		__constant_htonl(NFSERR_REMOTE)
+#define	nfserr_badhandle	__constant_htonl(NFSERR_BADHANDLE)
+#define	nfserr_notsync		__constant_htonl(NFSERR_NOTSYNC)
+#define	nfserr_badcookie	__constant_htonl(NFSERR_BADCOOKIE)
+#define	nfserr_notsupp		__constant_htonl(NFSERR_NOTSUPP)
+#define	nfserr_toosmall		__constant_htonl(NFSERR_TOOSMALL)
+#define	nfserr_serverfault	__constant_htonl(NFSERR_SERVERFAULT)
+#define	nfserr_badtype		__constant_htonl(NFSERR_BADTYPE)
+#define	nfserr_jukebox		__constant_htonl(NFSERR_JUKEBOX)
+
+/* Check for dir entries '.' and '..' */
+#define isdotent(n, l)	(l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
 
 /*
  * Time of server startup
diff -urN linux-2.2.19-pre8/include/linux/nfsd/xdr3.h linux/include/linux/nfsd/xdr3.h
--- linux-2.2.19-pre8/include/linux/nfsd/xdr3.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/nfsd/xdr3.h	Mon Dec  3 21:00:04 2001
@@ -296,19 +296,5 @@
 int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
 				int namlen, off_t offset, ino_t ino);
 
-#ifdef __KERNEL__
-
-/*
- * This is needed in nfs_readdir for encoding NFS3 directory cookies.
- */
-static inline u32 *
-enc64(u32 *p, u64 val)
-{
-	*p++ = htonl(val >> 32);
-	*p++ = htonl(val & 0xffffffff);
-	return p;
-}
-
-#endif /* __KERNEL__ */
 
 #endif /* _LINUX_NFSD_XDR3_H */
diff -urN linux-2.2.19-pre8/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.2.19-pre8/include/linux/sched.h	Mon Dec  3 20:59:33 2001
+++ linux/include/linux/sched.h	Mon Dec  3 21:00:04 2001
@@ -269,7 +269,7 @@
 	int pdeath_signal;  /*  The signal sent when the parent dies  */
 	/* ??? */
 	unsigned long personality;
-	unsigned int dumpable:2;
+	unsigned int dumpable:1;
 	int did_exec:1;
 	pid_t pid;
 	pid_t pgrp;
diff -urN linux-2.2.19-pre8/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux-2.2.19-pre8/include/linux/sysctl.h	Sun Dec 10 16:49:44 2000
+++ linux/include/linux/sysctl.h	Mon Dec  3 21:00:04 2001
@@ -30,7 +30,7 @@
 
 struct __sysctl_args {
 	int *name;
-	int nlen;
+	unsigned nlen;
 	void *oldval;
 	size_t *oldlenp;
 	void *newval;
@@ -465,7 +465,7 @@
 
 typedef struct ctl_table ctl_table;
 
-typedef int ctl_handler (ctl_table *table, int *name, int nlen,
+typedef int ctl_handler (ctl_table *table, int *name, unsigned nlen,
 			 void *oldval, size_t *oldlenp,
 			 void *newval, size_t newlen, 
 			 void **context);
@@ -484,12 +484,12 @@
 extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
 				 void *, size_t *);
 
-extern int do_sysctl (int *name, int nlen,
+extern int do_sysctl (int *name, unsigned nlen,
 		      void *oldval, size_t *oldlenp,
 		      void *newval, size_t newlen);
 
 extern int do_sysctl_strategy (ctl_table *table, 
-			       int *name, int nlen,
+			       int *name, unsigned nlen,
 			       void *oldval, size_t *oldlenp,
 			       void *newval, size_t newlen, void ** context);
 
diff -urN linux-2.2.19-pre8/kernel/sysctl.c linux/kernel/sysctl.c
--- linux-2.2.19-pre8/kernel/sysctl.c	Mon Dec  3 20:59:33 2001
+++ linux/kernel/sysctl.c	Mon Dec  3 21:00:04 2001
@@ -77,7 +77,7 @@
 
 extern int pgt_cache_water[];
 
-static int parse_table(int *, int, void *, size_t *, void *, size_t,
+static int parse_table(int *, unsigned, void *, size_t *, void *, size_t,
 		       ctl_table *, void **);
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp);
@@ -320,7 +320,7 @@
 }
 
 
-int do_sysctl (int *name, int nlen,
+int do_sysctl (int *name, unsigned nlen,
 	       void *oldval, size_t *oldlenp,
 	       void *newval, size_t newlen)
 {
@@ -330,10 +330,12 @@
 	
 	if (nlen == 0 || nlen >= CTL_MAXNAME)
 		return -ENOTDIR;
-	
-	if (oldval) 
-	{
-		int old_len;
+
+	if ((ssize_t)newlen < 0)
+		return -EINVAL;	
+
+	if (oldval) {
+		size_t old_len;
 		if (!oldlenp)
 			return -EFAULT;
 		if(get_user(old_len, oldlenp))
@@ -387,7 +389,7 @@
 	return test_perm(table->mode, op);
 }
 
-static int parse_table(int *name, int nlen,
+static int parse_table(int *name, unsigned nlen,
 		       void *oldval, size_t *oldlenp,
 		       void *newval, size_t newlen,
 		       ctl_table *table, void **context)
@@ -430,11 +432,12 @@
 
 /* Perform the actual read/write of a sysctl table entry. */
 int do_sysctl_strategy (ctl_table *table, 
-			int *name, int nlen,
+			int *name, unsigned nlen,
 			void *oldval, size_t *oldlenp,
 			void *newval, size_t newlen, void **context)
 {
-	int op = 0, rc, len;
+	int op = 0, rc;
+	size_t len;
 
 	if (oldval)
 		op |= 004;
@@ -642,7 +645,7 @@
 int proc_dostring(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
-	int len;
+	size_t len;
 	char *p, c;
 	
 	if (!table->data || !table->maxlen || !*lenp ||
@@ -710,7 +713,8 @@
 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp, int conv, int op)
 {
-	int *i, vleft, first=1, len, left, neg, val;
+	int *i, neg, val;
+	size_t len, left, vleft, first=1;
 	#define TMPBUFLEN 20
 	char buf[TMPBUFLEN], *p;
 	
@@ -832,7 +836,8 @@
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
-	int *i, *min, *max, vleft, first=1, len, left, neg, val;
+	int *i, *min, *max, neg, val;
+	size_t len, left, vleft, first=1;
 	#define TMPBUFLEN 20
 	char buf[TMPBUFLEN], *p;
 	
@@ -974,11 +979,12 @@
  */
 
 /* The generic string strategy routine: */
-int sysctl_string(ctl_table *table, int *name, int nlen,
+int sysctl_string(ctl_table *table, int *name, unsigned nlen,
 		  void *oldval, size_t *oldlenp,
 		  void *newval, size_t newlen, void **context)
 {
-	int l, len;
+	unsigned l;
+	size_t len;
 	
 	if (!table->data || !table->maxlen) 
 		return -ENOTDIR;
@@ -1017,11 +1023,12 @@
  * are between the minimum and maximum values given in the arrays
  * table->extra1 and table->extra2, respectively.
  */
-int sysctl_intvec(ctl_table *table, int *name, int nlen,
+int sysctl_intvec(ctl_table *table, int *name, unsigned nlen,
 		void *oldval, size_t *oldlenp,
 		void *newval, size_t newlen, void **context)
 {
-	int i, length, *vec, *min, *max;
+	int *vec, *min, *max;
+	size_t i, length;
 
 	if (newval && newlen) {
 		if (newlen % sizeof(int) != 0)
@@ -1051,7 +1058,7 @@
 }
 
 /* Strategy function to convert jiffies to seconds */ 
-int sysctl_jiffies(ctl_table *table, int *name, int nlen,
+int sysctl_jiffies(ctl_table *table, int *name, unsigned nlen,
 		void *oldval, size_t *oldlenp,
 		void *newval, size_t newlen, void **context)
 {
@@ -1159,21 +1166,21 @@
 	return -ENOSYS;
 }
 
-int sysctl_string(ctl_table *table, int *name, int nlen,
+int sysctl_string(ctl_table *table, int *name, unsigned nlen,
 		  void *oldval, size_t *oldlenp,
 		  void *newval, size_t newlen, void **context)
 {
 	return -ENOSYS;
 }
 
-int sysctl_intvec(ctl_table *table, int *name, int nlen,
+int sysctl_intvec(ctl_table *table, int *name, unsigned nlen,
 		void *oldval, size_t *oldlenp,
 		void *newval, size_t newlen, void **context)
 {
 	return -ENOSYS;
 }
 
-int sysctl_jiffies(ctl_table *table, int *name, int nlen,
+int sysctl_jiffies(ctl_table *table, int *name, unsigned nlen,
 		void *oldval, size_t *oldlenp,
 		void *newval, size_t newlen, void **context)
 {
diff -urN linux-2.2.19-pre8/net/Changes linux/net/Changes
--- linux-2.2.19-pre8/net/Changes	Sun Jun  7 10:37:42 1998
+++ linux/net/Changes	Wed Dec 31 16:00:00 1969
@@ -1,45 +0,0 @@
---------------- Things That Need Doing Before 2.2 ------------------
-
-o	insw_and_csum
-
--------------------------- Bugs to fix ------------------------------
-
-o	Should unix domain connect never block ?
-o	Screend loadable firewall module
-o	Fix merging the bridge code
-o	Remove kernel RARP and replace with user mode daemon.
-o	Merge ARM half word trap fixes for ethernet headers
-o	Stop route addition to downed interfaces
-o	Make sure route add window functionality is back or documented
-	equivalences are clear
-o	Merge ATM 
-o	Merge IRDA
-
-Possible projects for victim^H^H^H^H^Holunteers
-
-9.	Implementing streams. Not as a blind slow SYS5.4 style copy but actually
-working out how to do it so it runs like greased lightning. Quite a big
-problem. [See the LiS project]
-
-11.	IP over SCSI. [worked on]
-
-14.	Bidirectional PLIP. Also PLIP for the newer style parallel ports.
-
-15.	802.2LLC and thus Netbeui sockets. Becoming less important since the
-rumour is microsoft are phasing out netbeui for netbios/IP. Microsoft have
-gone for netbios/funny-ipx-variant it seems in Win95, but TCP is selectable.
-
-17.	PPP multilink. Another nasty job.
-
-19.	IPv4 IP-AH and IP-ESP.
-
-20.	(userspace) GUI interface to the bandwidth allocators so mere
-	mortals can do this
-
-
-BTW: Don't let the magic words 'kernel programming' worry you. Its like DOS
-- you make a mistake you have to reboot. You do at least get dumps and a
-kernel logger that is reliable. There is now a loadable module allowing
-use of gdb on the kernel (no breakpoints though!). No magic involved.
-
-Alan
diff -urN linux-2.2.19-pre8/net/Config.in linux/net/Config.in
--- linux-2.2.19-pre8/net/Config.in	Sun Dec 10 16:49:44 2000
+++ linux/net/Config.in	Mon Dec  3 21:00:04 2001
@@ -56,15 +56,16 @@
   bool 'Fast switching (read help!)' CONFIG_NET_FASTROUTE
   bool 'Forwarding between high speed interfaces' CONFIG_NET_HW_FLOWCONTROL
   bool 'CPU is too slow to handle full bandwidth' CONFIG_CPU_IS_SLOW
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  mainmenu_option next_comment
-  comment 'QoS and/or fair queueing'
-  bool 'QoS and/or fair queueing' CONFIG_NET_SCHED
-  if [ "$CONFIG_NET_SCHED" = "y" ]; then
-    source net/sched/Config.in
-  fi
-#  bool 'Network code profiler' CONFIG_NET_PROFILE
-  endmenu
-  fi
 fi
+
+mainmenu_option next_comment
+comment 'QoS and/or fair queueing'
+bool 'QoS and/or fair queueing' CONFIG_NET_SCHED
+if [ "$CONFIG_NET_SCHED" = "y" ]; then
+  source net/sched/Config.in
+fi
+endmenu
+
+#bool 'Network code profiler' CONFIG_NET_PROFILE
+
 endmenu
diff -urN linux-2.2.19-pre8/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux-2.2.19-pre8/net/ipv4/icmp.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/icmp.c	Mon Dec  3 21:00:04 2001
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.52.2.6 2000/08/31 23:49:16 davem Exp $
+ *	Version: $Id: icmp.c,v 1.52.2.7 2001/02/02 01:27:08 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
diff -urN linux-2.2.19-pre8/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- linux-2.2.19-pre8/net/ipv4/ip_input.c	Tue Jan  4 10:12:26 2000
+++ linux/net/ipv4/ip_input.c	Mon Dec  3 21:00:04 2001
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) module.
  *
- * Version:	$Id: ip_input.c,v 1.37 1999/04/22 10:38:36 davem Exp $
+ * Version:	$Id: ip_input.c,v 1.37.2.4 2001/01/04 04:20:16 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -urN linux-2.2.19-pre8/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c
--- linux-2.2.19-pre8/net/ipv4/ip_masq.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/ip_masq.c	Mon Dec  3 21:00:04 2001
@@ -4,7 +4,7 @@
  *
  * 	Copyright (c) 1994 Pauline Middelink
  *
- *	$Id: ip_masq.c,v 1.34.2.2 1999/08/07 10:56:28 davem Exp $
+ *	$Id: ip_masq.c,v 1.34.2.14 2001/02/02 01:27:08 davem Exp $
  *
  *
  *	See ip_fw.c for original log
diff -urN linux-2.2.19-pre8/net/ipv4/ip_masq_app.c linux/net/ipv4/ip_masq_app.c
--- linux-2.2.19-pre8/net/ipv4/ip_masq_app.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/ip_masq_app.c	Mon Dec  3 21:00:04 2001
@@ -2,7 +2,7 @@
  *		IP_MASQ_APP application masquerading module
  *
  *
- * 	$Id: ip_masq_app.c,v 1.16 1998/08/29 23:51:14 davem Exp $
+ * 	$Id: ip_masq_app.c,v 1.16.2.2 2001/01/04 05:28:46 davem Exp $
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
diff -urN linux-2.2.19-pre8/net/ipv4/ip_masq_mod.c linux/net/ipv4/ip_masq_mod.c
--- linux-2.2.19-pre8/net/ipv4/ip_masq_mod.c	Wed Jun  7 14:26:44 2000
+++ linux/net/ipv4/ip_masq_mod.c	Mon Dec  3 21:00:04 2001
@@ -4,7 +4,7 @@
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
- * 	$Id: ip_masq_mod.c,v 1.5.2.1 1999/07/02 10:10:03 davem Exp $
+ * 	$Id: ip_masq_mod.c,v 1.5.2.3 2001/01/04 04:20:16 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
diff -urN linux-2.2.19-pre8/net/ipv4/ip_masq_raudio.c linux/net/ipv4/ip_masq_raudio.c
--- linux-2.2.19-pre8/net/ipv4/ip_masq_raudio.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/ip_masq_raudio.c	Mon Dec  3 21:00:04 2001
@@ -2,7 +2,7 @@
  *		IP_MASQ_RAUDIO  - Real Audio masquerading module
  *
  *
- * Version:	@(#)$Id: ip_masq_raudio.c,v 1.11 1998/10/06 04:49:04 davem Exp $
+ * Version:	@(#)$Id: ip_masq_raudio.c,v 1.11.2.1 2001/01/10 01:52:33 davem Exp $
  *
  * Author:	Nigel Metheringham
  *		Real Time Streaming code by Progressive Networks
diff -urN linux-2.2.19-pre8/net/ipv4/ip_masq_user.c linux/net/ipv4/ip_masq_user.c
--- linux-2.2.19-pre8/net/ipv4/ip_masq_user.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/ip_masq_user.c	Mon Dec  3 21:00:04 2001
@@ -2,7 +2,7 @@
  *	IP_MASQ_USER user space control module
  *
  *
- *	$Id: ip_masq_user.c,v 1.1.2.4 2000/02/29 23:50:24 davem Exp $
+ *	$Id: ip_masq_user.c,v 1.1.2.6 2001/01/04 04:20:16 davem Exp $
  */
 
 #include <linux/config.h>
diff -urN linux-2.2.19-pre8/net/ipv4/route.c linux/net/ipv4/route.c
--- linux-2.2.19-pre8/net/ipv4/route.c	Sun Dec 10 16:49:44 2000
+++ linux/net/ipv4/route.c	Mon Dec  3 21:00:04 2001
@@ -1927,7 +1927,7 @@
 		return -EINVAL;
 }
 
-static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, int nlen,
+static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, unsigned nlen,
 			 void *oldval, size_t *oldlenp,
 			 void *newval, size_t newlen, 
 			 void **context)
diff -urN linux-2.2.19-pre8/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- linux-2.2.19-pre8/net/ipv4/sysctl_net_ipv4.c	Sun Dec 10 16:49:44 2000
+++ linux/net/ipv4/sysctl_net_ipv4.c	Mon Dec  3 21:00:04 2001
@@ -87,7 +87,7 @@
 	return ret;
 }
 
-static int ipv4_sysctl_forward_strategy(ctl_table *table, int *name, int nlen,
+static int ipv4_sysctl_forward_strategy(ctl_table *table, int *name, unsigned nlen,
 			 void *oldval, size_t *oldlenp,
 			 void *newval, size_t newlen, 
 			 void **context)
diff -urN linux-2.2.19-pre8/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux-2.2.19-pre8/net/ipv4/tcp.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/tcp.c	Mon Dec  3 21:00:04 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.140.2.15 2000/10/06 23:29:33 davem Exp $
+ * Version:	$Id: tcp.c,v 1.140.2.16 2001/01/04 05:28:46 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -urN linux-2.2.19-pre8/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- linux-2.2.19-pre8/net/ipv4/tcp_input.c	Sun Dec 10 16:49:44 2000
+++ linux/net/ipv4/tcp_input.c	Mon Dec  3 21:00:04 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.18 2000/12/08 20:29:33 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.19 2001/02/02 01:50:39 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -246,26 +246,22 @@
 }
 
 
-static int __tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
-{
-	u32 end_window = tp->rcv_wup + tp->rcv_wnd;
-
-	if (tp->rcv_wnd &&
-	    after(end_seq, tp->rcv_nxt) &&
-	    before(seq, end_window))
-		return 1;
-	if (seq != end_window)
-		return 0;
-	return (seq == end_seq);
-}
-
-/* This functions checks to see if the tcp header is actually acceptable. */
-extern __inline__ int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+/* Check segment sequence number for validity.
+ *
+ * Segment controls are considered valid, if the segment
+ * fits to the window after truncation to the window. Acceptability
+ * of data (and SYN, FIN, of course) is checked separately.
+ * See tcp_data_queue(), for example.
+ *
+ * Also, controls (RST is main one) are accepted using RCV.WUP instead
+ * of RCV.NXT. Peer still did not advance his SND.UNA when we
+ * delayed ACK, so that hisSND.UNA<=ourRCV.WUP.
+ * (borrowed from freebsd)
+ */
+static inline int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
 {
-	if (seq == tp->rcv_nxt)
-		return (tp->rcv_wnd || (end_seq == seq));
-
-	return __tcp_sequence(tp, seq, end_seq);
+	return	!before(end_seq, tp->rcv_wup) &&
+		!after(seq, tp->rcv_nxt + tcp_receive_window(tp));
 }
 
 /* When we get a reset we do this. */
@@ -1415,6 +1411,11 @@
 	if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
 		/* Ok. In sequence. */
 	queue_and_out:
+		if (tcp_receive_window(tp) == 0)
+			goto out_of_window;
+
+		/* We know it is in window now too. */
+
 		dst_confirm(sk->dst_cache);
 		__skb_queue_tail(&sk->receive_queue, skb);
 		tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
@@ -1441,6 +1442,7 @@
 		/* A retransmit, 2nd most common case.  Force an imediate ack. */
 		SOCK_DEBUG(sk, "retransmit received: seq %X\n", TCP_SKB_CB(skb)->seq);
 		tcp_enter_quickack_mode(tp);
+out_of_window:
 		kfree_skb(skb);
 		return;
 	}
@@ -1453,6 +1455,16 @@
 
 		goto queue_and_out;
 	}
+
+	/* Out of window. F.e. zero window probe.
+	 *
+	 * Note: it is highly possible that we may open window and enqueue
+	 * this segment now. However, this will be known only after we queue
+	 * it, which will result in queue full of successive 1 byte BSD
+	 * window probes, it is SWS in fact. So, always reject it and send ACK.
+	 */
+	if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt+tcp_receive_window(tp)))
+		goto out_of_window;
 
 	/* Ok. This is an out_of_order segment, force an ack. */
 	tp->delayed_acks++;
diff -urN linux-2.2.19-pre8/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- linux-2.2.19-pre8/net/ipv4/tcp_ipv4.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/tcp_ipv4.c	Mon Dec  3 21:00:04 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.175.2.17 2000/10/31 22:42:58 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.175.2.18 2001/02/02 01:27:08 davem Exp $
  *
  *		IPv4 specific functions
  *
diff -urN linux-2.2.19-pre8/net/ipv4/udp.c linux/net/ipv4/udp.c
--- linux-2.2.19-pre8/net/ipv4/udp.c	Mon Dec  3 20:59:33 2001
+++ linux/net/ipv4/udp.c	Mon Dec  3 21:00:04 2001
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.66.2.4 2000/03/10 00:16:05 davem Exp $
+ * Version:	$Id: udp.c,v 1.66.2.6 2001/02/02 01:27:09 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -urN linux-2.2.19-pre8/net/sched/cls_u32.c linux/net/sched/cls_u32.c
--- linux-2.2.19-pre8/net/sched/cls_u32.c	Thu Mar 25 09:23:34 1999
+++ linux/net/sched/cls_u32.c	Mon Dec  3 21:00:04 2001
@@ -254,7 +254,7 @@
 	do {
 		if (++tp_c->hgenerator == 0x7FF)
 			tp_c->hgenerator = 1;
-	} while (i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20));
+	} while (--i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20));
 
 	return i > 0 ? (tp_c->hgenerator|0x800)<<20 : 0;
 }
diff -urN linux-2.2.19-pre8/net/unix/af_unix.c linux/net/unix/af_unix.c
--- linux-2.2.19-pre8/net/unix/af_unix.c	Mon Dec  3 20:59:33 2001
+++ linux/net/unix/af_unix.c	Mon Dec  3 21:00:04 2001
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.76.2.5 2000/10/17 09:08:37 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.76.2.6 2001/01/04 05:28:48 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
