## Automatically generated incremental diff
## From:   linux-2.2.15-pre13
## To:     linux-2.2.15-pre14
## Robot:  $Id: make-incremental-diff,v 1.7 2001/12/04 05:19:54 hpa Exp $

diff -urN linux-2.2.15-pre13/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.15-pre13/Documentation/Configure.help	Mon Dec  3 22:01:04 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:01:10 2001
@@ -6785,6 +6785,8 @@
   This is support for all SysKonnect Token Ring cards, specifically
   SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect TR4/16(+) PCI
   (SK-4590), SysKonnect TR4/16 PCI (SK-4591) adapters.
+  It also supports Compaq PCI Token Ring adapters and Proteon ISA
+  Token Ring adapters (1392 and 1392+).
 
   If you have such an adapter and would like to use it, say Y or M and
   read the Token-Ring mini-HOWTO, available via FTP (user: anonymous)
diff -urN linux-2.2.15-pre13/Documentation/networking/sktr.txt linux/Documentation/networking/sktr.txt
--- linux-2.2.15-pre13/Documentation/networking/sktr.txt	Wed Jun 24 14:26:12 1998
+++ linux/Documentation/networking/sktr.txt	Mon Dec  3 22:01:10 2001
@@ -46,6 +46,11 @@
 Now just setup the device via ifconfig and set and routes you may have. After
 this you are ready to start sending some tokens.
 
+Parameters:
+The driver supports the usual parameters irq and dma (for ISA-adapters only).
+Additional, there is a parameter for setting the connection speed (4 MBits/sec
+or 16 MBit/sec). Default is 16, use "rate=4" to force 4 MBit.
+
 Errata:
 For anyone wondering where to pick up the SysKonnect adapters please browse
 to http://www.syskonnect.com
diff -urN linux-2.2.15-pre13/Makefile linux/Makefile
--- linux-2.2.15-pre13/Makefile	Mon Dec  3 22:01:04 2001
+++ linux/Makefile	Mon Dec  3 22:01:10 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 15
-EXTRAVERSION = pre13
+EXTRAVERSION = pre14
 
 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.15-pre13/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- linux-2.2.15-pre13/arch/sparc/mm/srmmu.c	Mon Dec  3 22:01:04 2001
+++ linux/arch/sparc/mm/srmmu.c	Mon Dec  3 22:01:10 2001
@@ -2424,7 +2424,15 @@
 	BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_swift, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(init_new_context, swift_init_new_context, BTFIXUPCALL_NORM);
 
+#if 1
+	/* If granular flushes are ever cured and reenabled in
+	 * swift.S, revert this setting back to non-global iommu
+	 * cache flushes. -DaveM
+	 */
+	flush_page_for_dma_global = 1;
+#else
 	flush_page_for_dma_global = 0;
+#endif
 
 	/* Are you now convinced that the Swift is one of the
 	 * biggest VLSI abortions of all time?  Bravo Fujitsu!
diff -urN linux-2.2.15-pre13/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S
--- linux-2.2.15-pre13/arch/sparc/mm/swift.S	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc/mm/swift.S	Mon Dec  3 22:01:10 2001
@@ -41,10 +41,10 @@
 swift_flush_page_to_ram:
 	sethi	%hi(0x2000), %o0
 1:	subcc	%o0, 0x10, %o0
-	sta	%g0, [%o0] ASI_M_TXTC_TAG
+	add	%o0, %o0, %o1
 	sta	%g0, [%o0] ASI_M_DATAC_TAG
 	bne	1b
-	 nop
+	 sta	%g0, [%o1] ASI_M_TXTC_TAG
 	retl
 	 nop
 #else
diff -urN linux-2.2.15-pre13/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- linux-2.2.15-pre13/arch/sparc64/kernel/entry.S	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/kernel/entry.S	Mon Dec  3 22:01:10 2001
@@ -945,7 +945,17 @@
 		 nop
 		ldx		[%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7
 		wr		%g0, %o7, %pcr
-		wr		%g0, %g0, %pic
+
+		/* Blackbird errata workaround.  See commentary in
+		 * smp.c:smp_percpu_timer_interrupt() for more
+		 * information.
+		 */
+		ba,pt		%xcc, 99f
+		 nop
+		.align		64
+99:		wr		%g0, %g0, %pic
+		rd		%pic, %g0
+
 1:		b,pt		%xcc, ret_sys_call
 		 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
 sparc_exit:	rdpr		%otherwin, %g1
diff -urN linux-2.2.15-pre13/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- linux-2.2.15-pre13/arch/sparc64/kernel/head.S	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/kernel/head.S	Mon Dec  3 22:01:10 2001
@@ -262,7 +262,16 @@
 
 	/* Setup "Linux Current Register", thanks Sun 8-) */
 	wr	%g0, 0x1, %pcr
-	wr	%g6, 0x0, %pic
+
+	/* Blackbird errata workaround.  See commentary in
+	 * smp.c:smp_percpu_timer_interrupt() for more
+	 * information.
+	 */
+	ba,pt	%xcc, 99f
+	 nop
+	.align	64
+99:	wr	%g6, %g0, %pic
+	rd	%pic, %g0
 #endif
 
 	mov	1, %g5
diff -urN linux-2.2.15-pre13/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- linux-2.2.15-pre13/arch/sparc64/kernel/setup.c	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/kernel/setup.c	Mon Dec  3 22:01:10 2001
@@ -160,9 +160,17 @@
 		}
 
 		if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
+			/* Spitfire Errata #32 workaround */
+			__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+					     "flush	%%g6"
+					     : /* No outputs */
+					     : "r" (0),
+					     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 			/*
 			 * Locked down tlb entry 63.
 			 */
+
 			tte = spitfire_get_dtlb_data(63);
 			res = PROM_TRUE;
 			goto done;
diff -urN linux-2.2.15-pre13/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- linux-2.2.15-pre13/arch/sparc64/kernel/smp.c	Mon Dec  3 22:01:04 2001
+++ linux/arch/sparc64/kernel/smp.c	Mon Dec  3 22:01:10 2001
@@ -301,6 +301,13 @@
 	       smp_processor_id(), data0, data1, data2, target);
 #endif
 again:
+	/* Ok, this is the real Spitfire Errata #54.
+	 * One must read back from a UDB internal register
+	 * after writes to the UDB interrupt dispatch, but
+	 * before the membar Sync for that write.
+	 * So we use the high UDB control register (ASI 0x7f,
+	 * ADDR 0x20) for the dummy read. -DaveM
+	 */
 	__asm__ __volatile__("
 	wrpr	%0, %1, %%pstate
 	wr	%%g0, %2, %%asi
@@ -309,10 +316,14 @@
 	stxa	%5, [0x60] %%asi
 	membar	#Sync
 	stxa	%%g0, [%6] %%asi
+	membar	#Sync
+	mov	0x20, %%g1
+	ldxa	[%%g1] 0x7f, %%g0
 	membar	#Sync"
 	: /* No outputs */
 	: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
-	  "r" (data0), "r" (data1), "r" (data2), "r" (target));
+	  "r" (data0), "r" (data1), "r" (data2), "r" (target)
+	: "g1");
 
 	/* NOTE: PSTATE_IE is still clear. */
 	stuck = 100000;
diff -urN linux-2.2.15-pre13/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- linux-2.2.15-pre13/arch/sparc64/lib/blockops.S	Tue Jan  4 10:12:13 2000
+++ linux/arch/sparc64/lib/blockops.S	Mon Dec  3 22:01:10 2001
@@ -46,13 +46,37 @@
 	sethi		%hi(TLBTEMP_ENT1), %o3
 	rdpr		%pstate, %g3
 	wrpr		%g3, PSTATE_IE, %pstate
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %o4
+	stxa		%g0, [%o4] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_TAG_READ, %o4
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %o5
+	stxa		%g0, [%o5] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_DATA_ACCESS, %o5
 	stxa		%o0, [%o2] ASI_DMMU
 	stxa		%g1, [%o3] ASI_DTLB_DATA_ACCESS
 	membar		#Sync
 	add		%o3, (TLBTEMP_ENTSZ), %o3
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %g5
+	stxa		%g0, [%g5] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_TAG_READ, %g5
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %g7
+	stxa		%g0, [%g7] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_DATA_ACCESS, %g7
 	stxa		%o1, [%o2] ASI_DMMU
 	stxa		%g2, [%o3] ASI_DTLB_DATA_ACCESS
@@ -120,7 +144,19 @@
 	sethi		%hi(TLBTEMP_ENT2), %o3
 	rdpr		%pstate, %g3
 	wrpr		%g3, PSTATE_IE, %pstate
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %g5
+	stxa		%g0, [%g5] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_TAG_READ, %g5
+
+	/* Spitfire Errata #32 workaround */
+	mov		0x8, %g7
+	stxa		%g0, [%g7] ASI_DMMU
+	flush		%g6
+
 	ldxa		[%o3] ASI_DTLB_DATA_ACCESS, %g7
 	stxa		%o0, [%o2] ASI_DMMU
 	stxa		%g1, [%o3] ASI_DTLB_DATA_ACCESS
diff -urN linux-2.2.15-pre13/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- linux-2.2.15-pre13/arch/sparc64/mm/init.c	Mon Dec  3 22:01:04 2001
+++ linux/arch/sparc64/mm/init.c	Mon Dec  3 22:01:10 2001
@@ -709,6 +709,14 @@
 
 	/* Now fixup OBP's idea about where we really are mapped. */
 	prom_printf("Remapping the kernel... ");
+
+	/* Spitfire Errata #32 workaround */
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "flush	%%g6"
+			     : /* No outputs */
+			     : "r" (0),
+			     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 	phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR;
 	phys_page += ((unsigned long)&prom_boot_page -
 		      (unsigned long)&empty_zero_page);
@@ -731,11 +739,27 @@
 		: "memory");
 
 	tte_vaddr = (unsigned long) &empty_zero_page;
+
+	/* Spitfire Errata #32 workaround */
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "flush	%%g6"
+			     : /* No outputs */
+			     : "r" (0),
+			     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 	kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63);
 
 	remap_func = (void *)  ((unsigned long) &prom_remap -
 				(unsigned long) &prom_boot_page);
 
+
+	/* Spitfire Errata #32 workaround */
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "flush	%%g6"
+			     : /* No outputs */
+			     : "r" (0),
+			     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 	remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR,
 		   (unsigned long) &empty_zero_page,
 		   prom_get_mmu_ihandle());
@@ -798,8 +822,16 @@
 
 	/* Only DTLB must be checked for VPTE entries. */
 	for(i = 0; i < 63; i++) {
-		unsigned long tag = spitfire_get_dtlb_tag(i);
+		unsigned long tag;
 
+		/* Spitfire Errata #32 workaround */
+		__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+				     "flush	%%g6"
+				     : /* No outputs */
+				     : "r" (0),
+				     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
+		tag = spitfire_get_dtlb_tag(i);
 		if(((tag & ~(PAGE_MASK)) == 0) &&
 		   ((tag &  (PAGE_MASK)) >= prom_reserved_base)) {
 			__asm__ __volatile__("stxa %%g0, [%0] %1"
@@ -912,10 +944,26 @@
 	for(i = 0; i < 63; i++) {
 		unsigned long data;
 
+
+		/* Spitfire Errata #32 workaround */
+		__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+				     "flush	%%g6"
+				     : /* No outputs */
+				     : "r" (0),
+				     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 		data = spitfire_get_dtlb_data(i);
 		if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
-			unsigned long tag = spitfire_get_dtlb_tag(i);
+			unsigned long tag;
+
+			/* Spitfire Errata #32 workaround */
+			__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+					     "flush	%%g6"
+					     : /* No outputs */
+					     : "r" (0),
+					     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 
+			tag = spitfire_get_dtlb_tag(i);
 			if(save_p) {
 				prom_dtlb[dtlb_seen].tlb_ent = i;
 				prom_dtlb[dtlb_seen].tlb_tag = tag;
@@ -935,10 +983,25 @@
 	for(i = 0; i < 63; i++) {
 		unsigned long data;
 
+		/* Spitfire Errata #32 workaround */
+		__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+				     "flush	%%g6"
+				     : /* No outputs */
+				     : "r" (0),
+				     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 		data = spitfire_get_itlb_data(i);
 		if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
-			unsigned long tag = spitfire_get_itlb_tag(i);
+			unsigned long tag;
+
+			/* Spitfire Errata #32 workaround */
+			__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+					     "flush	%%g6"
+					     : /* No outputs */
+					     : "r" (0),
+					     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 
+			tag = spitfire_get_itlb_tag(i);
 			if(save_p) {
 				prom_itlb[itlb_seen].tlb_ent = i;
 				prom_itlb[itlb_seen].tlb_tag = tag;
@@ -1018,6 +1081,13 @@
 			     : "=r" (pstate)
 			     : "i" (PSTATE_IE));
 	for(i = 0; i < 64; i++) {
+		/* Spitfire Errata #32 workaround */
+		__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+				     "flush	%%g6"
+				     : /* No outputs */
+				     : "r" (0),
+				     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 		if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
 			__asm__ __volatile__("stxa %%g0, [%0] %1"
 					     : /* no outputs */
@@ -1026,6 +1096,14 @@
 			spitfire_put_dtlb_data(i, 0x0UL);
 			membar("#Sync");
 		}
+
+		/* Spitfire Errata #32 workaround */
+		__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+				     "flush	%%g6"
+				     : /* No outputs */
+				     : "r" (0),
+				     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
 		if(!(spitfire_get_itlb_data(i) & _PAGE_L)) {
 			__asm__ __volatile__("stxa %%g0, [%0] %1"
 					     : /* no outputs */
diff -urN linux-2.2.15-pre13/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- linux-2.2.15-pre13/arch/sparc64/mm/ultra.S	Mon Dec  3 22:01:04 2001
+++ linux/arch/sparc64/mm/ultra.S	Mon Dec  3 22:01:10 2001
@@ -35,7 +35,7 @@
 __flush_tlb_range: /* %o0=(ctx&0x3ff), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
 		    * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
 		    */
-#define TLB_MAGIC	206 /* Students, do you know how I calculated this?  -DaveM */
+#define TLB_MAGIC	207 /* Students, do you know how I calculated this?  -DaveM */
 /*IC3*/	cmp		%o5, %o4
 	be,pt		%xcc, __flush_tlb_page
 	 srlx		%o5, 13, %g5
@@ -58,6 +58,12 @@
 	wrpr		%g1, PSTATE_IE, %pstate
 	mov		TLB_TAG_ACCESS, %g3
 	mov		(62 << 3), %g2
+
+	/* Spitfire Errata #32 workaround. */
+	mov		0x8, %o4
+	stxa		%g0, [%o4] ASI_DMMU
+	flush		%g6
+
 1:	ldxa		[%g2] ASI_ITLB_TAG_READ, %o4
 	and		%o4, 0x3ff, %o5
 	cmp		%o5, %o0
@@ -83,12 +89,27 @@
 	 wrpr		%g1, 0x0, %pstate
 4:	stxa		%g0, [%g3] ASI_IMMU
 	stxa		%g0, [%g2] ASI_ITLB_DATA_ACCESS
+	flush		%g6
+
+	/* Spitfire Errata #32 workaround. */
+	mov		0x8, %o4
+	stxa		%g0, [%o4] ASI_DMMU
+	flush		%g6
+
 	ba,pt		%xcc, 2b
-	 flush		%g6
+	 nop
+
 5:	stxa		%g0, [%g3] ASI_DMMU
 /*IC9*/	stxa		%g0, [%g2] ASI_DTLB_DATA_ACCESS
+	flush		%g6
+
+	/* Spitfire Errata #32 workaround. */
+	mov		0x8, %o4
+	stxa		%g0, [%o4] ASI_DMMU
+	flush		%g6
+
 	ba,pt		%xcc, 3b
-	 flush		%g6
+	 nop
 
 	.align		32
 __flush_tlb_mm_slow:
@@ -315,28 +336,51 @@
 	 clr		%l6
 99:	retry
 
+	.data
+
+errata32_hwbug:
+	.xword	0
+
+	.text
+
 	/* These two are not performance critical... */
 	.globl		xcall_flush_tlb_all
 xcall_flush_tlb_all:
+
+	/* Spitfire Errata #32 workaround. */
+	sethi		%hi(errata32_hwbug), %g4
+	stx		%g0, [%g4 + %lo(errata32_hwbug)]
+
 	clr		%g2
 	clr		%g3
 1:	ldxa		[%g3] ASI_DTLB_DATA_ACCESS, %g4
 	and		%g4, _PAGE_L, %g5
 	brnz,pn		%g5, 2f
 	 mov		TLB_TAG_ACCESS, %g7
+
 	stxa		%g0, [%g7] ASI_DMMU
 	membar		#Sync
-
 	stxa		%g0, [%g3] ASI_DTLB_DATA_ACCESS
 	membar		#Sync
+
+	/* Spitfire Errata #32 workaround. */
+	sethi		%hi(errata32_hwbug), %g4
+	stx		%g0, [%g4 + %lo(errata32_hwbug)]
+
 2:	ldxa		[%g3] ASI_ITLB_DATA_ACCESS, %g4
 	and		%g4, _PAGE_L, %g5
 	brnz,pn		%g5, 2f
 	 mov		TLB_TAG_ACCESS, %g7
+
 	stxa		%g0, [%g7] ASI_IMMU
 	membar		#Sync
-
 	stxa		%g0, [%g3] ASI_ITLB_DATA_ACCESS
+	membar		#Sync
+
+	/* Spitfire Errata #32 workaround. */
+	sethi		%hi(errata32_hwbug), %g4
+	stx		%g0, [%g4 + %lo(errata32_hwbug)]
+
 2:	add		%g2, 1, %g2
 	cmp		%g2, 63
 	ble,pt		%icc, 1b
diff -urN linux-2.2.15-pre13/drivers/char/console.c linux/drivers/char/console.c
--- linux-2.2.15-pre13/drivers/char/console.c	Mon Dec  3 22:01:04 2001
+++ linux/drivers/char/console.c	Mon Dec  3 22:01:11 2001
@@ -358,7 +358,7 @@
 static void update_attr(int currcons)
 {
 	attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
-	video_erase_char = (build_attr(currcons, color, 1, 0, 0, decscnm) << 8) | ' ';
+	video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -506,9 +506,6 @@
 {
     if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
 	return;
-	
-    disable_bh(CONSOLE_BH);
-    
     if (deccm) {
 	if (currcons == sel_cons)
 		clear_selection();
@@ -517,8 +514,6 @@
 	    sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
     } else
 	hide_cursor(currcons);
-	
-    enable_bh(CONSOLE_BH);
 }
 
 static void set_origin(int currcons)
@@ -1817,12 +1812,11 @@
 	himask = hi_font_mask;
 	charmask = himask ? 0x1ff : 0xff;
 
-	disable_bh(CONSOLE_BH);
-
 	/* undraw cursor first */
 	if (IS_FG)
 		hide_cursor(currcons);
 
+	disable_bh(CONSOLE_BH);
 	while (!tty->stopped && count) {
 		enable_bh(CONSOLE_BH);
 		if (from_user)
diff -urN linux-2.2.15-pre13/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c
--- linux-2.2.15-pre13/drivers/char/generic_serial.c	Mon Dec  3 22:01:04 2001
+++ linux/drivers/char/generic_serial.c	Mon Dec  3 22:01:11 2001
@@ -491,7 +491,7 @@
 void gs_shutdown_port (struct gs_port *port)
 {
 	long flags;
-
+	func_enter();
 	if (!(port->flags & ASYNC_INITIALIZED))
 		return;
 
@@ -510,6 +510,7 @@
 
 	port->flags &= ~ASYNC_INITIALIZED;
 	restore_flags (flags);
+	func_exit();
 }
 
 
diff -urN linux-2.2.15-pre13/drivers/char/sx.c linux/drivers/char/sx.c
--- linux-2.2.15-pre13/drivers/char/sx.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/char/sx.c	Mon Dec  3 22:01:11 2001
@@ -33,6 +33,13 @@
  *
  * Revision history:
  * $Log: sx.c,v $
+ * Revision 1.32  2000/03/07 90:00:00  wolff,pvdl
+ * - Fixed some sx_dprintk typos
+ * - added detection for an invalid board/module configuration
+ *
+ * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
+ * - Added support for EISA
+ *
  * Revision 1.30  2000/01/21 17:43:06  wolff
  * - Added support for SX+
  *
@@ -188,8 +195,8 @@
  * */
 
 
-#define RCS_ID "$Id: sx.c,v 1.30 2000/01/21 17:43:06 wolff Exp $"
-#define RCS_REV "$Revision: 1.30 $"
+#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.32 $"
 
 
 #include <linux/module.h>
@@ -291,7 +298,7 @@
 static int sx_init_board (struct sx_board *board);
 static int sx_init_portstructs (int nboards, int nports);
 static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-		         unsigned int cmd, unsigned long arg);
+                        unsigned int cmd, unsigned long arg);
 static int sx_fw_open(struct inode *inode, struct file *filp);
 static INT sx_fw_release(struct inode *inode, struct file *filp);
 static int sx_init_drivers(void);
@@ -330,11 +337,13 @@
 int sx_maxints = 100;
 
 /* These are the only open spaces in my computer. Yours may have more
-   or less.... */
+   or less.... -- REW 
+   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
+*/
 int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
                        0xc8000, 0xd8000, 0xe8000};
 int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                       0xc8000, 0xd8000, 0xe8000};
+                       0xc8000, 0xd8000, 0xe8000, 0xa0000};
 
 #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
 #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
@@ -346,6 +355,8 @@
 
 #ifndef TWO_ZERO
 #ifdef MODULE
+MODULE_PARM(sx_probe_addrs, "i");
+MODULE_PARM(si_probe_addrs, "i");
 MODULE_PARM(sx_poll, "i");
 MODULE_PARM(sx_slowpoll, "i");
 MODULE_PARM(sx_maxints, "i");
@@ -581,6 +592,8 @@
 			printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
 			return 0;
 		}
+	} else if (IS_EISA_BOARD(board)) {
+		outb(board->irq<<4, board->eisa_base+0xc02);
 	} else {
 		/* Gory details of the SI/ISA board */
 		write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_SET);
@@ -652,6 +665,9 @@
 {
 	if (IS_SX_BOARD (board)) {
 		write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+	} else if (IS_EISA_BOARD(board)) {
+		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
+		outb((board->irq<<4)|4, board->eisa_base+0xc02);
 	} else {
 		/* Don't bug me about the clear_set. 
 		   I haven't the foggiest idea what it's about -- REW */
@@ -675,6 +691,8 @@
 		write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | 
 		                                 SX_CONF_BUSEN | 
 		                                 SX_CONF_HOSTIRQ);
+	} else if (IS_EISA_BOARD(board)) {
+		inb(board->eisa_base+0xc03);  
 	} else {
 		switch (board->irq) {
 		case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
@@ -740,6 +758,18 @@
 	return module_type >> 4;
 }
 
+static void sx_reconfigure_port(struct sx_port *port)
+{
+	if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
+		if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+			printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+		}
+	} else {
+		sx_dprintk (SX_DEBUG_TERMIOS, 
+		            "sx: Not sending reconfigure: port isn't open (%02x).\n", 
+		            sx_read_channel_byte (port, hi_hstat));
+	}	
+}
 
 static void sx_setsignals (struct sx_port *port, int dtr, int rts)
 {
@@ -914,16 +944,7 @@
 	sx_write_channel_byte (port, hi_txoff, STOP_CHAR  (port->gs.tty));
 	sx_write_channel_byte (port, hi_rxoff, STOP_CHAR  (port->gs.tty));
 
-	if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
-		if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-			printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
-		}
-	} else {
-		sx_dprintk (SX_DEBUG_TERMIOS, 
-		            "sx: Not sending reconfigure: port isn't open (%02x).\n", 
-		            sx_read_channel_byte (port, hi_hstat));
-	}
-
+	sx_reconfigure_port(port);
 
 	/* Tell line discipline whether we will do input cooking */
 	if(I_OTHER(port->gs.tty)) {
@@ -1238,6 +1259,9 @@
 		sx_write_board_word (board, cc_int_pending, 0);
 		if (IS_SX_BOARD (board)) {
 			write_sx_byte (board, SX_RESET_IRQ, 1);
+		} else if (IS_EISA_BOARD(board)) {
+			inb(board->eisa_base+0xc03);
+			write_sx_word(board, 8, 0); 
 		} else {
 			write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
 			write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
@@ -1381,6 +1405,7 @@
 	port->gs.flags &= ~ GS_ACTIVE;
 	if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
 		sx_setsignals (port, 0, 0);
+		sx_reconfigure_port(port);
 	}
 
 	func_exit();
@@ -1661,10 +1686,11 @@
 		board = &boards[arg];
 		break;
 	case SXIO_GET_TYPE:
-		rc = -1; /* If we manage to miss one, return error. */
+		rc = -ENOENT; /* If we manage to miss one, return error. */
 		if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
 		if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
 		if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
+		if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
 		sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
 		break;
 	case SXIO_DO_RAMTEST:
@@ -1799,6 +1825,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
 			                     ((ival & TIOCM_RTS) ? 1 : -1));
+			sx_reconfigure_port(port);
 		}
 		break;
 	case TIOCMBIC:
@@ -1807,6 +1834,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
 			                     ((ival & TIOCM_RTS) ? 0 : -1));
+			sx_reconfigure_port(port);
 		}
 		break;
 	case TIOCMSET:
@@ -1815,6 +1843,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
 			                     ((ival & TIOCM_RTS) ? 1 : 0));
+			sx_reconfigure_port(port);
 		}
 		break;
 
@@ -1967,7 +1996,8 @@
 			chans=0;
 			break;
 		}
-		if (IS_SI_BOARD(board) && (mod_compat_type(type) == 4)) {
+		if ((IS_EISA_BOARD(board) || 
+		     IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
 			printk (KERN_ERR "sx: This is an invalid configuration.\n"
 			        "Don't use SXDCs on an SI/XIO adapter.\n");
 			chans=0;
@@ -2146,9 +2176,11 @@
 	if (sx_debug & SX_DEBUG_PROBE)
 		my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8);
 
-	for (i=0;i<8;i++) {
-		if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
-			return 0;
+	if (!IS_EISA_BOARD(board)) {
+		for (i=0;i<8;i++) {
+			if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+				return 0;
+			}
 		}
 	}
 
@@ -2370,7 +2402,7 @@
 	unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x00260000
+#define CNTRL_REG_GOODVALUE     0x18260000
 
 	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
 	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
@@ -2393,6 +2425,7 @@
 {
 	int i;
 	int found = 0;
+	int eisa_slot;
 	struct sx_board *board;
 
 #ifdef CONFIG_PCI
@@ -2481,6 +2514,7 @@
 	for (i=0;i<NR_SX_ADDRS;i++) {
 		board = &boards[found];
 		board->hw_base = sx_probe_addrs[i];
+		board->base2 =
 		board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
 		board->flags &= ~SX_BOARD_TYPE;
 		board->flags |=	SX_ISA_BOARD;
@@ -2496,6 +2530,7 @@
 	for (i=0;i<NR_SI_ADDRS;i++) {
 		board = &boards[found];
 		board->hw_base = si_probe_addrs[i];
+		board->base2 =
 		board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
 		board->flags &= ~SX_BOARD_TYPE;
 		board->flags |=  SI_ISA_BOARD;
@@ -2508,6 +2543,34 @@
 		}
 	}
 
+        sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
+        for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
+        {
+                if((inb(eisa_slot+0xc80)==0x4d) &&
+                   (inb(eisa_slot+0xc81)==0x98))
+                {
+			sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
+			                        "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
+
+			board = &boards[found];
+			board->eisa_base = eisa_slot;
+			board->flags &= ~SX_BOARD_TYPE;
+			board->flags |= SI_EISA_BOARD;
+
+			board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
+			board->base2 =
+			board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+
+			sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %x\n", board->hw_base);
+			sx_dprintk(SX_DEBUG_PROBE, "base: %x\n", board->base);
+			board->irq = inb(board->eisa_base+0xc02)>>4; 
+			sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+			
+			probe_si(board);
+
+			found++;
+		}
+	}
 	if (found) {
 		printk (KERN_INFO "sx: total of %d boards detected.\n", found);
 
@@ -2557,27 +2620,3 @@
 	func_exit();
 }
 #endif
-
-
-
-
-/*
- * Anybody who knows why this doesn't work for me, please tell me -- REW.
- * Snatched from scsi.c (fixed one spelling error):
- * Overrides for Emacs so that we follow Linus' 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: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -urN linux-2.2.15-pre13/drivers/char/sx.h linux/drivers/char/sx.h
--- linux-2.2.15-pre13/drivers/char/sx.h	Mon Dec  3 22:01:05 2001
+++ linux/drivers/char/sx.h	Mon Dec  3 22:01:11 2001
@@ -39,6 +39,7 @@
   unsigned int base;
   unsigned int base2;
   unsigned int hw_base;
+  int eisa_base;
   int port_base; /* Number of the first port */
   struct sx_port *ports;
   int nports;
@@ -71,6 +72,7 @@
 #define SX_PCI_BOARD         0x00000004
 #define SX_CFPCI_BOARD       0x00000008
 #define SX_CFISA_BOARD       0x00000010
+#define SI_EISA_BOARD        0x00000020
 
 #define SX_BOARD_PRESENT     0x00001000
 #define SX_BOARD_INITIALIZED 0x00002000
@@ -82,6 +84,8 @@
                                             SX_ISA_BOARD | SX_CFISA_BOARD))
 
 #define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
+
+#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
 
 #define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
 
diff -urN linux-2.2.15-pre13/drivers/char/sxboards.h linux/drivers/char/sxboards.h
--- linux-2.2.15-pre13/drivers/char/sxboards.h	Mon Aug  9 12:05:09 1999
+++ linux/drivers/char/sxboards.h	Mon Dec  3 22:01:11 2001
@@ -159,6 +159,7 @@
 
 #define		SI2_EISA_OFF	 	0x42
 #define		SI2_EISA_VAL	 	0x01
+#define		SI2_EISA_WINDOW_LEN     0x10000
 
 /*****************************************************************************
 ***********************************         **********************************
diff -urN linux-2.2.15-pre13/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c
--- linux-2.2.15-pre13/drivers/i2o/i2o_pci.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/i2o/i2o_pci.c	Mon Dec  3 22:01:11 2001
@@ -131,7 +131,7 @@
 		/* Skip I/O spaces */
 		if(!(dev->base_address[i]&PCI_BASE_ADDRESS_SPACE))
 		{
-			memptr=dev->base_address[i]&~3;
+			memptr=dev->base_address[i]&~15;
 			break;
 		}
 	}
diff -urN linux-2.2.15-pre13/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.2.15-pre13/drivers/net/Config.in	Mon Dec  3 22:01:05 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 22:01:11 2001
@@ -129,7 +129,9 @@
     fi
     tristate 'Apricot Xen-II on board Ethernet' CONFIG_APRICOT
     tristate 'CS89x0 support' CONFIG_CS89x0
-    tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+    fi
     tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
     tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
     if [ "$CONFIG_DEC_ELCP" != "y" ]; then
@@ -318,14 +320,16 @@
 if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
   bool 'WAN drivers' CONFIG_WAN_DRIVERS 
   if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
-    dep_tristate 'Sangoma WANPIPE(tm) multi-prot cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS 
+    dep_tristate 'Sangoma WANPIPE(tm) multi-port cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS 
+    if [ "$CONFIG_INET" != "n" ]; then
     if [ "$CONFIG_VENDOR_SANGOMA" != "n" ]; then
-      int  '  Maximum number of cards' CONFIG_WANPIPE_CARDS 1
-      #bool '  WANPIPE X.25 support' CONFIG_WANPIPE_X25
-      bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
-      bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
-      bool '  WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
-    fi
+        int  '  Maximum number of cards' CONFIG_WANPIPE_CARDS 1
+        #bool '  WANPIPE X.25 support' CONFIG_WANPIPE_X25
+        bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
+        bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
+        bool '  WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
+      fi
+    fi 
   fi
 fi
 
diff -urN linux-2.2.15-pre13/drivers/net/arlan-proc.c linux/drivers/net/arlan-proc.c
--- linux-2.2.15-pre13/drivers/net/arlan-proc.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/net/arlan-proc.c	Mon Dec  3 22:01:11 2001
@@ -10,7 +10,6 @@
 /* void enableReceive(struct device* dev);
 */
 
-static  int	arlan_command(struct device * dev, int command);
 
 
 #define ARLAN_STR_SIZE 	0x2ff0
@@ -185,6 +184,7 @@
 			return "type A672T";
 	}
 }
+#ifdef ARLAN_DEBUGING
 
 static void arlan_print_diagnostic_info(struct device *dev)
 {
@@ -396,6 +396,7 @@
 	return 0;		/* no errors */
 }
 
+#endif
 
 #ifdef ARLAN_PROC_INTERFACE
 #ifdef ARLAN_PROC_SHM_DUMP
@@ -820,6 +821,16 @@
         {num , #nam, &(arlan_conf[card].nam), \
          sizeof(int), 0600, NULL, &proc_dointvec}
 
+#ifdef ARLAN_DEBUGING
+  
+#define ARLAN_PROC_DEBUG_ENTRIES	{48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
+                 sizeof(int), 0600, NULL, &proc_dointvec},\
+ 	{49, "debug", &arlan_debug, \
+                 sizeof(int), 0600, NULL, &proc_dointvec},
+#else 
+#define ARLAN_PROC_DEBUG_ENTRIES
+#endif
+
 
 #define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
 	CTBLN(1,cardNo,spreadingCode),\
@@ -870,10 +881,7 @@
 	CTBLN(45,cardNo,radioType),\
 	CTBLN(46,cardNo,writeEEPROM),\
 	CTBLN(47,cardNo,writeRadioType),\
-	{48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},\
-	{49, "debug", &arlan_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},\
+ 	ARLAN_PROC_DEBUG_ENTRIES\
 	CTBLN(50,cardNo,in_speed),\
 	CTBLN(51,cardNo,out_speed),\
 	CTBLN(52,cardNo,in_speed10),\
@@ -1008,7 +1016,8 @@
 };
 #endif
 
-static int mmtu = 1234;
+
+// static int mmtu = 1234;
 
 static ctl_table arlan_root_table[] =
 {
@@ -1017,11 +1026,11 @@
 };
 
 /* Make sure that /proc/sys/dev is there */
-static ctl_table arlan_device_root_table[] =
-{
-	{CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
-	{0}
-};
+//static ctl_table arlan_device_root_table[] =
+//{
+//	{CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
+//	{0}
+//};
 
 
 
diff -urN linux-2.2.15-pre13/drivers/net/arlan.c linux/drivers/net/arlan.c
--- linux-2.2.15-pre13/drivers/net/arlan.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/net/arlan.c	Mon Dec  3 22:01:11 2001
@@ -18,28 +18,32 @@
 static int radioNodeId = radioNodeIdUNKNOWN;
 static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
 static char *siteName = siteNameUNKNOWN;
-static int irq = irqUNKNOWN;
 static int mem = memUNKNOWN;
-static int arlan_debug = debugUNKNOWN;
+int arlan_debug = debugUNKNOWN;
 static int probe = probeUNKNOWN;
 static int numDevices = numDevicesUNKNOWN;
-static int testMemory = testMemoryUNKNOWN;
 static int spreadingCode = spreadingCodeUNKNOWN;
 static int channelNumber = channelNumberUNKNOWN;
 static int channelSet = channelSetUNKNOWN;
 static int systemId = systemIdUNKNOWN;
 static int registrationMode = registrationModeUNKNOWN;
-static int txScrambled = 1;
 static int keyStart = 0;
-static int mdebug = 0;
 static int tx_delay_ms = 0;
 static int retries = 5;
 static int async = 1;
 static int tx_queue_len = 1;
+static int arlan_EEPROM_bad = 0;
+int arlan_entry_and_exit_debug = 0;
+
+#ifdef ARLAN_DEBUGING
+
 static int arlan_entry_debug = 0;
 static int arlan_exit_debug = 0;
-static int arlan_entry_and_exit_debug = 0;
-static int arlan_EEPROM_bad = 0;
+static int testMemory = testMemoryUNKNOWN;
+static int irq = irqUNKNOWN;
+static int txScrambled = 1;
+static int mdebug = 0;
+#endif
 
 #if LINUX_VERSION_CODE > 0x20100
 MODULE_PARM(irq, "i");
@@ -339,11 +343,15 @@
 	}
 	else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
 	{
+		priv->under_reset=1;
+		dev->tbusy = 1;
+
 		arlan_drop_tx(dev);
 		if (priv->tx_command_given || priv->rx_command_given)
 		{
 			printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
 		};
+		dev->tbusy = 1;
 		if (arlan_debug & ARLAN_DEBUG_RESET)
 			printk(KERN_ERR "%s: Doing chip reset\n", dev->name);
 		priv->lastReset = jiffies;
@@ -401,15 +409,10 @@
 		{
 			priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;
 			priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+			priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR;
 			priv->card_polling_interval = HZ / 10;
 			priv->tx_command_given = 0;
 			priv->under_config = 0;
-			if (dev->tbusy || !dev->start)
-			{
-				dev->tbusy = 0;
-				dev->start = 1;
-				mark_bh(NET_BH);
-			};
 		}
 		else
 		{
@@ -427,7 +430,7 @@
 			WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);
 			WRITESHMB(arlan->commandParameter[0], conf->rxParameter);
 			arlan_interrupt_lancpu(dev);
-			priv->rx_command_given;
+			priv->rx_command_given = 0; // mnjah, bad
 			priv->last_rx_time = arlan_time();
 			priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;
 			priv->card_polling_interval = 1;
@@ -435,6 +438,17 @@
 		else
 			priv->card_polling_interval = 2;
 	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR)
+	{
+		if ( !registrationBad(dev) && (dev->tbusy || !dev->start) )
+			{
+				priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR;
+
+				dev->tbusy = 0;
+				dev->start = 1;
+				mark_bh(NET_BH);
+			};
+	}
 	else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)
 	{
 		if (!test_and_set_bit(0, (void *) &priv->tx_command_given))
@@ -694,7 +708,7 @@
 	add_timer(&priv->timer);
 }
 
-
+#ifdef ARLAN_DEBUGING
 
 
 static void arlan_print_registers(struct device *dev, int line)
@@ -721,6 +735,7 @@
 
 	ARLAN_DEBUG_EXIT("arlan_print_registers");
 }
+#endif
 
 
 static int arlan_hw_tx(struct device *dev, char *buf, int length)
@@ -1042,12 +1057,18 @@
 	volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
 
 	ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
+//	if (check_mem_region(virt_to_phys((void *)memaddr),0x2000 )){
+//		// printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",virt_to_phys((void*)memaddr));
+//		return -ENODEV;
+//	};
 	memcpy_fromio(tempBuf, arlan->textRegion, 29);
 	tempBuf[30] = 0;
 
 	/* check for card at this address */
-	if (0 != strncmp(tempBuf, probeText, 29))
+	if (0 != strncmp(tempBuf, probeText, 29)){
+// not 		release_mem_region(virt_to_phys((void*)memaddr),0x2000);
 		return -ENODEV;
+	}
 
 //   printk(KERN_INFO "arlan found at 0x%x \n",memaddr);
 	ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
@@ -1066,17 +1087,17 @@
 	ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
 	if (mem != 0 && numDevices == 1)	/* Check a single specified location. */
 	{
-		if (arlan_probe_here(dev, mem) == 0)
+		if (arlan_probe_here(dev, (int) phys_to_virt(  mem) ) == 0)
 			return 0;
 		else
 			return -ENODEV;
 	}
-	for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000)
+	for (m = (int)phys_to_virt(lastFoundAt) + 0x2000; m <= (int)phys_to_virt(0xDE000); m += 0x2000)
 	{
 		if (arlan_probe_here(dev, m) == 0)
 		{
 			found++;
-			lastFoundAt = m;
+			lastFoundAt = (int)virt_to_phys((void*)m);
 			break;
 		}
 		probed++;
@@ -1103,7 +1124,7 @@
 	ARLAN_DEBUG_ENTRY("arlan_find_devices");
 	if (mem != 0 && numDevices == 1)	/* Check a single specified location. */
 		return 1;
-	for (m = 0xc000; m <= 0xDE000; m += 0x2000)
+	for (m =(int) phys_to_virt(0xc0000); m <=(int) phys_to_virt(0xDE000); m += 0x2000)
 	{
 		if (arlan_check_fingerprint(m) == 0)
 			found++;
@@ -1175,6 +1196,9 @@
 		printk(KERN_CRIT "init_etherdev failed ");
 		return 0;
 	}
+
+	memset(dev->priv,0,sizeof(struct arlan_private));
+
 	((struct arlan_private *) dev->priv)->conf =
 	    kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL);
 
@@ -1202,6 +1226,9 @@
 	dev->set_multicast_list = arlan_set_multicast;
 	dev->change_mtu = arlan_change_mtu;
 	dev->set_mac_address = arlan_mac_addr;
+	dev->tbusy = 1;
+	dev->start = 0;
+	
 	((struct arlan_private *) dev->priv)->irq_test_done = 0;
 	arlan_device[num] = dev;
 	((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]);
@@ -1224,7 +1251,7 @@
 	if (arlan_check_fingerprint(memaddr))
 		return -ENODEV;
 
-	printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr);
+	printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, (int) virt_to_phys((void*)memaddr));
 
 	if (!arlan_allocate_device(arlans_found, dev))
 		return -1;
@@ -1264,14 +1291,13 @@
 		return ret;
 
 	arlan = ((struct arlan_private *) dev->priv)->card;
-
 	if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev))
 	{
 		printk(KERN_ERR "%s: unable to get IRQ %d .\n",
 			dev->name, dev->irq);
 		return -EAGAIN;
 	}
-	arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+
 
 	priv->bad = 0;
 	priv->lastReset = 0;
@@ -1282,15 +1308,10 @@
 	dev->tbusy = 1;
 	priv->txOffset = 0;
 	dev->interrupt = 0;
-	dev->start = 1;
+	dev->start = 0;
 	dev->tx_queue_len = tx_queue_len;
-	init_timer(&priv->timer);
-	priv->timer.expires = jiffies + HZ / 10;
-	priv->timer.data = (unsigned long) dev;
-	priv->timer.function = &arlan_registration_timer;	/* timer handler */
 	priv->interrupt_processing_active = 0;
 	priv->command_lock = 0;
-	add_timer(&priv->timer);
 
 	priv->card_lock = MUTEX;
 	myATOMIC_INIT(priv->card_users, 1);	/* damn 2.0.33 */
@@ -1298,7 +1319,8 @@
 	priv->registrationLastSeen = jiffies;
 	priv->txLast = 0;
 	priv->tx_command_given = 0;
-
+	priv->rx_command_given = 0;
+	
 	priv->reRegisterExp = 1;
 	priv->nof_tx = 0;
 	priv->nof_tx_ack = 0;
@@ -1309,6 +1331,16 @@
 	priv->Conf->registrationInterrupts = 1;
 
 	dev->tbusy = 0;
+	init_timer(&priv->timer);
+	priv->timer.expires = jiffies + HZ / 10;
+	priv->timer.data = (unsigned long) dev;
+	priv->timer.function = &arlan_registration_timer;	/* timer handler */
+
+	arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+	udelay(200000);
+	dev->tbusy = 0;
+	dev->start = 1;
+	add_timer(&priv->timer);
 
 	MOD_INC_USE_COUNT;
 #ifdef CONFIG_PROC_FS
@@ -1901,29 +1933,31 @@
 	}
 	ARLAN_DEBUG_ENTRY("arlan_close");
 
+	del_timer(&priv->timer);
+
+	arlan_command(dev, ARLAN_COMMAND_POWERDOWN);
+
 	IFDEBUG(ARLAN_DEBUG_STARTUP)
 		printk(KERN_NOTICE "%s: Closing device\n", dev->name);
 
 	priv->open_time = 0;
 	dev->tbusy = 1;
 	dev->start = 0;
-	del_timer(&priv->timer);
 	free_irq(dev->irq, dev);
-
 	MOD_DEC_USE_COUNT;
 
 	ARLAN_DEBUG_EXIT("arlan_close");
 	return 0;
 }
 
-
+#ifdef ARLAN_DEBUGING
 static long alignLong(volatile u_char * ptr)
 {
 	long ret;
 	memcpy_fromio(&ret, (void *) ptr, 4);
 	return ret;
 }
-
+#endif
 
 /*
  * Get the current statistics.
@@ -2044,6 +2078,7 @@
 		}
 		if (probe)
 			arlan_probe_everywhere(arlan_device[i]);
+//		arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
 	}
 	printk(KERN_INFO "Arlan driver %s\n", arlan_version);
 	ARLAN_DEBUG_EXIT("init_module");
@@ -2063,6 +2098,9 @@
 	{
 		if (arlan_device[i])
 		{
+			arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
+
+//			release_mem_region(virt_to_phys(arlan_device[i]->mem_start), 0x2000 );
 			unregister_netdev(arlan_device[i]);
 			if (arlan_device[i]->priv)
 			{
diff -urN linux-2.2.15-pre13/drivers/net/arlan.h linux/drivers/net/arlan.h
--- linux-2.2.15-pre13/drivers/net/arlan.h	Mon Aug  9 12:04:39 1999
+++ linux/drivers/net/arlan.h	Mon Dec  3 22:01:11 2001
@@ -29,7 +29,7 @@
 #include <linux/etherdevice.h>
 
 
-#define DEBUG 1
+//#define ARLAN_DEBUGING 1
 
 #define ARLAN_PROC_INTERFACE
 #define MAX_ARLANS 4 /* not more than 4 ! */
@@ -46,13 +46,14 @@
 #endif
 
 extern struct device *arlan_device[MAX_ARLANS];
-static int	arlan_debug;
-static char *	siteName;
-static int	arlan_entry_debug;
-static int	arlan_exit_debug;
-static int	arlan_entry_and_exit_debug;
-static int	testMemory;
-static const char* arlan_version;
+extern int	arlan_debug;
+extern char *	siteName;
+extern int	arlan_entry_debug;
+extern int	arlan_exit_debug;
+extern int	arlan_entry_and_exit_debug;
+extern int	testMemory;
+extern const char* arlan_version;
+extern  int	arlan_command(struct device * dev, int command);
  
 #define SIDUNKNOWN -1
 #define radioNodeIdUNKNOWN -1
@@ -75,7 +76,8 @@
 #define IFDEBUG( L ) if ( (L) & arlan_debug ) 
 #define ARLAN_FAKE_HDR_LEN 12 
 
-#ifdef DEBUG
+#ifdef ARLAN_DEBUGING
+	#define DEBUG 1
 	#define ARLAN_ENTRY_EXIT_DEBUGING 1
 	#define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
 #else
@@ -532,26 +534,27 @@
 
 
 
-#define ARLAN_COMMAND_RX		0x00001
-#define ARLAN_COMMAND_NOOP		0x00002
-#define ARLAN_COMMAND_NOOPINT		0x00004
-#define ARLAN_COMMAND_TX		0x00008
-#define ARLAN_COMMAND_CONF		0x00010
-#define ARLAN_COMMAND_RESET		0x00020
-#define ARLAN_COMMAND_TX_ABORT		0x00040
-#define ARLAN_COMMAND_RX_ABORT		0x00080
-#define ARLAN_COMMAND_POWERDOWN		0x00100
-#define ARLAN_COMMAND_POWERUP		0x00200
-#define ARLAN_COMMAND_SLOW_POLL 	0x00400
-#define ARLAN_COMMAND_ACTIVATE 		0x00800
-#define ARLAN_COMMAND_INT_ACK		0x01000
-#define ARLAN_COMMAND_INT_ENABLE	0x02000
-#define ARLAN_COMMAND_WAIT_NOW		0x04000
-#define ARLAN_COMMAND_LONG_WAIT_NOW	0x08000
-#define ARLAN_COMMAND_STANDBY		0x10000
-#define ARLAN_COMMAND_INT_RACK		0x20000
-#define ARLAN_COMMAND_INT_RENABLE	0x40000
-#define ARLAN_COMMAND_CONF_WAIT		0x80000
+#define ARLAN_COMMAND_RX		0x000001
+#define ARLAN_COMMAND_NOOP		0x000002
+#define ARLAN_COMMAND_NOOPINT		0x000004
+#define ARLAN_COMMAND_TX		0x000008
+#define ARLAN_COMMAND_CONF		0x000010
+#define ARLAN_COMMAND_RESET		0x000020
+#define ARLAN_COMMAND_TX_ABORT		0x000040
+#define ARLAN_COMMAND_RX_ABORT		0x000080
+#define ARLAN_COMMAND_POWERDOWN		0x000100
+#define ARLAN_COMMAND_POWERUP		0x000200
+#define ARLAN_COMMAND_SLOW_POLL 	0x000400
+#define ARLAN_COMMAND_ACTIVATE 		0x000800
+#define ARLAN_COMMAND_INT_ACK		0x001000
+#define ARLAN_COMMAND_INT_ENABLE	0x002000
+#define ARLAN_COMMAND_WAIT_NOW		0x004000
+#define ARLAN_COMMAND_LONG_WAIT_NOW	0x008000
+#define ARLAN_COMMAND_STANDBY		0x010000
+#define ARLAN_COMMAND_INT_RACK		0x020000
+#define ARLAN_COMMAND_INT_RENABLE	0x040000
+#define ARLAN_COMMAND_CONF_WAIT		0x080000
+#define ARLAN_COMMAND_TBUSY_CLEAR	0x100000
 #define ARLAN_COMMAND_CLEAN_AND_CONF	(ARLAN_COMMAND_TX_ABORT\
 					| ARLAN_COMMAND_RX_ABORT\
 					| ARLAN_COMMAND_CONF)
diff -urN linux-2.2.15-pre13/drivers/net/comx.c linux/drivers/net/comx.c
--- linux-2.2.15-pre13/drivers/net/comx.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/net/comx.c	Mon Dec  3 22:01:11 2001
@@ -59,6 +59,10 @@
 #include <linux/kmod.h>
 #endif
 
+#ifndef CONFIG_PROC_FS
+#error For now, COMX really needs the /proc filesystem
+#endif
+
 #include "comx.h"
 #include "syncppp.h"
 
diff -urN linux-2.2.15-pre13/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- linux-2.2.15-pre13/drivers/net/dgrs.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/net/dgrs.c	Mon Dec  3 22:01:11 2001
@@ -861,6 +861,8 @@
 				return -EFAULT;
 			return (0);
 		case DGRS_SETFILTER:
+			if (!suser())
+				return -EPERM;
 			if (ioc.port > privN->bcomm->bc_nports)
 				return -EINVAL;
 			if (ioc.filter >= NFILTERS)
@@ -1198,7 +1200,7 @@
 	priv->intrcnt = 0;
 	for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
 	{
-		rmb();		/* gcc 2.95 needs this */
+		barrier();		/* gcc 2.95 needs this */
 		if (priv->intrcnt >= 2)
 			break;
 	}
diff -urN linux-2.2.15-pre13/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c
--- linux-2.2.15-pre13/drivers/net/hamradio/baycom_epp.c	Fri Mar 26 13:57:41 1999
+++ linux/drivers/net/hamradio/baycom_epp.c	Mon Dec  3 22:01:11 2001
@@ -1308,6 +1308,8 @@
 		break;		
 
 	case HDLCDRVCTL_CALIBRATE:
+		if (!suser())
+			return -EACCES;
 		bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8;
 		return 0;
 
diff -urN linux-2.2.15-pre13/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c
--- linux-2.2.15-pre13/drivers/net/hamradio/hdlcdrv.c	Mon Aug  9 12:04:39 1999
+++ linux/drivers/net/hamradio/hdlcdrv.c	Mon Dec  3 22:01:11 2001
@@ -701,6 +701,8 @@
 		break;		
 
 	case HDLCDRVCTL_CALIBRATE:
+		if(!suser())
+			return -EPERM;
 		s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
 		return 0;
 
diff -urN linux-2.2.15-pre13/drivers/net/plip.c linux/drivers/net/plip.c
--- linux-2.2.15-pre13/drivers/net/plip.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/net/plip.c	Mon Dec  3 22:01:11 2001
@@ -1198,6 +1198,8 @@
 		pc->nibble  = nl->nibble;
 		break;
 	case PLIP_SET_TIMEOUT:
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		nl->trigger = pc->trigger;
 		nl->nibble  = pc->nibble;
 		break;
diff -urN linux-2.2.15-pre13/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- linux-2.2.15-pre13/drivers/net/rcpci45.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/net/rcpci45.c	Mon Dec  3 22:01:11 2001
@@ -1152,6 +1152,9 @@
     printk("RCioctl: cmd = 0x%x\n", cmd);
 #endif
  
+    if(!capable(CAP_NET_ADMIN))
+    	return -EPERM;
+    	
     switch (cmd)  {
  
     case RCU_PROTOCOL_REV:
@@ -1165,17 +1168,8 @@
 
     case RCU_COMMAND:
     {
-#ifdef LINUX_2_1
         if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
              return -EFAULT;
-#else
-        int error;
-        error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
-        if (error)  {
-            return error;
-        }
-        memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
-#endif
         
 #ifdef RCDEBUG
         printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
@@ -1284,11 +1278,8 @@
             RCUD_DEFAULT -> rc = 0x11223344;
             break;
         }
-#ifdef LINUX_2_1
-        copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
-#else
-        memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
-#endif
+        if(copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser)))
+        	return -EFAULT;
         break;
     }   /* RCU_COMMAND */ 
 
diff -urN linux-2.2.15-pre13/drivers/net/sbni.c linux/drivers/net/sbni.c
--- linux-2.2.15-pre13/drivers/net/sbni.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/net/sbni.c	Mon Dec  3 22:01:11 2001
@@ -1223,6 +1223,8 @@
 		}
 		case SIOCDEVRESINSTATS:
 		{
+			if(!capable(CAP_NET_ADMIN))
+				return -EPERM;
 			DP( printk("%s: SIOCDEVRESINSTATS\n",dev->name); )
 			lp->in_stats.all_rx_number = 0;
 			lp->in_stats.bad_rx_number = 0;
diff -urN linux-2.2.15-pre13/drivers/net/sktr.c linux/drivers/net/sktr.c
--- linux-2.2.15-pre13/drivers/net/sktr.c	Tue Jan  4 10:12:18 2000
+++ linux/drivers/net/sktr.c	Mon Dec  3 22:01:11 2001
@@ -13,6 +13,8 @@
  *	- SysKonnect TR4/16(+) ISA	(SK-4190)
  *	- SysKonnect TR4/16(+) PCI	(SK-4590)
  *	- SysKonnect TR4/16 PCI		(SK-4591)
+ *	- Compact TR PCI adapters
+ *	- Proteon TR ISA adapters	(1392, 1392+)
  *
  *  Sources:
  *  	- The hardware related parts of this driver are take from
@@ -23,10 +25,13 @@
  *  	  as samples for some tasks.
  *
  *  Maintainer(s):
- *    JS        Jay Schulist            jschlst@samba.anu.edu.au
+ *    retired: JS        Jay Schulist            jschlst@samba.anu.edu.au
  *    CG	Christoph Goos          cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
  *
+ *  Contributor(s):
+ *    AB	Alexander Bech		Initiated Proteon works
+ *
  *  Modification History:
  *	29-Aug-97	CG	Created
  *	04-Apr-98	CG	Fixed problems caused by tok_timer_check
@@ -38,14 +43,17 @@
  *	21-Sep-99	AF	Added multicast changes recommended by 
  *				  Jochen Friedrich <jochen@nwe.de> (untested)
  *				Added detection of compatible Compaq PCI card  
+ *	04-Jan-2000	CG	Fixed tx-send/release synchronization
+ *	04-Mar-2000	CG	Added detection/init of Proteon ISA card
+ *	05-Mar-2000	CG	Added line speed setting (parameter "rate")
  *
  *  To do:
- *    1. Selectable 16 Mbps or 4Mbps
+ *    1. Selectable 16 Mbps or 4Mbps (CG: done)
  *    2. Multi/Broadcast packet handling (might be done)
  *
  */
 
-static const char *version = "sktr.c: v1.01 08/29/97 by Christoph Goos\n";
+static const char *version = "sktr.c: v1.02 08/29/97 by Christoph Goos\n";
 
 #ifdef MODULE
 #include <linux/module.h>
@@ -71,6 +79,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -82,7 +91,11 @@
 
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int sktr_portlist[] __initdata = {
-	0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,
+	0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
+	0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.
+	0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.
+	0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.
+	0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.
 	0
 };
 
@@ -100,11 +113,28 @@
 	0
 };
 
+static unsigned short proteon_irqlist[] = {
+	7, 6, 5, 4, 3, 12, 11, 10, 9,
+	0
+};
+static int proteon_dmalist[] __initdata = {
+	5, 6, 7,
+	0
+};
+
+
 /* Card names */
 static char *pci_cardname = "SK NET TR 4/16 PCI\0";
 static char *isa_cardname = "SK NET TR 4/16 ISA\0";
+static char *proteon_cardname = "Proteon 1392\0";
 static char *AdapterName;
 
+static int AdapterNum = 0;
+
+#ifdef MODULE
+static int rate[SKTR_MAX_ADAPTERS] 	= { SPEED_16,  };
+#endif
+
 /* Use 0 for production, 1 for verification, 2 for debug, and
  * 3 for very verbose debug.
  */
@@ -152,8 +182,10 @@
 static void 	sktr_init_net_local(struct device *dev);
 static void 	sktr_init_opb(struct net_local *tp);
 static void 	sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int 	sktr_isa_chk_card(struct device *dev, int ioaddr);
+static int 	sktr_isa_chk_card(struct device *dev, int ioaddr,
+			int *cardtype);
 static int      sktr_isa_chk_ioaddr(int ioaddr);
+static int      prot_isa_chk_ioaddr(int ioaddr);
 /* "O" */
 static int 	sktr_open(struct device *dev);
 static void	sktr_open_adapter(struct device *dev);
@@ -170,6 +202,8 @@
 static int 	sktr_reset_adapter(struct device *dev);
 static void 	sktr_reset_interrupt(struct device *dev);
 static void 	sktr_ring_status_irq(struct device *dev);
+static void	sktr_reg_setup(struct device *dev);
+static void	prot_reg_setup(struct device *dev);
 /* "S" */
 static int 	sktr_send_packet(struct sk_buff *skb, struct device *dev);
 static void 	sktr_set_multicast_list(struct device *dev);
@@ -304,16 +338,32 @@
 }
 
 /*
- * Detect and setup the ISA SysKonnect TR cards.
+ * Detect and setup the ISA Proteon and SysKonnect TR cards.
  */
-__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
+__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr,
+int *cardtype))
 {
 	int i, err;
 	unsigned long flags;
+	unsigned short *irqlist;
+	int *dmalist;
+
+	err = prot_isa_chk_ioaddr(ioaddr);
+	if (err < 0) {
+		err = sktr_isa_chk_ioaddr(ioaddr);
+		if(err < 0)
+			return (-ENODEV);
+		AdapterName = isa_cardname;
+		*cardtype = SK_ISA;
+		irqlist = sktr_irqlist;
+		dmalist = sktr_dmalist;
+	} else {
+		AdapterName = proteon_cardname;
+		*cardtype = PROT_ISA;
+		irqlist = proteon_irqlist;
+		dmalist = proteon_dmalist;
+	}
 
-	err = sktr_isa_chk_ioaddr(ioaddr);
-	if(err < 0)
-		return (-ENODEV);
 
         if(virt_to_bus((void*)((unsigned long)dev->priv+sizeof(struct net_local)))
 		> ISA_MAX_ADDRESS)
@@ -323,8 +373,6 @@
                 return (-EAGAIN);
         }
 
-	AdapterName = isa_cardname;
-
         /* Grab the region so that no one else tries to probe our ioports. */
         request_region(ioaddr, SKTR_IO_EXTENT, AdapterName);
         dev->base_addr = ioaddr;
@@ -332,15 +380,15 @@
         /* Autoselect IRQ and DMA if dev->irq == 0 */
         if(dev->irq == 0)
         {
-                for(i = 0; sktr_irqlist[i] != 0; i++)
+                for(i = 0; irqlist[i] != 0; i++)
                 {
-                        dev->irq = sktr_irqlist[i];
+                        dev->irq = irqlist[i];
                         err = request_irq(dev->irq, &sktr_interrupt, 0, AdapterName, dev);
                         if(!err)
 				break;
                 }
 
-                if(sktr_irqlist[i] == 0)
+                if(irqlist[i] == 0)
                 {
                         printk("%s: AutoSelect no IRQ available\n", dev->name);
                         return (-EAGAIN);
@@ -359,9 +407,9 @@
         /* Always allocate the DMA channel after IRQ and clean up on failure */
         if(dev->dma == 0)
         {
-                for(i = 0; sktr_dmalist[i] != 0; i++)
+                for(i = 0; dmalist[i] != 0; i++)
                 {
-			dev->dma = sktr_dmalist[i];
+			dev->dma = dmalist[i];
                         err = request_dma(dev->dma, AdapterName);
                         if(!err)
                                 break;
@@ -416,10 +464,9 @@
 	err = sktr_pci_chk_card(dev);
 	if(err < 0)
 	{
-		err = sktr_isa_chk_card(dev, ioaddr);
+		err = sktr_isa_chk_card(dev, ioaddr, &DeviceType);
 		if(err < 0)
 			return (-ENODEV);
-		DeviceType = SK_ISA;
 	}
 
 	/* Setup this devices private information structure */
@@ -428,6 +475,12 @@
 		return (-ENOMEM);
 	memset(tp, 0, sizeof(struct net_local));
 	tp->DeviceType = DeviceType;
+	if(DeviceType == SK_ISA || DeviceType == PROT_ISA)
+		tp->BusType = BUS_TYPE_ISA;
+	else
+		tp->BusType = BUS_TYPE_PCI;
+	tp->DataRate = rate[AdapterNum];
+	AdapterNum++;
 
 	dev->priv		= tp;
 	dev->init               = sktr_init_card;
@@ -486,6 +539,28 @@
 }
 
 /*
+ * This function tests if a proteon adapter is really installed at the
+ * given I/O address. Return negative if no adapter at IO addr.
+ */
+__initfunc(static int prot_isa_chk_ioaddr(int ioaddr))
+{
+	unsigned char chk1, chk2;
+	int i;
+
+	chk1 = inb(ioaddr + 0x1f);	/* Get Proteon ID reg 1 */
+	if (chk1 != 0x1f)
+		return (-1);
+	chk1 = inb(ioaddr + 0x1e) & 0x07;	/* Get Proteon ID reg 0 */
+	for (i=0; i<16; i++) {
+		chk2 = inb(ioaddr + 0x1e) & 0x07;
+		if (((chk1 + 1) & 0x07) != chk2)
+			return (-1);
+		chk1 = chk2;
+	}
+	return (0);
+}
+
+/*
  * Open/initialize the board. This is called sometime after
  * booting when the 'ifconfig' program is run.
  *
@@ -502,7 +577,7 @@
 	err = sktr_chipset_init(dev);
 	if(err)
 	{
-		printk(KERN_INFO "%s: Chipset initialization error\n", 
+		printk("%s: Chipset initialization error\n", 
 			dev->name);
 		return (-1);
 	}
@@ -574,14 +649,90 @@
 	return;
 }
 
+/* setup non-standard registers for SK ISA adapters */
+static void sktr_reg_setup(struct device *dev)
+{
+	struct net_local *tp = (struct net_local *)dev->priv;
+	unsigned char PosReg, Tmp;
+	int i;
+	unsigned short *irqlist;
+
+	irqlist = sktr_irqlist;
+	PosReg = 0;
+	for(i = 0; irqlist[i] != 0; i++)
+	{
+		if(irqlist[i] == dev->irq)
+			break;
+	}
+
+	/* Choose default cycle time, 500 nsec   */
+	PosReg |= CYCLE_TIME << 2;
+	PosReg |= i << 4;
+	i = dev->dma - 5;
+	PosReg |= i;
+
+	if(tp->DataRate == SPEED_4)
+		PosReg |= LINE_SPEED_BIT;
+	else
+		PosReg &= ~LINE_SPEED_BIT;
+
+	outb(PosReg, dev->base_addr + POSREG);
+	Tmp = inb(dev->base_addr + POSREG);
+	if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
+		printk("%s: POSREG error\n", dev->name);
+
+	return;
+}
+
+/* setup non-standard registers for Proteon ISA adapters */
+static void prot_reg_setup(struct device *dev)
+{
+	struct net_local *tp = (struct net_local *)dev->priv;
+	unsigned char PosReg;
+	int i;
+	unsigned short *irqlist;
+
+	/* Proteon reset sequence */
+	outb(0, dev->base_addr + 0x11);
+	mdelay(20);
+	outb(0x04, dev->base_addr + 0x11);
+	mdelay(20);
+	outb(0, dev->base_addr + 0x11);
+	mdelay(100);
+
+	/* set control/status reg */
+	PosReg = inb(dev->base_addr + 0x11);
+	PosReg |= 0x78;
+	PosReg &= 0xf9;
+	if(tp->DataRate == SPEED_4)
+		PosReg |= 0x20;
+	else
+		PosReg &= ~0x20;
+
+	outb(PosReg, dev->base_addr + 0x11);
+	outb(0xff, dev->base_addr + 0x12);
+	irqlist = proteon_irqlist;
+	for(i = 0; irqlist[i] != 0; i++)
+	{
+		if(irqlist[i] == dev->irq)
+			break;
+	}
+
+	PosReg = i;
+	i = (7 - dev->dma) << 4;
+	PosReg |= i;
+	outb(PosReg, dev->base_addr + 0x13);
+
+	return;
+}
+
 /*
  * Initialize the chipset
  */
 static int sktr_chipset_init(struct device *dev)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
-	unsigned char PosReg, Tmp;
-	int i, err;
+	int err;
 
 	sktr_init_ipb(tp);
 	sktr_init_opb(tp);
@@ -590,43 +741,28 @@
 	/* Set pos register: selects irq and dma channel.
 	 * Only for ISA bus adapters.
 	 */
-	if(dev->dma > 0)
-	{
-		PosReg = 0;
-		for(i = 0; sktr_irqlist[i] != 0; i++)
-		{
-			if(sktr_irqlist[i] == dev->irq)
-				break;
-		}
-
-		/* Choose default cycle time, 500 nsec   */
-		PosReg |= CYCLE_TIME << 2;
-		PosReg |= i << 4;
-		i = dev->dma - 5;
-		PosReg |= i;
-
-		if(tp->DataRate == SPEED_4)
-			PosReg |= LINE_SPEED_BIT;
-		else
-			PosReg &= ~LINE_SPEED_BIT;
-
-		outb(PosReg, dev->base_addr + POSREG);
-		Tmp = inb(dev->base_addr + POSREG);
-		if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
-			printk(KERN_INFO "%s: POSREG error\n", dev->name);
-	}
+	if (tp->DeviceType == SK_ISA)
+		sktr_reg_setup(dev);
+	else if (tp->DeviceType == PROT_ISA)
+		prot_reg_setup(dev);
 
 	err = sktr_reset_adapter(dev);
-	if(err < 0)
+	if(err < 0) {
+		printk("sktr_reset_adapter failed\n");
 		return (-1);
+	}
 
 	err = sktr_bringup_diags(dev);
-	if(err < 0)
+	if(err < 0) {
+		printk("sktr_bringup_diag failed\n");
 		return (-1);
+	}
 
 	err = sktr_init_adapter(dev);
-	if(err < 0)
+	if(err < 0) {
+		printk("sktr_init_adapter failed\n");
 		return (-1);
+	}
 
 	return (0);
 }
@@ -660,9 +796,10 @@
 	tp->LobeWireFaultLogged	= 0;
 	tp->LastOpenStatus	= 0;
 	tp->MaxPacketSize	= DEFAULT_PACKET_SIZE;
+	tp->Sending		= 0;
 
 	skb_queue_head_init(&tp->SendSkbQueue);
-	tp->QueueSkb = MAX_TX_QUEUE;
+	atomic_set(&tp->QueueSkb, MAX_TX_QUEUE);
 
 	/* Create circular chain of transmit lists */
 	for (i = 0; i < TPL_NUM; i++)
@@ -704,12 +841,14 @@
 			skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
 
 			/* data unreachable for DMA ? then use local buffer */
-			if(tp->DeviceType == SK_ISA &&
+			if(tp->BusType == BUS_TYPE_ISA &&
 				virt_to_bus(tp->Rpl[i].Skb->data) +
 				tp->MaxPacketSize > ISA_MAX_ADDRESS)
 			{
 				tp->Rpl[i].SkbStat = SKB_DATA_COPY;
-				tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
+				tp->Rpl[i].FragList[0].DataAddr =
+					htonl(virt_to_bus(
+					tp->LocalRxBuffers[i]));
 				tp->Rpl[i].MData = tp->LocalRxBuffers[i];
 			}
 			else	/* DMA directly in skb->data */
@@ -880,13 +1019,13 @@
 		return (1);
 	}
 
-	if(tp->QueueSkb == 0)
+	if(atomic_read(&tp->QueueSkb) == 0)
 		return (1);	/* Return with tbusy set: queue full */
 
-	tp->QueueSkb--;
+	atomic_dec(&tp->QueueSkb);
 	skb_queue_tail(&tp->SendSkbQueue, skb);
 	sktr_hardware_send_packet(dev, tp);
-	if(tp->QueueSkb > 0)
+	if(atomic_read(&tp->QueueSkb) > 0)
 		dev->tbusy = 0;
 
 	return (0);
@@ -903,6 +1042,7 @@
 	struct sk_buff *skb;
 	int i;
     
+	tp->Sending = 1;
 	for(;;)
 	{
 		/* Try to get a free TPL from the chain.
@@ -912,18 +1052,21 @@
 		 */
 		if(tp->TplFree->NextTPLPtr->BusyFlag)	/* No free TPL */
 		{
-			printk(KERN_INFO "%s: No free TPL\n", dev->name);
+			// printk("%s: No free TPL\n", dev->name);
+			tp->Sending = 0;
 			return;
 		}
 
 		/* Send first buffer from queue */
 		skb = skb_dequeue(&tp->SendSkbQueue);
-		if(skb == NULL)
+		if(skb == NULL) {
+			tp->Sending = 0;
 			return;
+		}
 
-		tp->QueueSkb++;
+		atomic_inc(&tp->QueueSkb);
 		/* Is buffer reachable for Busmaster-DMA? */
-		if(tp->DeviceType == SK_ISA && 
+		if(tp->BusType == BUS_TYPE_ISA && 
 			virt_to_bus((void*)(((long) skb->data) + skb->len))
 			> ISA_MAX_ADDRESS)
 		{
@@ -946,6 +1089,7 @@
 
 		tp->LastSendTime	= jiffies;
 		tpl 			= tp->TplFree;	/* Get the "free" TPL */
+		tpl->Status		= 0;		/* set to INVALID */
 		tpl->BusyFlag 		= 1;		/* Mark TPL as busy */
 		tp->TplFree 		= tpl->NextTPLPtr;
     
@@ -967,6 +1111,7 @@
 		sktr_exec_sifcmd(dev, CMD_TX_VALID);
 	}
 
+	tp->Sending = 0;
 	return;
 }
 
@@ -1012,7 +1157,8 @@
 
 	sktr_chk_outstanding_cmds(dev);
 	if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
-		&& (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy))
+		&& (atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE ||
+		tp->TplFree != tp->TplBusy))
 	{
 		/* Anything to send, but stalled to long */
 		tp->LastSendTime = jiffies;
@@ -1059,7 +1205,8 @@
 
 		if(!sktr_chk_ssb(tp, irq_type))
 		{
-			printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
+			printk(KERN_DEBUG "%s: DATA LATE occurred\n",
+				dev->name);
 			break;
 		}
 
@@ -1107,7 +1254,7 @@
 				break;
 
 			default:
-				printk(KERN_INFO "Unknown Token Ring IRQ\n");
+				printk(KERN_DEBUG "Unknown Token Ring IRQ\n");
 				break;
 		}
 
@@ -1255,19 +1402,19 @@
 		else 	/* The adapter did not open. */
 		{
 	    		if(ssb_parm_0 & NODE_ADDR_ERROR)
-				printk(KERN_INFO "%s: Node address error\n",
+				printk("%s: Node address error\n",
 					dev->name);
 	    		if(ssb_parm_0 & LIST_SIZE_ERROR)
-				printk(KERN_INFO "%s: List size error\n",
+				printk("%s: List size error\n",
 					dev->name);
 	    		if(ssb_parm_0 & BUF_SIZE_ERROR)
-				printk(KERN_INFO "%s: Buffer size error\n",
+				printk("%s: Buffer size error\n",
 					dev->name);
 	    		if(ssb_parm_0 & TX_BUF_COUNT_ERROR)
-				printk(KERN_INFO "%s: Tx buffer count error\n",
+				printk("%s: Tx buffer count error\n",
 					dev->name);
 	    		if(ssb_parm_0 & INVALID_OPEN_OPTION)
-				printk(KERN_INFO "%s: Invalid open option\n",
+				printk("%s: Invalid open option\n",
 					dev->name);
 	    		if(ssb_parm_0 & OPEN_ERROR)
 			{
@@ -1278,7 +1425,7 @@
 						if(!tp->LobeWireFaultLogged)
 						{
 							tp->LobeWireFaultLogged = 1;
-							printk(KERN_INFO "%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
+							printk("%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
 		    				}
 						tp->ReOpenInProgress	= 1;
 						tp->AdapterOpenFlag 	= 0;
@@ -1287,27 +1434,27 @@
 						return;
 
 					case PHYSICAL_INSERTION:
-						printk(KERN_INFO "%s: %s Physical insertion.\n", dev->name, open_err);
+						printk("%s: %s Physical insertion.\n", dev->name, open_err);
 						break;
 
 					case ADDRESS_VERIFICATION:
-						printk(KERN_INFO "%s: %s Address verification.\n", dev->name, open_err);
+						printk("%s: %s Address verification.\n", dev->name, open_err);
 						break;
 
 					case PARTICIPATION_IN_RING_POLL:
-						printk(KERN_INFO "%s: %s Participation in ring poll.\n", dev->name, open_err);
+						printk("%s: %s Participation in ring poll.\n", dev->name, open_err);
 						break;
 
 					case REQUEST_INITIALISATION:
-						printk(KERN_INFO "%s: %s Request initialisation.\n", dev->name, open_err);
+						printk("%s: %s Request initialisation.\n", dev->name, open_err);
 						break;
 
 					case FULLDUPLEX_CHECK:
-						printk(KERN_INFO "%s: %s Full duplex check.\n", dev->name, open_err);
+						printk("%s: %s Full duplex check.\n", dev->name, open_err);
 						break;
 
 					default:
-						printk(KERN_INFO "%s: %s Unknown open phase\n", dev->name, open_err);
+						printk("%s: %s Unknown open phase\n", dev->name, open_err);
 						break;
 				}
 
@@ -1315,61 +1462,61 @@
 				switch(ssb_parm_0 & OPEN_ERROR_CODES_MASK)
 				{
 					case OPEN_FUNCTION_FAILURE:
-						printk(KERN_INFO "%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
+						printk("%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_FUNCTION_FAILURE;
 						break;
 
 					case OPEN_SIGNAL_LOSS:
-						printk(KERN_INFO "%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
+						printk("%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_SIGNAL_LOSS;
 						break;
 
 					case OPEN_TIMEOUT:
-						printk(KERN_INFO "%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
+						printk("%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_TIMEOUT;
 						break;
 
 					case OPEN_RING_FAILURE:
-						printk(KERN_INFO "%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
+						printk("%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_RING_FAILURE;
 						break;
 
 					case OPEN_RING_BEACONING:
-						printk(KERN_INFO "%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
+						printk("%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_RING_BEACONING;
 						break;
 
 					case OPEN_DUPLICATE_NODEADDR:
-						printk(KERN_INFO "%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
+						printk("%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_DUPLICATE_NODEADDR;
 						break;
 
 					case OPEN_REQUEST_INIT:
-						printk(KERN_INFO "%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
+						printk("%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_REQUEST_INIT;
 						break;
 
 					case OPEN_REMOVE_RECEIVED:
-						printk(KERN_INFO "%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
+						printk("%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_REMOVE_RECEIVED;
 						break;
 
 					case OPEN_FULLDUPLEX_SET:
-						printk(KERN_INFO "%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
+						printk("%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_FULLDUPLEX_SET;
 						break;
 
 					default:
-						printk(KERN_INFO "%s: %s Unknown open err code", dev->name, code_err);
+						printk("%s: %s Unknown open err code", dev->name, code_err);
 						tp->LastOpenStatus =
 							OPEN_FUNCTION_FAILURE;
 						break;
@@ -1646,7 +1793,7 @@
 	do {
 		retry_cnt--;
 		if(sktr_debug > 3)
-			printk(KERN_INFO "BUD-Status: \n");
+			printk("BUD-Status: \n");
 		loop_cnt = BUD_MAX_LOOPCNT;	/* maximum: three seconds*/
 		do {			/* Inspect BUD results */
 			loop_cnt--;
@@ -1655,7 +1802,7 @@
 			Status &= STS_MASK;
 
 			if(sktr_debug > 3)
-				printk(KERN_INFO " %04X \n", Status);
+				printk(" %04X \n", Status);
 			/* BUD successfully completed */
 			if(Status == STS_INITIALIZE)
 				return (1);
@@ -1666,7 +1813,7 @@
 		/* Error preventing completion of BUD */
 		if(retry_cnt > 0)
 		{
-			printk(KERN_INFO "%s: Adapter Software Reset.\n", 
+			printk("%s: Adapter Software Reset.\n", 
 				dev->name);
 			sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);
 			sktr_wait(HALF_SECOND);
@@ -1676,7 +1823,7 @@
 	Status = inw(ioaddr + SIFSTS);
 	Status &= STS_ERROR_MASK;	/* Hardware error occurred! */
 
-	printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
+	printk("%s: Bring Up Diagnostics Error (%04X) occurred\n",
 		dev->name, Status);
 
 	return (-1);
@@ -1977,56 +2124,57 @@
 	/* First: fill up statistics */
 	if(tp->ssb.Parm[0] & SIGNAL_LOSS)
 	{
-		printk(KERN_INFO "%s: Signal Loss\n", dev->name);
+		printk("%s: Signal Loss\n", dev->name);
 		tp->MacStat.line_errors++;
 	}
 
 	/* Adapter is closed, but initialized */
 	if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT)
 	{
-		printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n", 
+		printk("%s: Lobe Wire Fault, Reopen Adapter\n", 
 			dev->name);
 		tp->MacStat.line_errors++;
 	}
 
 	if(tp->ssb.Parm[0] & RING_RECOVERY)
-		printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+		printk("%s: Ring Recovery\n", dev->name);
 
 	/* Counter overflow: read error log */
 	if(tp->ssb.Parm[0] & COUNTER_OVERFLOW)
 	{
-		printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+		printk("%s: Counter Overflow\n", dev->name);
 		sktr_exec_cmd(dev, OC_READ_ERROR_LOG);
 	}
 
 	/* Adapter is closed, but initialized */
 	if(tp->ssb.Parm[0] & REMOVE_RECEIVED)
-		printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n", 
+		printk("%s: Remove Received, Reopen Adapter\n", 
 			dev->name);
 
 	/* Adapter is closed, but initialized */
 	if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR)
-		printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n", 
+		printk("%s: Auto Removal Error, Reopen Adapter\n", 
 			dev->name);
 
 	if(tp->ssb.Parm[0] & HARD_ERROR)
-		printk(KERN_INFO "%s: Hard Error\n", dev->name);
+		printk("%s: Hard Error\n", dev->name);
 
 	if(tp->ssb.Parm[0] & SOFT_ERROR)
-		printk(KERN_INFO "%s: Soft Error\n", dev->name);
+		printk("%s: Soft Error\n", dev->name);
 
 	if(tp->ssb.Parm[0] & TRANSMIT_BEACON)
-		printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+		printk("%s: Transmit Beacon\n", dev->name);
 
 	if(tp->ssb.Parm[0] & SINGLE_STATION)
-		printk(KERN_INFO "%s: Single Station\n", dev->name);
+		printk("%s: Single Station\n", dev->name);
 
 	/* Check if adapter has been closed */
 	if(tp->ssb.Parm[0] & ADAPTER_CLOSED)
 	{
-		printk(KERN_INFO "%s: Adapter closed (Reopening)," 
+		printk("%s: Adapter closed (Reopening)," 
 			"QueueSkb %d, CurrentRingStat %x\n",
-			dev->name, tp->QueueSkb, tp->CurrentRingStatus);
+			dev->name, atomic_read(&tp->QueueSkb),
+			tp->CurrentRingStatus);
 		tp->AdapterOpenFlag = 0;
 		sktr_open_adapter(dev);
 	}
@@ -2067,69 +2215,69 @@
 	switch(AdapterCheckBlock[0])
 	{
 		case DIO_PARITY:
-			printk(KERN_INFO "%s: DIO parity error\n", dev->name);
+			printk("%s: DIO parity error\n", dev->name);
 			break;
 
 		case DMA_READ_ABORT:
-			printk(KERN_INFO "%s DMA read operation aborted:\n",
+			printk("%s DMA read operation aborted:\n",
 				dev->name);
 			switch (AdapterCheckBlock[1])
 			{
 				case 0:
-					printk(KERN_INFO "Timeout\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Timeout\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2],
 						AdapterCheckBlock[3]);
 					break;
 
 				case 1:
-					printk(KERN_INFO "Parity error\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Parity error\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2], 
 						AdapterCheckBlock[3]);
 					break;
 
 				case 2: 
-					printk(KERN_INFO "Bus error\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Bus error\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2], 
 						AdapterCheckBlock[3]);
 					break;
 
 				default:
-					printk(KERN_INFO "Unknown error.\n");
+					printk("Unknown error.\n");
 					break;
 			}
 			break;
 
 		case DMA_WRITE_ABORT:
-			printk(KERN_INFO "%s: DMA write operation aborted: \n",
+			printk("%s: DMA write operation aborted: \n",
 				dev->name);
 			switch (AdapterCheckBlock[1])
 			{
 				case 0: 
-					printk(KERN_INFO "Timeout\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Timeout\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2], 
 						AdapterCheckBlock[3]);
 					break;
 
 				case 1: 
-					printk(KERN_INFO "Parity error\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Parity error\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2], 
 						AdapterCheckBlock[3]);
 					break;
 
 				case 2: 
-					printk(KERN_INFO "Bus error\n");
-					printk(KERN_INFO "Address: %04X %04X\n",
+					printk("Bus error\n");
+					printk("Address: %04X %04X\n",
 						AdapterCheckBlock[2], 
 						AdapterCheckBlock[3]);
 					break;
 
 				default:
-					printk(KERN_INFO "Unknown error.\n");
+					printk("Unknown error.\n");
 					break;
 			}
 			break;
@@ -2207,7 +2355,7 @@
 	sktr_read_ram(dev, (unsigned char *)&adapterram,
 			(unsigned short)SWAPB(tp->intptrs.AdapterRAMPtr), 2);
 
-	printk(KERN_INFO "%s: Adapter RAM size: %d K\n", 
+	printk("%s: Adapter RAM size: %d K\n", 
 		dev->name, SWAPB(adapterram));
 
 	return;
@@ -2301,7 +2449,7 @@
 		sktr_write_tpl_status(tpl, 0);	/* Clear VALID bit */
 		tpl->BusyFlag = 0;		/* "free" TPL */
 
-		printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
+		printk("Cancel tx (%08lXh).\n", (unsigned long)tpl);
 
 		dev_kfree_skb(tpl->Skb);
 	}
@@ -2311,7 +2459,7 @@
 		skb = skb_dequeue(&tp->SendSkbQueue);
 		if(skb == NULL)
 			break;
-		tp->QueueSkb++;
+		atomic_inc(&tp->QueueSkb);
 		dev_kfree_skb(skb);
 	}
 
@@ -2360,7 +2508,7 @@
 
 			if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED))
 			{
-				printk(KERN_INFO "%s: (DA=%08lX not recognized)",
+				printk("%s: (DA=%08lX not recognized)",
 					dev->name,
 					*(unsigned long *)&tpl->MData[2+2]);
 			}
@@ -2387,7 +2535,7 @@
 	}
 
 	dev->tbusy = 0;
-	if(tp->QueueSkb < MAX_TX_QUEUE)
+	if(atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE && !tp->Sending)
 		sktr_hardware_send_packet(dev, tp);
 
 	return;
@@ -2529,12 +2677,14 @@
 			skb_put(rpl->Skb, tp->MaxPacketSize);
 
 			/* Data unreachable for DMA ? then use local buffer */
-			if(tp->DeviceType == SK_ISA &&
+			if(tp->BusType == BUS_TYPE_ISA &&
 				virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize
 				> ISA_MAX_ADDRESS)
 			{
 				rpl->SkbStat = SKB_DATA_COPY;
-				rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
+				rpl->FragList[0].DataAddr = 
+					htonl(virt_to_bus(
+					tp->LocalRxBuffers[rpl->RPLIndex]));
 				rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
 			}
 			else
@@ -2637,13 +2787,14 @@
 #ifdef MODULE
 
 static struct device* dev_sktr[SKTR_MAX_ADAPTERS];
-static int io[SKTR_MAX_ADAPTERS]	= { 0, 0 };
-static int irq[SKTR_MAX_ADAPTERS] 	= { 0, 0 };
-static int mem[SKTR_MAX_ADAPTERS] 	= { 0, 0 };
+static int io[SKTR_MAX_ADAPTERS]	= { 0,  };
+static int irq[SKTR_MAX_ADAPTERS] 	= { 0,  };
+static int dma[SKTR_MAX_ADAPTERS] 	= { 0,  };
 
 MODULE_PARM(io,  "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(rate, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
 
 int init_module(void)
 {
@@ -2651,8 +2802,6 @@
 
 	for(i = 0; i < SKTR_MAX_ADAPTERS; i++)
 	{
-                irq[i] = 0;
-                mem[i] = 0;
                 dev_sktr[i] = NULL;
                 dev_sktr[i] = init_trdev(dev_sktr[i], 0);
                 if(dev_sktr[i] == NULL)
@@ -2660,7 +2809,7 @@
 
 		dev_sktr[i]->base_addr = io[i];
                 dev_sktr[i]->irq       = irq[i];
-                dev_sktr[i]->mem_start = mem[i];
+                dev_sktr[i]->dma       = dma[i];
                 dev_sktr[i]->init      = &sktr_probe;
 
                 if(register_trdev(dev_sktr[i]) != 0)
diff -urN linux-2.2.15-pre13/drivers/net/sktr.h linux/drivers/net/sktr.h
--- linux-2.2.15-pre13/drivers/net/sktr.h	Tue Oct 26 17:53:40 1999
+++ linux/drivers/net/sktr.h	Mon Dec  3 22:01:11 2001
@@ -16,8 +16,14 @@
 #define TR_RCF_LONGEST_FRAME_MASK 0x0070
 #define TR_RCF_FRAME4K 0x0030
 
+/* DeviceType values */
 #define SK_ISA 0
 #define SK_PCI 1
+#define PROT_ISA 2
+
+/* BusType values */
+#define BUS_TYPE_PCI	0
+#define BUS_TYPE_ISA	1
 
 /*------------------------------------------------------------------*/
 /*  Bit order for adapter communication with DMA		    */
@@ -1067,6 +1073,7 @@
 	unsigned short CMDqueue;
 
 	unsigned int DeviceType;
+	unsigned int BusType;
 
 	unsigned long AdapterOpenFlag:1;
 	unsigned long AdapterVirtOpenFlag:1;
@@ -1077,6 +1084,7 @@
 	unsigned long LobeWireFaultLogged:1;
 	unsigned long ReOpenInProgress:1;
 	unsigned long Sleeping:1;
+	unsigned long Sending:1;
 
 	unsigned long LastOpenStatus;
 	unsigned short CurrentRingStatus;
@@ -1086,7 +1094,7 @@
 	unsigned long LastSendTime;
 
 	struct sk_buff_head SendSkbQueue;
-	unsigned short QueueSkb;
+	atomic_t QueueSkb;
 
 	struct tr_statistics MacStat;	/* MAC statistics structure */
 
diff -urN linux-2.2.15-pre13/drivers/net/syncppp.c linux/drivers/net/syncppp.c
--- linux-2.2.15-pre13/drivers/net/syncppp.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/net/syncppp.c	Mon Dec  3 22:01:11 2001
@@ -326,7 +326,7 @@
 	h=(struct ppp_header *)skb->data;
 	if(sp->pp_flags&PP_CISCO)
 	{
-		h->address = CISCO_MULTICAST;
+		h->address = CISCO_UNICAST;
 		h->control = 0;
 	}
 	else
diff -urN linux-2.2.15-pre13/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
--- linux-2.2.15-pre13/drivers/scsi/3w-xxxx.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/scsi/3w-xxxx.c	Mon Dec  3 22:01:11 2001
@@ -91,7 +91,7 @@
 };
 
 /* Globals */
-char *tw_driver_version="1.0.000";
+char *tw_driver_version="1.1.000";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -2053,7 +2053,7 @@
 	command_packet->status = 0;
 	command_packet->flags = 0;
 
-        if ((srb->cmnd[0] == WRITE_6) || (srb->cmnd[0] == WRITE_10)) {
+        if (srb->cmnd[0] == WRITE_10) {
 	  if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
 	    command_packet->flags = 1;
         }
diff -urN linux-2.2.15-pre13/drivers/scsi/53c8xx_d.h linux/drivers/scsi/53c8xx_d.h
--- linux-2.2.15-pre13/drivers/scsi/53c8xx_d.h	Mon May 11 12:49:02 1998
+++ linux/drivers/scsi/53c8xx_d.h	Mon Dec  3 22:01:11 2001
@@ -1,4 +1,4 @@
-u32 SCRIPT[] = {
+static u32 SCRIPT[] = {
 /*
 
 
@@ -2179,40 +2179,40 @@
 };
 
 #define A_NCR53c7xx_msg_abort	0x00000000
-u32 A_NCR53c7xx_msg_abort_used[] = {
+static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
 	0x00000249,
 };
 
 #define A_NCR53c7xx_msg_reject	0x00000000
-u32 A_NCR53c7xx_msg_reject_used[] = {
+static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
 	0x00000172,
 };
 
 #define A_NCR53c7xx_sink	0x00000000
-u32 A_NCR53c7xx_sink_used[] = {
+static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
 	0x00000233,
 	0x00000239,
 	0x0000023f,
 };
 
 #define A_NCR53c7xx_zero	0x00000000
-u32 A_NCR53c7xx_zero_used[] = {
+static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
 	0x0000022f,
 	0x00000245,
 };
 
 #define A_NOP_insn	0x00000000
-u32 A_NOP_insn_used[] = {
+static u32 A_NOP_insn_used[] __attribute((unused)) = {
 	0x00000010,
 };
 
 #define A_addr_reconnect_dsa_head	0x00000000
-u32 A_addr_reconnect_dsa_head_used[] = {
+static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
 	0x000001a7,
 };
 
 #define A_addr_scratch	0x00000000
-u32 A_addr_scratch_used[] = {
+static u32 A_addr_scratch_used[] __attribute((unused)) = {
 	0x00000004,
 	0x0000001b,
 	0x00000046,
@@ -2227,13 +2227,13 @@
 };
 
 #define A_addr_temp	0x00000000
-u32 A_addr_temp_used[] = {
+static u32 A_addr_temp_used[] __attribute((unused)) = {
 	0x00000025,
 	0x00000034,
 };
 
 #define A_dmode_memory_to_memory	0x00000000
-u32 A_dmode_memory_to_memory_used[] = {
+static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
 	0x00000005,
 	0x0000001c,
 	0x00000027,
@@ -2251,7 +2251,7 @@
 };
 
 #define A_dmode_memory_to_ncr	0x00000000
-u32 A_dmode_memory_to_ncr_used[] = {
+static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
 	0x00000000,
 	0x00000017,
 	0x00000030,
@@ -2260,7 +2260,7 @@
 };
 
 #define A_dmode_ncr_to_memory	0x00000000
-u32 A_dmode_ncr_to_memory_used[] = {
+static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
 	0x00000022,
 	0x00000064,
 	0x00000070,
@@ -2272,161 +2272,161 @@
 };
 
 #define A_dsa_check_reselect	0x00000000
-u32 A_dsa_check_reselect_used[] = {
+static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
 	0x000001bd,
 };
 
 #define A_dsa_cmdout	0x00000048
-u32 A_dsa_cmdout_used[] = {
+static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
 	0x00000094,
 };
 
 #define A_dsa_cmnd	0x00000038
-u32 A_dsa_cmnd_used[] = {
+static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_datain	0x00000054
-u32 A_dsa_datain_used[] = {
+static u32 A_dsa_datain_used[] __attribute((unused)) = {
 	0x000000bb,
 };
 
 #define A_dsa_dataout	0x00000050
-u32 A_dsa_dataout_used[] = {
+static u32 A_dsa_dataout_used[] __attribute((unused)) = {
 	0x000000a5,
 };
 
 #define A_dsa_end	0x00000070
-u32 A_dsa_end_used[] = {
+static u32 A_dsa_end_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_fields_start	0x00000000
-u32 A_dsa_fields_start_used[] = {
+static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_msgin	0x00000058
-u32 A_dsa_msgin_used[] = {
+static u32 A_dsa_msgin_used[] __attribute((unused)) = {
 	0x00000188,
 };
 
 #define A_dsa_msgout	0x00000040
-u32 A_dsa_msgout_used[] = {
+static u32 A_dsa_msgout_used[] __attribute((unused)) = {
 	0x00000086,
 };
 
 #define A_dsa_msgout_other	0x00000068
-u32 A_dsa_msgout_other_used[] = {
+static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
 	0x00000180,
 };
 
 #define A_dsa_next	0x00000030
-u32 A_dsa_next_used[] = {
+static u32 A_dsa_next_used[] __attribute((unused)) = {
 	0x0000005c,
 };
 
 #define A_dsa_restore_pointers	0x00000000
-u32 A_dsa_restore_pointers_used[] = {
+static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
 	0x0000012e,
 };
 
 #define A_dsa_save_data_pointer	0x00000000
-u32 A_dsa_save_data_pointer_used[] = {
+static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
 	0x00000115,
 };
 
 #define A_dsa_select	0x0000003c
-u32 A_dsa_select_used[] = {
+static u32 A_dsa_select_used[] __attribute((unused)) = {
 	0x00000081,
 };
 
 #define A_dsa_status	0x00000060
-u32 A_dsa_status_used[] = {
+static u32 A_dsa_status_used[] __attribute((unused)) = {
 	0x00000184,
 };
 
 #define A_dsa_temp_addr_array_value	0x00000000
-u32 A_dsa_temp_addr_array_value_used[] = {
+static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_dsa_value	0x00000000
-u32 A_dsa_temp_addr_dsa_value_used[] = {
+static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
 	0x00000003,
 };
 
 #define A_dsa_temp_addr_new_value	0x00000000
-u32 A_dsa_temp_addr_new_value_used[] = {
+static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
 };
 
 #define A_dsa_temp_addr_next	0x00000000
-u32 A_dsa_temp_addr_next_used[] = {
+static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
 	0x00000015,
 	0x0000004e,
 };
 
 #define A_dsa_temp_addr_residual	0x00000000
-u32 A_dsa_temp_addr_residual_used[] = {
+static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
 	0x0000002a,
 	0x00000039,
 };
 
 #define A_dsa_temp_addr_saved_pointer	0x00000000
-u32 A_dsa_temp_addr_saved_pointer_used[] = {
+static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
 	0x00000026,
 	0x00000033,
 };
 
 #define A_dsa_temp_addr_saved_residual	0x00000000
-u32 A_dsa_temp_addr_saved_residual_used[] = {
+static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
 	0x0000002b,
 	0x00000038,
 };
 
 #define A_dsa_temp_lun	0x00000000
-u32 A_dsa_temp_lun_used[] = {
+static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
 	0x0000004b,
 };
 
 #define A_dsa_temp_next	0x00000000
-u32 A_dsa_temp_next_used[] = {
+static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
 	0x0000001a,
 };
 
 #define A_dsa_temp_sync	0x00000000
-u32 A_dsa_temp_sync_used[] = {
+static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
 	0x00000053,
 };
 
 #define A_dsa_temp_target	0x00000000
-u32 A_dsa_temp_target_used[] = {
+static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
 	0x00000040,
 };
 
 #define A_int_debug_break	0x03000000
-u32 A_int_debug_break_used[] = {
+static u32 A_int_debug_break_used[] __attribute((unused)) = {
 	0x00000217,
 };
 
 #define A_int_debug_panic	0x030b0000
-u32 A_int_debug_panic_used[] = {
+static u32 A_int_debug_panic_used[] __attribute((unused)) = {
 	0x000001e8,
 	0x000001f8,
 };
 
 #define A_int_err_check_condition	0x00030000
-u32 A_int_err_check_condition_used[] = {
+static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
 	0x00000194,
 };
 
 #define A_int_err_no_phase	0x00040000
-u32 A_int_err_no_phase_used[] = {
+static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
 };
 
 #define A_int_err_selected	0x00010000
-u32 A_int_err_selected_used[] = {
+static u32 A_int_err_selected_used[] __attribute((unused)) = {
 	0x000001da,
 };
 
 #define A_int_err_unexpected_phase	0x00000000
-u32 A_int_err_unexpected_phase_used[] = {
+static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
 	0x0000008c,
 	0x00000092,
 	0x0000009a,
@@ -2444,67 +2444,67 @@
 };
 
 #define A_int_err_unexpected_reselect	0x00020000
-u32 A_int_err_unexpected_reselect_used[] = {
+static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
 	0x000001ba,
 };
 
 #define A_int_msg_1	0x01020000
-u32 A_int_msg_1_used[] = {
+static u32 A_int_msg_1_used[] __attribute((unused)) = {
 	0x0000010e,
 	0x00000110,
 };
 
 #define A_int_msg_sdtr	0x01010000
-u32 A_int_msg_sdtr_used[] = {
+static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
 	0x0000016c,
 };
 
 #define A_int_msg_wdtr	0x01000000
-u32 A_int_msg_wdtr_used[] = {
+static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
 	0x00000160,
 };
 
 #define A_int_norm_aborted	0x02040000
-u32 A_int_norm_aborted_used[] = {
+static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
 	0x0000024d,
 };
 
 #define A_int_norm_command_complete	0x02020000
-u32 A_int_norm_command_complete_used[] = {
+static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_disconnected	0x02030000
-u32 A_int_norm_disconnected_used[] = {
+static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reselect_complete	0x02010000
-u32 A_int_norm_reselect_complete_used[] = {
+static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_reset	0x02050000
-u32 A_int_norm_reset_used[] = {
+static u32 A_int_norm_reset_used[] __attribute((unused)) = {
 };
 
 #define A_int_norm_select_complete	0x02000000
-u32 A_int_norm_select_complete_used[] = {
+static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
 };
 
 #define A_int_test_1	0x04000000
-u32 A_int_test_1_used[] = {
+static u32 A_int_test_1_used[] __attribute((unused)) = {
 	0x000001fd,
 };
 
 #define A_int_test_2	0x04010000
-u32 A_int_test_2_used[] = {
+static u32 A_int_test_2_used[] __attribute((unused)) = {
 	0x00000215,
 };
 
 #define A_int_test_3	0x04020000
-u32 A_int_test_3_used[] = {
+static u32 A_int_test_3_used[] __attribute((unused)) = {
 };
 
 #define A_msg_buf	0x00000000
-u32 A_msg_buf_used[] = {
+static u32 A_msg_buf_used[] __attribute((unused)) = {
 	0x00000102,
 	0x0000014e,
 	0x00000158,
@@ -2514,24 +2514,24 @@
 };
 
 #define A_reconnect_dsa_head	0x00000000
-u32 A_reconnect_dsa_head_used[] = {
+static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
 	0x0000006c,
 	0x00000074,
 	0x000001a0,
 };
 
 #define A_reselected_identify	0x00000000
-u32 A_reselected_identify_used[] = {
+static u32 A_reselected_identify_used[] __attribute((unused)) = {
 	0x00000045,
 	0x0000019c,
 };
 
 #define A_reselected_tag	0x00000000
-u32 A_reselected_tag_used[] = {
+static u32 A_reselected_tag_used[] __attribute((unused)) = {
 };
 
 #define A_schedule	0x00000000
-u32 A_schedule_used[] = {
+static u32 A_schedule_used[] __attribute((unused)) = {
 	0x0000007e,
 	0x00000192,
 	0x000001e2,
@@ -2539,12 +2539,12 @@
 };
 
 #define A_test_dest	0x00000000
-u32 A_test_dest_used[] = {
+static u32 A_test_dest_used[] __attribute((unused)) = {
 	0x000001fb,
 };
 
 #define A_test_src	0x00000000
-u32 A_test_src_used[] = {
+static u32 A_test_src_used[] __attribute((unused)) = {
 	0x000001fa,
 };
 
@@ -2582,7 +2582,7 @@
 #define Ent_test_2	0x000007f8
 #define Ent_test_2_msgout	0x00000810
 #define Ent_wait_reselect	0x00000654
-u32 LABELPATCHES[] = {
+static u32 LABELPATCHES[] __attribute((unused)) = {
 	0x00000008,
 	0x0000000a,
 	0x00000013,
@@ -2666,12 +2666,12 @@
 	0x00000243,
 };
 
-struct {
+static struct {
 	u32	offset;
 	void		*address;
-} EXTERNAL_PATCHES[] = {
+} EXTERNAL_PATCHES[] __attribute((unused)) = {
 };
 
-u32 INSTRUCTIONS	= 301;
-u32 PATCHES	= 81;
-u32 EXTERNAL_PATCHES_LEN	= 0;
+static u32 INSTRUCTIONS __attribute((unused))	= 301;
+static u32 PATCHES __attribute((unused))	= 81;
+static u32 EXTERNAL_PATCHES_LEN __attribute((unused))	= 0;
diff -urN linux-2.2.15-pre13/drivers/scsi/README.aic7xxx linux/drivers/scsi/README.aic7xxx
--- linux-2.2.15-pre13/drivers/scsi/README.aic7xxx	Tue Oct 26 17:53:41 1999
+++ linux/drivers/scsi/README.aic7xxx	Mon Dec  3 22:01:11 2001
@@ -208,6 +208,19 @@
 	will often result in the machine crashing or spontaneously rebooting
 	during startup.  Examples of machines that need this are the
 	Dell PowerEdge 6300 machines.
+
+    "aic7xxx=seltime:2" - This option controls how long the card waits
+        during a device selection sequence for the device to respond.
+	The original SCSI spec says that this "should be" 256ms.  This
+	is generally not required with modern devices.  However, some
+	very old SCSI I devices need the full 256ms.  Most modern devices
+	can run fine with only 64ms.  The default for this option is
+	64ms.  If you need to change this option, then use the following
+	table to set the proper value in the example above:
+	  0  -  256ms
+	  1  -  128ms
+	  2  -   64ms
+	  3  -   32ms
 	
     "aic7xxx=panic_on_abort" - This option is for debugging and will cause
         the driver to panic the linux kernel and freeze the system the first
@@ -485,12 +498,14 @@
 
   Web sites
   ------------------------------
-    http://people.redhat.com/dledford/aic7xxx.html
-      - Primary web site maintained by Doug Ledford.
+    http://people.redhat.com/dledford/
+      - My web site, also the primary aic7xxx site with several related
+        pages.
 
 Dean W. Gehnert
 deang@teleport.com
 
 $Revision: 3.0 $
 
-Modified by Doug Ledford 1998-9
+Modified by Doug Ledford 1998-2000
+
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx/aic7xxx.reg	Mon Aug  9 12:04:39 1999
+++ linux/drivers/scsi/aic7xxx/aic7xxx.reg	Mon Dec  3 22:01:11 2001
@@ -691,7 +691,8 @@
 	mask	NO_IDENT	0x20|SEQINT	/* no IDENTIFY after reconnect*/
 	mask	NO_MATCH	0x30|SEQINT	/* no cmd match for reconnect */
 	mask	EXTENDED_MSG	0x40|SEQINT	/* Extended message received */
-	mask	ABORT_REQUESTED 0x50|SEQINT	/* Reconect of aborted SCB */
+	mask	WIDE_RESIDUE	0x50|SEQINT	/* need kernel to back up */
+						/* the SG array for us */
 	mask	REJECT_MSG	0x60|SEQINT	/* Reject message received */
 	mask	BAD_STATUS	0x70|SEQINT	/* Bad status from target */
 	mask	RESIDUAL	0x80|SEQINT	/* Residual byte count != 0 */
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx/aic7xxx.seq	Tue Jan  4 10:12:19 2000
+++ linux/drivers/scsi/aic7xxx/aic7xxx.seq	Mon Dec  3 22:01:11 2001
@@ -182,6 +182,15 @@
 		and	SCSIID, OID;		/* Clear old target */
 		or	SCSIID, A;
 	}
+	mov	SCSIDATL, ALLZEROS;		/* clear out the latched */
+						/* data register, this */
+						/* fixes a bug on some */
+						/* controllers where the */
+						/* last byte written to */
+						/* this register can leak */
+						/* onto the data bus at */
+						/* bad times, such as during */
+						/* selection timeouts */
 	mvi	SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
 
 /*
@@ -448,8 +457,9 @@
 		if ((p->features & AHC_ULTRA2) != 0) {
 			bmov	HADDR, SHADDR, 4;
 			bmov    HCNT, SCB_RESID_DCNT, 3;
+		} else {
+			bmov    STCNT, SCB_RESID_DCNT, 3;
 		}
-		bmov    STCNT, SCB_RESID_DCNT, 3;
 	} else {
 		mvi	DINDEX, STCNT;
 		mvi	SCB_RESID_DCNT	call bcopy_3;
@@ -517,10 +527,12 @@
 	}
 data_phase_inbounds:
 /* If we are the last SG block, tell the hardware. */
-if ((p->features & AHC_ULTRA2) == 0) {
 	cmp	SG_COUNT,0x01 jne data_phase_wideodd;
-	and	DMAPARAMS, ~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;
@@ -530,7 +542,7 @@
 		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 . + 2;
+		test	SSTAT0,SDONE	jnz data_phase_dma_done;
 		clr	SINDEX;			/* Remember the phasemiss */
 	} else {
 		mov	DMAPARAMS  call dma;
@@ -615,9 +627,10 @@
 	test    SSTAT1, REQINIT jz .;
 	test	SSTAT1,PHASEMIS	jz data_phase_loop;
 
+/* 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 .;
+		test	SSTAT0, SDONE	jnz .;
 	}
 
 data_phase_finish:
@@ -713,7 +726,7 @@
 		mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
 		test	SSTAT0, SDONE jnz .;
 p_command_dma_loop:
-		test	SSTAT0, DMADONE jnz p_command_ultra2_dma_done;
+		test	SSTAT0, SDONE jnz p_command_ultra2_dma_done;
 		test	SSTAT1,PHASEMIS	jz p_command_dma_loop;	/* ie. underrun */
 p_command_ultra2_dma_done:
 		and     DFCNTRL, ~HDMAEN;
@@ -830,6 +843,7 @@
 	cmp	A,MSG_EXTENDED		je mesgin_extended;
 	cmp	A,MSG_MESSAGE_REJECT	je mesgin_reject;
 	cmp	A,MSG_NOOP		je mesgin_done;
+	cmp	A,MSG_IGN_WIDE_RESIDUE	je mesgin_wide_residue;
 
 rej_mesgin:
 /*
@@ -1057,6 +1071,33 @@
 	jmp	mesgin_done;
 
 /*
+ * Wide Residue.  We handle the simple cases, but pass of the one hard case
+ * to the kernel (when the residue byte happened to cause us to advance our
+ * sg element array, so we know have to back that advance out).
+ */
+mesgin_wide_residue:
+	mvi	ARG_1	call inb_next; /* ACK the wide_residue and get */
+				       /* the size byte */
+/*
+ * See if we'll ignore this wide residue (because it's an overrun byte)
+ */
+	test	SCB_RESID_SGCNT,0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[0],0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[1],0xff jnz wide_residue_int;
+	test	SCB_RESID_DCNT[2],0xff jnz wide_residue_int;
+	jmp	mesgin_done;
+
+wide_residue_int:
+/*
+ * In order for this to be reliable, we have to do all sorts of horrible
+ * magic in terms of resetting the datafifo and reloading the shadow layer
+ * with the correct new values (so that a subsequent save data pointers
+ * message will do the right thing).  We let the kernel do that work.
+ */
+ 	mvi	INTSTAT,WIDE_RESIDUE;
+	jmp	mesgin_done;
+	
+/*
  * [ ADD MORE MESSAGE HANDLING HERE ]
  */
 
@@ -1093,7 +1134,7 @@
 	 * before continuing.
 	 */
 	test	SSTAT1, REQINIT	jz inb_next_wait;
-	test	SSTAT1, SCSIPERR jnz inb_next_wait;
+	test	SSTAT1, SCSIPERR jnz .;
 	and	LASTPHASE, PHASE_MASK, SCSISIGI;
 	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;
 inb_first:
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/scsi/aic7xxx.c	Mon Dec  3 22:01:11 2001
@@ -270,7 +270,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.23"
+#define AIC7XXX_C_VERSION  "5.1.28"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -519,6 +519,7 @@
   "Adaptec AHA-394X Ultra SCSI host adapter",           /* AIC_7882 */
   "Adaptec AHA-398X Ultra SCSI host adapter",           /* AIC_7883 */
   "Adaptec AHA-2944 Ultra SCSI host adapter",           /* AIC_7884 */
+  "Adaptec AHA-2940UW Pro Ultra SCSI host adapter",     /* AIC_7887 */
   "Adaptec AIC-7895 Ultra SCSI host adapter",           /* AIC_7895 */
   "Adaptec AIC-7890/1 Ultra2 SCSI host adapter",        /* AIC_7890 */
   "Adaptec AHA-293X Ultra2 SCSI host adapter",          /* AIC_7890 */
@@ -833,6 +834,8 @@
   *  and what flags weren't.  This way, I could clean up the flag usage on
   *  a use by use basis.  Doug Ledford
   */
+        AHC_MOTHERBOARD           = 0x00020000,
+        AHC_NO_STPWEN             = 0x00040000,
         AHC_RESET_DELAY           = 0x00080000,
         AHC_A_SCANNED             = 0x00100000,
         AHC_B_SCANNED             = 0x00200000,
@@ -1364,10 +1367,10 @@
 /*
  * So that we can set how long each device is given as a selection timeout.
  * The table of values goes like this:
- * 	0 - 256ms
- * 	1 - 128ms
- * 	2 - 64ms
- * 	3 - 32ms
+ *   0 - 256ms
+ *   1 - 128ms
+ *   2 - 64ms
+ *   3 - 32ms
  * We default to 64ms because it's fast.  Some old SCSI-I devices need a
  * longer time.  The final value has to be left shifted by 3, hence 0x10
  * is the final value.
@@ -1439,15 +1442,6 @@
  ***************************************************************************/
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-static inline void
-mdelay(int milliseconds)
-{
-  int i;
-
-  for(i=0; i<milliseconds; i++)
-    udelay(1000);
-}
-
 static inline int
 time_after_eq(unsigned long a, unsigned long b)
 {
@@ -1490,12 +1484,15 @@
   if(p->maddr)
   {
     writeb(val, p->maddr + port);
+    mb(); /* locked operation in order to force ordering */
+    readb(p->maddr + HCNTRL); /* dummy read to flush the write */
   }
   else
   {
     outb(val, p->base + port);
+    mb(); /* locked operation in order to force ordering */
+    inb(p->base + HCNTRL); /* dummy read to flush the write */
   }
-  mb();
 #else
   outb(val, p->base + port);
 #endif
@@ -1878,13 +1875,10 @@
         }
       }
       aic_outb(p, (instr.integer & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
-      udelay(50);
       aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
-      udelay(50);
+      udelay(10);
       break;
 
     default:
@@ -1998,21 +1992,6 @@
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_delay
- *
- * Description:
- *   Delay for specified amount of time.  We use mdelay because the timer
- *   interrupt is not guaranteed to be enabled.  This will cause an
- *   infinite loop since jiffies (clock ticks) is not updated.
- *-F*************************************************************************/
-static void
-aic7xxx_delay(int seconds)
-{
-  mdelay(seconds * 1000);
-}
-
-/*+F*************************************************************************
- * Function:
  *   aic7xxx_info
  *
  * Description:
@@ -2982,6 +2961,19 @@
         p->needwdtr_copy &= ~(1<<tindex);
         p->needsdtr &= ~(1<<tindex);
         p->needsdtr_copy &= ~(1<<tindex);
+        /*
+         * 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;
+        }
       }
       /*
        * Get the INQUIRY checksum.  We use this on Ultra 160/m
@@ -3896,11 +3888,19 @@
   while ( (aic_inb(p, SCSISEQ) & SCSIRSTO) == 0)
     mdelay(5);
 
-  mdelay(10);
+  /*
+   * Some of the new Ultra2 chipsets need a longer delay after a chip
+   * reset than just the init setup creates, so we have to delay here
+   * before we go into a reset in order to make the chips happy.
+   */
+  if (p->features & AHC_ULTRA2)
+    mdelay(250);
+  else
+    mdelay(50);
 
   /* Turn off the bus reset. */
   aic_outb(p, 0, SCSISEQ);
-  mdelay(5);
+  mdelay(10);
 
   aic7xxx_clear_intstat(p);
   /* Re-enable reset interrupts. */
@@ -4779,11 +4779,6 @@
             case CHECK_CONDITION:
               if ( !(scb->flags & SCB_SENSE) )
               {
-                /*
-                 * XXX - How do we save the residual (if there is one).
-                 */
-                if ( hscb->residual_SG_segment_count != 0 )
-                  aic7xxx_calculate_residual(p, scb);
 
                 /*
                    * Send a sense command to the requesting target.
@@ -5304,6 +5299,188 @@
       }
       break;
 
+    case WIDE_RESIDUE:
+      {
+        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;
+        int i;
+
+        if(scb_index > p->scb_data->numscbs)
+        {
+          printk(WARN_LEAD "invalid scb_index during WIDE_RESIDUE.\n",
+            p->host_no, -1, -1, -1);
+          /*
+           * XXX: Add error handling here
+           */
+          break;
+        }
+        scb = p->scb_data->scb_array[scb_index];
+        if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+        {
+          printk(WARN_LEAD "invalid scb during WIDE_RESIDUE flags:0x%x "
+                 "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb),
+                 scb->flags, (unsigned int)scb->cmd);
+          break;
+        }
+
+        /*
+         * We have a valid scb to use on this WIDE_RESIDUE message, so
+         * we need to walk the sg list looking for this particular sg
+         * segment, then see if we happen to be at the very beginning of
+         * the segment.  If we are, then we have to back things up to
+         * the previous segment.  If not, then we simply need to remove
+         * one byte from this segments address and add one to the byte
+         * count.
+         */
+        cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) |
+          (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 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) << 24);
+        index = scb->sg_count - (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(cur_addr < native_addr ||
+           cur_addr > (native_addr + native_length))
+        {
+          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));
+          break;
+        }
+
+        /*
+         * 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(cur_addr == native_addr)
+        {
+          if(index == 0)
+          {
+            printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
+                   "transferred.\n", p->host_no, CTL_OF_SCB(scb));
+            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);
+          /*
+           * 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.
+           */
+          if(p->features & AHC_ULTRA2)
+          {
+            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+            i=0;
+            udelay(1);
+            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+            {
+              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+              udelay(1);
+            }
+          }
+          else
+          {
+            aic_outb(p, 1, STCNT); 
+            aic_outb(p, 0, STCNT + 1); 
+            aic_outb(p, 0, 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);
+            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+          }
+        }
+        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.
+           */
+          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);
+          if(p->features & AHC_ULTRA2)
+          {
+            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+            i=0;
+            udelay(1);
+            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+            {
+              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+              udelay(1);
+            }
+          }
+          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);
+            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+          }
+        }
+      }
+      break;
+
+        
 #if AIC7XXX_NOT_YET 
     case TRACEPOINT:
       {
@@ -6232,15 +6409,39 @@
       }
     }
     /*
-     * Restarting the sequencer will stop the selection and make sure devices
-     * are allowed to reselect in.
+     * Keep the sequencer from trying to restart any selections
      */
     aic_outb(p, 0, SCSISEQ);
+    /*
+     * Make sure the data bits on the bus are released
+     */
+    if(p->features & AHC_WIDE)
+      aic_outb(p, 0, SCSIBUSH);
+    aic_outb(p, 0, SCSIBUSL);
+    /*
+     * Clear the target id bit from the SCSI bus
+     */
+    if(p->features & AHC_ULTRA2)
+      aic_outb(p, aic_inb(p, SCSIID_ULTRA2) & 0x0f, SCSIID_ULTRA2);
+    else
+      aic_outb(p, aic_inb(p, SCSIID) & 0x0f, SCSIID);
+
+    /*
+     * Delay for the selection timeout delay period then stop the selection
+     */
+    udelay(301);
     aic_outb(p, CLRSELINGO, CLRSINT0);
+    /*
+     * Clear out all the interrupt status bits
+     */
     aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
     p->flags &= ~AHC_HANDLING_REQINITS;
     aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
     aic_outb(p, CLRSCSIINT, CLRINT);
+    /*
+     * Restarting the sequencer will stop the selection and make sure devices
+     * are allowed to reselect in.
+     */
     restart_sequencer(p);
     unpause_sequencer(p, TRUE);
   }
@@ -6807,11 +7008,11 @@
   if(!p)
     return;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
-  spin_lock_irqsave(&io_request_lock, cpu_flags);
   if(test_and_set_bit(AHC_IN_ISR_BIT, &p->flags))
   {
     return;
   }
+  spin_lock_irqsave(&io_request_lock, cpu_flags);
   do
   {
     aic7xxx_isr(irq, dev_id, regs);
@@ -7210,6 +7411,21 @@
 #undef CLOCK_PULSE
 }
 
+#define CLOCK_PULSE(p)                                               \
+  do {                                                               \
+    int limit = 0;                                                   \
+    do {                                                             \
+      mb();                                                          \
+      pause_sequencer(p);  /* This is just to generate some PCI */   \
+                           /* traffic so the PCI read is flushed */  \
+                           /* it shouldn't be needed, but some */    \
+                           /* chipsets do indeed appear to need */   \
+                           /* something to force PCI reads to get */ \
+                           /* flushed */                             \
+      udelay(1);           /* Do nothing */                          \
+    } while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)); \
+  } while(0)
+
 /*+F*************************************************************************
  * Function:
  *   acquire_seeprom
@@ -7220,7 +7436,6 @@
 static int
 acquire_seeprom(struct aic7xxx_host *p)
 {
-  int wait;
 
   /*
    * Request access of the memory port.  When access is
@@ -7230,12 +7445,7 @@
    * should be no contention.
    */
   aic_outb(p, SEEMS, SEECTL);
-  wait = 1000;  /* 1000 msec = 1 second */
-  while ((wait > 0) && ((aic_inb(p, SEECTL) & SEERDY) == 0))
-  {
-    wait--;
-    mdelay(1);  /* 1 msec */
-  }
+  CLOCK_PULSE(p);
   if ((aic_inb(p, SEECTL) & SEERDY) == 0)
   {
     aic_outb(p, 0, SEECTL);
@@ -7254,6 +7464,10 @@
 static void
 release_seeprom(struct aic7xxx_host *p)
 {
+  /*
+   * Make sure the SEEPROM is ready before we release it.
+   */
+  CLOCK_PULSE(p);
   aic_outb(p, 0, SEECTL);
 }
 
@@ -7320,18 +7534,6 @@
   };
   struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
 
-#define CLOCK_PULSE(p)                                               \
-  {                                                                  \
-    int limit = 0;                                                   \
-    while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)) \
-    {                                                                \
-      mb();                                                          \
-      pause_sequencer(p);  /* This is just to generate some PCI */   \
-                           /* so the PCI read is flushed */          \
-      udelay(10);  /* Do nothing */                                  \
-    }                                                                \
-  }
-
   /*
    * Request access of the memory port.
    */
@@ -7447,7 +7649,6 @@
   }
 
   return (1);
-#undef CLOCK_PULSE
 }
 
 /*+F*************************************************************************
@@ -7462,12 +7663,18 @@
 {
   unsigned char brdctl, value;
 
+  /*
+   * Make sure the SEEPROM is ready before we access it
+   */
+  CLOCK_PULSE(p);
   if (p->features & AHC_ULTRA2)
   {
     brdctl = BRDRW_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
-    return(aic_inb(p, BRDCTL));
+    CLOCK_PULSE(p);
+    value = aic_inb(p, BRDCTL);
+    CLOCK_PULSE(p);
+    return(value);
   }
   brdctl = BRDRW;
   if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) ||
@@ -7476,10 +7683,11 @@
     brdctl |= BRDCS;
   }
   aic_outb(p, brdctl, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   value = aic_inb(p, BRDCTL);
+  CLOCK_PULSE(p);
   aic_outb(p, 0, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   return (value);
 }
 
@@ -7495,18 +7703,23 @@
 {
   unsigned char brdctl;
 
+  /*
+   * Make sure the SEEPROM is ready before we access it
+   */
+  CLOCK_PULSE(p);
   if (p->features & AHC_ULTRA2)
   {
     brdctl = value;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     brdctl |= BRDSTB_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDSTB_ULTRA2;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(4);
+    CLOCK_PULSE(p);
     read_brdctl(p);
+    CLOCK_PULSE(p);
   }
   else
   {
@@ -7518,16 +7731,16 @@
     }
     brdctl = BRDSTB | BRDCS;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl |= value;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDSTB;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
     brdctl &= ~BRDCS;
     aic_outb(p, brdctl, BRDCTL);
-    udelay(1);
+    CLOCK_PULSE(p);
   }
 }
 
@@ -7545,16 +7758,64 @@
   unsigned char brdctl;
 
   aic_outb(p, BRDRW | BRDCS, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   aic_outb(p, 0, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   brdctl = aic_inb(p, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   *int_50 = !(brdctl & BRDDAT5);
   *ext_present = !(brdctl & BRDDAT6);
   *eeprom = (aic_inb(p, SPIOCAP) & EEPROM);
 }
 
+#undef CLOCK_PULSE
+
+/*+F*************************************************************************
+ * Function:
+ *   aic2940_uwpro_cable_detect
+ *
+ * Description:
+ *   Detect the cables that are present on the 2940-UWPro cards
+ *
+ * NOTE: This functions assumes the SEEPROM will have already been aquired
+ *       prior to invocation of this function.
+ *-F*************************************************************************/
+static void
+aic2940_uwpro_wide_cable_detect(struct aic7xxx_host *p, int *int_68,
+    int *ext_68, int *eeprom)
+{
+  unsigned char brdctl;
+
+  /*
+   * First read the status of our cables.  Set the rom bank to
+   * 0 since the bank setting serves as a multiplexor for the
+   * cable detection logic.  BRDDAT5 controls the bank switch.
+   */
+  write_brdctl(p, 0);
+
+  /*
+   * Now we read the state of the internal 68 connector.  BRDDAT6
+   * is don't care, BRDDAT7 is internal 68.  The cable is
+   * present if the bit is 0
+   */
+  brdctl = read_brdctl(p);
+  *int_68 = !(brdctl & BRDDAT7);
+
+  /*
+   * Set the bank bit in brdctl and then read the external cable state
+   * and the EEPROM status
+   */
+  write_brdctl(p, BRDDAT5);
+  brdctl = read_brdctl(p);
+
+  *ext_68 = !(brdctl & BRDDAT6);
+  *eeprom = !(brdctl & BRDDAT7);
+
+  /*
+   * We're done, the calling function will release the SEEPROM for us
+   */
+}
+
 /*+F*************************************************************************
  * Function:
  *   aic787x_cable_detect
@@ -7659,183 +7920,279 @@
       max_target = 8;
     aic_outb(p, SEEMS | SEECS, SEECTL);
     sxfrctl1 &= ~STPWEN;
-    if ( (p->adapter_control & CFAUTOTERM) ||
-         (p->features & AHC_NEW_AUTOTERM) )
+    /*
+     * The termination/cable detection logic is split into three distinct
+     * groups.  Ultra2 and later controllers, 2940UW-Pro controllers, and
+     * older 7850, 7860, 7870, 7880, and 7895 controllers.  Each has its
+     * own unique way of detecting their cables and writing the results
+     * back to the card.
+     */
+    if (p->features & AHC_ULTRA2)
     {
-      if ( (p->adapter_control & CFAUTOTERM) &&
-          !(p->features & AHC_NEW_AUTOTERM) )
-      {
-        printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) Please verify driver detected settings are "
-          "correct.\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) If not, then please properly set the device "
-          "termination\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting CTRL-A "
-          "when prompted\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
-      }
-      /* Configure auto termination. */
-
-      if (p->features & AHC_NEW_AUTOTERM)
-      {
-        if (aic7xxx_override_term == -1)
-          aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
-                                     &enableLVD_low, &enableLVD_high,
-                                     &eprom_present);
-        if (!(p->adapter_control & CFSEAUTOTERM))
-        {
-          enableSE_low = (p->adapter_control & CFSTERM);
-          enableSE_high = (p->adapter_control & CFWSTERM);
-        }
-        if (!(p->adapter_control & CFAUTOTERM))
-        {
-          enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
-        }
-        internal50_present = 0;
-        internal68_present = 1;
-        external_present = 1;
-      }
-      else if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
-      {
-        aic787x_cable_detect(p, &internal50_present, &internal68_present,
-          &external_present, &eprom_present);
-      }
-      else
+      /*
+       * As long as user hasn't overridden term settings, always check the
+       * cable detection logic
+       */
+      if (aic7xxx_override_term == -1)
       {
-        aic785x_cable_detect(p, &internal50_present, &external_present,
-          &eprom_present);
+        aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
+                                   &enableLVD_low, &enableLVD_high,
+                                   &eprom_present);
       }
       
-      if (max_target <= 8)
-        internal68_present = 0;
-
-      if ( !(p->features & AHC_NEW_AUTOTERM) )
-      {
-        if (max_target > 8)
-        {
-          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
-                 "Ext-68 %s)\n", p->host_no,
-                 internal50_present ? "YES" : "NO",
-                 internal68_present ? "YES" : "NO",
-                 external_present ? "YES" : "NO");
-        }
-        else
-        {
-          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
-                 p->host_no,
-                 internal50_present ? "YES" : "NO",
-                 external_present ? "YES" : "NO");
-        }
-      }
-      if (aic7xxx_verbose & VERBOSE_PROBE2)
-        printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
-             eprom_present ? "is" : "is not");
-
       /*
-       * Now set the termination based on what we found.  BRDDAT6
-       * controls wide termination enable.
-       * Flash Enable = BRDDAT7
-       * SE High Term Enable = BRDDAT6
-       * SE Low Term Enable = BRDDAT5 (7890)
-       * LVD High Term Enable = BRDDAT4 (7890)
+       * If the user is overriding settings, then they have been preserved
+       * to here as fake adapter_control entries.  Parse them and allow
+       * them to override the detected settings (if we even did detection).
        */
-      if ( !(p->features & AHC_NEW_AUTOTERM) &&
-           (internal50_present && internal68_present && external_present) )
-      {
-        printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
-               "in use at a time!\n", p->host_no);
-        /*
-         * Force termination (low and high byte) on.  This is safer than
-         * leaving it completely off, especially since this message comes
-         * most often from motherboard controllers that don't even have 3
-         * connectors, but instead are failing the cable detection.
-         */
-        internal50_present = external_present = 0;
-        enableSE_high = enableSE_low = 1;
-      }
-
-      if ((max_target > 8) &&
-          ((external_present == 0) || (internal68_present == 0) ||
-           (enableSE_high != 0)))
+      if (!(p->adapter_control & CFSEAUTOTERM))
       {
-        brddat |= BRDDAT6;
-        p->flags |= AHC_TERM_ENB_SE_HIGH;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
-                 p->host_no);
+        enableSE_low = (p->adapter_control & CFSTERM);
+        enableSE_high = (p->adapter_control & CFWSTERM);
       }
-
-      if ( (((internal50_present ? 1 : 0) +
-             (internal68_present ? 1 : 0) +
-             (external_present   ? 1 : 0)) <= 1) ||
-           (enableSE_low != 0) )
+      if (!(p->adapter_control & CFAUTOTERM))
       {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
-          sxfrctl1 |= STPWEN;
-        p->flags |= AHC_TERM_ENB_SE_LOW;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
+        enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
       }
 
+      /*
+       * Now take those settings that we have and translate them into the
+       * values that must be written into the registers.
+       *
+       * Flash Enable = BRDDAT7
+       * Secondary High Term Enable = BRDDAT6
+       * Secondary Low Term Enable = BRDDAT5
+       * LVD/Primary High Term Enable = BRDDAT4
+       * LVD/Primary Low Term Enable = STPWEN bit in SXFRCTL1
+       */
       if (enableLVD_low != 0)
       {
         sxfrctl1 |= STPWEN;
         p->flags |= AHC_TERM_ENB_LVD;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) LVD/Primary Low byte termination "
+                 "Enabled\n", p->host_no);
       }
           
       if (enableLVD_high != 0)
       {
         brddat |= BRDDAT4;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) LVD/Primary High byte termination "
+                 "Enabled\n", p->host_no);
       }
-    }
-    else
-    {
-      if (p->adapter_control & CFSTERM)
+
+      if (enableSE_low != 0)
       {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
-          sxfrctl1 |= STPWEN;
+        brddat |= BRDDAT5;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Secondary Low byte termination "
+                 "Enabled\n", p->host_no);
       }
 
-      if (p->adapter_control & CFWSTERM)
+      if (enableSE_high != 0)
       {
         brddat |= BRDDAT6;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
-                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Secondary High byte termination "
+                 "Enabled\n", p->host_no);
       }
     }
-    aic_outb(p, sxfrctl1, SXFRCTL1);
-    write_brdctl(p, brddat);
-    release_seeprom(p);
-  }
-}
+    else if (p->features & AHC_NEW_AUTOTERM)
+    {
+      /*
+       * The 50 pin connector termination is controlled by STPWEN in the
+       * SXFRCTL1 register.  Since the Adaptec docs typically say the
+       * controller is not allowed to be in the middle of a cable and
+       * this is the only connection on that stub of the bus, there is
+       * no need to even check for narrow termination, it's simply
+       * always on.
+       */
+      sxfrctl1 |= STPWEN;
+      if (aic7xxx_verbose & VERBOSE_PROBE2)
+        printk(KERN_INFO "(scsi%d) Narrow channel termination Enabled\n",
+               p->host_no);
 
-/*+F*************************************************************************
- * Function:
- *   detect_maxscb
- *
- * Description:
- *   Detects the maximum number of SCBs for the controller and returns
- *   the count and a mask in p (p->maxscbs, p->qcntmask).
- *-F*************************************************************************/
-static void
+      if (p->adapter_control & CFAUTOTERM)
+      {
+        aic2940_uwpro_wide_cable_detect(p, &internal68_present,
+                                        &external_present,
+                                        &eprom_present);
+        printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+               "Ext-68 %s)\n", p->host_no,
+               "Don't Care",
+               internal68_present ? "YES" : "NO",
+               external_present ? "YES" : "NO");
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
+        if (internal68_present && external_present)
+        {
+          brddat = 0;
+          p->flags &= ~AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Disabled\n",
+                   p->host_no);
+        }
+        else
+        {
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
+        }
+      }
+      else
+      {
+        /*
+         * The termination of the Wide channel is done more like normal
+         * though, and the setting of this termination is done by writing
+         * either a 0 or 1 to BRDDAT6 of the BRDDAT register
+         */
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
+        }
+        else
+        {
+          brddat = 0;
+        }
+      }
+    }
+    else
+    {
+      if (p->adapter_control & CFAUTOTERM)
+      {
+        if (p->flags & AHC_MOTHERBOARD)
+        {
+          printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
+                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Please verify driver detected settings "
+            "are correct.\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) If not, then please properly set the "
+            "device termination\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting "
+            "CTRL-A when prompted\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
+        }
+        /* Configure auto termination. */
+
+        if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
+        {
+          aic787x_cable_detect(p, &internal50_present, &internal68_present,
+            &external_present, &eprom_present);
+        }
+        else
+        {
+          aic785x_cable_detect(p, &internal50_present, &external_present,
+            &eprom_present);
+        }
+
+        if (max_target <= 8)
+          internal68_present = 0;
+
+        if (max_target > 8)
+        {
+          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+                 "Ext-68 %s)\n", p->host_no,
+                 internal50_present ? "YES" : "NO",
+                 internal68_present ? "YES" : "NO",
+                 external_present ? "YES" : "NO");
+        }
+        else
+        {
+          printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
+                 p->host_no,
+                 internal50_present ? "YES" : "NO",
+                 external_present ? "YES" : "NO");
+        }
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
+
+        /*
+         * Now set the termination based on what we found.  BRDDAT6
+         * controls wide termination enable.
+         * Flash Enable = BRDDAT7
+         * SE High Term Enable = BRDDAT6
+         */
+        if (internal50_present && internal68_present && external_present)
+        {
+          printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
+                 p->host_no);
+          printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
+                 "in use at a time!\n", p->host_no);
+          /*
+           * Force termination (low and high byte) on.  This is safer than
+           * leaving it completely off, especially since this message comes
+           * most often from motherboard controllers that don't even have 3
+           * connectors, but instead are failing the cable detection.
+           */
+          internal50_present = external_present = 0;
+          enableSE_high = enableSE_low = 1;
+        }
+
+        if ((max_target > 8) &&
+            ((external_present == 0) || (internal68_present == 0)) )
+        {
+          brddat |= BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
+
+        if ( ((internal50_present ? 1 : 0) +
+              (internal68_present ? 1 : 0) +
+              (external_present   ? 1 : 0)) <= 1 )
+        {
+          sxfrctl1 |= STPWEN;
+          p->flags |= AHC_TERM_ENB_SE_LOW;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
+      }
+      else /* p->adapter_control & CFAUTOTERM */
+      {
+        if (p->adapter_control & CFSTERM)
+        {
+          sxfrctl1 |= STPWEN;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
+
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat |= BRDDAT6;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
+      }
+    }
+
+    aic_outb(p, sxfrctl1, SXFRCTL1);
+    write_brdctl(p, brddat);
+    release_seeprom(p);
+  }
+}
+
+/*+F*************************************************************************
+ * Function:
+ *   detect_maxscb
+ *
+ * Description:
+ *   Detects the maximum number of SCBs for the controller and returns
+ *   the count and a mask in p (p->maxscbs, p->qcntmask).
+ *-F*************************************************************************/
+static void
 detect_maxscb(struct aic7xxx_host *p)
 {
   int i;
@@ -7907,12 +8264,6 @@
   unsigned char term, scsi_conf;
   struct Scsi_Host *host;
 
-  /*
-   * Lock out other contenders for our i/o space.
-   */
-  request_region(p->base, MAXREG - MINREG, "aic7xxx");
-
-
   host = p->host;
 
   p->scb_data->maxscbs = AIC7XXX_MAXSCB;
@@ -7984,7 +8335,7 @@
       printk("VLB slot %d\n", p->pci_device_fn);
       break;
     default:
-      printk("PCI %d/%d\n", PCI_SLOT(p->pci_device_fn),
+      printk("PCI %d/%d/%d\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
         PCI_FUNC(p->pci_device_fn));
       break;
   }
@@ -8020,6 +8371,20 @@
   }
   aic_outb(p, 0, SEQ_FLAGS);
 
+  /*
+   * We are starting to do real work on the card....it's possible we could
+   * generate some spurious interrupts at this point, especially in the
+   * event of a PCI error or some such.  If there are other devices already
+   * registered on the same interrupt as us, this could cause the machine
+   * to lock up.  So, we disable the interrupt this card is on until we
+   * finish our card setup.  We only need to do this for modules, if we are
+   * compiled into the kernel then interrupts are already off during this
+   * part of the code.
+   */
+#ifdef MODULE
+  disable_irq(p->irq);
+#endif
+
   detect_maxscb(p);
 
 
@@ -8055,15 +8420,15 @@
 #endif
       if ( (aic7xxx_stpwlev >> p->instance) & 0x01 )
       {
-        devconfig |= 0x02;
+        devconfig |= STPWLEVEL;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("(scsi%d) Force setting STPWLEV bit\n", p->host_no);
+          printk("(scsi%d) Force setting STPWLEVEL bit\n", p->host_no);
       }
       else
       {
-        devconfig &= ~0x02;
+        devconfig &= ~STPWLEVEL;
         if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("(scsi%d) Force clearing STPWLEV bit\n", p->host_no);
+          printk("(scsi%d) Force clearing STPWLEVEL bit\n", p->host_no);
       }
 #if LINUX_KERNEL_VERSION > KERNEL_VERSION(2,1,92)
       pci_write_config_byte(p->pdev, DEVCONFIG, devconfig);
@@ -8125,11 +8490,6 @@
   }
 
   /*
-   * Clear out any possible pending interrupts.
-   */
-  aic7xxx_clear_intstat(p);
-
-  /*
    * Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels
    */
   if (p->features & AHC_TWIN)
@@ -8172,7 +8532,17 @@
   aic_outb(p, (scsi_conf & ENSPCHK) | aic7xxx_seltime | term | 
        ENSTIMER | ACTNEGEN, SXFRCTL1);
   aic_outb(p, 0, SIMODE0);
-  aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
+  /*
+   * If we are a cardbus adapter then don't enable SCSI reset detection.
+   * We shouldn't likely be sharing SCSI busses with someone else, and
+   * if we don't have a cable currently plugged into the controller then
+   * we won't have a power source for the SCSI termination, which means
+   * we'll see infinite incoming bus resets.
+   */
+  if(p->flags & AHC_NO_STPWEN)
+    aic_outb(p, ENSELTIMO | ENSCSIPERR, SIMODE1);
+  else
+    aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
   aic_outb(p, 0, SCSIRATE);
   if ( p->features & AHC_ULTRA2)
     aic_outb(p, 0, SCSIOFFSET);
@@ -8245,6 +8615,10 @@
     {
       printk("(scsi%d) Unable to allocate hardware SCB array; "
              "failing detection.\n", p->host_no);
+      aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+      enable_irq(p->irq);
+#endif
       p->irq = 0;
       return(0);
     }
@@ -8319,11 +8693,6 @@
   first_aic7xxx = p;
 
   /*
-   * Clear out any possible pending interrupts, again.
-   */
-  aic7xxx_clear_intstat(p);
-
-  /*
    * Allocate the first set of scbs for this controller.  This is to stream-
    * line code elsewhere in the driver.  If we have to check for the existence
    * of scbs in certain code sections, it slows things down.  However, as
@@ -8377,20 +8746,21 @@
       printk(KERN_INFO "(scsi%d) Resetting channel%s\n", p->host_no, channel);
     }
     
-    /*
-     * Some of the new Ultra2 chipsets need a longer delay after a chip
-     * reset than just the init setup creates, so we have to delay here
-     * before we go into a reset in order to make the chips happy.
-     */
-    if (p->features & AHC_ULTRA2)
-      mdelay(250);
     aic7xxx_reset_current_bus(p);
 
     /*
-     * Delay for the reset delay.
+     * Delay for the reset delay by setting the timer, this will delay
+     * future commands sent to any devices.
      */
-    if (!reset_delay)
-      aic7xxx_delay(AIC7XXX_RESET_DELAY);
+    p->flags |= AHC_RESET_DELAY;
+    for(i=0; i<MAX_TARGETS; i++)
+    {
+      p->dev_expires[i] = jiffies + (4 * HZ);
+      p->dev_timer_active |= (0x01 << i);
+    }
+    p->dev_timer.expires = p->dev_expires[p->scsi_id];
+    add_timer(&p->dev_timer);
+    p->dev_timer_active |= (0x01 << MAX_TARGETS);
   }
   else
   {
@@ -8400,11 +8770,6 @@
              "the no_reset\n", p->host_no);
       printk(KERN_INFO "(scsi%d) option unless you have a verifiable need "
              "for it.\n", p->host_no);
-      printk(KERN_INFO "(scsi%d) The no_reset option is known to break some "
-             "systems,\n", p->host_no);
-      printk(KERN_INFO "(scsi%d) and is not supported by the driver author\n",
-             p->host_no);
-      aic7xxx_delay(AIC7XXX_RESET_DELAY);
     }
   }
   
@@ -8430,10 +8795,23 @@
   {
     printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
            "controller.\n", p->host_no, p->irq);
+    aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+    enable_irq(p->irq);
+#endif
     p->irq = 0;
     return (0);
   }
 
+  if(aic_inb(p, INTSTAT) & INT_PEND)
+    printk(INFO_LEAD "spurious interrupt during configuration, cleared.\n",
+      p->host_no, -1, -1 , -1);
+  aic7xxx_clear_intstat(p);
+
+#ifdef MODULE
+  enable_irq(p->irq);
+#endif
+
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
   return (found);
@@ -8463,10 +8841,10 @@
    * In the future, we may call this function as a last resort for
    * error handling.  Let's be nice and not do any unecessary delays.
    */
-  wait = 1000;  /* 1 second (1000 * 1 msec) */
+  wait = 1000;  /* 1 msec (1000 * 1 msec) */
   while (--wait && !(aic_inb(p, HCNTRL) & CHIPRSTACK))
   {
-    mdelay(1);  /* 1 msec */
+    udelay(1);  /* 1 usec */
   }
 
   pause_sequencer(p);
@@ -9102,260 +9480,6 @@
   template->sg_tablesize = AIC7XXX_MAX_SG;
 
 
-#if defined(__i386__) || defined(__alpha__)
-#ifdef CONFIG_PCI
-  /*
-   * PCI-bus chipset probe.
-   */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-  if (pci_present())
-  {
-    if (pci_find_device(PCI_VENDOR_ID_INTEL,
-                        PCI_DEVICE_ID_INTEL_82450GX,
-                        NULL))
-      aic7xxx_no_probe = 1;
-    if (pci_find_device(PCI_VENDOR_ID_INTEL,
-                        PCI_DEVICE_ID_INTEL_82451NX,
-                        NULL))
-      aic7xxx_no_probe = 1;
-  }
-#else
-#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
-  if (pcibios_present())
-  {
-    unsigned char pci_bus, pci_devfn;
-    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                              PCI_DEVICE_ID_INTEL_82450GX,
-                              0, &pci_bus, &pci_devfn)) )
-      aic7xxx_no_probe = 1;
-    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                              PCI_DEVICE_ID_INTEL_82451NX,
-                              0, &pci_bus, &pci_devfn)) )
-      aic7xxx_no_probe = 1;
-  }
-#endif /* LINUX_VERSION_CODE */
-#endif /* CONFIG_PCI */
-  /*
-   * EISA/VL-bus card signature probe.
-   */
-  slot = MINSLOT;
-  while ( (slot <= MAXSLOT) && 
-         !(aic7xxx_no_probe) )
-  {
-    base = SLOTBASE(slot) + MINREG;
-
-    if (check_region(base, MAXREG - MINREG))
-    {
-      /*
-       * Some other driver has staked a
-       * claim to this i/o region already.
-       */
-      slot++;
-      continue; /* back to the beginning of the for loop */
-    }
-    flags = 0;
-    type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
-    if (type == -1)
-    {
-      slot++;
-      continue;
-    }
-    temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
-    if (temp_p == NULL)
-    {
-      printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
-      slot++;
-      continue; /* back to the beginning of the while loop */
-    }
-    /*
-     * Pause the card preserving the IRQ type.  Allow the operator
-     * to override the IRQ trigger.
-     */
-    if (aic7xxx_irq_trigger == 1)
-      hcntrl = IRQMS;  /* Level */
-    else if (aic7xxx_irq_trigger == 0)
-      hcntrl = 0;  /* Edge */
-    else
-      hcntrl = inb(base + HCNTRL) & IRQMS;  /* Default */
-    memset(temp_p, 0, sizeof(struct aic7xxx_host));
-    temp_p->unpause = hcntrl | INTEN;
-    temp_p->pause = hcntrl | PAUSE | INTEN;
-    temp_p->base = base;
-    temp_p->mbase = 0;
-    temp_p->maddr = 0;
-    temp_p->pci_bus = 0;
-    temp_p->pci_device_fn = slot;
-    aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
-    while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
-    if (aic7xxx_chip_reset(temp_p) == -1)
-      temp_p->irq = 0;
-    else
-      temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
-    temp_p->flags |= AHC_PAGESCBS;
-
-    switch (temp_p->irq)
-    {
-      case 9:
-      case 10:
-      case 11:
-      case 12:
-      case 14:
-      case 15:
-        break;
-
-      default:
-        printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
-          "level %d, ignoring.\n", temp_p->irq);
-        kfree(temp_p);
-        slot++;
-        continue; /* back to the beginning of the while loop */
-    }
-
-    /*
-     * We are commited now, everything has been checked and this card
-     * has been found, now we just set it up
-     */
-
-    /*
-     * Insert our new struct into the list at the end
-     */
-    if (list_p == NULL)
-    {
-      list_p = current_p = temp_p;
-    }
-    else
-    {
-      current_p = list_p;
-      while (current_p->next != NULL)
-        current_p = current_p->next;
-      current_p->next = temp_p;
-    }
-
-    switch (type)
-    {
-      case 0:
-        temp_p->board_name_index = 2;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("aic7xxx: <%s> at EISA %d\n",
-               board_names[2], slot);
-        /* FALLTHROUGH */
-      case 1:
-      {
-        temp_p->chip = AHC_AIC7770 | AHC_EISA;
-        temp_p->features |= AHC_AIC7770_FE;
-        temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
-
-        /*
-         * Get the primary channel information.  Right now we don't
-         * do anything with this, but someday we will be able to inform
-         * the mid-level SCSI code which channel is primary.
-         */
-        if (temp_p->board_name_index == 0)
-        {
-          temp_p->board_name_index = 3;
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at EISA %d\n",
-                 board_names[3], slot);
-        }
-        if (temp_p->bios_control & CHANNEL_B_PRIMARY)
-        {
-          temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
-        }
-
-        if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
-        {
-          temp_p->flags &= ~AHC_BIOS_ENABLED;
-        }
-        else
-        {
-          temp_p->flags &= ~AHC_USEDEFAULTS;
-          temp_p->flags |= AHC_BIOS_ENABLED;
-          if ( (temp_p->bios_control & 0x20) == 0 )
-          {
-            temp_p->bios_address = 0xcc000;
-            temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
-          }
-          else
-          {
-            temp_p->bios_address = 0xd0000;
-            temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
-          }
-        }
-        temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
-        temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
-        if (temp_p->features & AHC_WIDE)
-        {
-          temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
-          temp_p->scsi_id_b = temp_p->scsi_id;
-        }
-        else
-        {
-          temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
-          temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
-        }
-        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
-        break;
-      }
-
-      case 2:
-      case 3:
-        temp_p->chip = AHC_AIC7770 | AHC_VL;
-        temp_p->features |= AHC_AIC7770_FE;
-        if (type == 2)
-          temp_p->flags |= AHC_BIOS_ENABLED;
-        else
-          temp_p->flags &= ~AHC_BIOS_ENABLED;
-        if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
-          sxfrctl1 = STPWEN;
-        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
-        temp_p->board_name_index = 4;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk("aic7xxx: <%s> at VLB %d\n",
-               board_names[2], slot);
-        switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
-        {
-          case 0x00:
-            temp_p->bios_address = 0xe0000;
-            break;
-          case 0x20:
-            temp_p->bios_address = 0xc8000;
-            break;
-          case 0x40:
-            temp_p->bios_address = 0xd0000;
-            break;
-          case 0x60:
-            temp_p->bios_address = 0xd8000;
-            break;
-          default:
-            break; /* can't get here */
-        }
-        break;
-
-      default:  /* Won't get here. */
-        break;
-    }
-    if (aic7xxx_verbose & VERBOSE_PROBE2)
-    {
-      printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
-        (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
-        temp_p->irq,
-        (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
-      printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
-             (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
-    }
-
-    /*
-     * Set the FIFO threshold and the bus off time.
-     */
-    hostconf = aic_inb(temp_p, HOSTCONF);
-    aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
-    aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
-    slot++;
-    found++;
-  }
-
-#endif /* defined(__i386__) || defined(__alpha__) */
-
 #ifdef CONFIG_PCI
   /*
    * PCI-bus probe.
@@ -9399,7 +9523,7 @@
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AHC_AIC7860,
@@ -9407,7 +9531,8 @@
        AHC_AIC7860_FE,                                       8,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AHC_AIC7870,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,      9,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7870_FE,                                       9,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AHC_AIC7870,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     10,
@@ -9424,7 +9549,8 @@
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     13,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7880, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     14,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7880_FE,                                      14,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7881, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     15,
@@ -9447,78 +9573,78 @@
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 18,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 19,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7895_FE,                                      19,
+       AHC_AIC7895_FE,                                      20,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      21,
+       AHC_AIC7890_FE,                                      22,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      22,
+       AHC_AIC7890_FE,                                      23,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      23,
+       AHC_AIC7896_FE,                                      24,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      24,
+       AHC_AIC7896_FE,                                      25,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      25,
+       AHC_AIC7896_FE,                                      26,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7860_FE,                                      26,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_NO_STPWEN,
+       AHC_AIC7860_FE,                                      27,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
     };
 
@@ -9594,10 +9720,11 @@
           if ( temp_p == NULL )
             continue;
           if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
-              PCI_SLOT(temp_p->pdev->devfn),
-              PCI_FUNC(temp_p->pdev->devfn));
+              temp_p->pci_bus,
+              PCI_SLOT(temp_p->pci_device_fn),
+              PCI_FUNC(temp_p->pci_device_fn));
           pci_read_config_word(pdev, PCI_COMMAND, &command);
           if (aic7xxx_verbose & VERBOSE_PROBE2)
           {
@@ -9653,8 +9780,9 @@
           if ( temp_p == NULL )
             continue;
           if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
               PCI_SLOT(temp_p->pci_device_fn),
               PCI_FUNC(temp_p->pci_device_fn));
           pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
@@ -9684,14 +9812,28 @@
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
 #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
 
+          if(check_region(temp_p->base, MAXREG - MINREG))
+          {
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
+              board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
+              PCI_SLOT(temp_p->pci_device_fn),
+              PCI_FUNC(temp_p->pci_device_fn));
+            printk("aic7xxx: I/O ports already in use, ignoring.\n");
+            kfree(temp_p);
+            temp_p = NULL;
+            continue;
+          }
+
           temp_p->unpause = INTEN;
           temp_p->pause = temp_p->unpause | PAUSE;
           if ( ((temp_p->base == 0) &&
                 (temp_p->mbase == 0)) ||
                (temp_p->irq == 0) )
           {
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
+              temp_p->pci_bus,
               PCI_SLOT(temp_p->pci_device_fn),
               PCI_FUNC(temp_p->pci_device_fn));
             printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
@@ -9726,8 +9868,9 @@
                 /*
                  * OK.....we failed our test....go back to programmed I/O
                  */
-                printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                   board_names[aic_pdevs[i].board_name_index],
+                  temp_p->pci_bus,
                   PCI_SLOT(temp_p->pci_device_fn),
                   PCI_FUNC(temp_p->pci_device_fn));
                 printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
@@ -9744,6 +9887,11 @@
 #endif
 
           /*
+           * Lock out other contenders for our i/o space.
+           */
+          request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
+
+          /*
            * We HAVE to make sure the first pause_sequencer() and all other
            * subsequent I/O that isn't PCI config space I/O takes place
            * after the MMAPed I/O region is configured and tested.  The
@@ -9775,14 +9923,31 @@
           /*
            * Get current termination setting
            */
-          sxfrctl1 = aic_inb(temp_p, SXFRCTL1) & STPWEN;
+          sxfrctl1 = aic_inb(temp_p, SXFRCTL1);
 
           if (aic7xxx_chip_reset(temp_p) == -1)
           {
+            release_region(temp_p->base, MAXREG - MINREG);
             kfree(temp_p);
             temp_p = NULL;
             continue;
           }
+          /*
+           * Very quickly put the term setting back into the register since
+           * the chip reset may cause odd things to happen.  This is to keep
+           * LVD busses with lots of drives from draining the power out of
+           * the diffsense line before we get around to running the
+           * configure_termination() function.  Also restore the STPWLEVEL
+           * bit of DEVCONFIG
+           */
+          aic_outb(temp_p, sxfrctl1, SXFRCTL1);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
+          pcibios_write_config_dword(temp_p->pci_bus, temp_p->pci_device_fn,
+            DEVCONFIG, devconfig);
+#else
+          pci_write_config_dword(temp_p->pdev, DEVCONFIG, devconfig);
+#endif
+          sxfrctl1 &= STPWEN;
 
           /*
            * We need to set the CHNL? assignments before loading the SEEPROM
@@ -10009,8 +10174,9 @@
                 }
                 else if (aic_inb(temp_p, DSCOMMAND0) & RAMPSM_ULTRA2)
                 {
-                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                     board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
                     PCI_SLOT(temp_p->pci_device_fn),
                     PCI_FUNC(temp_p->pci_device_fn));
                   printk("aic7xxx: external SCB RAM detected, "
@@ -10027,8 +10193,9 @@
                 }
                 else if (devconfig & RAMPSM)
                 {
-                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n", 
+                  printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n", 
                     board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
                     PCI_SLOT(temp_p->pci_device_fn),
                     PCI_FUNC(temp_p->pci_device_fn));
                   printk("aic7xxx: external SCB RAM detected, "
@@ -10093,6 +10260,235 @@
     } /* for PCI_DEVICES */
   } /* PCI BIOS present */
 #endif CONFIG_PCI
+
+#if defined(__i386__) || defined(__alpha__)
+  /*
+   * EISA/VL-bus card signature probe.
+   */
+  slot = MINSLOT;
+  while ( (slot <= MAXSLOT) && 
+         !(aic7xxx_no_probe) )
+  {
+    base = SLOTBASE(slot) + MINREG;
+
+    if (check_region(base, MAXREG - MINREG))
+    {
+      /*
+       * Some other driver has staked a
+       * claim to this i/o region already.
+       */
+      slot++;
+      continue; /* back to the beginning of the for loop */
+    }
+    flags = 0;
+    type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
+    if (type == -1)
+    {
+      slot++;
+      continue;
+    }
+    temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
+    if (temp_p == NULL)
+    {
+      printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+      slot++;
+      continue; /* back to the beginning of the while loop */
+    }
+    /*
+     * Lock out other contenders for our i/o space.
+     */
+    request_region(base, MAXREG - MINREG, "aic7xxx");
+
+    /*
+     * Pause the card preserving the IRQ type.  Allow the operator
+     * to override the IRQ trigger.
+     */
+    if (aic7xxx_irq_trigger == 1)
+      hcntrl = IRQMS;  /* Level */
+    else if (aic7xxx_irq_trigger == 0)
+      hcntrl = 0;  /* Edge */
+    else
+      hcntrl = inb(base + HCNTRL) & IRQMS;  /* Default */
+    memset(temp_p, 0, sizeof(struct aic7xxx_host));
+    temp_p->unpause = hcntrl | INTEN;
+    temp_p->pause = hcntrl | PAUSE | INTEN;
+    temp_p->base = base;
+    temp_p->mbase = 0;
+    temp_p->maddr = 0;
+    temp_p->pci_bus = 0;
+    temp_p->pci_device_fn = slot;
+    aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
+    while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
+    if (aic7xxx_chip_reset(temp_p) == -1)
+      temp_p->irq = 0;
+    else
+      temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
+    temp_p->flags |= AHC_PAGESCBS;
+
+    switch (temp_p->irq)
+    {
+      case 9:
+      case 10:
+      case 11:
+      case 12:
+      case 14:
+      case 15:
+        break;
+
+      default:
+        printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
+          "level %d, ignoring.\n", temp_p->irq);
+        kfree(temp_p);
+        release_region(base, MAXREG - MINREG);
+        slot++;
+        continue; /* back to the beginning of the while loop */
+    }
+
+    /*
+     * We are commited now, everything has been checked and this card
+     * has been found, now we just set it up
+     */
+
+    /*
+     * Insert our new struct into the list at the end
+     */
+    if (list_p == NULL)
+    {
+      list_p = current_p = temp_p;
+    }
+    else
+    {
+      current_p = list_p;
+      while (current_p->next != NULL)
+        current_p = current_p->next;
+      current_p->next = temp_p;
+    }
+
+    switch (type)
+    {
+      case 0:
+        temp_p->board_name_index = 2;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk("aic7xxx: <%s> at EISA %d\n",
+               board_names[2], slot);
+        /* FALLTHROUGH */
+      case 1:
+      {
+        temp_p->chip = AHC_AIC7770 | AHC_EISA;
+        temp_p->features |= AHC_AIC7770_FE;
+        temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
+
+        /*
+         * Get the primary channel information.  Right now we don't
+         * do anything with this, but someday we will be able to inform
+         * the mid-level SCSI code which channel is primary.
+         */
+        if (temp_p->board_name_index == 0)
+        {
+          temp_p->board_name_index = 3;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk("aic7xxx: <%s> at EISA %d\n",
+                 board_names[3], slot);
+        }
+        if (temp_p->bios_control & CHANNEL_B_PRIMARY)
+        {
+          temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
+        }
+
+        if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
+        {
+          temp_p->flags &= ~AHC_BIOS_ENABLED;
+        }
+        else
+        {
+          temp_p->flags &= ~AHC_USEDEFAULTS;
+          temp_p->flags |= AHC_BIOS_ENABLED;
+          if ( (temp_p->bios_control & 0x20) == 0 )
+          {
+            temp_p->bios_address = 0xcc000;
+            temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
+          }
+          else
+          {
+            temp_p->bios_address = 0xd0000;
+            temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
+          }
+        }
+        temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
+        temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
+        if (temp_p->features & AHC_WIDE)
+        {
+          temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
+          temp_p->scsi_id_b = temp_p->scsi_id;
+        }
+        else
+        {
+          temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
+          temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
+        }
+        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+        break;
+      }
+
+      case 2:
+      case 3:
+        temp_p->chip = AHC_AIC7770 | AHC_VL;
+        temp_p->features |= AHC_AIC7770_FE;
+        if (type == 2)
+          temp_p->flags |= AHC_BIOS_ENABLED;
+        else
+          temp_p->flags &= ~AHC_BIOS_ENABLED;
+        if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
+          sxfrctl1 = STPWEN;
+        aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+        temp_p->board_name_index = 4;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk("aic7xxx: <%s> at VLB %d\n",
+               board_names[2], slot);
+        switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
+        {
+          case 0x00:
+            temp_p->bios_address = 0xe0000;
+            break;
+          case 0x20:
+            temp_p->bios_address = 0xc8000;
+            break;
+          case 0x40:
+            temp_p->bios_address = 0xd0000;
+            break;
+          case 0x60:
+            temp_p->bios_address = 0xd8000;
+            break;
+          default:
+            break; /* can't get here */
+        }
+        break;
+
+      default:  /* Won't get here. */
+        break;
+    }
+    if (aic7xxx_verbose & VERBOSE_PROBE2)
+    {
+      printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
+        (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
+        temp_p->irq,
+        (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
+      printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
+             (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
+    }
+
+    /*
+     * Set the FIFO threshold and the bus off time.
+     */
+    hostconf = aic_inb(temp_p, HOSTCONF);
+    aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
+    aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
+    slot++;
+    found++;
+  }
+
+#endif /* defined(__i386__) || defined(__alpha__) */
+
   /*
    * Now, we re-order the probed devices by BIOS address and BUS class.
    * In general, we follow this algorithm to make the adapters show up
@@ -11165,8 +11561,10 @@
              (scb->flags & SCB_WAITINGQ) ? "WAITINGQ" : "Sent" );
     }
   }
-#endif
   sti();
+#else
+  spin_unlock_irq(&io_request_lock);
+#endif
   for(;;) barrier();
 }
 
@@ -11956,6 +12354,7 @@
           0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
           0xe0, 0xf1, 0xf4, 0xfc} },
   };
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
 #ifdef CONFIG_PCI
   static struct register_ranges cards_ns[] = {
     { 0, {0,} }, /* none */
@@ -11977,6 +12376,7 @@
           0xff, 0xff} }
   };
 #endif
+#endif
   chip = p->chip & AHC_CHIPID_MASK;
   /*
    * Let's run through the PCI space first....
@@ -11993,11 +12393,12 @@
       break;
     case AHC_PCI:
     default:
-      printk("PCI %d/%d.\n", PCI_SLOT(p->pci_device_fn),
+      printk("PCI %d/%d/%d.\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
              PCI_FUNC(p->pci_device_fn));
       break;
   }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
 #ifdef CONFIG_PCI
   {
     unsigned char temp;
@@ -12010,11 +12411,7 @@
           j <= cards_ns[chip].range_val[ i * 2 + 1 ] ;
           j++)
       {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-        pci_read_config_byte(p->pdev, j, &temp);
-#else
         pcibios_read_config_byte(p->pci_bus, p->pci_device_fn, j, &temp);
-#endif
         printk("%02x:%02x ", j, temp);
         if(++k == 13)
         {
@@ -12027,6 +12424,7 @@
   if(k != 0)
     printk("\n");
 #endif /* CONFIG_PCI */
+#endif
 
   /*
    * Now the registers on the card....
@@ -12049,6 +12447,7 @@
   }
   if(k != 0)
     printk("\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
   if (p->flags & AHC_SEEPROM_FOUND)
   {
     unsigned short *sc1;
@@ -12064,6 +12463,7 @@
         printk("  ");
     }
   }
+#endif
 
   /*
    * If this was an Ultra2 controller, then we just hosed the card in terms
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx_proc.c	Tue Jan  4 10:12:19 2000
+++ linux/drivers/scsi/aic7xxx_proc.c	Mon Dec  3 22:01:11 2001
@@ -178,7 +178,7 @@
   size += sprintf(BLS, "           SCSI Adapter: %s\n",
       board_names[p->board_name_index]);
   if (p->flags & AHC_TWIN)
-    size += sprintf(BLS, "                         Twin Channel\n");
+    size += sprintf(BLS, "                         Twin Channel Controller ");
   else
   {
     char *channel = "";
@@ -209,9 +209,22 @@
       ultra = "Ultra-2 LVD/SE ";
     else if (p->features & AHC_ULTRA)
       ultra = "Ultra ";
-    size += sprintf(BLS, "                           %s%sController%s\n",
+    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);
@@ -223,11 +236,6 @@
   if( (p->chip & (AHC_VL | AHC_EISA)) )
   {
     size += sprintf(BLS, "    BIOS Memory Address: 0x%08x\n", p->bios_address);
-  }
-  if( p->chip & AHC_PCI )
-  {
-    size += sprintf(BLS, "    PCI Bus 0x%02x Device 0x%02x\n", p->pci_bus,
-              p->pci_device_fn);
   }
   size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
           (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx_reg.h	Mon Aug  9 12:04:40 1999
+++ linux/drivers/scsi/aic7xxx_reg.h	Mon Dec  3 22:01:11 2001
@@ -188,8 +188,8 @@
 #define		BRDRW           	0x04
 #define		BRDRW_ULTRA2    	0x02
 #define		BRDCTL1         	0x02
-#define		BRDSTB_ULTRA2   	0x01
 #define		BRDCTL0         	0x01
+#define		BRDSTB_ULTRA2   	0x01
 
 #define	SEECTL          		0x1e
 #define		EXTARBACK       	0x80
@@ -402,7 +402,7 @@
 #define		RESIDUAL        	0x81
 #define		BAD_STATUS      	0x71
 #define		REJECT_MSG      	0x61
-#define		ABORT_REQUESTED 	0x51
+#define		WIDE_RESIDUE    	0x51
 #define		EXTENDED_MSG    	0x41
 #define		NO_MATCH        	0x31
 #define		NO_IDENT        	0x21
@@ -465,6 +465,8 @@
 #define		TARGCRCENDEN    	0x08
 #define		TARGCRCCNTEN    	0x04
 
+#define	QOUTCNT         		0x9e
+
 #define	SCSIPHASE       		0x9e
 #define		SP_STATUS       	0x20
 #define		SP_COMMAND      	0x10
@@ -473,8 +475,6 @@
 #define		SP_DATA_IN      	0x02
 #define		SP_DATA_OUT     	0x01
 
-#define	QOUTCNT         		0x9e
-
 #define	SFUNCT          		0x9f
 #define		ALT_MODE        	0x80
 
@@ -595,8 +595,8 @@
 #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		WR_DFTHRSH_MIN  	0x00
 
 #define	SG_CACHEPTR     		0xfc
 #define		SG_USER_DATA    	0xfc
@@ -604,18 +604,18 @@
 #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	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
diff -urN linux-2.2.15-pre13/drivers/scsi/aic7xxx_seq.c linux/drivers/scsi/aic7xxx_seq.c
--- linux-2.2.15-pre13/drivers/scsi/aic7xxx_seq.c	Tue Jan  4 10:12:19 2000
+++ linux/drivers/scsi/aic7xxx_seq.c	Mon Dec  3 22:01:11 2001
@@ -8,14 +8,14 @@
 	0x12, 0x6a, 0x00, 0x00,
 	0xff, 0x6a, 0xd6, 0x09,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x00, 0x65, 0x42, 0x59,
+	0x00, 0x65, 0x44, 0x59,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x4e, 0xc8, 0x08,
 	0xbf, 0x60, 0xc0, 0x08,
-	0x60, 0x0b, 0x86, 0x68,
+	0x60, 0x0b, 0x88, 0x68,
 	0x40, 0x00, 0x0e, 0x68,
 	0x08, 0x1f, 0x3e, 0x10,
-	0x60, 0x0b, 0x86, 0x68,
+	0x60, 0x0b, 0x88, 0x68,
 	0x40, 0x00, 0x0e, 0x68,
 	0x08, 0x1f, 0x3e, 0x10,
 	0xff, 0x3e, 0x4a, 0x60,
@@ -26,12 +26,12 @@
 	0x00, 0x4d, 0x12, 0x70,
 	0x01, 0x4e, 0x9c, 0x18,
 	0xbf, 0x60, 0xc0, 0x08,
-	0x00, 0x6a, 0xa8, 0x5c,
+	0x00, 0x6a, 0xbe, 0x5c,
 	0xff, 0x4e, 0xc8, 0x18,
-	0x02, 0x6a, 0xbe, 0x5b,
+	0x02, 0x6a, 0xd4, 0x5b,
 	0xff, 0x52, 0x20, 0x09,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x52, 0x34, 0x5c,
+	0x00, 0x52, 0x4a, 0x5c,
 	0x03, 0xb0, 0x52, 0x31,
 	0xff, 0xb0, 0x52, 0x09,
 	0xff, 0xb1, 0x54, 0x09,
@@ -52,51 +52,52 @@
 	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,
+	0x80, 0x37, 0x70, 0x68,
 	0xff, 0x65, 0xca, 0x18,
 	0xff, 0x37, 0xdc, 0x08,
 	0xff, 0x6e, 0xc8, 0x08,
-	0x00, 0x6c, 0x76, 0x78,
+	0x00, 0x6c, 0x78, 0x78,
 	0x20, 0x01, 0x02, 0x00,
 	0x4c, 0x37, 0xc8, 0x28,
-	0x08, 0x1f, 0x7e, 0x78,
+	0x08, 0x1f, 0x80, 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, 0x0e, 0x69,
-	0x80, 0x0b, 0x00, 0x79,
+	0x40, 0x0b, 0x10, 0x69,
+	0x80, 0x0b, 0x02, 0x79,
 	0xa4, 0x6a, 0x06, 0x00,
 	0x40, 0x6a, 0x16, 0x00,
-	0x10, 0x03, 0xfc, 0x78,
+	0x10, 0x03, 0xfe, 0x78,
 	0xff, 0x50, 0xc8, 0x08,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x49, 0x6a, 0x24, 0x5c,
+	0x49, 0x6a, 0x3a, 0x5c,
 	0x01, 0x6a, 0x26, 0x01,
 	0xff, 0x6a, 0xca, 0x08,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x9c, 0x78,
+	0x02, 0x0b, 0x9e, 0x78,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x06, 0xcc, 0x08,
 	0xff, 0x66, 0x32, 0x09,
 	0x01, 0x65, 0xca, 0x18,
-	0x80, 0x66, 0xaa, 0x78,
+	0x80, 0x66, 0xac, 0x78,
 	0xff, 0x66, 0xa2, 0x08,
-	0x10, 0x03, 0x9a, 0x68,
+	0x10, 0x03, 0x9c, 0x68,
 	0xfc, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0xb2, 0x48,
+	0x00, 0x65, 0xb4, 0x48,
 	0xff, 0x6a, 0x32, 0x01,
 	0x01, 0x64, 0x18, 0x19,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x84, 0x6a, 0x06, 0x00,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0xbc, 0x78,
+	0x02, 0x0b, 0xbe, 0x78,
 	0xff, 0x06, 0xc8, 0x08,
 	0xff, 0x64, 0x32, 0x09,
 	0xff, 0x6a, 0xca, 0x08,
@@ -110,33 +111,33 @@
 	0x0b, 0x65, 0xca, 0x18,
 	0xff, 0x65, 0xc8, 0x08,
 	0x00, 0x8c, 0x18, 0x19,
-	0x02, 0x0b, 0xd8, 0x78,
-	0x01, 0x65, 0xde, 0x60,
+	0x02, 0x0b, 0xda, 0x78,
+	0x01, 0x65, 0xe0, 0x60,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x06, 0x32, 0x09,
 	0xff, 0x65, 0xca, 0x18,
-	0xff, 0x65, 0xd8, 0x68,
+	0xff, 0x65, 0xda, 0x68,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x9a, 0x5c,
-	0x40, 0x51, 0xf0, 0x78,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x40, 0x51, 0xf2, 0x78,
 	0xe4, 0x6a, 0x06, 0x00,
 	0x08, 0x01, 0x02, 0x00,
-	0x04, 0x6a, 0x56, 0x5b,
+	0x04, 0x6a, 0x6c, 0x5b,
 	0x01, 0x50, 0xa0, 0x18,
-	0x00, 0x50, 0xf6, 0xe0,
+	0x00, 0x50, 0xf8, 0xe0,
 	0xff, 0x6a, 0xa0, 0x08,
 	0xff, 0x6a, 0x3a, 0x01,
 	0x02, 0x6a, 0x22, 0x01,
-	0x40, 0x51, 0xfc, 0x68,
+	0x40, 0x51, 0xfe, 0x68,
 	0xff, 0x6a, 0x06, 0x08,
 	0x00, 0x65, 0x0e, 0x40,
 	0x20, 0x6a, 0x16, 0x00,
 	0xf0, 0x19, 0x6e, 0x08,
 	0x08, 0x6a, 0x18, 0x00,
 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x66, 0x58,
+	0x08, 0x6a, 0x68, 0x58,
 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x24, 0x41,
 	0x12, 0x6a, 0x00, 0x00,
 	0x40, 0x6a, 0x16, 0x00,
 	0xff, 0x3e, 0x20, 0x09,
@@ -144,23 +145,23 @@
 	0xff, 0xa1, 0x6e, 0x08,
 	0x08, 0x6a, 0x18, 0x00,
 	0x08, 0x11, 0x22, 0x00,
-	0x08, 0x6a, 0x66, 0x58,
+	0x08, 0x6a, 0x68, 0x58,
 	0x80, 0x6a, 0x68, 0x00,
 	0x80, 0x36, 0x6c, 0x00,
-	0x00, 0x65, 0x08, 0x5c,
+	0x00, 0x65, 0x1e, 0x5c,
 	0xff, 0x3d, 0xc8, 0x08,
-	0xbf, 0x64, 0x5a, 0x79,
-	0x80, 0x64, 0x20, 0x72,
-	0xa0, 0x64, 0x50, 0x72,
-	0xc0, 0x64, 0x48, 0x72,
-	0xe0, 0x64, 0x90, 0x72,
+	0xbf, 0x64, 0x5c, 0x79,
+	0x80, 0x64, 0x24, 0x72,
+	0xa0, 0x64, 0x54, 0x72,
+	0xc0, 0x64, 0x4c, 0x72,
+	0xe0, 0x64, 0x94, 0x72,
 	0x01, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x24, 0x41,
 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0x42, 0x59,
+	0x00, 0x65, 0x44, 0x59,
 	0xff, 0x06, 0xd4, 0x08,
 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0x3c, 0x79,
+	0x09, 0x0c, 0x3e, 0x79,
 	0x08, 0x0c, 0x0e, 0x68,
 	0x01, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0x26, 0x09,
@@ -173,25 +174,25 @@
 	0x03, 0xa9, 0x18, 0x31,
 	0x03, 0xa9, 0x10, 0x30,
 	0x08, 0x6a, 0xcc, 0x00,
-	0xa9, 0x6a, 0x1e, 0x5c,
-	0x00, 0x65, 0x7a, 0x41,
+	0xa9, 0x6a, 0x34, 0x5c,
+	0x00, 0x65, 0x7c, 0x41,
 	0xa8, 0x6a, 0x6a, 0x00,
 	0x79, 0x6a, 0x6a, 0x00,
-	0x40, 0x3d, 0x62, 0x69,
+	0x40, 0x3d, 0x64, 0x69,
 	0x04, 0x35, 0x6a, 0x00,
-	0x00, 0x65, 0x78, 0x5b,
+	0x00, 0x65, 0x8e, 0x5b,
 	0x80, 0x6a, 0xd4, 0x01,
-	0x10, 0x36, 0x4e, 0x69,
+	0x10, 0x36, 0x50, 0x69,
 	0x10, 0x36, 0x6c, 0x00,
 	0x07, 0xac, 0x10, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x05, 0xa3, 0x70, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0x16, 0x5c,
-	0x00, 0x65, 0x10, 0x5c,
+	0xac, 0x6a, 0x2c, 0x5c,
+	0x00, 0x65, 0x26, 0x5c,
 	0x38, 0x6a, 0xcc, 0x00,
-	0xa3, 0x6a, 0x1a, 0x5c,
-	0xff, 0x38, 0x8a, 0x69,
+	0xa3, 0x6a, 0x30, 0x5c,
+	0xff, 0x38, 0x8c, 0x69,
 	0x80, 0x02, 0x04, 0x00,
 	0xe7, 0x35, 0x6a, 0x08,
 	0x03, 0x69, 0x18, 0x31,
@@ -199,327 +200,337 @@
 	0xff, 0x6a, 0x10, 0x00,
 	0xff, 0x6a, 0x12, 0x00,
 	0xff, 0x6a, 0x14, 0x00,
-	0x01, 0x38, 0x8e, 0x61,
+	0x01, 0x38, 0x92, 0x61,
 	0xbf, 0x35, 0x6a, 0x08,
+	0x02, 0x6a, 0xf8, 0x01,
 	0xff, 0x69, 0xca, 0x08,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0x92, 0x69,
-	0x04, 0x0b, 0x9e, 0x69,
-	0x10, 0x0c, 0x94, 0x79,
-	0x04, 0x0b, 0x9c, 0x69,
+	0x04, 0x0b, 0x96, 0x69,
+	0x04, 0x0b, 0xa2, 0x69,
+	0x10, 0x0c, 0x98, 0x79,
+	0x04, 0x0b, 0xa2, 0x69,
 	0xff, 0x6a, 0xca, 0x08,
-	0x00, 0x35, 0x60, 0x5b,
-	0x80, 0x02, 0xf2, 0x69,
-	0xff, 0x65, 0xe2, 0x79,
+	0x00, 0x35, 0x76, 0x5b,
+	0x80, 0x02, 0xf6, 0x69,
+	0xff, 0x65, 0xe6, 0x79,
 	0xff, 0x38, 0x70, 0x18,
-	0xff, 0x38, 0xe2, 0x79,
-	0x80, 0xea, 0xbe, 0x61,
+	0xff, 0x38, 0xe6, 0x79,
+	0x80, 0xea, 0xc2, 0x61,
 	0xef, 0x38, 0xc8, 0x18,
 	0x80, 0x6a, 0xc8, 0x00,
-	0x00, 0x65, 0xb0, 0x49,
+	0x00, 0x65, 0xb4, 0x49,
 	0x33, 0x38, 0xc8, 0x28,
 	0xff, 0x64, 0xd0, 0x09,
 	0x04, 0x39, 0xc0, 0x31,
 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0xb6, 0x79,
+	0x80, 0xeb, 0xba, 0x79,
 	0xf7, 0xeb, 0xd6, 0x09,
-	0x08, 0xeb, 0xba, 0x69,
+	0x08, 0xeb, 0xbe, 0x69,
 	0x01, 0x6a, 0xd6, 0x01,
 	0x08, 0xe9, 0x10, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x39, 0x6a, 0x1c, 0x5c,
+	0x39, 0x6a, 0x32, 0x5c,
 	0x08, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x9a, 0x5c,
-	0x88, 0x6a, 0x8a, 0x5c,
-	0x00, 0x65, 0x10, 0x5c,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x88, 0x6a, 0xa0, 0x5c,
+	0x00, 0x65, 0x26, 0x5c,
 	0xff, 0x6a, 0xc8, 0x08,
 	0x08, 0x39, 0x72, 0x18,
 	0x00, 0x3a, 0x74, 0x20,
-	0x01, 0x0c, 0xda, 0x79,
-	0x10, 0x0c, 0x7a, 0x79,
+	0x01, 0x0c, 0xde, 0x79,
+	0x10, 0x0c, 0x7c, 0x79,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x0b, 0xe0, 0x69,
-	0x00, 0x65, 0xfa, 0x59,
+	0x04, 0x0b, 0xe4, 0x69,
+	0x00, 0x65, 0xfe, 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, 0x22, 0x41,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0xfe, 0x59,
 	0x7f, 0x02, 0x04, 0x08,
 	0xe1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x22, 0x41,
-	0x04, 0x93, 0x10, 0x6a,
+	0x00, 0x65, 0x24, 0x41,
+	0x04, 0x93, 0x14, 0x6a,
 	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0xfe, 0x69,
+	0x20, 0x93, 0x02, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0x00, 0x7a,
-	0x01, 0x94, 0x00, 0x7a,
-	0x01, 0x94, 0x00, 0x7a,
-	0x01, 0x94, 0x00, 0x7a,
-	0x01, 0x94, 0x00, 0x7a,
-	0x01, 0x94, 0x00, 0x7a,
-	0x10, 0x94, 0x0e, 0x6a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x01, 0x94, 0x04, 0x7a,
+	0x10, 0x94, 0x12, 0x6a,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x12, 0x6a,
+	0x08, 0x93, 0x16, 0x6a,
 	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x16, 0x6a,
+	0x20, 0x93, 0x1a, 0x6a,
 	0x03, 0x08, 0x52, 0x31,
 	0xff, 0x38, 0x50, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x00, 0x65, 0x78, 0x5b,
+	0x00, 0x65, 0x8e, 0x5b,
 	0x05, 0xb4, 0x10, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x03, 0x8c, 0x10, 0x30,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xb4, 0x6a, 0x1a, 0x5c,
+	0xb4, 0x6a, 0x30, 0x5c,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
-	0x00, 0x65, 0x10, 0x5c,
-	0x3d, 0x6a, 0x60, 0x5b,
+	0x00, 0x65, 0x26, 0x5c,
+	0x3d, 0x6a, 0x76, 0x5b,
 	0xac, 0x6a, 0x26, 0x01,
-	0x04, 0x0b, 0x36, 0x6a,
-	0x01, 0x0b, 0x3c, 0x6a,
-	0x10, 0x0c, 0x38, 0x7a,
+	0x04, 0x0b, 0x3a, 0x6a,
+	0x04, 0x0b, 0x40, 0x6a,
+	0x10, 0x0c, 0x3c, 0x7a,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x3e, 0x6a,
+	0x08, 0x93, 0x42, 0x6a,
 	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0x42, 0x6a,
+	0x20, 0x93, 0x46, 0x6a,
 	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0x22, 0x41,
-	0x00, 0x65, 0x78, 0x5b,
+	0x00, 0x65, 0x24, 0x41,
+	0x00, 0x65, 0x8e, 0x5b,
 	0xff, 0x06, 0x44, 0x09,
-	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x24, 0x41,
 	0x10, 0x3d, 0x06, 0x00,
 	0xff, 0x34, 0xca, 0x08,
-	0x80, 0x65, 0x74, 0x62,
+	0x80, 0x65, 0x78, 0x62,
 	0x0f, 0xa1, 0xca, 0x08,
 	0x07, 0xa1, 0xca, 0x08,
 	0x40, 0xa0, 0xc8, 0x08,
 	0x00, 0x65, 0xca, 0x00,
 	0x80, 0x65, 0xca, 0x00,
-	0x80, 0xa0, 0x64, 0x7a,
+	0x80, 0xa0, 0x68, 0x7a,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x76, 0x42,
-	0x20, 0xa0, 0x7c, 0x7a,
+	0x00, 0x65, 0x7a, 0x42,
+	0x20, 0xa0, 0x80, 0x7a,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x08, 0x5c,
-	0xa0, 0x3d, 0x84, 0x62,
+	0x00, 0x65, 0x1e, 0x5c,
+	0xa0, 0x3d, 0x88, 0x62,
 	0x23, 0xa0, 0x0c, 0x08,
-	0x00, 0x65, 0x08, 0x5c,
-	0xa0, 0x3d, 0x84, 0x62,
-	0x00, 0xb9, 0x7c, 0x42,
-	0xff, 0x65, 0x7c, 0x62,
+	0x00, 0x65, 0x1e, 0x5c,
+	0xa0, 0x3d, 0x88, 0x62,
+	0x00, 0xb9, 0x80, 0x42,
+	0xff, 0x65, 0x80, 0x62,
 	0xa1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
-	0x10, 0x51, 0x84, 0x72,
+	0x10, 0x51, 0x88, 0x72,
 	0x40, 0x6a, 0x18, 0x00,
 	0xff, 0x65, 0x0c, 0x08,
-	0x00, 0x65, 0x08, 0x5c,
-	0xa0, 0x3d, 0x4e, 0x72,
+	0x00, 0x65, 0x1e, 0x5c,
+	0xa0, 0x3d, 0x52, 0x72,
 	0x40, 0x6a, 0x18, 0x00,
 	0xff, 0x34, 0xa6, 0x08,
-	0x80, 0x34, 0x8c, 0x62,
+	0x80, 0x34, 0x90, 0x62,
 	0x7f, 0xa0, 0x40, 0x09,
 	0x08, 0x6a, 0x68, 0x00,
-	0x00, 0x65, 0x22, 0x41,
-	0x64, 0x6a, 0x50, 0x5b,
-	0x80, 0x64, 0x00, 0x6b,
-	0x04, 0x64, 0xe2, 0x72,
-	0x02, 0x64, 0xe8, 0x72,
-	0x00, 0x6a, 0xaa, 0x72,
-	0x03, 0x64, 0xfc, 0x72,
-	0x01, 0x64, 0xde, 0x72,
-	0x07, 0x64, 0x3e, 0x73,
-	0x08, 0x64, 0xa6, 0x72,
+	0x00, 0x65, 0x24, 0x41,
+	0x64, 0x6a, 0x66, 0x5b,
+	0x80, 0x64, 0x06, 0x6b,
+	0x04, 0x64, 0xe8, 0x72,
+	0x02, 0x64, 0xee, 0x72,
+	0x00, 0x6a, 0xb0, 0x72,
+	0x03, 0x64, 0x02, 0x73,
+	0x01, 0x64, 0xe4, 0x72,
+	0x07, 0x64, 0x44, 0x73,
+	0x08, 0x64, 0xac, 0x72,
+	0x23, 0x64, 0x48, 0x73,
 	0x11, 0x6a, 0x22, 0x01,
-	0x07, 0x6a, 0x42, 0x5b,
+	0x07, 0x6a, 0x58, 0x5b,
 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x22, 0x41,
-	0xff, 0xa8, 0xae, 0x6a,
-	0xff, 0xa2, 0xc6, 0x7a,
+	0x00, 0x65, 0x24, 0x41,
+	0xff, 0xa8, 0xb4, 0x6a,
+	0xff, 0xa2, 0xcc, 0x7a,
 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x34, 0x5c,
-	0xff, 0xa2, 0xc6, 0x7a,
+	0x00, 0xb9, 0x4a, 0x5c,
+	0xff, 0xa2, 0xcc, 0x7a,
 	0x71, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
-	0x40, 0x51, 0xc6, 0x62,
+	0x40, 0x51, 0xcc, 0x62,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x34, 0x5c,
+	0x00, 0xb9, 0x4a, 0x5c,
 	0xff, 0x3e, 0x74, 0x09,
 	0xff, 0x90, 0x7c, 0x08,
 	0x00, 0x65, 0x50, 0x58,
-	0x00, 0x65, 0x34, 0x41,
-	0x20, 0xa0, 0xce, 0x6a,
+	0x00, 0x65, 0x36, 0x41,
+	0x20, 0xa0, 0xd4, 0x6a,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0xde, 0x5b,
-	0xff, 0x6a, 0xf4, 0x5b,
+	0x00, 0x6a, 0xf4, 0x5b,
+	0xff, 0x6a, 0x0a, 0x5c,
 	0xff, 0xf8, 0xc8, 0x08,
 	0xff, 0x4f, 0xc8, 0x08,
-	0x01, 0x6a, 0xde, 0x5b,
-	0x00, 0xb9, 0xf4, 0x5b,
+	0x01, 0x6a, 0xf4, 0x5b,
+	0x00, 0xb9, 0x0a, 0x5c,
 	0x01, 0x4f, 0x9e, 0x18,
 	0x02, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xa2, 0x5c,
-	0x00, 0x65, 0x34, 0x41,
+	0x00, 0x65, 0xb8, 0x5c,
+	0x00, 0x65, 0x36, 0x41,
 	0x41, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x24, 0x41,
 	0x04, 0xa0, 0x40, 0x01,
-	0x00, 0x65, 0xba, 0x5c,
-	0x00, 0x65, 0x34, 0x41,
-	0x10, 0x36, 0xa6, 0x7a,
+	0x00, 0x65, 0xd0, 0x5c,
+	0x00, 0x65, 0x36, 0x41,
+	0x10, 0x36, 0xac, 0x7a,
 	0x05, 0x38, 0x46, 0x31,
 	0x04, 0x14, 0x58, 0x31,
 	0x03, 0xa9, 0x60, 0x31,
 	0xa3, 0x6a, 0xcc, 0x00,
-	0x38, 0x6a, 0x1a, 0x5c,
+	0x38, 0x6a, 0x30, 0x5c,
 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0x1c, 0x5c,
-	0xa9, 0x6a, 0x1e, 0x5c,
-	0x00, 0x65, 0xa6, 0x42,
+	0x14, 0x6a, 0x32, 0x5c,
+	0xa9, 0x6a, 0x34, 0x5c,
+	0x00, 0x65, 0xac, 0x42,
 	0xef, 0x36, 0x6c, 0x08,
-	0x00, 0x65, 0xa6, 0x42,
+	0x00, 0x65, 0xac, 0x42,
 	0x0f, 0x64, 0xc8, 0x08,
 	0x07, 0x64, 0xc8, 0x08,
 	0x00, 0x37, 0x6e, 0x00,
 	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0xae, 0x5b,
-	0xff, 0x51, 0x12, 0x73,
-	0x20, 0x36, 0x1c, 0x7b,
-	0x00, 0x90, 0x9c, 0x5b,
-	0x00, 0x65, 0x1e, 0x43,
+	0x00, 0x65, 0xc4, 0x5b,
+	0xff, 0x51, 0x18, 0x73,
+	0x20, 0x36, 0x22, 0x7b,
+	0x00, 0x90, 0xb2, 0x5b,
+	0x00, 0x65, 0x24, 0x43,
 	0xff, 0x06, 0xd4, 0x08,
-	0x00, 0x65, 0x08, 0x5c,
-	0xe0, 0x3d, 0x38, 0x63,
-	0x20, 0x12, 0x38, 0x63,
-	0x51, 0x6a, 0x46, 0x5b,
-	0x00, 0x65, 0x96, 0x5b,
+	0x00, 0x65, 0x1e, 0x5c,
+	0xe0, 0x3d, 0x3e, 0x63,
+	0x20, 0x12, 0x3e, 0x63,
+	0x51, 0x6a, 0x5c, 0x5b,
+	0x00, 0x65, 0xac, 0x5b,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0xa1, 0x30, 0x63,
-	0x04, 0xa0, 0x30, 0x7b,
+	0x00, 0xa1, 0x36, 0x63,
+	0x04, 0xa0, 0x36, 0x7b,
 	0xfb, 0xa0, 0x40, 0x09,
 	0x80, 0x36, 0x6c, 0x00,
-	0x80, 0xa0, 0xa6, 0x7a,
+	0x80, 0xa0, 0xac, 0x7a,
 	0x7f, 0xa0, 0x40, 0x09,
-	0xff, 0x6a, 0x42, 0x5b,
-	0x00, 0x65, 0xa6, 0x42,
-	0x04, 0xa0, 0x36, 0x7b,
-	0x00, 0x65, 0xba, 0x5c,
-	0x00, 0x65, 0x38, 0x43,
-	0x00, 0x65, 0xa2, 0x5c,
+	0xff, 0x6a, 0x58, 0x5b,
+	0x00, 0x65, 0xac, 0x42,
+	0x04, 0xa0, 0x3c, 0x7b,
+	0x00, 0x65, 0xd0, 0x5c,
+	0x00, 0x65, 0x3e, 0x43,
+	0x00, 0x65, 0xb8, 0x5c,
 	0x31, 0x6a, 0x22, 0x01,
-	0x0c, 0x6a, 0x42, 0x5b,
-	0x00, 0x65, 0xa6, 0x42,
+	0x0c, 0x6a, 0x58, 0x5b,
+	0x00, 0x65, 0xac, 0x42,
 	0x61, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0xa6, 0x42,
+	0x00, 0x65, 0xac, 0x42,
+	0x51, 0x6a, 0x5c, 0x5b,
+	0xff, 0xa8, 0x54, 0x6b,
+	0xff, 0xa9, 0x54, 0x6b,
+	0xff, 0xaa, 0x54, 0x6b,
+	0xff, 0xab, 0x54, 0x6b,
+	0x00, 0x65, 0xac, 0x42,
+	0x51, 0x6a, 0x22, 0x01,
+	0x00, 0x65, 0xac, 0x42,
 	0x10, 0x3d, 0x06, 0x00,
 	0xff, 0x65, 0x68, 0x0c,
 	0xff, 0x06, 0xd4, 0x08,
-	0x01, 0x0c, 0x48, 0x7b,
-	0x04, 0x0c, 0x48, 0x6b,
+	0x01, 0x0c, 0x5e, 0x7b,
+	0x04, 0x0c, 0x60, 0x6b,
 	0xe0, 0x03, 0x7a, 0x08,
-	0xe0, 0x3d, 0x5c, 0x63,
+	0xe0, 0x3d, 0x72, 0x63,
 	0xff, 0x65, 0xcc, 0x08,
 	0xff, 0x12, 0xda, 0x0c,
 	0xff, 0x06, 0xd4, 0x0c,
 	0xff, 0x65, 0x0c, 0x08,
-	0x02, 0x0b, 0x58, 0x7b,
+	0x02, 0x0b, 0x6e, 0x7b,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0xd1, 0x6a, 0x22, 0x01,
-	0x00, 0x65, 0x22, 0x41,
+	0x00, 0x65, 0x24, 0x41,
 	0xff, 0x65, 0x26, 0x09,
-	0x01, 0x0b, 0x70, 0x6b,
-	0x10, 0x0c, 0x62, 0x7b,
-	0x04, 0x0b, 0x6a, 0x6b,
+	0x01, 0x0b, 0x86, 0x6b,
+	0x10, 0x0c, 0x78, 0x7b,
+	0x04, 0x0b, 0x80, 0x6b,
 	0xff, 0x6a, 0xca, 0x08,
-	0x04, 0x93, 0x6e, 0x6b,
-	0x01, 0x94, 0x6c, 0x7b,
-	0x10, 0x94, 0x6e, 0x6b,
+	0x04, 0x93, 0x84, 0x6b,
+	0x01, 0x94, 0x82, 0x7b,
+	0x10, 0x94, 0x84, 0x6b,
 	0xc7, 0x93, 0x26, 0x09,
 	0xff, 0x99, 0xd4, 0x08,
-	0x38, 0x93, 0x72, 0x6b,
+	0x38, 0x93, 0x88, 0x6b,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0x36, 0x76, 0x6b,
+	0x80, 0x36, 0x8c, 0x6b,
 	0x21, 0x6a, 0x22, 0x05,
 	0xff, 0x65, 0x20, 0x09,
-	0xff, 0x51, 0x84, 0x63,
+	0xff, 0x51, 0x9a, 0x63,
 	0xff, 0x37, 0xc8, 0x08,
-	0xa1, 0x6a, 0x90, 0x43,
+	0xa1, 0x6a, 0xa6, 0x43,
 	0xff, 0x51, 0xc8, 0x08,
-	0xb9, 0x6a, 0x90, 0x43,
+	0xb9, 0x6a, 0xa6, 0x43,
 	0xff, 0x90, 0xa4, 0x08,
-	0xff, 0xba, 0x94, 0x73,
+	0xff, 0xba, 0xaa, 0x73,
 	0xff, 0xba, 0x20, 0x09,
 	0xff, 0x65, 0xca, 0x18,
-	0x00, 0x6c, 0x88, 0x63,
+	0x00, 0x6c, 0x9e, 0x63,
 	0xff, 0x90, 0xca, 0x0c,
 	0xff, 0x6a, 0xca, 0x04,
-	0x20, 0x36, 0xa8, 0x7b,
-	0x00, 0x90, 0x7c, 0x5b,
-	0xff, 0x65, 0xa8, 0x73,
-	0xff, 0x52, 0xa6, 0x73,
+	0x20, 0x36, 0xbe, 0x7b,
+	0x00, 0x90, 0x92, 0x5b,
+	0xff, 0x65, 0xbe, 0x73,
+	0xff, 0x52, 0xbc, 0x73,
 	0xff, 0xba, 0xcc, 0x08,
 	0xff, 0x52, 0x20, 0x09,
 	0xff, 0x66, 0x74, 0x09,
 	0xff, 0x65, 0x20, 0x0d,
 	0xff, 0xba, 0x7e, 0x0c,
-	0x00, 0x6a, 0xa8, 0x5c,
+	0x00, 0x6a, 0xbe, 0x5c,
 	0x0d, 0x6a, 0x6a, 0x00,
-	0x00, 0x51, 0x34, 0x44,
-	0xff, 0x3f, 0x02, 0x74,
+	0x00, 0x51, 0x4a, 0x44,
+	0xff, 0x3f, 0x18, 0x74,
 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3f, 0x7c, 0x5b,
-	0xff, 0x65, 0x02, 0x74,
+	0x00, 0x3f, 0x92, 0x5b,
+	0xff, 0x65, 0x18, 0x74,
 	0x20, 0x36, 0x6c, 0x00,
-	0x20, 0xa0, 0xbc, 0x6b,
+	0x20, 0xa0, 0xd2, 0x6b,
 	0xff, 0xb9, 0xa2, 0x0c,
 	0xff, 0x6a, 0xa2, 0x04,
 	0xff, 0x65, 0xa4, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x28, 0x5c,
+	0x45, 0x6a, 0x3e, 0x5c,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x09, 0x6a, 0xd6, 0x01,
-	0x80, 0xeb, 0xc8, 0x7b,
+	0x80, 0xeb, 0xde, 0x7b,
 	0x01, 0x6a, 0xd6, 0x01,
 	0x01, 0xe9, 0xa4, 0x34,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x28, 0x5c,
+	0x45, 0x6a, 0x3e, 0x5c,
 	0x01, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0x0d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x9a, 0x5c,
+	0x00, 0x65, 0xb0, 0x5c,
 	0xff, 0x99, 0xa4, 0x0c,
 	0xff, 0x65, 0xa4, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x28, 0x5c,
+	0x45, 0x6a, 0x3e, 0x5c,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x05,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x45, 0x6a, 0x28, 0x5c,
+	0x45, 0x6a, 0x3e, 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, 0xf8, 0x7b,
+	0x80, 0xee, 0x0e, 0x7c,
 	0xff, 0x6a, 0xdc, 0x0d,
 	0xff, 0x65, 0x32, 0x09,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x9a, 0x44,
+	0x00, 0x65, 0xb0, 0x44,
 	0xff, 0x37, 0xc8, 0x08,
-	0x00, 0x6a, 0xbe, 0x5b,
+	0x00, 0x6a, 0xd4, 0x5b,
 	0xff, 0x52, 0xa2, 0x0c,
-	0x01, 0x0c, 0x08, 0x7c,
-	0x04, 0x0c, 0x08, 0x6c,
+	0x01, 0x0c, 0x1e, 0x7c,
+	0x04, 0x0c, 0x1e, 0x6c,
 	0xe0, 0x03, 0x06, 0x08,
 	0xe0, 0x03, 0x7a, 0x0c,
 	0xff, 0x8c, 0x10, 0x08,
@@ -542,29 +553,29 @@
 	0x00, 0x6c, 0xda, 0x24,
 	0xff, 0x65, 0xc8, 0x08,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0x24, 0x5c,
+	0x41, 0x6a, 0x3a, 0x5c,
 	0xff, 0x90, 0xe2, 0x09,
 	0x20, 0x6a, 0xd0, 0x01,
-	0x04, 0x35, 0x46, 0x7c,
+	0x04, 0x35, 0x5c, 0x7c,
 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0x42, 0x64,
-	0x00, 0x65, 0x52, 0x44,
+	0xdc, 0xee, 0x58, 0x64,
+	0x00, 0x65, 0x68, 0x44,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x20, 0xa0, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x4c, 0x7c,
+	0x80, 0xee, 0x62, 0x7c,
 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x50, 0x64,
+	0xd8, 0xee, 0x66, 0x64,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x54, 0x6c,
+	0x18, 0xee, 0x6a, 0x6c,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x41, 0x6a, 0x24, 0x5c,
+	0x41, 0x6a, 0x3a, 0x5c,
 	0x20, 0x6a, 0x18, 0x01,
 	0xff, 0x6a, 0x1a, 0x09,
 	0xff, 0x6a, 0x1c, 0x09,
 	0xff, 0x35, 0x26, 0x09,
-	0x04, 0x35, 0x7e, 0x6c,
+	0x04, 0x35, 0x94, 0x6c,
 	0xa0, 0x6a, 0xca, 0x00,
 	0x20, 0x65, 0xc8, 0x18,
 	0xff, 0x6c, 0x32, 0x09,
@@ -575,14 +586,14 @@
 	0xff, 0x6c, 0x32, 0x09,
 	0xff, 0x6c, 0x32, 0x09,
 	0xff, 0x6c, 0x32, 0x09,
-	0x00, 0x65, 0x6a, 0x64,
+	0x00, 0x65, 0x80, 0x64,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x9a, 0x5c,
-	0x04, 0x35, 0x76, 0x7b,
-	0xa0, 0x6a, 0x8a, 0x5c,
-	0x00, 0x65, 0x8c, 0x5c,
-	0x00, 0x65, 0x8c, 0x5c,
-	0x00, 0x65, 0x8c, 0x44,
+	0x00, 0x65, 0xb0, 0x5c,
+	0x04, 0x35, 0x8c, 0x7b,
+	0xa0, 0x6a, 0xa0, 0x5c,
+	0x00, 0x65, 0xa2, 0x5c,
+	0x00, 0x65, 0xa2, 0x5c,
+	0x00, 0x65, 0xa2, 0x44,
 	0xff, 0x65, 0xcc, 0x08,
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x08,
@@ -591,19 +602,19 @@
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x08,
 	0xff, 0x99, 0xda, 0x0c,
-	0x08, 0x94, 0x9a, 0x7c,
+	0x08, 0x94, 0xb0, 0x7c,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x9e, 0x6c,
+	0x08, 0x93, 0xb4, 0x6c,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0xff, 0x40, 0x74, 0x09,
 	0xff, 0x90, 0x80, 0x08,
 	0xff, 0x6a, 0x72, 0x05,
-	0xff, 0x40, 0xb6, 0x64,
-	0xff, 0x3f, 0xae, 0x64,
+	0xff, 0x40, 0xcc, 0x64,
+	0xff, 0x3f, 0xc4, 0x64,
 	0xff, 0x6a, 0xca, 0x04,
 	0xff, 0x3f, 0x20, 0x09,
 	0x01, 0x6a, 0x6a, 0x00,
-	0x00, 0xb9, 0x34, 0x5c,
+	0x00, 0xb9, 0x4a, 0x5c,
 	0xff, 0xba, 0x7e, 0x0c,
 	0xff, 0x40, 0x20, 0x09,
 	0xff, 0xba, 0x80, 0x0c,
@@ -744,66 +755,68 @@
 	{ aic7xxx_patch4_func, 40, 4, 1 },
 	{ aic7xxx_patch8_func, 44, 3, 2 },
 	{ aic7xxx_patch0_func, 47, 3, 1 },
-	{ aic7xxx_patch9_func, 52, 7, 1 },
-	{ aic7xxx_patch4_func, 60, 3, 1 },
-	{ aic7xxx_patch8_func, 63, 2, 1 },
-	{ aic7xxx_patch1_func, 68, 60, 1 },
-	{ aic7xxx_patch8_func, 162, 1, 2 },
-	{ aic7xxx_patch0_func, 163, 2, 1 },
-	{ aic7xxx_patch2_func, 167, 3, 3 },
-	{ aic7xxx_patch8_func, 167, 2, 1 },
-	{ aic7xxx_patch0_func, 170, 2, 1 },
-	{ aic7xxx_patch8_func, 173, 1, 2 },
-	{ aic7xxx_patch0_func, 174, 1, 1 },
-	{ aic7xxx_patch2_func, 178, 1, 1 },
-	{ aic7xxx_patch2_func, 181, 3, 2 },
-	{ aic7xxx_patch0_func, 184, 5, 1 },
-	{ aic7xxx_patch2_func, 192, 2, 3 },
-	{ aic7xxx_patch8_func, 192, 1, 1 },
-	{ aic7xxx_patch0_func, 194, 3, 1 },
-	{ aic7xxx_patch10_func, 197, 2, 1 },
-	{ aic7xxx_patch8_func, 199, 7, 2 },
-	{ aic7xxx_patch0_func, 206, 1, 1 },
-	{ aic7xxx_patch2_func, 211, 14, 3 },
-	{ aic7xxx_patch10_func, 224, 1, 1 },
-	{ aic7xxx_patch0_func, 225, 9, 1 },
-	{ aic7xxx_patch8_func, 239, 2, 1 },
-	{ aic7xxx_patch8_func, 241, 1, 1 },
-	{ aic7xxx_patch10_func, 242, 6, 3 },
-	{ aic7xxx_patch2_func, 242, 2, 2 },
-	{ aic7xxx_patch0_func, 244, 4, 1 },
-	{ aic7xxx_patch8_func, 249, 1, 1 },
-	{ aic7xxx_patch8_func, 253, 19, 1 },
-	{ aic7xxx_patch2_func, 273, 3, 3 },
-	{ aic7xxx_patch10_func, 275, 1, 1 },
-	{ aic7xxx_patch0_func, 276, 5, 1 },
-	{ aic7xxx_patch10_func, 281, 1, 2 },
-	{ aic7xxx_patch0_func, 282, 9, 1 },
-	{ aic7xxx_patch11_func, 298, 1, 2 },
-	{ aic7xxx_patch0_func, 299, 1, 1 },
-	{ aic7xxx_patch5_func, 359, 1, 2 },
-	{ aic7xxx_patch0_func, 360, 1, 1 },
-	{ aic7xxx_patch3_func, 363, 1, 1 },
-	{ aic7xxx_patch2_func, 373, 3, 2 },
-	{ aic7xxx_patch0_func, 376, 5, 1 },
-	{ aic7xxx_patch11_func, 384, 1, 2 },
-	{ aic7xxx_patch0_func, 385, 1, 1 },
-	{ aic7xxx_patch6_func, 390, 1, 1 },
-	{ aic7xxx_patch1_func, 427, 3, 1 },
-	{ aic7xxx_patch10_func, 432, 11, 1 },
-	{ aic7xxx_patch2_func, 480, 7, 2 },
-	{ aic7xxx_patch0_func, 487, 8, 1 },
-	{ aic7xxx_patch2_func, 496, 4, 2 },
-	{ aic7xxx_patch0_func, 500, 6, 1 },
-	{ aic7xxx_patch2_func, 506, 4, 2 },
-	{ aic7xxx_patch0_func, 510, 3, 1 },
-	{ aic7xxx_patch12_func, 520, 10, 1 },
-	{ aic7xxx_patch2_func, 539, 17, 4 },
-	{ aic7xxx_patch13_func, 547, 4, 2 },
-	{ aic7xxx_patch0_func, 551, 2, 1 },
-	{ aic7xxx_patch0_func, 556, 33, 1 },
-	{ aic7xxx_patch12_func, 589, 4, 1 },
-	{ aic7xxx_patch6_func, 593, 2, 1 },
-	{ aic7xxx_patch6_func, 596, 9, 1 },
+	{ aic7xxx_patch9_func, 53, 7, 1 },
+	{ aic7xxx_patch4_func, 61, 3, 1 },
+	{ aic7xxx_patch8_func, 64, 2, 1 },
+	{ aic7xxx_patch1_func, 69, 60, 1 },
+	{ aic7xxx_patch8_func, 163, 1, 2 },
+	{ aic7xxx_patch0_func, 164, 2, 1 },
+	{ aic7xxx_patch2_func, 168, 3, 4 },
+	{ aic7xxx_patch8_func, 168, 2, 2 },
+	{ aic7xxx_patch0_func, 170, 1, 1 },
+	{ aic7xxx_patch0_func, 171, 2, 1 },
+	{ aic7xxx_patch8_func, 174, 1, 2 },
+	{ aic7xxx_patch0_func, 175, 1, 1 },
+	{ aic7xxx_patch2_func, 179, 1, 1 },
+	{ aic7xxx_patch2_func, 182, 3, 2 },
+	{ aic7xxx_patch0_func, 185, 5, 1 },
+	{ aic7xxx_patch2_func, 193, 2, 3 },
+	{ aic7xxx_patch8_func, 193, 1, 1 },
+	{ aic7xxx_patch0_func, 195, 3, 1 },
+	{ aic7xxx_patch10_func, 199, 1, 2 },
+	{ aic7xxx_patch0_func, 200, 1, 1 },
+	{ aic7xxx_patch8_func, 201, 7, 2 },
+	{ aic7xxx_patch0_func, 208, 1, 1 },
+	{ aic7xxx_patch2_func, 213, 14, 3 },
+	{ aic7xxx_patch10_func, 226, 1, 1 },
+	{ aic7xxx_patch0_func, 227, 9, 1 },
+	{ aic7xxx_patch8_func, 241, 2, 1 },
+	{ aic7xxx_patch8_func, 243, 1, 1 },
+	{ aic7xxx_patch10_func, 244, 6, 3 },
+	{ aic7xxx_patch2_func, 244, 2, 2 },
+	{ aic7xxx_patch0_func, 246, 4, 1 },
+	{ aic7xxx_patch8_func, 251, 1, 1 },
+	{ aic7xxx_patch8_func, 255, 19, 1 },
+	{ aic7xxx_patch2_func, 275, 3, 3 },
+	{ aic7xxx_patch10_func, 277, 1, 1 },
+	{ aic7xxx_patch0_func, 278, 5, 1 },
+	{ aic7xxx_patch10_func, 283, 1, 2 },
+	{ aic7xxx_patch0_func, 284, 9, 1 },
+	{ aic7xxx_patch11_func, 300, 1, 2 },
+	{ aic7xxx_patch0_func, 301, 1, 1 },
+	{ aic7xxx_patch5_func, 362, 1, 2 },
+	{ aic7xxx_patch0_func, 363, 1, 1 },
+	{ aic7xxx_patch3_func, 366, 1, 1 },
+	{ aic7xxx_patch2_func, 376, 3, 2 },
+	{ aic7xxx_patch0_func, 379, 5, 1 },
+	{ aic7xxx_patch11_func, 387, 1, 2 },
+	{ aic7xxx_patch0_func, 388, 1, 1 },
+	{ aic7xxx_patch6_func, 393, 1, 1 },
+	{ aic7xxx_patch1_func, 438, 3, 1 },
+	{ aic7xxx_patch10_func, 443, 11, 1 },
+	{ aic7xxx_patch2_func, 491, 7, 2 },
+	{ aic7xxx_patch0_func, 498, 8, 1 },
+	{ aic7xxx_patch2_func, 507, 4, 2 },
+	{ aic7xxx_patch0_func, 511, 6, 1 },
+	{ aic7xxx_patch2_func, 517, 4, 2 },
+	{ aic7xxx_patch0_func, 521, 3, 1 },
+	{ aic7xxx_patch12_func, 531, 10, 1 },
+	{ aic7xxx_patch2_func, 550, 17, 4 },
+	{ aic7xxx_patch13_func, 558, 4, 2 },
+	{ aic7xxx_patch0_func, 562, 2, 1 },
+	{ aic7xxx_patch0_func, 567, 33, 1 },
+	{ aic7xxx_patch12_func, 600, 4, 1 },
+	{ aic7xxx_patch6_func, 604, 2, 1 },
+	{ aic7xxx_patch6_func, 607, 9, 1 },
 
 };
diff -urN linux-2.2.15-pre13/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- linux-2.2.15-pre13/drivers/scsi/atp870u.c	Tue Jan  4 10:12:19 2000
+++ linux/drivers/scsi/atp870u.c	Mon Dec  3 22:01:11 2001
@@ -111,6 +111,11 @@
 	{
 		tmport += 0x1f;
 		j = inb(tmport);
+		if((j&0x80)==0)
+		{
+			dev->in_int=0;
+			return;
+		}
 
 		tmpcip = dev->pciport;
 		if ((inb(tmpcip) & 0x08) != 0) 
diff -urN linux-2.2.15-pre13/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- linux-2.2.15-pre13/drivers/scsi/hosts.h	Tue May 11 10:36:25 1999
+++ linux/drivers/scsi/hosts.h	Mon Dec  3 22:01:11 2001
@@ -484,10 +484,10 @@
 #ifdef CONFIG_SCSI_PLUTO_MODULE
 #define SD_EXTRA_DEVS 40
 #else
-#define SD_EXTRA_DEVS 4
+#define SD_EXTRA_DEVS 16
 #endif
 #define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 2
+#define SR_EXTRA_DEVS 4
 #define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
 
 #endif
diff -urN linux-2.2.15-pre13/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- linux-2.2.15-pre13/drivers/scsi/megaraid.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/scsi/megaraid.c	Mon Dec  3 22:01:11 2001
@@ -2,14 +2,14 @@
  *
  *                    Linux MegaRAID device driver
  *
- * Copyright 1999 American Megatrends Inc.
+ * Copyright 1998 American Megatrends Inc.
  *
  *              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 of the License, or (at your option) any later version.
  *
- * Version : 1.07
+ * Version : 1.04
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
@@ -111,19 +111,6 @@
  *    The addtional 32 bit field for 64bit address in the newly defined
  *      mailbox64 structure is set to 0 at this point.
  *
- * Version 1.05
- *    Changed the queing implementation for handling SCBs and completed
- *      commands.
- *    Added spinlocks in the interrupt service routine to enable the dirver
- *      function in the SMP environment.
- *    Fixed the problem of unnecessary aborts in the abort entry point, which
- *      also enables the driver to handle large amount of I/O requests for
- *      long duration of time.
- *
- * Version 1.07
- *    Removed the usage of uaccess.h file for kernel versions less than
- *    2.0.36, as this file is not present in those versions.
- *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
@@ -138,8 +125,7 @@
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v107 (December 22, 1999)"
-
+#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -159,6 +145,8 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
@@ -181,9 +169,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#if LINUX_VERSION_CODE > 0x020024
 #include <asm/uaccess.h>
-#endif
 
 #include "sd.h"
 #include "scsi.h"
@@ -223,6 +209,31 @@
 #define MAX_SERBUF 160
 #define COM_BASE 0x2f8
 
+#define ENQUEUE(obj,type,list,next) \
+{ type **node; long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+}
+
+/* a non-locking version (if we already have the lock) */
+#define ENQUEUE_NL(obj,type,list,next) \
+{ type **node; \
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+}
+
+#define DEQUEUE(obj,type,list,next) \
+{ long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  if ((obj=list) != NULL) {\
+    list = (type *)(list)->##next; \
+  } \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
 
 u32 RDINDOOR (mega_host_config * megaCfg)
 {
@@ -254,67 +265,19 @@
 			 u_char * mboxData,
 			 mega_scb * scb,
 			 int intr);
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 			 u32 * buffer, u32 * length);
 
 static int mega_busyWaitMbox(mega_host_config *);
 static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (mega_host_config *);
+static void mega_rundoneq (void);
 static void mega_cmd_done (mega_host_config *, mega_scb *, int);
 static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void mega_freeSgList(mega_host_config *megaCfg);
+static inline void freeSgList(mega_host_config *megaCfg);
 static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
                                     mega_Enquiry3 *enquiry3,
                                     megaRaidProductInfo *productInfo );
 
-
-
-
-#if LINUX_VERSION_CODE > 0x020100
-#  include <asm/spinlock.h>
-#  include <linux/smp.h>
-#  define cpuid smp_processor_id()
-#  if LINUX_VERSION_CODE < 0x020195
-#    define DRIVER_LOCK_T unsigned long cpu_flags = 0;
-#    define DRIVER_LOCK_INIT(p) \
-       spin_lock_init(&p->mega_lock);
-#    define DRIVER_LOCK(p) \
-       if(!p->cpu_lock_count[cpuid]) { \
-         spin_lock_irqsave(&p->mega_lock, cpu_flags); \
-         p->cpu_lock_count[cpuid]++; \
-       } else { \
-         p->cpu_lock_count[cpuid]++; \
-       }
-#    define DRIVER_UNLOCK(p) \
-       if(--p->cpu_lock_count[cpuid] == 0) \
-         spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
-#    define IO_LOCK(p)   spin_lock_irqsave(&io_request_lock,cpu_flags);
-#    define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
-#  else
-#    define DRIVER_LOCK_T
-#    define DRIVER_LOCK_INIT(p)
-#    define DRIVER_LOCK(p)
-#    define DRIVER_UNLOCK(p)
-#    define IO_LOCK_T unsigned long io_flags = 0;
-#    define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
-#    define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
-#  endif
-#else
-#  define cpuid 0
-#  define DRIVER_LOCK_T long cpu_flags;
-#  define DRIVER_LOCK_INIT(p)
-#  define DRIVER_LOCK(p) \
-       save_flags(cpu_flags); \
-       cli();
-#  define DRIVER_UNLOCK(p) \
-       restore_flags(cpu_flags);
-#  define IO_LOCK_T unsigned long io_flags = 0;
-#  define IO_LOCK(p)   DRIVER_LOCK(p)
-#  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
-#  define le32_to_cpu(x) (x)
-#  define cpu_to_le32(x) (x)
-#endif
-
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
 #if SERDEBUG
@@ -334,7 +297,6 @@
 /*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
     XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
     processor id cannot be scanned */
-
 static char *megaraid;
 #if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
@@ -352,10 +314,13 @@
 
 static mega_scb *pLastScb = NULL;
 
+/* Queue of pending/completed SCBs */
+static Scsi_Cmnd *qCompleted = NULL;
 
 #if SERDEBUG
 volatile static spinlock_t serial_lock;
 #endif
+volatile static spinlock_t mega_lock;
 
 struct proc_dir_entry proc_scsi_megaraid =
 {
@@ -421,7 +386,7 @@
 #define TRACE(A)
 #endif
 
-static void callDone (Scsi_Cmnd * SCpnt)
+void callDone (Scsi_Cmnd * SCpnt)
 {
   if (SCpnt->result) {
     TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
@@ -441,66 +406,37 @@
  * Free a SCB structure
  *=======================
  */
-static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
 {
-
-  mega_scb *pScbtmp;
-
-  if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
-    return ;
-  }
+  mega_scb **ppScb;
 
   /* Unlink from pending queue */
-
-  if(pScb == megaCfg->qPendingH) {
-    if(megaCfg->qPendingH == megaCfg->qPendingT ) 
-      megaCfg->qPendingH = megaCfg->qPendingT = NULL;
-    else {
-      megaCfg->qPendingH = megaCfg->qPendingH->next;
-    }
-    megaCfg->qPcnt--;
-  }
-  else {
-    for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
-      if (pScbtmp->next == pScb) {
-        pScbtmp->next = pScb->next;
-        if(pScb == megaCfg->qPendingT) {
-          megaCfg->qPendingT = pScbtmp;
-        }
-        megaCfg->qPcnt--;
+  for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
+    if (*ppScb == pScb) {
+	*ppScb = pScb->next;
 	break;
     }
   }
-  }
 
-  /* Link back into free list */
+  /* Link back into list */
   pScb->state = SCB_FREE;
   pScb->SCpnt = NULL;
 
-  if(megaCfg->qFreeH == (mega_scb *) NULL ) {
-    megaCfg->qFreeH = megaCfg->qFreeT = pScb;
-  }
-  else {
-    megaCfg->qFreeT->next  = pScb;
-    megaCfg->qFreeT = pScb;
-  }
-  megaCfg->qFreeT->next = NULL;
-  megaCfg->qFcnt++;
-
+  pScb->next     = megaCfg->qFree;
+  megaCfg->qFree = pScb;
 }
 
 /*===========================
  * Allocate a SCB structure
  *===========================
  */
-static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
   mega_scb *pScb;
 
   /* Unlink command from Free List */
-  if ((pScb = megaCfg->qFreeH) != NULL) {
-    megaCfg->qFreeH = pScb->next;
-    megaCfg->qFcnt--;
+  if ((pScb = megaCfg->qFree) != NULL) {
+    megaCfg->qFree = pScb->next;
     
     pScb->isrcount = jiffies;
     pScb->next  = NULL;
@@ -519,72 +455,62 @@
  * Initialize SCB structures
  *================================================
  */
-static int mega_initSCB (mega_host_config * megaCfg)
+static int initSCB (mega_host_config * megaCfg)
 {
   int idx;
 
-  megaCfg->qFreeH = NULL;
-  megaCfg->qFcnt = 0;
-#if DEBUG
-if(megaCfg->max_cmds >= MAX_COMMANDS) {
-printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
-}
-#endif
-
+  megaCfg->qFree = NULL;
   for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
     megaCfg->scbList[idx].idx    = idx;
     megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
 					   GFP_ATOMIC | GFP_DMA);
     if (megaCfg->scbList[idx].sgList == NULL) {
       printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
-      mega_freeSgList(megaCfg);
+      freeSgList(megaCfg);
       return -1;
     }
     
     if (idx < MAX_COMMANDS) {
       /* Link to free list */
-      mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
+      freeSCB(megaCfg, &megaCfg->scbList[idx]);
     }
   }
   return 0;
 }
 
 /* Run through the list of completed requests */
-static void mega_rundoneq (mega_host_config *megaCfg)
+static void mega_rundoneq ()
 {
   Scsi_Cmnd *SCpnt;
 
-  while ((SCpnt = megaCfg->qCompletedH) != NULL) {
-    megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
-    megaCfg->qCcnt--;
+  while (1) {
+    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    if (SCpnt == NULL)
+      return;
 
-    SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
     /* Callback */
     callDone (SCpnt);
   }
-  megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
 }
 
 /*
- * Runs through the list of pending requests
- * Assumes that mega_lock spin_lock has been acquired.
- */
+  Runs through the list of pending requests
+  Assumes that mega_lock spin_lock has been acquired.
+*/
 static void mega_runpendq(mega_host_config *megaCfg)
 {
   mega_scb *pScb;
 
   /* Issue any pending commands to the card */
-  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
     if (pScb->state == SCB_ACTIVE) {
-      if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
-	return;
+      megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
     }
   }
 }
 
 /* Add command to the list of completed requests */
-static void
-mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
 			   int status)
 {
   int islogical;
@@ -598,6 +524,7 @@
   }
 
   SCpnt = pScb->SCpnt;
+  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
   pthru = &pScb->pthru;
   mbox = (mega_mailbox *) &pScb->mboxData;
 
@@ -606,7 +533,7 @@
 	TRACE(("pScb->idx = ",pScb->idx));
 	TRACE(("pScb->state = ",pScb->state));
 	TRACE(("pScb->state = ",pScb->state));
-	printk("megaraid:Problem...!\n");
+	printk("Problem...!\n");
 	while(1);
   }
 
@@ -661,18 +588,10 @@
   /* not IOCTL_CMD_NEW SCB, freeSCB()*/
   /* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
    * after copy data back to user space*/
-     mega_freeSCB(megaCfg, pScb);
+     freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-   }
-   megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-   megaCfg->qCcnt++;
+  ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 }
 
 /*-------------------------------------------------------------------
@@ -712,11 +631,13 @@
 
   if ( islogical ) {
 	lun = (SCpnt->target * 8) + lun;
+#if 1
         if ( lun > FC_MAX_LOGICAL_DRIVES ){
             SCpnt->result = (DID_BAD_TARGET << 16);
             callDone (SCpnt);
             return NULL;
         }
+#endif
   }
   /*-----------------------------------------------------
    *
@@ -740,7 +661,7 @@
     case READ_CAPACITY:
     case INQUIRY:
       /* Allocate a SCB and initialize passthru */
-      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -771,7 +692,7 @@
     case READ_10:
     case WRITE_10:
       /* Allocate a SCB and initialize mailbox */
-      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -807,7 +728,7 @@
       }
 
       /* Calculate Scatter-Gather info */
-      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
 					  (u32 *) & mbox->xferaddr,
 					  (u32 *) & seg);
 
@@ -826,7 +747,7 @@
    *-----------------------------------------------------*/
   else {
     /* Allocate a SCB and initialize passthru */
-    if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
       SCpnt->result = (DID_ERROR << 16);
       callDone (SCpnt);
       return NULL;
@@ -847,7 +768,7 @@
     pthru->cdblen = SCpnt->cmd_len;
     memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -874,12 +795,20 @@
   unsigned char *data = (unsigned char *)SCpnt->request_buffer;
   int i;
 
-  if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
     SCpnt->result = (DID_ERROR << 16);
     callDone (SCpnt);
     return NULL;
   }
 
+#if 0
+  printk("\nBUF: ");
+  for (i=0;i<18;i++) {
+     printk(" %x",data[i]);
+  }
+  printk("......\n");
+#endif
+
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
@@ -902,7 +831,7 @@
     mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
     mailbox->xferaddr = virt_to_bus (pthru);
 
-    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+    pthru->numsgelements = build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -914,14 +843,6 @@
   }
   /* else normal (nonpassthru) command */
 
-#if LINUX_VERSION_CODE > 0x020024
-/*
- * usage of the function copy from user is used in case of data more than
- * 4KB.  This is used only with adapters which supports more than 8 logical
- * drives.  This feature is disabled on kernels earlier or same as 2.0.36
- * as the uaccess.h file is not available with those kernels.
- */
-
   if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
             /* use external data area for large xfers  */
      /* If cmnd[0] is set to IOCTL_CMD_NEW then *
@@ -947,7 +868,6 @@
       copy_from_user(kern_area,user_area,xfer_size);
       pScb->kern_area = kern_area;
   }
-#endif
 
   mbox->cmd = data[0];
   mbox->channel = data[1];
@@ -970,7 +890,7 @@
   } 
   else {
 
-      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
 				      (u32 *) & mbox->xferaddr,
 				      (u32 *) & seg);
 
@@ -998,36 +918,32 @@
 }
 #endif
 
-#if DEBUG
-static unsigned int cum_time = 0;
-static unsigned int cum_time_cnt = 0;
-#endif
-
 /*--------------------------------------------------------------------
  * Interrupt service routine
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
-#if LINUX_VERSION_CODE >= 0x20100
-  IO_LOCK_T
-#endif
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
-  u32 dword=0;
+  u32 dword;
   mega_mailbox *mbox;
   mega_scb *pScb;
-  u_char qCnt, qStatus;
-  u_char            completed[MAX_FIRMWARE_STATUS];
-  Scsi_Cmnd *SCpnt;
+  long flags;
+  int qCnt, qStatus;
 
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-  if (megaCfg->host->irq == irq) {
+#if LINUX_VERSION_CODE >= 0x20100
+  spin_lock_irqsave (&io_request_lock, flags);
+#endif
+
+  while (megaCfg->host->irq == irq) {
+
+    spin_lock_irqsave (&mega_lock, flags);
 
     if (megaCfg->flag & IN_ISR) {
       TRACE (("ISR called reentrantly!!\n"));
-      printk ("ISR called reentrantly!!\n");
     }
 
     megaCfg->flag |= IN_ISR;
@@ -1036,67 +952,48 @@
 	printk(KERN_WARNING "Error: mailbox busy in isr!\n");
     }
 
+
     /* Check if a valid interrupt is pending */
     if (megaCfg->flag & BOARD_QUARTZ) {
       dword = RDOUTDOOR (megaCfg);
       if (dword != 0x10001234) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	return;
+	spin_unlock_irqrestore (&mega_lock, flags);
+	break;
       }
+      WROUTDOOR (megaCfg, dword);
+
+      /* Copy to temp location */
+      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+      /* Acknowledge interrupt */
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x02);
     }
     else {
       byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
       if ((byte & VALID_INTR_BYTE) == 0) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	return;
+	spin_unlock_irqrestore (&mega_lock, flags);
+	break;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
-    }
-
-    for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
-
-#if LINUX_VERSION_CODE >= 0x20100
-    IO_LOCK;
-#endif
-
-    qCnt = 0xff;
-    while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) 
-      ;
-
-    qStatus = 0xff;
-    while ((qStatus = megaCfg->mbox->status) == 0xFF)
-      ;
 
-    /* Get list of completed requests */
-    for (idx = 0; idx<qCnt; idx++) {
-      while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
-	printk("p");
-      }
-      completed[idx] = sIdx;
-      sIdx = 0xFF;
-    }
+      /* Copy to temp location */
+      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
 
-    if (megaCfg->flag & BOARD_QUARTZ) {
-      WROUTDOOR (megaCfg, dword);
       /* Acknowledge interrupt */
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
-      while (RDINDOOR (megaCfg) & 0x02);
-    }
-    else {
       CLEAR_INTR (megaCfg->host->io_port);
     }
 
-#if DEBUG
-    if(qCnt >= MAX_FIRMWARE_STATUS) {
-      printk("megaraid_isr: cmplt=%d ", qCnt);
-    }
-#endif
+    qCnt = mbox->numstatus;
+    qStatus = mbox->status;
 
     for (idx = 0; idx < qCnt; idx++) {
-      sIdx = completed[idx];
-      if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
+      sIdx = mbox->completed[idx];
+      if (sIdx > 0) {
 	pScb = &megaCfg->scbList[sIdx - 1];
 
 	/* ASSERT(pScb->state == SCB_ISSUED); */
@@ -1104,30 +1001,12 @@
 #if DEBUG
 	if (((jiffies) - pScb->isrcount) > maxCmdTime) {
 	  maxCmdTime = (jiffies) - pScb->isrcount;
-	  printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
+	  printk("cmd time = %u\n", maxCmdTime);
 	}
 #endif
-/*
- * Assuming that the scsi command, for which an abort request was received
- * earlier has completed.
- */
+
 	if (pScb->state == SCB_ABORTED) {
-          SCpnt = pScb->SCpnt;
-	}
-	if (pScb->state == SCB_RESET) {
-          SCpnt = pScb->SCpnt;
-	  mega_freeSCB (megaCfg, pScb);
-	  SCpnt->result = (DID_RESET << 16) ;
-          if( megaCfg->qCompletedH == NULL ) {
-            megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-          }
-          else {
-            megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-            megaCfg->qCompletedT = SCpnt;
-          }
-          megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-          megaCfg->qCcnt++;
-          continue;
+	  printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
 	}
 
         if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) 
@@ -1138,23 +1017,24 @@
 	mega_cmd_done(megaCfg, pScb, qStatus);
 
       }
-      else {
-        printk("megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
-	for(;;);
-      }
-    }
 
-    mega_rundoneq(megaCfg);
+    }
+    spin_unlock_irqrestore (&mega_lock, flags);
 
     megaCfg->flag &= ~IN_ISR;
+
+    mega_rundoneq();
+
     /* Loop through any pending requests */
+    spin_lock_irqsave(&mega_lock, flags);
     mega_runpendq(megaCfg);
-#if LINUX_VERSION_CODE >= 0x20100
-    IO_UNLOCK;
-#endif
+    spin_unlock_irqrestore(&mega_lock,flags);
 
   }
 
+#if LINUX_VERSION_CODE >= 0x20100
+  spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
 }
 
 /*==================================================*/
@@ -1198,6 +1078,7 @@
   mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
   u_char byte;
   u32 cmdDone;
+  Scsi_Cmnd *SCpnt;
   u32 phys_mbox;
   u8 retval=-1;
 
@@ -1206,12 +1087,18 @@
 
   phys_mbox = virt_to_bus (megaCfg->mbox);
 
+#if 0
+  if (intr && mbox->busy) {
+    return 0;
+  }
+#endif
+
 #if DEBUG
   showMbox(pScb);
 #endif
 
   /* Wait until mailbox is free */
-  if (mega_busyWaitMbox (megaCfg)) {
+  while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
 
@@ -1221,10 +1108,14 @@
     
     /* Abort command */
     if (pScb == NULL) {
-	TRACE(("NULL pScb in megaIssue\n"));
 	printk("NULL pScb in megaIssue\n");
+	TRACE(("NULL pScb in megaIssue\n"));
     }
-    mega_cmd_done (megaCfg, pScb, 0x08);
+    SCpnt = pScb->SCpnt;
+    freeSCB(megaCfg, pScb);
+
+    SCpnt->result = (DID_ABORT << 16);
+    callDone(SCpnt);
     return -1;
   }
 
@@ -1263,6 +1154,7 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
+	mega_rundoneq ();
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1276,25 +1168,26 @@
       while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
 
+
       ENABLE_INTR (megaCfg->host->io_port);
       CLEAR_INTR (megaCfg->host->io_port);
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
+	mega_rundoneq ();
       }
       else {
 	TRACE (("Error: NULL pScb!\n"));
       }
+
     }
     enable_irq(megaCfg->host->irq);
     retval=mbox->status;
   }
-#if DEBUG
   while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox on exit......!\n");
     udelay(1000);
   }
-#endif
 
   return retval;
 }
@@ -1302,7 +1195,7 @@
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 	      u32 * buffer, u32 * length)
 {
   struct scatterlist *sgList;
@@ -1361,7 +1254,9 @@
   paddr = (paddr + 4 + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
-  if (!(megaCfg->flag & BOARD_QUARTZ)) {
+  if (megaCfg->flag & BOARD_QUARTZ) {
+  }
+  else {
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
@@ -1419,6 +1314,8 @@
   u32 paddr;
   u8 retval;
 
+  spin_lock_init (&mega_lock);
+
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
@@ -1478,17 +1375,28 @@
     /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ 
   megaCfg->host->max_lun =              /* max lun */
     (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; 
-  megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
 
   megaCfg->numldrv = enquiry3Pnt->numLDrv;
   megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
-  if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
 
-  megaCfg->host->can_queue   = megaCfg->max_cmds;
+#if 0 
+  int i;
+  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
+  for (i = 0; i < megaCfg->numldrv; i++) {
+    printk ("%d: size: %d prop: %x state: %x\n", i,
+	    enquiry3Pnt->lDrvSize[i],
+	    enquiry3Pnt->lDrvProp[i],
+	    enquiry3Pnt->lDrvState[i]);
+  }
 
-  if (megaCfg->host->can_queue >= MAX_COMMANDS) {
-    megaCfg->host->can_queue = MAX_COMMANDS-1;
+  printk (KERN_DEBUG "---- Physical drive info ----\n");
+  for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
+    if (i && !(i % 8))
+      printk ("\n");
+    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
   }
+  printk ("\n");
+#endif
 
 #ifdef HP			/* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
@@ -1535,7 +1443,7 @@
   return 0;
 }
 
-int mega_findCard (Scsi_Host_Template * pHostTmpl,
+int findCard (Scsi_Host_Template * pHostTmpl,
 	  u16 pciVendor, u16 pciDev,
 	  long flag)
 {
@@ -1548,6 +1456,10 @@
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
+
+#if 0
+  } /* keep auto-indenters happy */
+#endif
 #else
   
   struct pci_dev *pdev = pci_devices;
@@ -1561,7 +1473,7 @@
       pcibios_read_config_word (pciBus, pciDevFun,
 				PCI_CONF_AMISIG,
 				&magic);
-      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
+      if (magic != AMI_SIGNATURE) {
         pciIdx++;
 	continue;		/* not an AMI board */
       }
@@ -1606,15 +1518,8 @@
 	    host->host_no, (u_int) megaBase, megaIrq);
 
     /* Copy resource info into structure */
-    megaCfg->qCompletedH = NULL;
-    megaCfg->qCompletedT = NULL;
-    megaCfg->qPendingH = NULL;
-    megaCfg->qPendingT = NULL;
-    megaCfg->qFreeH    = NULL;
-    megaCfg->qFreeT    = NULL;
-    megaCfg->qFcnt = 0;
-    megaCfg->qPcnt = 0;
-    megaCfg->qCcnt = 0;
+    megaCfg->qPending = NULL;
+    megaCfg->qFree    = NULL;
     megaCfg->flag = flag;
     megaCfg->host = host;
     megaCfg->base = megaBase;
@@ -1646,7 +1551,7 @@
     mega_i_query_adapter (megaCfg);
     
     /* Initialize SCBs */
-    if (mega_initSCB (megaCfg)) {
+    if (initSCB (megaCfg)) {
       scsi_unregister (host);
       continue;
     }
@@ -1684,9 +1589,9 @@
 
   printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
 
-  count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
-  count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
-  count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
+  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
+  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
 
   return count;
 }
@@ -1721,13 +1626,13 @@
     release_region (megaCfg->host->io_port, 16);
   }
 
-  mega_freeSgList(megaCfg);
+  freeSgList(megaCfg);
   scsi_unregister (pSHost);
 
   return 0;
 }
 
-static inline void mega_freeSgList(mega_host_config *megaCfg)
+static inline void freeSgList(mega_host_config *megaCfg)
 {
   int i;
 
@@ -1773,12 +1678,13 @@
  *-----------------------------------------------------------------*/
 int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 {
-  DRIVER_LOCK_T
   mega_host_config *megaCfg;
   mega_scb *pScb;
+  long flags;
+
+  spin_lock_irqsave(&mega_lock,flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
-  DRIVER_LOCK(megaCfg);
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
     if (SCpnt->channel < SCpnt->host->max_channel)
@@ -1796,56 +1702,33 @@
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
     SCpnt->result = (DID_ABORT << 16);
-    /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-    }
-    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-    megaCfg->qCcnt++;
+    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 
-    DRIVER_UNLOCK(megaCfg);
+    spin_unlock_irqrestore(&mega_lock,flags);
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
     SCpnt->result = (DID_RESET << 16);
-    /* Add Scsi_Command to end of completed queue */
-    if( megaCfg->qCompletedH == NULL ) {
-      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-    }
-    else {
-      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-      megaCfg->qCompletedT = SCpnt;
-    }
-    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-    megaCfg->qCcnt++;
+    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
 
-    DRIVER_UNLOCK(megaCfg);
+    spin_unlock_irqrestore(&mega_lock,flags);
     return 0;
   }
 
-  megaCfg->flag |= IN_QUEUE;
   /* Allocate and build a SCB request */
   if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
               /*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
     /* Add SCB to the head of the pending queue */
-    /* Add SCB to the head of the pending queue */
-    if( megaCfg->qPendingH == NULL ) {
-      megaCfg->qPendingH = megaCfg->qPendingT = pScb;
+    ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
+
+    /* Issue any pending command to the card if not in ISR */
+    if (!(megaCfg->flag & IN_ISR)) {
+      mega_runpendq(megaCfg);
     }
     else {
-      megaCfg->qPendingT->next = pScb;
-      megaCfg->qPendingT = pScb;
+      printk("IRQ pend...\n");
     }
-    megaCfg->qPendingT->next = NULL;
-    megaCfg->qPcnt++;
-
-      mega_runpendq(megaCfg);
 
-#if LINUX_VERSION_CODE > 0x020024
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
           char *user_area;
@@ -1861,13 +1744,12 @@
 
           kfree(pScb->kern_area);
 
-          mega_freeSCB(megaCfg, pScb);
+          freeSCB(megaCfg, pScb);
     }
-#endif
+
   }
 
-  megaCfg->flag &= ~IN_QUEUE;
-  DRIVER_UNLOCK(megaCfg);
+  spin_unlock_irqrestore(&mega_lock,flags);
 
   return 0;
 }
@@ -1905,92 +1787,78 @@
 /*---------------------------------------------------------------------
  * Abort a previous SCSI request
  *---------------------------------------------------------------------*/
-int
-megaraid_abort (Scsi_Cmnd * SCpnt)
+int megaraid_abort (Scsi_Cmnd * SCpnt)
 {
   mega_host_config *megaCfg;
-  int   rc; //, idx;
+  int   rc, idx;
+  long  flags;
   mega_scb *pScb;
 
-  rc = SCSI_ABORT_NOT_RUNNING;
+  rc = SCSI_ABORT_SUCCESS;
+
+  spin_lock_irqsave (&mega_lock, flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_ABORT;
 
-  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
 #if DEBUG
       showMbox(pScb);
 #endif
 
-/*
- * If the command is queued to be issued to the firmware, abort the scsi cmd,
- * If the command is already aborted in a previous call to the _abort entry
- *  point, return SCSI_ABORT_SNOOZE, suggesting a reset.
- * If the command is issued to the firmware, which might complete after
- *  some time, we will mark the scb as aborted, and return to the mid layer, 
- *  that abort could not be done.
- *  In the ISR, when this command actually completes, we will perform a normal
- *  completion.
- *
- * Oct 27, 1999
- */
+      printk("Abort: %d %u\n", 
+	     SCpnt->timeout_per_command,
+	     (uint)((jiffies) - pScb->isrcount));
 
       switch(pScb->state) {
       case SCB_ABORTED: /* Already aborted */
 	rc = SCSI_ABORT_SNOOZE;
 	break;
       case SCB_ISSUED: /* Waiting on ISR result */
-	rc = SCSI_ABORT_NOT_RUNNING;
+	rc = SCSI_ABORT_PENDING;
 	pScb->state = SCB_ABORTED;
 	break;
-      case SCB_ACTIVE: /* still on the pending queue */
-	mega_freeSCB (megaCfg, pScb);
-	SCpnt->result = (DID_ABORT << 16) ;
-        if( megaCfg->qCompletedH == NULL ) {
-          megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
-        }
-        else {
-          megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
-          megaCfg->qCompletedT = SCpnt;
-        }
-        megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
-        megaCfg->qCcnt++;
-	rc = SCSI_ABORT_SUCCESS;
-        break;
-      default:
-        printk("megaraid_abort: unknown command state!!\n");
-        rc = SCSI_ABORT_NOT_RUNNING;
-	break;
       }
-      break;
     }
   }
 
-  megaCfg->flag &= ~IN_ABORT;
-
+#if 0
+  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+	  SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+	  SCpnt->lun));
+  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+    if (pScb->SCpnt == SCpnt) { 
+      ser_printk("** %d<%x>  %c\n", pScb->SCpnt->pid, pScb->idx+1,
+		 pScb->state == SCB_ACTIVE ? 'A' : 'I');
 #if DEBUG
-if(megaCfg->flag & IN_QUEUE)  printk("ma:flag is in queue\n");
-if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
+      showMbox(pScb);
 #endif
+    }
+  }
+#endif
+
+  /*
+   * Walk list of SCBs for any that are still outstanding
+   */
+  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+    if (megaCfg->scbList[idx].state != SCB_FREE) {
+      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
+	freeSCB (megaCfg, &megaCfg->scbList[idx]);
+
+	SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
+	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+      }
+    }
+  }
   
-/*
- * This is required here to complete any completed requests to be communicated
- * over to the mid layer.
- * Calling just mega_rundoneq() did not work.
- */
-if(megaCfg->qCompletedH) {
-  SCpnt = megaCfg->qCompletedH;
-  megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
-  megaCfg->qCcnt--;
-
-  SCpnt->host_scribble = (unsigned char *) NULL ;
-  /* Callback */
-  callDone (SCpnt);
-}
-  mega_rundoneq(megaCfg);
+  megaCfg->flag &= ~IN_ABORT;
+
+  spin_unlock_irqrestore (&mega_lock, flags);
+
+  mega_rundoneq();
 
   return rc;
 }
@@ -2002,18 +1870,14 @@
 {
   mega_host_config *megaCfg;
   int idx;
-  int rc;
-  mega_scb *pScb;
+  long flags;
+
+  spin_lock_irqsave (&mega_lock, flags);
 
-  rc = SCSI_RESET_NOT_RUNNING;
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_RESET;
 
-  printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
-	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
-	  SCpnt->lun, rstflags);
-
   TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
 	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
 	  SCpnt->lun));
@@ -2024,18 +1888,20 @@
   for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].state != SCB_FREE) {
       SCpnt = megaCfg->scbList[idx].SCpnt;
-      pScb = &megaCfg->scbList[idx];
       if (SCpnt != NULL) {
-        pScb->state = SCB_RESET;
-        break;
+	freeSCB (megaCfg, &megaCfg->scbList[idx]);
+	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
       }
     }
   }
 
   megaCfg->flag &= ~IN_RESET;
 
-  mega_rundoneq(megaCfg);
-  return rc;
+  spin_unlock_irqrestore (&mega_lock, flags);
+
+  mega_rundoneq();
+  return SCSI_RESET_PUNT;
 }
 
 /*-------------------------------------------------------------
@@ -2081,3 +1947,4 @@
 
 #include "scsi_module.c"
 #endif
+
diff -urN linux-2.2.15-pre13/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- linux-2.2.15-pre13/drivers/scsi/megaraid.h	Mon Dec  3 22:01:05 2001
+++ linux/drivers/scsi/megaraid.h	Mon Dec  3 22:01:11 2001
@@ -8,7 +8,6 @@
 #define IN_ISR                  0x80000000L
 #define IN_ABORT                0x40000000L
 #define IN_RESET                0x20000000L
-#define IN_QUEUE                0x10000000L
 #define BOARD_QUARTZ            0x08000000L
 #define BOARD_40LD              0x04000000L
 
@@ -22,15 +21,9 @@
 
 #define MEGA_CMD_TIMEOUT        10
 
-/* Feel free to fiddle with these.. max values are:
-   SGLIST     0..26
-   COMMANDS   0..253
-   CMDPERLUN  0..63
-*/
-#define MAX_SGLIST              0x1A
-#define MAX_COMMANDS            127
+#define MAX_SGLIST              17
+#define MAX_COMMANDS            250
 #define MAX_CMD_PER_LUN         63
-#define MAX_FIRMWARE_STATUS     46
 
 #define MAX_LOGICAL_DRIVES      8
 #define MAX_CHANNEL             5
@@ -107,7 +100,6 @@
 #define PCI_CONF_IRQ_OFFSET        0x3c
 #define PCI_CONF_AMISIG            0xa0
 #define AMI_SIGNATURE              0x3344
-#define AMI_SIGNATURE_471          0xCCCC
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
@@ -513,7 +505,7 @@
     u32 dataxferlen;
 } mega_passthru;
 
-struct _mega_mailbox {
+typedef struct _mega_mailbox {
     /* 0x0 */ u8 cmd;
     /* 0x1 */ u8 cmdid;
     /* 0x2 */ u16 numsectors;
@@ -528,9 +520,8 @@
     /* 0x12 */ u8 completed[46];
     u8 mraid_poll;
     u8 mraid_ack;
-    u8 pad[16]; /* for alignment purposes */
-}__attribute__((packed));
-typedef struct _mega_mailbox mega_mailbox;
+    u8 pad[16];
+} mega_mailbox;
 
 typedef struct {
     u32 xferSegment;      /* for 64-bit controllers */
@@ -584,16 +575,8 @@
     u32 flag;
     u32 base;
  
-    mega_scb *qFreeH;
-    mega_scb *qFreeT;
-    mega_scb *qPendingH;
-    mega_scb *qPendingT;
-    
-    Scsi_Cmnd *qCompletedH;
-    Scsi_Cmnd *qCompletedT;
-    u32 qFcnt;
-    u32 qPcnt;
-    u32 qCcnt;
+    mega_scb *qFree;
+    mega_scb *qPending;
 
     u32 nReads[FC_MAX_LOGICAL_DRIVES];
     u32 nWrites[FC_MAX_LOGICAL_DRIVES];
diff -urN linux-2.2.15-pre13/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- linux-2.2.15-pre13/drivers/telephony/ixj.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/telephony/ixj.c	Mon Dec  3 22:01:11 2001
@@ -3800,6 +3800,32 @@
 	case PHONE_CPT_STOP:
 		ixj_cpt_stop(board);
 		break;
+	case PHONE_QUERY_CODEC:
+	{
+		struct phone_codec_data pd;
+		int val;
+		int proto_size[] = {
+			-1, 
+			12, 10, 16, 9, 8, 48, 5,
+			40, 40, 80, 40, 40
+		};
+		if(copy_from_user(&pd, (void *)arg, sizeof(pd)))
+			return -EFAULT;
+		if(pd.type<1 || pd.type>12)
+			return -EPROTONOSUPPORT;
+		if(pd.type<G729)
+			val=proto_size[pd.type];
+		else switch(j->baseframe.low)
+		{
+			case 0xA0:val=2*proto_size[pd.type];break;
+			case 0x50:val=proto_size[pd.type];break;
+			default:val=proto_size[pd.type]*3;break;
+		}
+		pd.buf_min=pd.buf_max=pd.buf_opt=val;
+		if(copy_to_user((void *)arg, &pd, sizeof(pd)))
+			return -EFAULT;
+		return 0;
+	}
 	case IXJCTL_DSP_IDLE:
 		idle(board);
 		break;
@@ -3840,6 +3866,7 @@
 		ixj_daa_cr4(board, arg | 0x02);
 		break;
 	case IXJCTL_PSTN_LINETEST:
+	case PHONE_PSTN_LINETEST:
 		retval = ixj_linetest(board);
 		break;
 	case IXJCTL_CID:
diff -urN linux-2.2.15-pre13/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- linux-2.2.15-pre13/drivers/video/fbcon.c	Mon Dec  3 22:01:05 2001
+++ linux/drivers/video/fbcon.c	Wed Aug 25 17:29:49 1999
@@ -1087,12 +1087,8 @@
 
 static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
 {
-    unsigned short *p;
-    
-    if (conp->vc_num != fg_console)
-    	return;
-    p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
-
+    unsigned short *p = (unsigned short *)
+    	(conp->vc_origin + t * conp->vc_size_row);
     while (count) {
     	scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
     	count--;
diff -urN linux-2.2.15-pre13/fs/ext2/dir.c linux/fs/ext2/dir.c
--- linux-2.2.15-pre13/fs/ext2/dir.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/ext2/dir.c	Mon Dec  3 22:01:11 2001
@@ -196,15 +196,18 @@
 				 * version stamp to detect whether or
 				 * not the directory has been modified
 				 * during the copy operation.
+				 * AV: It can't be modified, but it fscking
+				 * can be seeked by another process that shares
+				 * the descriptor.
 				 */
-				unsigned long version = inode->i_version;
+				unsigned long version = filp->f_version;
 
 				error = filldir(dirent, de->name,
 						de->name_len,
 						filp->f_pos, le32_to_cpu(de->inode));
 				if (error)
 					break;
-				if (version != inode->i_version)
+				if (version != filp->f_version)
 					goto revalidate;
 				stored ++;
 			}
diff -urN linux-2.2.15-pre13/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h
--- linux-2.2.15-pre13/include/asm-sparc/vaddrs.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc/vaddrs.h	Mon Dec  3 22:01:12 2001
@@ -20,8 +20,8 @@
 #define  IOBASE_LEN     0x00300000  /* Length of the IO area */
 #define  IOBASE_END     0xfe300000
 #define  DVMA_VADDR     0xfff00000  /* Base area of the DVMA on suns */
-#define  DVMA_LEN       0x00040000  /* Size of the DVMA address space */
-#define  DVMA_END       0xfff40000
+#define  DVMA_LEN       0x000c0000  /* Size of the DVMA address space */
+#define  DVMA_END       0xfffc0000
 
 /* IOMMU Mapping area, must be on a 16MB boundary!  Note this
  * doesn't count the DVMA areas, the prom lives between the
diff -urN linux-2.2.15-pre13/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- linux-2.2.15-pre13/include/asm-sparc64/system.h	Tue May 11 08:24:32 1999
+++ linux/include/asm-sparc64/system.h	Mon Dec  3 22:01:12 2001
@@ -106,7 +106,16 @@
 #define read_pcr(__p)  __asm__ __volatile__("rd	%%pcr, %0" : "=r" (__p))
 #define write_pcr(__p) __asm__ __volatile__("wr	%0, 0x0, %%pcr" : : "r" (__p));
 #define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-#define reset_pic()    __asm__ __volatile__("wr	%g0, 0x0, %pic");
+
+/* Blackbird errata workaround.  See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define reset_pic()    						\
+	__asm__ __volatile__("ba,pt	%xcc, 99f\n\t"		\
+			     ".align	64\n"			\
+			  "99:wr	%g0, 0x0, %pic\n\t"	\
+			     "rd	%pic, %g0")
 
 #ifndef __ASSEMBLY__
 
diff -urN linux-2.2.15-pre13/include/linux/telephony.h linux/include/linux/telephony.h
--- linux-2.2.15-pre13/include/linux/telephony.h	Tue Jan  4 10:12:25 2000
+++ linux/include/linux/telephony.h	Mon Dec  3 22:01:12 2001
@@ -158,6 +158,16 @@
 	WSS = 12
 } phone_codec;
 
+struct phone_codec_data
+{
+	phone_codec type;
+	unsigned short buf_min, buf_opt, buf_max;
+};
+
+#define PHONE_QUERY_CODEC		_IOWR ('q', 0xA7, struct phone_codec_data *)
+#define PHONE_PSTN_LINETEST		_IO ('q', 0xA8)
+
+
 /******************************************************************************
 *
 * The exception structure allows us to multiplex multiple events onto the
diff -urN linux-2.2.15-pre13/include/linux/videodev.h linux/include/linux/videodev.h
--- linux-2.2.15-pre13/include/linux/videodev.h	Tue Oct 26 17:53:42 1999
+++ linux/include/linux/videodev.h	Mon Dec  3 22:01:12 2001
@@ -238,7 +238,7 @@
 #define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
 #define VIDIOCSPICT		_IOW('v',7,struct video_picture)	/* Set picture properties */
 #define VIDIOCCAPTURE		_IOW('v',8,int)				/* Start, end capture */
-#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Set the video overlay window */
+#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Get the video overlay window */
 #define VIDIOCSWIN		_IOW('v',10, struct video_window)	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
 #define VIDIOCGFBUF		_IOR('v',11, struct video_buffer)	/* Get frame buffer */
 #define VIDIOCSFBUF		_IOW('v',12, struct video_buffer)	/* Set frame buffer - root only */
diff -urN linux-2.2.15-pre13/ipc/sem.c linux/ipc/sem.c
--- linux-2.2.15-pre13/ipc/sem.c	Tue Jan  4 10:12:25 2000
+++ linux/ipc/sem.c	Mon Dec  3 22:01:12 2001
@@ -282,7 +282,7 @@
         for (q = sma->sem_pending; q; q = q->next) {
                         
                 if (q->status == 1)
-                        return; /* wait for other process */
+			continue; /* this one was woken up before */
 
                 error = try_atomic_semop(sma, q->sops, q->nsops,
                                          q->undo, q->pid, q->alter);
diff -urN linux-2.2.15-pre13/net/ipv4/udp.c linux/net/ipv4/udp.c
--- linux-2.2.15-pre13/net/ipv4/udp.c	Mon Aug  9 12:05:10 1999
+++ linux/net/ipv4/udp.c	Mon Dec  3 22:01:12 2001
@@ -857,6 +857,7 @@
 		sin->sin_family = AF_INET;
 		sin->sin_port = skb->h.uh->source;
 		sin->sin_addr.s_addr = skb->nh.iph->saddr;
+		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 		if (flags&MSG_PROXY)
 		{
