## Automatically generated incremental diff
## From:   linux-2.4.32-pre2
## To:     linux-2.4.32-pre3
## Robot:  $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $

diff -urN linux-2.4.32-pre2/Documentation/Configure.help linux-2.4.32-pre3/Documentation/Configure.help
--- linux-2.4.32-pre2/Documentation/Configure.help	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/Documentation/Configure.help	2005-08-08 20:06:12.365627833 -0700
@@ -28990,6 +28990,9 @@
   the TEA algorithm to address a potential key weakness
   in the TEA algorithm.
 
+  Xtendend Encryption Tiny Algorithm is a mis-implementation
+  of the XTEA algorithm for compatibility purposes.
+
 CONFIG_CRYPTO_ARC4
   ARC4 cipher algorithm.
   
diff -urN linux-2.4.32-pre2/Documentation/crypto/api-intro.txt linux-2.4.32-pre3/Documentation/crypto/api-intro.txt
--- linux-2.4.32-pre2/Documentation/crypto/api-intro.txt	2004-11-17 03:54:20.000000000 -0800
+++ linux-2.4.32-pre3/Documentation/crypto/api-intro.txt	2005-08-08 20:06:12.366627877 -0700
@@ -221,6 +221,7 @@
 
 TEA/XTEA algorithm contributors:
   Aaron Grothe
+  Michael Ringe
 
 Khazad algorithm contributors:
   Aaron Grothe
diff -urN linux-2.4.32-pre2/Makefile linux-2.4.32-pre3/Makefile
--- linux-2.4.32-pre2/Makefile	2005-08-08 20:06:10.595549912 -0700
+++ linux-2.4.32-pre3/Makefile	2005-08-08 20:06:12.421630298 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 32
-EXTRAVERSION = -pre2
+EXTRAVERSION = -pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.32-pre2/arch/alpha/kernel/Makefile linux-2.4.32-pre3/arch/alpha/kernel/Makefile
--- linux-2.4.32-pre2/arch/alpha/kernel/Makefile	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.32-pre3/arch/alpha/kernel/Makefile	2005-08-08 20:06:12.316625676 -0700
@@ -76,7 +76,7 @@
 obj-y    += sys_alcor.o
 endif
 ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
-obj-y    += sys_cabriolet.o
+obj-y    += sys_cabriolet.o ns87312.o
 endif
 
 obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o
diff -urN linux-2.4.32-pre2/arch/i386/kernel/pci-irq.c linux-2.4.32-pre3/arch/i386/kernel/pci-irq.c
--- linux-2.4.32-pre2/arch/i386/kernel/pci-irq.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/arch/i386/kernel/pci-irq.c	2005-08-08 20:06:12.318625764 -0700
@@ -664,6 +664,13 @@
 static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
 {
 	/* FIXME: We should move some of the quirk fixup stuff here */
+
+	if (router->device == PCI_DEVICE_ID_VIA_82C686 &&
+		device == PCI_DEVICE_ID_VIA_82C586_0) {
+		/* Asus k7m bios wrongly reports 82C686A as 586-compatible */
+		device = PCI_DEVICE_ID_VIA_82C686;
+	}
+
 	switch(device)
 	{
 		case PCI_DEVICE_ID_VIA_82C586_0:
diff -urN linux-2.4.32-pre2/arch/ppc/kernel/time.c linux-2.4.32-pre3/arch/ppc/kernel/time.c
--- linux-2.4.32-pre2/arch/ppc/kernel/time.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/arch/ppc/kernel/time.c	2005-08-08 20:06:12.325626072 -0700
@@ -84,7 +84,7 @@
 
 extern unsigned long wall_jiffies;
 
-static long time_offset;
+static long timezone_offset;
 
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 
@@ -187,7 +187,7 @@
 		     xtime.tv_sec - last_rtc_update >= 659 &&
 		     abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
 		     jiffies - wall_jiffies == 1) {
-		  	if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
+		  	if (ppc_md.set_rtc_time(xtime.tv_sec+1 + timezone_offset) == 0)
 				last_rtc_update = xtime.tv_sec+1;
 			else
 				/* Try again one minute later */
@@ -297,7 +297,7 @@
 	unsigned old_stamp, stamp, elapsed;
 
         if (ppc_md.time_init != NULL)
-                time_offset = ppc_md.time_init();
+                timezone_offset = ppc_md.time_init();
 
 	if (__USE_RTC()) {
 		/* 601 processor: dec counts down by 128 every 128ns */
@@ -344,9 +344,9 @@
 	/* If platform provided a timezone (pmac), we correct the time
 	 * using do_sys_settimeofday() which in turn calls warp_clock()
 	 */
-        if (time_offset) {
+        if (timezone_offset) {
         	struct timezone tz;
-        	tz.tz_minuteswest = -time_offset / 60;
+        	tz.tz_minuteswest = -timezone_offset / 60;
         	tz.tz_dsttime = 0;
         	do_sys_settimeofday(NULL, &tz);
         }
diff -urN linux-2.4.32-pre2/crypto/tcrypt.c linux-2.4.32-pre3/crypto/tcrypt.c
--- linux-2.4.32-pre2/crypto/tcrypt.c	2004-11-17 03:54:21.000000000 -0800
+++ linux-2.4.32-pre3/crypto/tcrypt.c	2005-08-08 20:06:12.337626600 -0700
@@ -64,7 +64,7 @@
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
 	"arc4", "michael_mic", "deflate", "tea", "xtea", "khazad", 
-	"wp512", "wp384", "wp256", "tnepres", "anubis", NULL
+	"wp512", "wp384", "wp256", "tnepres", "anubis", "xeta", NULL
 };
 
 static void
@@ -590,6 +590,10 @@
 		test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
 		test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
 
+		//XETA
+		test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS);
+		test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -725,6 +729,11 @@
 		test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
 		break;
 
+	case 30:
+		test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS);
+		test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -urN linux-2.4.32-pre2/crypto/tcrypt.h linux-2.4.32-pre3/crypto/tcrypt.h
--- linux-2.4.32-pre2/crypto/tcrypt.h	2004-11-17 03:54:21.000000000 -0800
+++ linux-2.4.32-pre3/crypto/tcrypt.h	2005-08-08 20:06:12.339626688 -0700
@@ -2085,7 +2085,7 @@
 		.klen	= 16,
 		.input  = { [0 ... 8] = 0x00 },
 		.ilen	= 8,
-		.result	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.result	= { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
 		.rlen	= 8,
 	}, {
 		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
@@ -2093,13 +2093,13 @@
 		.klen	= 16,
 		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
 		.ilen	= 8,
-		.result	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.result	= { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
 		.rlen	= 8,
 	}, {
 		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
-		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+		.input	= { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
 		.ilen	= 16,
 		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
@@ -2114,10 +2114,10 @@
 			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
 			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
 		.ilen	= 32,
-		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
-			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.result	= { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+			    0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+			    0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+			    0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
 		.rlen	= 32,
 	}
 };
@@ -2127,7 +2127,7 @@
 	{
 		.key    = { [0 ... 15] = 0x00 },
 		.klen	= 16,
-		.input	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.input	= { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
 		.ilen	= 8,
 		.result = { [0 ... 8] = 0x00 },
 		.rlen	= 8,
@@ -2135,7 +2135,7 @@
 		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
 			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
 		.klen	= 16,
-		.input	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.input	= { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
 		.ilen	= 8,
 		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
 		.rlen	= 8,
@@ -2143,8 +2143,8 @@
 		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
-		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
-			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+		.input	= { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+			    0x77, 0x4d, 0xd4, 0xb4, 0x87, 0x24, 0xe3, 0x9a },
 		.ilen	= 16,
 		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
@@ -2153,10 +2153,10 @@
 		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
 			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
 		.klen	= 16,
-		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
-			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.input	= { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+			    0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+			    0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+			    0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
 		.ilen	= 32,
 		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
 			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
@@ -2469,6 +2469,100 @@
 	},
 };
 
+/* 
+ * XETA test vectors 
+ */
+#define XETA_ENC_TEST_VECTORS	4
+#define XETA_DEC_TEST_VECTORS	4
+
+struct cipher_testvec xeta_enc_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input  = { [0 ... 8] = 0x00 },
+		.ilen	= 8,
+		.result	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.ilen	= 8,
+		.result	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.ilen	= 16,
+		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.ilen	= 32,
+		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.rlen	= 32,
+	}
+};
+
+struct cipher_testvec xeta_dec_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.ilen	= 8,
+		.result = { [0 ... 8] = 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+		.ilen	= 16,
+		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.ilen	= 32,
+		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.rlen	= 32,
+	}
+};
+
 /*
  * Compression stuff.
  */
diff -urN linux-2.4.32-pre2/crypto/tea.c linux-2.4.32-pre3/crypto/tea.c
--- linux-2.4.32-pre2/crypto/tea.c	2004-11-17 03:54:21.000000000 -0800
+++ linux-2.4.32-pre3/crypto/tea.c	2005-08-08 20:06:12.340626732 -0700
@@ -1,11 +1,15 @@
 /* 
  * Cryptographic API.
  *
- * TEA and Xtended TEA Algorithms
+ * TEA, XTEA, and XETA crypto alogrithms
  *
  * The TEA and Xtended TEA algorithms were developed by David Wheeler 
  * and Roger Needham at the Computer Laboratory of Cambridge University.
  *
+ * Due to the order of evaluation in XTEA many people have incorrectly
+ * implemented it.  XETA (XTEA in the wrong order), exists for 
+ * compatibility with these implementations.
+ *
  * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -153,9 +157,9 @@
 	z = u32_in (src + 4);
 
 	while (sum != limit) {
-		y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
+		y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); 
 		sum += XTEA_DELTA;
-		z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
+		z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); 
 	}
 	
 	u32_out (dst, y);
@@ -175,6 +179,51 @@
 	sum = XTEA_DELTA * XTEA_ROUNDS;
 
 	while (sum) {
+		z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]);
+		sum -= XTEA_DELTA;
+		y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]);
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+
+}
+
+static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+	u32 y, z, sum = 0;
+	u32 limit = XTEA_DELTA * XTEA_ROUNDS;
+
+	struct xtea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	while (sum != limit) {
+		y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
+		sum += XTEA_DELTA;
+		z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
+
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+
+}
+
+static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+	u32 y, z, sum;
+	struct tea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	sum = XTEA_DELTA * XTEA_ROUNDS;
+
+	while (sum) {
 		z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
 		sum -= XTEA_DELTA;
 		y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
@@ -215,6 +264,22 @@
 	.cia_decrypt		=	xtea_decrypt } }
 };
 
+
+static struct crypto_alg xeta_alg = {
+	.cra_name		=	"xeta",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	XTEA_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof (struct xtea_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(xtea_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	XTEA_KEY_SIZE,
+	.cia_max_keysize	=	XTEA_KEY_SIZE,
+	.cia_setkey		= 	xtea_setkey,
+	.cia_encrypt		=	xeta_encrypt,
+	.cia_decrypt		=	xeta_decrypt } }
+};
+
 static int __init init(void)
 {
 	int ret = 0;
@@ -229,6 +294,13 @@
 		goto out;
 	}
 
+	ret = crypto_register_alg(&xeta_alg);
+	if (ret < 0) {
+		crypto_unregister_alg(&tea_alg);
+		crypto_unregister_alg(&xtea_alg);
+		goto out;
+	}
+
 out:	
 	return ret;
 }
@@ -237,10 +309,11 @@
 {
 	crypto_unregister_alg(&tea_alg);
 	crypto_unregister_alg(&xtea_alg);
+	crypto_unregister_alg(&xeta_alg);
 }
 
 module_init(init);
 module_exit(fini);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");
+MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");
diff -urN linux-2.4.32-pre2/drivers/char/cyclades.c linux-2.4.32-pre3/drivers/char/cyclades.c
--- linux-2.4.32-pre2/drivers/char/cyclades.c	2005-01-19 06:09:44.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/cyclades.c	2005-08-08 20:06:12.371628097 -0700
@@ -2960,10 +2960,15 @@
 cy_write(struct tty_struct * tty, int from_user,
            const unsigned char *buf, int count)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+  struct cyclades_port *info;
   unsigned long flags;
   int c, ret = 0;
 
+    if (!tty)
+	return 0;
+
+    info = (struct cyclades_port *)tty->driver_data;
+  
 #ifdef CY_DEBUG_IO
     printk("cyc:cy_write ttyC%d\n", info->line); /* */
 #endif
@@ -2972,7 +2977,7 @@
         return 0;
     }
         
-    if (!tty || !info->xmit_buf || !tmp_buf){
+    if (!info->xmit_buf || !tmp_buf){
         return 0;
     }
 
@@ -3047,9 +3052,14 @@
 static void
 cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
-  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+  struct cyclades_port *info;
   unsigned long flags;
 
+    if (!tty)
+        return;
+
+    info = (struct cyclades_port *)tty->driver_data;
+  
 #ifdef CY_DEBUG_IO
     printk("cyc:cy_put_char ttyC%d\n", info->line);
 #endif
@@ -3057,7 +3067,7 @@
     if (serial_paranoia_check(info, tty->device, "cy_put_char"))
         return;
 
-    if (!tty || !info->xmit_buf)
+    if (!info->xmit_buf)
         return;
 
     CY_LOCK(info, flags);
diff -urN linux-2.4.32-pre2/drivers/char/esp.c linux-2.4.32-pre3/drivers/char/esp.c
--- linux-2.4.32-pre2/drivers/char/esp.c	2005-01-19 06:09:45.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/esp.c	2005-08-08 20:06:12.375628273 -0700
@@ -1251,13 +1251,18 @@
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	struct esp_struct *info;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+
+	info = (struct esp_struct *)tty->driver_data;
+	
 	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
 		return;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		return;
 
 	save_flags(flags); cli();
@@ -1296,13 +1301,19 @@
 		    const unsigned char *buf, int count)
 {
 	int	c, t, ret = 0;
-	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	struct esp_struct *info;
 	unsigned long flags;
 
+
+	if (!tty)
+		return 0;
+	
+	info = (struct esp_struct *)tty->driver_data;
+
 	if (serial_paranoia_check(info, tty->device, "rs_write"))
 		return 0;
 
-	if (!tty || !info->xmit_buf || !tmp_buf)
+	if (!info->xmit_buf || !tmp_buf)
 		return 0;
 	    
 	if (from_user)
diff -urN linux-2.4.32-pre2/drivers/char/isicom.c linux-2.4.32-pre3/drivers/char/isicom.c
--- linux-2.4.32-pre2/drivers/char/isicom.c	2005-01-19 06:09:46.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/isicom.c	2005-08-08 20:06:12.376628317 -0700
@@ -1223,9 +1223,15 @@
 static int isicom_write(struct tty_struct * tty, int from_user,
 			const unsigned char * buf, int count)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port * port;
 	unsigned long flags;
 	int cnt, total = 0;
+
+	if (!tty)
+		return 0;
+	
+	port = (struct isi_port *) tty->driver_data;
+	
 #ifdef ISICOM_DEBUG
 	printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
 			port->channel+1, count);
@@ -1233,7 +1239,7 @@
 	if (isicom_paranoia_check(port, tty->device, "isicom_write"))
 		return 0;
 	
-	if (!tty || !port->xmit_buf || !tmp_buf)
+	if (!port->xmit_buf || !tmp_buf)
 		return 0;
 	if (from_user)
 		down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
@@ -1281,13 +1287,18 @@
 /* put_char et all */
 static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
 {
-	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_port * port;
 	unsigned long flags;
+
+	if (!tty)
+		return;
+
+	port = (struct isi_port *) tty->driver_data;
 	
 	if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
 		return;
 	
-	if (!tty || !port->xmit_buf)
+	if (!port->xmit_buf)
 		return;
 #ifdef ISICOM_DEBUG
 	printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
diff -urN linux-2.4.32-pre2/drivers/char/mxser.c linux-2.4.32-pre3/drivers/char/mxser.c
--- linux-2.4.32-pre2/drivers/char/mxser.c	2005-01-19 06:09:47.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/mxser.c	2005-08-08 20:06:12.378628405 -0700
@@ -911,10 +911,15 @@
 		       const unsigned char *buf, int count)
 {
 	int c, total = 0;
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info;
 	unsigned long flags;
 
-	if (!tty || !info->xmit_buf || !mxvar_tmp_buf)
+	if (!tty)
+		return (0);
+	
+	info = (struct mxser_struct *) tty->driver_data;
+	
+	if (!info->xmit_buf || !mxvar_tmp_buf)
 		return (0);
 
 	save_flags(flags);
@@ -979,10 +984,15 @@
 
 static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info;
 	unsigned long flags;
 
-	if (!tty || !info->xmit_buf)
+	if (!tty)
+		return;
+
+	info = (struct mxser_struct *) tty->driver_data;
+	
+	if (!info->xmit_buf)
 		return;
 
 	save_flags(flags);
diff -urN linux-2.4.32-pre2/drivers/char/riscom8.c linux-2.4.32-pre3/drivers/char/riscom8.c
--- linux-2.4.32-pre2/drivers/char/riscom8.c	2005-01-19 06:09:49.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/riscom8.c	2005-08-08 20:06:12.379628449 -0700
@@ -1220,17 +1220,22 @@
 static int rc_write(struct tty_struct * tty, int from_user, 
 		    const unsigned char *buf, int count)
 {
-	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+	struct riscom_port *port;
 	struct riscom_board *bp;
 	int c, total = 0;
 	unsigned long flags;
+
+	if (!tty)
+		return 0;
+
+	port = (struct riscom_port *)tty->driver_data;
 				
 	if (rc_paranoia_check(port, tty->device, "rc_write"))
 		return 0;
 	
 	bp = port_Board(port);
 
-	if (!tty || !port->xmit_buf || !tmp_buf)
+	if (!port->xmit_buf || !tmp_buf)
 		return 0;
 
 	save_flags(flags);
@@ -1298,13 +1303,18 @@
 
 static void rc_put_char(struct tty_struct * tty, unsigned char ch)
 {
-	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+	struct riscom_port *port;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+
+	port = (struct riscom_port *)tty->driver_data;
+
 	if (rc_paranoia_check(port, tty->device, "rc_put_char"))
 		return;
 
-	if (!tty || !port->xmit_buf)
+	if (!port->xmit_buf)
 		return;
 
 	save_flags(flags); cli();
diff -urN linux-2.4.32-pre2/drivers/char/serial.c linux-2.4.32-pre3/drivers/char/serial.c
--- linux-2.4.32-pre2/drivers/char/serial.c	2005-01-19 06:09:50.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/serial.c	2005-08-08 20:06:12.382628581 -0700
@@ -1827,13 +1827,18 @@
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	struct async_struct *info;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+	
+	info =  (struct async_struct *)tty->driver_data;
+	
 	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
 		return;
 
-	if (!tty || !info->xmit.buf)
+	if (!info->xmit.buf)
 		return;
 
 	save_flags(flags); cli();
@@ -1873,13 +1878,18 @@
 		    const unsigned char *buf, int count)
 {
 	int	c, ret = 0;
-	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	struct async_struct *info;
 	unsigned long flags;
 				
+	if (!tty)
+		return 0;
+
+	info = (struct async_struct *)tty->driver_data;
+	
 	if (serial_paranoia_check(info, tty->device, "rs_write"))
 		return 0;
 
-	if (!tty || !info->xmit.buf || !tmp_buf)
+	if (!info->xmit.buf || !tmp_buf)
 		return 0;
 
 	save_flags(flags);
diff -urN linux-2.4.32-pre2/drivers/char/specialix.c linux-2.4.32-pre3/drivers/char/specialix.c
--- linux-2.4.32-pre2/drivers/char/specialix.c	2005-01-19 06:09:51.000000000 -0800
+++ linux-2.4.32-pre3/drivers/char/specialix.c	2005-08-08 20:06:12.383628625 -0700
@@ -1600,17 +1600,22 @@
 static int sx_write(struct tty_struct * tty, int from_user, 
                     const unsigned char *buf, int count)
 {
-	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+	struct specialix_port *port;
 	struct specialix_board *bp;
 	int c, total = 0;
 	unsigned long flags;
+
+	if (!tty)
+		return 0;
+
+	port = (struct specialix_port *)tty->driver_data;
 				
 	if (sx_paranoia_check(port, tty->device, "sx_write"))
 		return 0;
 	
 	bp = port_Board(port);
 
-	if (!tty || !port->xmit_buf || !tmp_buf)
+	if (!port->xmit_buf || !tmp_buf)
 		return 0;
 
 	save_flags(flags);
@@ -1676,13 +1681,18 @@
 
 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
 {
-	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+	struct specialix_port *port;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+
+	port = (struct specialix_port *)tty->driver_data;
+
 	if (sx_paranoia_check(port, tty->device, "sx_put_char"))
 		return;
 
-	if (!tty || !port->xmit_buf)
+	if (!port->xmit_buf)
 		return;
 
 	save_flags(flags); cli();
diff -urN linux-2.4.32-pre2/drivers/md/md.c linux-2.4.32-pre3/drivers/md/md.c
--- linux-2.4.32-pre2/drivers/md/md.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.32-pre3/drivers/md/md.c	2005-08-08 20:06:12.386628757 -0700
@@ -1271,148 +1271,164 @@
 	memcpy (sb, freshest->sb, sizeof(*sb));
 
 	/*
-	 * at this point we have picked the 'best' superblock
-	 * from all available superblocks.
-	 * now we validate this superblock and kick out possibly
-	 * failed disks.
+	 * For multipathing, lots of things are different from "true"
+	 * RAIDs.
+	 * All rdev's could be read, so they are no longer faulty.
+	 * As there is just one sb, trying to find changed devices via the
+	 * this_disk pointer is useless too.
+	 *
+	 * lmb@suse.de, 2002-09-12
 	 */
-	ITERATE_RDEV(mddev,rdev,tmp) {
-		/*
-		 * Kick all non-fresh devices
-		 */
-		__u64 ev1, ev2;
-		ev1 = md_event(rdev->sb);
-		ev2 = md_event(sb);
-		++ev1;
-		if (ev1 < ev2) {
-			printk(KERN_WARNING "md: kicking non-fresh %s from array!\n",
-						partition_name(rdev->dev));
-			kick_rdev_from_array(rdev);
-			continue;
-		}
-	}
 
-	/*
-	 * Fix up changed device names ... but only if this disk has a
-	 * recent update time. Use faulty checksum ones too.
-	 */
-	if (mddev->sb->level != -4)
-	ITERATE_RDEV(mddev,rdev,tmp) {
-		__u64 ev1, ev2, ev3;
-		if (rdev->faulty || rdev->alias_device) {
-			MD_BUG();
-			goto abort;
-		}
-		ev1 = md_event(rdev->sb);
-		ev2 = md_event(sb);
-		ev3 = ev2;
-		--ev3;
-		if ((rdev->dev != rdev->old_dev) &&
-			((ev1 == ev2) || (ev1 == ev3))) {
+	if (sb->level == -4) {
+		int desc_nr = 0;
+
+		/* ... and initialize from the current rdevs instead */
+		ITERATE_RDEV(mddev,rdev,tmp) {
 			mdp_disk_t *desc;
 
-			printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n",
-			       partition_name(rdev->old_dev), partition_name(rdev->dev));
-			if (rdev->desc_nr == -1) {
-				MD_BUG();
-				goto abort;
-			}
+			rdev->desc_nr=desc_nr;
+
 			desc = &sb->disks[rdev->desc_nr];
-			if (rdev->old_dev != MKDEV(desc->major, desc->minor)) {
-				MD_BUG();
-				goto abort;
-			}
-			desc->major = MAJOR(rdev->dev);
-			desc->minor = MINOR(rdev->dev);
-			desc = &rdev->sb->this_disk;
+
+			desc->number = desc_nr;
 			desc->major = MAJOR(rdev->dev);
 			desc->minor = MINOR(rdev->dev);
-		}
-	}
+			desc->raid_disk = desc_nr;
 
-	/*
-	 * Remove unavailable and faulty devices ...
-	 *
-	 * note that if an array becomes completely unrunnable due to
-	 * missing devices, we do not write the superblock back, so the
-	 * administrator has a chance to fix things up. The removal thus
-	 * only happens if it's nonfatal to the contents of the array.
-	 */
-	for (i = 0; i < MD_SB_DISKS; i++) {
-		int found;
-		mdp_disk_t *desc;
-		kdev_t dev;
+			/* We could read from it, so it isn't faulty
+			 * any longer */
+			if (disk_faulty(desc))
+				mark_disk_spare(desc);
 
-		desc = sb->disks + i;
-		dev = MKDEV(desc->major, desc->minor);
+			memcpy(&rdev->sb->this_disk,desc,sizeof(*desc));
+
+			desc_nr++;
+		}
 
+		/* Kick out all old info about disks we used to have,
+		 * if any */
+		for (i = desc_nr; i < MD_SB_DISKS; i++)
+			memset(&(sb->disks[i]),0,sizeof(mdp_disk_t));
+	} else {
 		/*
-		 * We kick faulty devices/descriptors immediately.
-		 *
-		 * Note: multipath devices are a special case.  Since we
-		 * were able to read the superblock on the path, we don't
-		 * care if it was previously marked as faulty, it's up now
-		 * so enable it.
+		 * at this point we have picked the 'best' superblock
+		 * from all available superblocks.
+		 * now we validate this superblock and kick out possibly
+		 * failed disks.
 		 */
-		if (disk_faulty(desc) && mddev->sb->level != -4) {
-			found = 0;
-			ITERATE_RDEV(mddev,rdev,tmp) {
-				if (rdev->desc_nr != desc->number)
-					continue;
-				printk(KERN_WARNING "md%d: kicking faulty %s!\n",
-					mdidx(mddev),partition_name(rdev->dev));
-				kick_rdev_from_array(rdev);
-				found = 1;
-				break;
-			}
-			if (!found) {
-				if (dev == MKDEV(0,0))
-					continue;
-				printk(KERN_WARNING "md%d: removing former faulty %s!\n",
-					mdidx(mddev), partition_name(dev));
-			}
-			remove_descriptor(desc, sb);
-			continue;
-		} else if (disk_faulty(desc)) {
+		ITERATE_RDEV(mddev,rdev,tmp) {
 			/*
-			 * multipath entry marked as faulty, unfaulty it
+			 * Kick all non-fresh devices
 			 */
-			rdev = find_rdev(mddev, dev);
-			if(rdev)
-				mark_disk_spare(desc);
-			else
-				remove_descriptor(desc, sb);
+			__u64 ev1, ev2;
+			ev1 = md_event(rdev->sb);
+			ev2 = md_event(sb);
+			++ev1;
+			if (ev1 < ev2) {
+				printk(KERN_WARNING "md: kicking non-fresh %s from array!\n",
+							partition_name(rdev->dev));
+				kick_rdev_from_array(rdev);
+				continue;
+			}
 		}
 
-		if (dev == MKDEV(0,0))
-			continue;
 		/*
-		 * Is this device present in the rdev ring?
+		 * Fix up changed device names ... but only if this disk has a
+		 * recent update time. Use faulty checksum ones too.
 		 */
-		found = 0;
 		ITERATE_RDEV(mddev,rdev,tmp) {
+			__u64 ev1, ev2, ev3;
+			if (rdev->faulty || rdev->alias_device) {
+				MD_BUG();
+				goto abort;
+			}
+			ev1 = md_event(rdev->sb);
+			ev2 = md_event(sb);
+			ev3 = ev2;
+			--ev3;
+			if ((rdev->dev != rdev->old_dev) &&
+				((ev1 == ev2) || (ev1 == ev3))) {
+				mdp_disk_t *desc;
+
+				printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n",
+				       partition_name(rdev->old_dev), partition_name(rdev->dev));
+				if (rdev->desc_nr == -1) {
+					MD_BUG();
+					goto abort;
+				}
+				desc = &sb->disks[rdev->desc_nr];
+				if (rdev->old_dev != MKDEV(desc->major, desc->minor)) {
+					MD_BUG();
+					goto abort;
+				}
+				desc->major = MAJOR(rdev->dev);
+				desc->minor = MINOR(rdev->dev);
+				desc = &rdev->sb->this_disk;
+				desc->major = MAJOR(rdev->dev);
+				desc->minor = MINOR(rdev->dev);
+			}
+		}
+
+		/*
+		 * Remove unavailable and faulty devices ...
+		 *
+		 * note that if an array becomes completely unrunnable due to
+		 * missing devices, we do not write the superblock back, so the
+		 * administrator has a chance to fix things up. The removal thus
+		 * only happens if it's nonfatal to the contents of the array.
+		 */
+		for (i = 0; i < MD_SB_DISKS; i++) {
+			int found;
+			mdp_disk_t *desc;
+			kdev_t dev;
+
+			desc = sb->disks + i;
+			dev = MKDEV(desc->major, desc->minor);
+
 			/*
-			 * Multi-path IO special-case: since we have no
-			 * this_disk descriptor at auto-detect time,
-			 * we cannot check rdev->number.
-			 * We can check the device though.
+			 * We kick faulty devices/descriptors immediately.
 			 */
-			if ((sb->level == -4) && (rdev->dev ==
-					MKDEV(desc->major,desc->minor))) {
-				found = 1;
-				break;
+			if (disk_faulty(desc)) {
+				found = 0;
+				ITERATE_RDEV(mddev,rdev,tmp) {
+					if (rdev->desc_nr != desc->number)
+						continue;
+					printk(KERN_WARNING "md%d: kicking faulty %s!\n",
+						mdidx(mddev),partition_name(rdev->dev));
+					kick_rdev_from_array(rdev);
+					found = 1;
+					break;
+				}
+				if (!found) {
+					if (dev == MKDEV(0,0))
+						continue;
+					printk(KERN_WARNING "md%d: removing former faulty %s!\n",
+						mdidx(mddev), partition_name(dev));
+				}
+				remove_descriptor(desc, sb);
+				continue;
 			}
-			if (rdev->desc_nr == desc->number) {
-				found = 1;
-				break;
+
+			if (dev == MKDEV(0,0))
+				continue;
+			/*
+			 * Is this device present in the rdev ring?
+			 */
+			found = 0;
+			ITERATE_RDEV(mddev,rdev,tmp) {
+				if (rdev->desc_nr == desc->number) {
+					found = 1;
+					break;
+				}
 			}
-		}
-		if (found)
-			continue;
+			if (found)
+				continue;
 
-		printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n",
-		       mdidx(mddev), partition_name(dev));
-		remove_descriptor(desc, sb);
+			printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n",
+			       mdidx(mddev), partition_name(dev));
+			remove_descriptor(desc, sb);
+		}
 	}
 
 	/*
diff -urN linux-2.4.32-pre2/drivers/scsi/ahci.c linux-2.4.32-pre3/drivers/scsi/ahci.c
--- linux-2.4.32-pre2/drivers/scsi/ahci.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/ahci.c	2005-08-08 20:06:12.387628801 -0700
@@ -38,7 +38,8 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"1.00"
+#define DRV_VERSION	"1.01"
+
 
 enum {
 	AHCI_PCI_BAR		= 5,
@@ -48,6 +49,7 @@
 	AHCI_CMD_SLOT_SZ	= 32 * 32,
 	AHCI_RX_FIS_SZ		= 256,
 	AHCI_CMD_TBL_HDR	= 0x80,
+	AHCI_CMD_TBL_CDB	= 0x40,
 	AHCI_CMD_TBL_SZ		= AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16),
 	AHCI_PORT_PRIV_DMA_SZ	= AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ +
 				  AHCI_RX_FIS_SZ,
@@ -132,6 +134,9 @@
 	PORT_CMD_ICC_ACTIVE	= (0x1 << 28), /* Put i/f in active state */
 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
+
+	/* hpriv->flags bits */
+	AHCI_FLAG_MSI		= (1 << 0),
 };
 
 struct ahci_cmd_hdr {
@@ -181,13 +186,14 @@
 static u8 ahci_check_status(struct ata_port *ap);
 static u8 ahci_check_err(struct ata_port *ap);
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_remove_one (struct pci_dev *pdev);
 
 static Scsi_Host_Template ahci_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
-	.ioctl			= ata_scsi_ioctl,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -256,6 +262,12 @@
 	  board_ahci }, /* ICH7R */
 	{ PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ULi M5288 */
+	{ PCI_VENDOR_ID_INTEL, 0x2681, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ESB2 */
+	{ PCI_VENDOR_ID_INTEL, 0x2682, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ESB2 */
+	{ PCI_VENDOR_ID_INTEL, 0x2683, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ESB2 */
 	{ }	/* terminate list */
 };
 
@@ -264,7 +276,7 @@
 	.name			= DRV_NAME,
 	.id_table		= ahci_pci_tbl,
 	.probe			= ahci_init_one,
-	.remove			= ata_pci_remove_one,
+	.remove			= ahci_remove_one,
 };
 
 
@@ -282,6 +294,8 @@
 {
 	struct ahci_host_priv *hpriv = host_set->private_data;
 	kfree(hpriv);
+
+	ata_host_stop(host_set);
 }
 
 static int ahci_port_start(struct ata_port *ap)
@@ -289,26 +303,19 @@
 	struct device *dev = ap->host_set->dev;
 	struct ahci_host_priv *hpriv = ap->host_set->private_data;
 	struct ahci_port_priv *pp;
-	int rc;
 	void *mem, *mmio = ap->host_set->mmio_base;
 	void *port_mmio = ahci_port_base(mmio, ap->port_no);
 	dma_addr_t mem_dma;
 
-	rc = ata_port_start(ap);
-	if (rc)
-		return rc;
-
 	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
-	if (!pp) {
-		rc = -ENOMEM;
-		goto err_out;
-	}
+	if (!pp)
+		return -ENOMEM;
 	memset(pp, 0, sizeof(*pp));
 
 	mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
 	if (!mem) {
-		rc = -ENOMEM;
-		goto err_out_kfree;
+		kfree(pp);
+		return -ENOMEM;
 	}
 	memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
 
@@ -358,12 +365,6 @@
 	readl(port_mmio + PORT_CMD); /* flush */
 
 	return 0;
-
-err_out_kfree:
-	kfree(pp);
-err_out:
-	ata_port_stop(ap);
-	return rc;
 }
 
 
@@ -389,7 +390,6 @@
 	dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
 			  pp->cmd_slot, pp->cmd_slot_dma);
 	kfree(pp);
-	ata_port_stop(ap);
 }
 
 static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
@@ -496,7 +496,8 @@
 
 static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
-	struct ahci_port_priv *pp = qc->ap->private_data;
+	struct ata_port *ap = qc->ap;
+	struct ahci_port_priv *pp = ap->private_data;
 	u32 opts;
 	const u32 cmd_fis_len = 5; /* five dwords */
 
@@ -508,18 +509,8 @@
 	opts = (qc->n_elem << 16) | cmd_fis_len;
 	if (qc->tf.flags & ATA_TFLAG_WRITE)
 		opts |= AHCI_CMD_WRITE;
-
-	switch (qc->tf.protocol) {
-	case ATA_PROT_ATAPI:
-	case ATA_PROT_ATAPI_NODATA:
-	case ATA_PROT_ATAPI_DMA:
+	if (is_atapi_taskfile(&qc->tf))
 		opts |= AHCI_CMD_ATAPI;
-		break;
-
-	default:
-		/* do nothing */
-		break;
-	}
 
 	pp->cmd_slot[0].opts = cpu_to_le32(opts);
 	pp->cmd_slot[0].status = 0;
@@ -531,6 +522,10 @@
 	 * a SATA Register - Host to Device command FIS.
 	 */
 	ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+	if (opts & AHCI_CMD_ATAPI) {
+		memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+		memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
+	}
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
 		return;
@@ -853,15 +848,19 @@
 }
 
 /* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
+static void pci_intx(struct pci_dev *pdev, int enable)
 {
-	u16 pci_command;
+	u16 pci_command, new;
 
 	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-	if (pci_command & PCI_COMMAND_INTX_DISABLE) {
-		pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+
+	if (enable)
+		new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+	else
+		new = pci_command | PCI_COMMAND_INTX_DISABLE;
+
+	if (new != pci_command)
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
-	}
 }
 
 static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -943,7 +942,7 @@
 	unsigned long base;
 	void *mmio_base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int pci_dev_busy = 0;
+	int have_msi, pci_dev_busy = 0;
 	int rc;
 
 	VPRINTK("ENTER\n");
@@ -961,12 +960,17 @@
 		goto err_out;
 	}
 
-	pci_enable_intx(pdev);
+	if (pci_enable_msi(pdev) == 0)
+		have_msi = 1;
+	else {
+		pci_intx(pdev, 1);
+		have_msi = 0;
+	}
 
 	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (probe_ent == NULL) {
 		rc = -ENOMEM;
-		goto err_out_regions;
+		goto err_out_msi;
 	}
 
 	memset(probe_ent, 0, sizeof(*probe_ent));
@@ -999,6 +1003,9 @@
 	probe_ent->mmio_base = mmio_base;
 	probe_ent->private_data = hpriv;
 
+	if (have_msi)
+		hpriv->flags |= AHCI_FLAG_MSI;
+
 	/* initialize adapter */
 	rc = ahci_host_init(probe_ent);
 	if (rc)
@@ -1016,7 +1023,11 @@
 	iounmap(mmio_base);
 err_out_free_ent:
 	kfree(probe_ent);
-err_out_regions:
+err_out_msi:
+	if (have_msi)
+		pci_disable_msi(pdev);
+	else
+		pci_intx(pdev, 0);
 	pci_release_regions(pdev);
 err_out:
 	if (!pci_dev_busy)
@@ -1024,6 +1035,38 @@
 	return rc;
 }
 
+static void ahci_remove_one (struct pci_dev *pdev)
+{
+	struct device *dev = pci_dev_to_dev(pdev);
+	struct ata_host_set *host_set = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host_set->private_data;
+	struct ata_port *ap;
+	Scsi_Host_Template *sht;
+	int have_msi, rc;
+
+	/* FIXME: this unregisters all ports attached to the
+	 * Scsi_Host_Template given.  We _might_ have multiple
+	 * templates (though we don't ATM), so this is ok... for now.
+	 */
+	ap = host_set->ports[0];
+	sht = ap->host->hostt;
+	rc = scsi_unregister_module(MODULE_SCSI_HA, sht);
+	/* FIXME: handle 'rc' failure? */
+
+	have_msi = hpriv->flags & AHCI_FLAG_MSI;
+	free_irq(host_set->irq, host_set);
+
+	host_set->ops->host_stop(host_set);
+	kfree(host_set);
+
+	if (have_msi)
+		pci_disable_msi(pdev);
+	else
+		pci_intx(pdev, 0);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	dev_set_drvdata(dev, NULL);
+}
 
 static int __init ahci_init(void)
 {
diff -urN linux-2.4.32-pre2/drivers/scsi/ata_piix.c linux-2.4.32-pre3/drivers/scsi/ata_piix.c
--- linux-2.4.32-pre2/drivers/scsi/ata_piix.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/ata_piix.c	2005-08-08 20:06:12.387628801 -0700
@@ -61,6 +61,7 @@
 	ich6_sata		= 3,
 	ich6_sata_rm		= 4,
 	ich7_sata		= 5,
+	esb2_sata		= 6,
 };
 
 static int piix_init_one (struct pci_dev *pdev,
@@ -93,6 +94,7 @@
 	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
 	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
+	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata },
 
 	{ }	/* terminate list */
 };
@@ -151,6 +153,7 @@
 
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_operations piix_sata_ops = {
@@ -178,6 +181,7 @@
 
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info piix_port_info[] = {
@@ -256,6 +260,18 @@
 		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &piix_sata_ops,
 	},
+
+	/* esb2_sata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -650,15 +666,6 @@
 	return ata_pci_init_one(pdev, port_info, n_ports);
 }
 
-/**
- *	piix_init -
- *
- *	LOCKING:
- *
- *	RETURNS:
- *
- */
-
 static int __init piix_init(void)
 {
 	int rc;
@@ -685,13 +692,6 @@
 	return rc;
 }
 
-/**
- *	piix_exit -
- *
- *	LOCKING:
- *
- */
-
 static void __exit piix_exit(void)
 {
 	scsi_unregister_module(MODULE_SCSI_HA, &piix_sht);
diff -urN linux-2.4.32-pre2/drivers/scsi/libata-core.c linux-2.4.32-pre3/drivers/scsi/libata-core.c
--- linux-2.4.32-pre2/drivers/scsi/libata-core.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/libata-core.c	2005-08-08 20:06:12.391628977 -0700
@@ -185,6 +185,28 @@
 	ata_wait_idle(ap);
 }
 
+
+/**
+ *	ata_tf_load - send taskfile registers to host controller
+ *	@ap: Port to which output is sent
+ *	@tf: ATA taskfile register set
+ *
+ *	Outputs ATA taskfile to standard ATA host controller using MMIO
+ *	or PIO as indicated by the ATA_FLAG_MMIO flag.
+ *	Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ *	Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ *	hob_lbal, hob_lbam, and hob_lbah.
+ *
+ *	This function waits for idle (!BUSY and !DRQ) after writing
+ *	registers.  If the control register has a new value, this
+ *	function also waits for idle after writing control and before
+ *	writing the remaining registers.
+ *
+ *	May be used as the tf_load() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -194,11 +216,11 @@
 }
 
 /**
- *	ata_exec_command - issue ATA command to host controller
+ *	ata_exec_command_pio - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO/MMIO write to ATA command register, with proper
+ *	Issues PIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
@@ -234,6 +256,18 @@
 	ata_pause(ap);
 }
 
+
+/**
+ *	ata_exec_command - issue ATA command to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues PIO/MMIO write to ATA command register, with proper
+ *	synchronization with interrupt handler / other threads.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
 void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -304,7 +338,7 @@
 }
 
 /**
- *	ata_tf_read - input device's ATA taskfile shadow registers
+ *	ata_tf_read_pio - input device's ATA taskfile shadow registers
  *	@ap: Port from which input is read
  *	@tf: ATA taskfile register set for storing input
  *
@@ -367,6 +401,23 @@
 	}
 }
 
+
+/**
+ *	ata_tf_read - input device's ATA taskfile shadow registers
+ *	@ap: Port from which input is read
+ *	@tf: ATA taskfile register set for storing input
+ *
+ *	Reads ATA taskfile registers for currently-selected device
+ *	into @tf.
+ *
+ *	Reads nsect, lbal, lbam, lbah, and device.  If ATA_TFLAG_LBA48
+ *	is set, also reads the hob registers.
+ *
+ *	May be used as the tf_read() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -380,7 +431,7 @@
  *	@ap: port where the device is
  *
  *	Reads ATA taskfile status register for currently-selected device
- *	and return it's value. This also clears pending interrupts
+ *	and return its value. This also clears pending interrupts
  *      from this device
  *
  *	LOCKING:
@@ -396,7 +447,7 @@
  *	@ap: port where the device is
  *
  *	Reads ATA taskfile status register for currently-selected device
- *	via MMIO and return it's value. This also clears pending interrupts
+ *	via MMIO and return its value. This also clears pending interrupts
  *      from this device
  *
  *	LOCKING:
@@ -407,6 +458,20 @@
        	return readb((void __iomem *) ap->ioaddr.status_addr);
 }
 
+
+/**
+ *	ata_check_status - Read device status reg & clear interrupt
+ *	@ap: port where the device is
+ *
+ *	Reads ATA taskfile status register for currently-selected device
+ *	and return its value. This also clears pending interrupts
+ *      from this device
+ *
+ *	May be used as the check_status() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 u8 ata_check_status(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -414,6 +479,20 @@
 	return ata_check_status_pio(ap);
 }
 
+
+/**
+ *	ata_altstatus - Read device alternate status reg
+ *	@ap: port where the device is
+ *
+ *	Reads ATA taskfile alternate status register for
+ *	currently-selected device and return its value.
+ *
+ *	Note: may NOT be used as the check_altstatus() entry in
+ *	ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 u8 ata_altstatus(struct ata_port *ap)
 {
 	if (ap->ops->check_altstatus)
@@ -424,6 +503,20 @@
 	return inb(ap->ioaddr.altstatus_addr);
 }
 
+
+/**
+ *	ata_chk_err - Read device error reg
+ *	@ap: port where the device is
+ *
+ *	Reads ATA taskfile error register for
+ *	currently-selected device and return its value.
+ *
+ *	Note: may NOT be used as the check_err() entry in
+ *	ata_port_operations.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 u8 ata_chk_err(struct ata_port *ap)
 {
 	if (ap->ops->check_err)
@@ -872,10 +965,24 @@
 	}
 }
 
+
+/**
+ *	ata_noop_dev_select - Select device 0/1 on ATA bus
+ *	@ap: ATA channel to manipulate
+ *	@device: ATA device (numbered from zero) to select
+ *
+ *	This function performs no actual function.
+ *
+ *	May be used as the dev_select() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	caller.
+ */
 void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
 {
 }
 
+
 /**
  *	ata_std_dev_select - Select device 0/1 on ATA bus
  *	@ap: ATA channel to manipulate
@@ -883,7 +990,9 @@
  *
  *	Use the method defined in the ATA specification to
  *	make either device 0, or device 1, active on the
- *	ATA channel.
+ *	ATA channel.  Works with both PIO and MMIO.
+ *
+ *	May be used as the dev_select() entry in ata_port_operations.
  *
  *	LOCKING:
  *	caller.
@@ -1185,11 +1294,47 @@
 	DPRINTK("EXIT, err\n");
 }
 
+
+static inline u8 ata_dev_knobble(struct ata_port *ap)
+{
+	return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
+}
+
+/**
+ * 	ata_dev_config - Run device specific handlers and check for
+ * 			 SATA->PATA bridges
+ * 	@ap: Bus 
+ * 	@i:  Device
+ *
+ * 	LOCKING:
+ */
+ 
+void ata_dev_config(struct ata_port *ap, unsigned int i)
+{
+	/* limit bridge transfers to udma5, 200 sectors */
+	if (ata_dev_knobble(ap)) {
+		printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
+			ap->id, ap->device->devno);
+		ap->udma_mask &= ATA_UDMA5;
+		ap->host->max_sectors = ATA_MAX_SECTORS;
+		ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
+		ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+	}
+
+	if (ap->ops->dev_config)
+		ap->ops->dev_config(ap, &ap->device[i]);
+}
+
 /**
  *	ata_bus_probe - Reset and probe ATA bus
  *	@ap: Bus to probe
  *
+ *	Master ATA bus probing function.  Initiates a hardware-dependent
+ *	bus reset, then attempts to identify any devices found on
+ *	the bus.
+ *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  *	RETURNS:
  *	Zero on success, non-zero on error.
@@ -1207,8 +1352,7 @@
 		ata_dev_identify(ap, i);
 		if (ata_dev_present(&ap->device[i])) {
 			found = 1;
-			if (ap->ops->dev_config)
-				ap->ops->dev_config(ap, &ap->device[i]);
+			ata_dev_config(ap,i);
 		}
 	}
 
@@ -1228,10 +1372,14 @@
 }
 
 /**
- *	ata_port_probe -
- *	@ap:
+ *	ata_port_probe - Mark port as enabled
+ *	@ap: Port for which we indicate enablement
  *
- *	LOCKING:
+ *	Modify @ap data structure such that the system
+ *	thinks that the entire port is enabled.
+ *
+ *	LOCKING: host_set lock, or some other form of
+ *	serialization.
  */
 
 void ata_port_probe(struct ata_port *ap)
@@ -1240,10 +1388,15 @@
 }
 
 /**
- *	__sata_phy_reset -
- *	@ap:
+ *	__sata_phy_reset - Wake/reset a low-level SATA PHY
+ *	@ap: SATA port associated with target SATA PHY.
+ *
+ *	This function issues commands to standard SATA Sxxx
+ *	PHY registers, to wake up the phy (and device), and
+ *	clear any reset condition.
  *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  */
 void __sata_phy_reset(struct ata_port *ap)
@@ -1252,11 +1405,13 @@
 	unsigned long timeout = jiffies + (HZ * 5);
 
 	if (ap->flags & ATA_FLAG_SATA_RESET) {
-		scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */
-		scr_read(ap, SCR_STATUS);	/* dummy read; flush */
-		udelay(400);			/* FIXME: a guess */
+		/* issue phy wake/reset */
+		scr_write_flush(ap, SCR_CONTROL, 0x301);
+		/* Couldn't find anything in SATA I/II specs, but
+		 * AHCI-1.1 10.4.2 says at least 1 ms. */
+		mdelay(1);
 	}
-	scr_write(ap, SCR_CONTROL, 0x300);	/* issue phy wake/clear reset */
+	scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
 
 	/* wait for phy to become ready, if necessary */
 	do {
@@ -1288,10 +1443,14 @@
 }
 
 /**
- *	__sata_phy_reset -
- *	@ap:
+ *	sata_phy_reset - Reset SATA bus.
+ *	@ap: SATA port associated with target SATA PHY.
+ *
+ *	This function resets the SATA bus, and then probes
+ *	the bus for devices.
  *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  */
 void sata_phy_reset(struct ata_port *ap)
@@ -1303,10 +1462,16 @@
 }
 
 /**
- *	ata_port_disable -
- *	@ap:
+ *	ata_port_disable - Disable port.
+ *	@ap: Port to be disabled.
  *
- *	LOCKING:
+ *	Modify @ap data structure such that the system
+ *	thinks that the entire port is disabled, and should
+ *	never attempt to probe or communicate with devices
+ *	on this port.
+ *
+ *	LOCKING: host_set lock, or some other form of
+ *	serialization.
  */
 
 void ata_port_disable(struct ata_port *ap)
@@ -1415,7 +1580,10 @@
  *	ata_set_mode - Program timings and issue SET FEATURES - XFER
  *	@ap: port on which timings will be programmed
  *
+ *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
+ *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  */
 static void ata_set_mode(struct ata_port *ap)
@@ -1466,7 +1634,10 @@
  *	@tmout_pat: impatience timeout
  *	@tmout: overall timeout
  *
- *	LOCKING:
+ *	Sleep until ATA Status register bit BSY clears,
+ *	or a timeout occurs.
+ *
+ *	LOCKING: None.
  *
  */
 
@@ -1552,10 +1723,14 @@
 }
 
 /**
- *	ata_bus_edd -
- *	@ap:
+ *	ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
+ *	@ap: Port to reset and probe
+ *
+ *	Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
+ *	probe the bus.  Not often used these days.
  *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  */
 
@@ -1632,8 +1807,8 @@
  *	the device is ATA or ATAPI.
  *
  *	LOCKING:
- *	Inherited from caller.  Some functions called by this function
- *	obtain the host_set lock.
+ *	PCI/etc. bus probe sem.
+ *	Obtains host_set lock.
  *
  *	SIDE EFFECTS:
  *	Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
@@ -1746,6 +1921,7 @@
 	"HITACHI CDR-8335",
 	"HITACHI CDR-8435",
 	"Toshiba CD-ROM XM-6202B",
+	"TOSHIBA CD-ROM XM-1702BC",
 	"CD-532E-A",
 	"E-IDE CD-ROM CR-840",
 	"CD-ROM Drive/F5A",
@@ -1753,7 +1929,6 @@
 	"SAMSUNG CD-ROM SC-148C",
 	"SAMSUNG CD-ROM SC",
 	"SanDisk SDP3B-64",
-	"SAMSUNG CD-ROM SN-124",
 	"ATAPI CD-ROM DRIVE 40X MAXIMUM",
 	"_NEC DV5800A",
 };
@@ -1875,7 +2050,11 @@
  *	@xfer_mode_out: (output) SET FEATURES - XFER MODE code
  *	@xfer_shift_out: (output) bit shift that selects this mode
  *
+ *	Based on host and device capabilities, determine the
+ *	maximum transfer mode that is amenable to all.
+ *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  *	RETURNS:
  *	Zero on success, negative on error.
@@ -1908,7 +2087,11 @@
  *	@ap: Port associated with device @dev
  *	@dev: Device to which command will be sent
  *
+ *	Issue SET FEATURES - XFER MODE command to device @dev
+ *	on port @ap.
+ *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  */
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
@@ -1946,10 +2129,13 @@
 }
 
 /**
- *	ata_sg_clean -
- *	@qc:
+ *	ata_sg_clean - Unmap DMA memory associated with command
+ *	@qc: Command containing DMA memory to be released
+ *
+ *	Unmap all mapped DMA memory associated with this command.
  *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
  */
 
 static void ata_sg_clean(struct ata_queued_cmd *qc)
@@ -1980,7 +2166,11 @@
  *	ata_fill_sg - Fill PCI IDE PRD table
  *	@qc: Metadata associated with taskfile to be transferred
  *
+ *	Fill PCI IDE PRD (scatter-gather) table with segments
+ *	associated with the current disk command.
+ *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
  *
  */
 static void ata_fill_sg(struct ata_queued_cmd *qc)
@@ -2027,7 +2217,13 @@
  *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
  *	@qc: Metadata associated with taskfile to check
  *
+ *	Allow low-level driver to filter ATA PACKET commands, returning
+ *	a status indicating whether or not it is OK to use DMA for the
+ *	supplied PACKET command.
+ *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
  *	RETURNS: 0 when ATAPI DMA can be used
  *               nonzero otherwise
  */
@@ -2045,6 +2241,8 @@
  *	ata_qc_prep - Prepare taskfile for submission
  *	@qc: Metadata associated with taskfile to be prepared
  *
+ *	Prepare ATA taskfile for submission.
+ *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
@@ -2056,6 +2254,32 @@
 	ata_fill_sg(qc);
 }
 
+/**
+ *	ata_sg_init_one - Associate command with memory buffer
+ *	@qc: Command to be associated
+ *	@buf: Memory buffer
+ *	@buflen: Length of memory buffer, in bytes.
+ *
+ *	Initialize the data-related elements of queued_cmd @qc
+ *	to point to a single memory buffer, @buf of byte length @buflen.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+
+
+/**
+ *	ata_sg_init_one - Prepare a one-entry scatter-gather list.
+ *	@qc:  Queued command
+ *	@buf:  transfer buffer
+ *	@buflen:  length of buf
+ *
+ *	Builds a single-entry scatter-gather list to initiate a
+ *	transfer utilizing the specified buffer.
+ *
+ *	LOCKING:
+ */
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
 	struct scatterlist *sg;
@@ -2070,9 +2294,35 @@
 	sg = qc->sg;
 	sg->page = virt_to_page(buf);
 	sg->offset = (unsigned long) buf & ~PAGE_MASK;
-	sg_dma_len(sg) = buflen;
+	sg->length = buflen;
 }
 
+/**
+ *	ata_sg_init - Associate command with scatter-gather table.
+ *	@qc: Command to be associated
+ *	@sg: Scatter-gather table.
+ *	@n_elem: Number of elements in s/g table.
+ *
+ *	Initialize the data-related elements of queued_cmd @qc
+ *	to point to a scatter-gather table @sg, containing @n_elem
+ *	elements.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+
+/**
+ *	ata_sg_init - Assign a scatter gather list to a queued command
+ *	@qc:  Queued command
+ *	@sg:  Scatter-gather list
+ *	@n_elem:  length of sg list
+ *
+ *	Attaches a scatter-gather list to a queued command.
+ *
+ *	LOCKING:
+ */
+
 void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 		 unsigned int n_elem)
 {
@@ -2082,14 +2332,16 @@
 }
 
 /**
- *	ata_sg_setup_one -
- *	@qc:
+ *	ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+ *	@qc: Command with memory buffer to be mapped.
+ *
+ *	DMA-map the memory buffer associated with queued_cmd @qc.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  *
  *	RETURNS:
- *
+ *	Zero on success, negative on error.
  */
 
 static int ata_sg_setup_one(struct ata_queued_cmd *qc)
@@ -2100,11 +2352,12 @@
 	dma_addr_t dma_address;
 
 	dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt,
-				     sg_dma_len(sg), dir);
+				     sg->length, dir);
 	if (dma_mapping_error(dma_address))
 		return -1;
 
 	sg_dma_address(sg) = dma_address;
+	sg_dma_len(sg) = sg->length;
 
 	DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
 		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
@@ -2113,13 +2366,16 @@
 }
 
 /**
- *	ata_sg_setup -
- *	@qc:
+ *	ata_sg_setup - DMA-map the scatter-gather table associated with a command.
+ *	@qc: Command with scatter-gather table to be mapped.
+ *
+ *	DMA-map the scatter-gather table associated with queued_cmd @qc.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  *
  *	RETURNS:
+ *	Zero on success, negative on error.
  *
  */
 
@@ -2149,6 +2405,7 @@
  *	@ap:
  *
  *	LOCKING:
+ *	None.  (executing in kernel thread context)
  *
  *	RETURNS:
  *
@@ -2196,6 +2453,7 @@
  *	@ap:
  *
  *	LOCKING:
+ *	None.  (executing in kernel thread context)
  */
 
 static void ata_pio_complete (struct ata_port *ap)
@@ -2238,6 +2496,18 @@
 	ata_qc_complete(qc, drv_stat);
 }
 
+
+/**
+ *	swap_buf_le16 -
+ *	@buf:  Buffer to swap
+ *	@buf_words:  Number of 16-bit words in buffer.
+ *
+ *	Swap halves of 16-bit words if needed to convert from
+ *	little-endian byte order to native cpu byte order, or
+ *	vice-versa.
+ *
+ *	LOCKING:
+ */
 void swap_buf_le16(u16 *buf, unsigned int buf_words)
 {
 #ifdef __BIG_ENDIAN
@@ -2309,7 +2579,7 @@
 	qc->cursect++;
 	qc->cursg_ofs++;
 
-	if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+	if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
 		qc->cursg++;
 		qc->cursg_ofs = 0;
 	}
@@ -2338,7 +2608,6 @@
 next_sg:
 	sg = &qc->sg[qc->cursg];
 
-next_page:
 	page = sg->page;
 	offset = sg->offset + qc->cursg_ofs;
 
@@ -2346,7 +2615,8 @@
 	page = nth_page(page, (offset >> PAGE_SHIFT));
 	offset %= PAGE_SIZE;
 
-	count = min(sg_dma_len(sg) - qc->cursg_ofs, bytes);
+	/* don't overrun current sg */
+	count = min(sg->length - qc->cursg_ofs, bytes);
 
 	/* don't cross page boundaries */
 	count = min(count, (unsigned int)PAGE_SIZE - offset);
@@ -2357,7 +2627,7 @@
 	qc->curbytes += count;
 	qc->cursg_ofs += count;
 
-	if (qc->cursg_ofs == sg_dma_len(sg)) {
+	if (qc->cursg_ofs == sg->length) {
 		qc->cursg++;
 		qc->cursg_ofs = 0;
 	}
@@ -2370,8 +2640,6 @@
 	kunmap(page);
 
 	if (bytes) {
-		if (qc->cursg_ofs < sg_dma_len(sg))
-			goto next_page;
 		goto next_sg;
 	}
 }
@@ -2413,6 +2681,7 @@
  *	@ap:
  *
  *	LOCKING:
+ *	None.  (executing in kernel thread context)
  */
 
 static void ata_pio_block(struct ata_port *ap)
@@ -2539,7 +2808,7 @@
 	ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
 	qc->dma_dir = DMA_FROM_DEVICE;
 
-	memset(&qc->cdb, 0, sizeof(ap->cdb_len));
+	memset(&qc->cdb, 0, ap->cdb_len);
 	qc->cdb[0] = REQUEST_SENSE;
 	qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
 
@@ -2582,6 +2851,7 @@
  *	transaction completed successfully.
  *
  *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
  */
 
 static void ata_qc_timeout(struct ata_queued_cmd *qc)
@@ -2691,6 +2961,7 @@
  *	@dev: Device from whom we request an available command structure
  *
  *	LOCKING:
+ *	None.
  */
 
 static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
@@ -2716,6 +2987,7 @@
  *	@dev: Device from whom we request an available command structure
  *
  *	LOCKING:
+ *	None.
  */
 
 struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
@@ -2780,6 +3052,7 @@
  *	in case something prevents using it.
  *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
  *
  */
 void ata_qc_free(struct ata_queued_cmd *qc)
@@ -2793,9 +3066,13 @@
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
- *	@drv_stat: ATA status register contents
+ *	@drv_stat: ATA Status register contents
+ *
+ *	Indicate to the mid and upper layers that an ATA
+ *	command has completed, with either an ok or not-ok status.
  *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
  *
  */
 
@@ -2811,6 +3088,7 @@
 
 	/* call completion callback */
 	rc = qc->complete_fn(qc, drv_stat);
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
@@ -2839,7 +3117,7 @@
 			return 1;
 
 		/* fall through */
-	
+
 	default:
 		return 0;
 	}
@@ -2890,6 +3168,7 @@
 	return -1;
 }
 
+
 /**
  *	ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
  *	@qc: command to issue to device
@@ -2899,6 +3178,8 @@
  *	classes called "protocols", and issuing each type of protocol
  *	is slightly different.
  *
+ *	May be used as the qc_issue() entry in ata_port_operations.
+ *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  *
@@ -2956,7 +3237,7 @@
 }
 
 /**
- *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
@@ -3063,6 +3344,18 @@
 	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+
+/**
+ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	Writes the ATA_DMA_START flag to the DMA command register.
+ *
+ *	May be used as the bmdma_start() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
 void ata_bmdma_start(struct ata_queued_cmd *qc)
 {
 	if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3071,6 +3364,20 @@
 		ata_bmdma_start_pio(qc);
 }
 
+
+/**
+ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	Writes address of PRD table to device's PRD Table Address
+ *	register, sets the DMA control register, and calls
+ *	ops->exec_command() to start the transfer.
+ *
+ *	May be used as the bmdma_setup() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
 void ata_bmdma_setup(struct ata_queued_cmd *qc)
 {
 	if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3079,6 +3386,19 @@
 		ata_bmdma_setup_pio(qc);
 }
 
+
+/**
+ *	ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *	@ap: Port associated with this ATA transaction.
+ *
+ *	Clear interrupt and error flags in DMA status register.
+ *
+ *	May be used as the irq_clear() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
     if (ap->flags & ATA_FLAG_MMIO) {
@@ -3091,6 +3411,19 @@
 
 }
 
+
+/**
+ *	ata_bmdma_status - Read PCI IDE BMDMA status
+ *	@ap: Port associated with this ATA transaction.
+ *
+ *	Read and return BMDMA status register.
+ *
+ *	May be used as the bmdma_status() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
 u8 ata_bmdma_status(struct ata_port *ap)
 {
 	u8 host_stat;
@@ -3102,6 +3435,19 @@
 	return host_stat;
 }
 
+
+/**
+ *	ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+ *	@ap: Port associated with this ATA transaction.
+ *
+ *	Clears the ATA_DMA_START flag in the dma control register
+ *
+ *	May be used as the bmdma_stop() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
 void ata_bmdma_stop(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
@@ -3201,13 +3547,18 @@
 
 /**
  *	ata_interrupt - Default ATA host interrupt handler
- *	@irq: irq line
- *	@dev_instance: pointer to our host information structure
+ *	@irq: irq line (unused)
+ *	@dev_instance: pointer to our ata_host_set information structure
  *	@regs: unused
  *
+ *	Default interrupt handler for PCI IDE devices.  Calls
+ *	ata_host_intr() for each port that is not disabled.
+ *
  *	LOCKING:
+ *	Obtains host_set lock during operation.
  *
  *	RETURNS:
+ *	IRQ_NONE or IRQ_HANDLED.
  *
  */
 
@@ -3229,7 +3580,8 @@
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+			    (qc->flags & ATA_QCFLAG_ACTIVE))
 				handled |= ata_host_intr(ap, qc);
 		}
 	}
@@ -3299,6 +3651,19 @@
 	ata_qc_complete(qc, ATA_ERR);
 }
 
+
+/**
+ *	ata_port_start - Set port up for dma.
+ *	@ap: Port to initialize
+ *
+ *	Called just after data structures for each port are
+ *	initialized.  Allocates space for PRD table.
+ *
+ *	May be used as the port_start() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ */
+
 int ata_port_start (struct ata_port *ap)
 {
 	struct device *dev = ap->host_set->dev;
@@ -3312,6 +3677,18 @@
 	return 0;
 }
 
+
+/**
+ *	ata_port_stop - Undo ata_port_start()
+ *	@ap: Port to shut down
+ *
+ *	Frees the PRD table.
+ *
+ *	May be used as the port_stop() entry in ata_port_operations.
+ *
+ *	LOCKING:
+ */
+
 void ata_port_stop (struct ata_port *ap)
 {
 	struct device *dev = ap->host_set->dev;
@@ -3319,6 +3696,13 @@
 	dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
 }
 
+void ata_host_stop (struct ata_host_set *host_set)
+{
+	if (host_set->mmio_base)
+		iounmap(host_set->mmio_base);
+}
+
+
 /**
  *	ata_host_remove - Unregister SCSI host structure with upper layers
  *	@ap: Port to unregister
@@ -3347,7 +3731,11 @@
  *	@ent: Probe information provided by low-level driver
  *	@port_no: Port number associated with this ata_port
  *
+ *	Initialize a new ata_port structure, and its associated
+ *	scsi_host.
+ *
  *	LOCKING:
+ *	Inherited from caller.
  *
  */
 
@@ -3401,9 +3789,13 @@
  *	@host_set: Collections of ports to which we add
  *	@port_no: Port number associated with this host
  *
+ *	Attach low-level ATA driver to system.
+ *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  *	RETURNS:
+ *	New ata_port on success, for NULL on error.
  *
  */
 
@@ -3436,12 +3828,22 @@
 }
 
 /**
- *	ata_device_add -
- *	@ent:
+ *	ata_device_add - Register hardware device with ATA and SCSI layers
+ *	@ent: Probe information describing hardware device to be registered
+ *
+ *	This function processes the information provided in the probe
+ *	information struct @ent, allocates the necessary ATA and SCSI
+ *	host information structures, initializes them, and registers
+ *	everything with requisite kernel subsystems.
+ *
+ *	This function requests irqs, probes the ATA bus, and probes
+ *	the SCSI bus.
  *
  *	LOCKING:
+ *	PCI/etc. bus probe sem.
  *
  *	RETURNS:
+ *	Number of ports registered.  Zero on error (no ports registered).
  *
  */
 
@@ -3612,7 +4014,15 @@
 /**
  *	ata_std_ports - initialize ioaddr with standard port offsets.
  *	@ioaddr: IO address structure to be initialized
+ *
+ *	Utility function which initializes data_addr, error_addr,
+ *	feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+ *	device_addr, status_addr, and command_addr to standard offsets
+ *	relative to cmd_addr.
+ *
+ *	Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
  */
+
 void ata_std_ports(struct ata_ioports *ioaddr)
 {
 	ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
@@ -3654,6 +4064,20 @@
 	return probe_ent;
 }
 
+
+
+/**
+ *	ata_pci_init_native_mode - Initialize native-mode driver
+ *	@pdev:  pci device to be initialized
+ *	@port:  array[2] of pointers to port info structures.
+ *
+ *	Utility function which allocates and initializes an
+ *	ata_probe_ent structure for a standard dual-port
+ *	PIO-based IDE controller.  The returned ata_probe_ent
+ *	structure can be passed to ata_device_add().  The returned
+ *	ata_probe_ent structure should then be freed with kfree().
+ */
+
 #ifdef CONFIG_PCI
 struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
@@ -3735,10 +4159,19 @@
  *	@port_info: Information from low-level host driver
  *	@n_ports: Number of ports attached to host controller
  *
+ *	This is a helper function which can be called from a driver's
+ *	xxx_init_one() probe function if the hardware uses traditional
+ *	IDE taskfile registers.
+ *
+ *	This function calls pci_enable_device(), reserves its register
+ *	regions, sets the dma mask, enables bus master mode, and calls
+ *	ata_device_add()
+ *
  *	LOCKING:
  *	Inherited from PCI layer (may sleep).
  *
  *	RETURNS:
+ *	Zero on success, negative on errno-based value on error.
  *
  */
 
@@ -3882,10 +4315,6 @@
 	/* FIXME: handle 'rc' failure? */
 
 	free_irq(host_set->irq, host_set);
-	if (host_set->ops->host_stop)
-		host_set->ops->host_stop(host_set);
-	if (host_set->mmio_base)
-		iounmap(host_set->mmio_base);
 
 	for (i = 0; i < host_set->n_ports; i++) {
 		ap = host_set->ports[i];
@@ -3900,6 +4329,9 @@
 		}
 	}
 
+	if (host_set->ops->host_stop)
+		host_set->ops->host_stop(host_set);
+
 	kfree(host_set);
 
 	pci_release_regions(pdev);
@@ -3958,15 +4390,6 @@
 #endif /* CONFIG_PCI */
 
 
-/**
- *	ata_init -
- *
- *	LOCKING:
- *
- *	RETURNS:
- *
- */
-
 static int __init ata_init(void)
 {
 	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
@@ -4007,6 +4430,7 @@
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
+EXPORT_SYMBOL_GPL(ata_host_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
@@ -4029,6 +4453,7 @@
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_id_string);
+EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 #ifdef CONFIG_PCI
diff -urN linux-2.4.32-pre2/drivers/scsi/libata-scsi.c linux-2.4.32-pre3/drivers/scsi/libata-scsi.c
--- linux-2.4.32-pre2/drivers/scsi/libata-scsi.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/libata-scsi.c	2005-08-08 20:06:12.393629065 -0700
@@ -906,7 +906,7 @@
 }
 
 /**
- *	ata_scsiop_noop -
+ *	ata_scsiop_noop - Command handler that simply returns success.
  *	@args: device IDENTIFY data / SCSI command of interest.
  *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *	@buflen: Response buffer length.
@@ -1135,8 +1135,12 @@
 		n_sectors = ata_id_u32(args->id, 60);
 	n_sectors--;		/* ATA TotalUserSectors - 1 */
 
-	tmp = n_sectors;	/* note: truncates, if lba48 */
 	if (args->cmd->cmnd[0] == READ_CAPACITY) {
+		if( n_sectors >= 0xffffffffULL )
+			tmp = 0xffffffff ;  /* Return max count on overflow */
+		else
+			tmp = n_sectors ;
+
 		/* sector count, 32-bit */
 		rbuf[0] = tmp >> (8 * 3);
 		rbuf[1] = tmp >> (8 * 2);
@@ -1150,10 +1154,12 @@
 
 	} else {
 		/* sector count, 64-bit */
-		rbuf[2] = n_sectors >> (8 * 7);
-		rbuf[3] = n_sectors >> (8 * 6);
-		rbuf[4] = n_sectors >> (8 * 5);
-		rbuf[5] = n_sectors >> (8 * 4);
+		tmp = n_sectors >> (8 * 4);
+		rbuf[2] = tmp >> (8 * 3);
+		rbuf[3] = tmp >> (8 * 2);
+		rbuf[4] = tmp >> (8 * 1);
+		rbuf[5] = tmp;
+		tmp = n_sectors;
 		rbuf[6] = tmp >> (8 * 3);
 		rbuf[7] = tmp >> (8 * 2);
 		rbuf[8] = tmp >> (8 * 1);
diff -urN linux-2.4.32-pre2/drivers/scsi/libata.h linux-2.4.32-pre3/drivers/scsi/libata.h
--- linux-2.4.32-pre2/drivers/scsi/libata.h	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/libata.h	2005-08-08 20:06:12.392629021 -0700
@@ -26,7 +26,7 @@
 #define __LIBATA_H__
 
 #define DRV_NAME	"libata"
-#define DRV_VERSION	"1.10"	/* must be exactly four chars */
+#define DRV_VERSION	"1.11"	/* must be exactly four chars */
 
 struct ata_scsi_args {
 	u16			*id;
diff -urN linux-2.4.32-pre2/drivers/scsi/megaraid2.c linux-2.4.32-pre3/drivers/scsi/megaraid2.c
--- linux-2.4.32-pre2/drivers/scsi/megaraid2.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/megaraid2.c	2005-08-08 20:06:12.397629242 -0700
@@ -14,7 +14,7 @@
  *	  - speed-ups (list handling fixes, issued_list, optimizations.)
  *	  - lots of cleanups.
  *
- * Version : v2.10.8.2 (July 26, 2004)
+ * Version : v2.10.10.1 (January 27, 2005)
  *
  * Authors:	Atul Mukker <Atul.Mukker@lsil.com>
  *		Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
@@ -46,7 +46,7 @@
 
 #include "megaraid2.h"
 
-#if defined(__x86_64__)
+#ifdef LSI_CONFIG_COMPAT
 #include <asm/ioctl32.h>
 #endif
 
@@ -181,7 +181,7 @@
 	/*
 	 * Scan PCI bus for our all devices.
 	 */
-	for( i = 0; i < sizeof(dev_sw_table)/sizeof(u16); i += 2 ) {
+	for( i = 0; i < ((int) (sizeof(dev_sw_table)/sizeof(u16))); i += 2 ) {
 
 		mega_find_card(host_template, dev_sw_table[i],
 				dev_sw_table[i+1]);
@@ -233,7 +233,7 @@
 				"MegaRAID Shutdown routine not registered!!\n");
 		}
 
-#if defined(__x86_64__)
+#ifdef LSI_CONFIG_COMPAT
 		/*
 		 * Register the 32-bit ioctl conversion
 		 */
@@ -341,6 +341,7 @@
 				(subsysvid != INTEL_SUBSYS_VID) &&
 				(subsysvid != FSC_SUBSYS_VID) &&
 				(subsysvid != ACER_SUBSYS_VID) &&
+				(subsysvid != NEC_SUBSYS_VID) &&
 				(subsysvid != LSI_SUBSYS_VID) ) continue;
 
 
@@ -821,6 +822,78 @@
 }
 
 
+/**
+ * issue_scb()
+ * @adapter - pointer to our soft state
+ * @scb - scsi control block
+ *
+ * Post a command to the card if the mailbox is available, otherwise return
+ * busy. We also take the scb from the pending list if the mailbox is
+ * available.
+ */
+static inline int
+issue_scb(adapter_t *adapter, scb_t *scb)
+{
+	volatile mbox64_t	*mbox64 = adapter->mbox64;
+	volatile mbox_t		*mbox = adapter->mbox;
+	unsigned int	i = 0;
+
+	if(unlikely(mbox->busy)) {
+		do {
+			udelay(1);
+			i++;
+		} while( mbox->busy && (i < max_mbox_busy_wait) );
+
+		if(mbox->busy) return -1;
+	}
+
+	/* Copy mailbox data into host structure */
+	memcpy((char *)mbox, (char *)scb->raw_mbox, 16);
+
+	mbox->cmdid = scb->idx;	/* Set cmdid */
+	mbox->busy = 1;		/* Set busy */
+
+
+	/*
+	 * Increment the pending queue counter
+	 */
+	atomic_inc(&adapter->pend_cmds);
+
+	switch (mbox->cmd) {
+	case MEGA_MBOXCMD_EXTPTHRU:
+		if( !adapter->has_64bit_addr ) break;
+		// else fall through
+	case MEGA_MBOXCMD_LREAD64:
+	case MEGA_MBOXCMD_LWRITE64:
+	case MEGA_MBOXCMD_PASSTHRU64:
+		mbox64->xfer_segment_lo = mbox->xferaddr;
+		mbox64->xfer_segment_hi = 0;
+		mbox->xferaddr = 0xFFFFFFFF;
+		break;
+	default:
+		mbox64->xfer_segment_lo = 0;
+		mbox64->xfer_segment_hi = 0;
+	}
+
+	/*
+	 * post the command
+	 */
+	scb->state |= SCB_ISSUED;
+
+	if( likely(adapter->flag & BOARD_MEMMAP) ) {
+		mbox->poll = 0;
+		mbox->ack = 0;
+		WRINDOOR(adapter, adapter->mbox_dma | 0x1);
+	}
+	else {
+		irq_enable(adapter);
+		issue_command(adapter);
+	}
+
+	return 0;
+}
+
+
 /*
  * mega_query_adapter()
  * @adapter - pointer to our soft state
@@ -990,78 +1063,6 @@
 
 
 /**
- * issue_scb()
- * @adapter - pointer to our soft state
- * @scb - scsi control block
- *
- * Post a command to the card if the mailbox is available, otherwise return
- * busy. We also take the scb from the pending list if the mailbox is
- * available.
- */
-static inline int
-issue_scb(adapter_t *adapter, scb_t *scb)
-{
-	volatile mbox64_t	*mbox64 = adapter->mbox64;
-	volatile mbox_t		*mbox = adapter->mbox;
-	unsigned int	i = 0;
-
-	if(unlikely(mbox->busy)) {
-		do {
-			udelay(1);
-			i++;
-		} while( mbox->busy && (i < max_mbox_busy_wait) );
-
-		if(mbox->busy) return -1;
-	}
-
-	/* Copy mailbox data into host structure */
-	memcpy((char *)mbox, (char *)scb->raw_mbox, 16);
-
-	mbox->cmdid = scb->idx;	/* Set cmdid */
-	mbox->busy = 1;		/* Set busy */
-
-
-	/*
-	 * Increment the pending queue counter
-	 */
-	atomic_inc(&adapter->pend_cmds);
-
-	switch (mbox->cmd) {
-	case MEGA_MBOXCMD_EXTPTHRU:
-		if( !adapter->has_64bit_addr ) break;
-		// else fall through
-	case MEGA_MBOXCMD_LREAD64:
-	case MEGA_MBOXCMD_LWRITE64:
-	case MEGA_MBOXCMD_PASSTHRU64:
-		mbox64->xfer_segment_lo = mbox->xferaddr;
-		mbox64->xfer_segment_hi = 0;
-		mbox->xferaddr = 0xFFFFFFFF;
-		break;
-	default:
-		mbox64->xfer_segment_lo = 0;
-		mbox64->xfer_segment_hi = 0;
-	}
-
-	/*
-	 * post the command
-	 */
-	scb->state |= SCB_ISSUED;
-
-	if( likely(adapter->flag & BOARD_MEMMAP) ) {
-		mbox->poll = 0;
-		mbox->ack = 0;
-		WRINDOOR(adapter, adapter->mbox_dma | 0x1);
-	}
-	else {
-		irq_enable(adapter);
-		issue_command(adapter);
-	}
-
-	return 0;
-}
-
-
-/**
  * mega_runpendq()
  * @adapter - pointer to our soft state
  *
@@ -1074,7 +1075,6 @@
 		__mega_runpendq(adapter);
 }
 
-
 static void
 __mega_runpendq(adapter_t *adapter)
 {
@@ -1176,80 +1176,6 @@
 	return ldrv_num;
 }
 
-/*
- * Wait until the controller's mailbox is available
- */
-static inline int
-mega_busywait_mbox (adapter_t *adapter)
-{
-	if (adapter->mbox->busy)
-		return __mega_busywait_mbox(adapter);
-	return 0;
-}
-
-
-/**
- * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs
- * @adapter	- controller's soft state
- *
- * Interrupt ackrowledgement sequence for IO mapped HBAs
- */
-static inline void
-megaraid_iombox_ack_sequence(adapter_t *adapter)
-{
-	u8	status;
-	u8	nstatus;
-	u8	completed[MAX_FIRMWARE_STATUS];
-	u8	byte;
-	int	i;
-
-
-	/*
-	 * loop till F/W has more commands for us to complete.
-	 */
-	do {
-		/* Check if a valid interrupt is pending */
-		byte = irq_state(adapter);
-		if( (byte & VALID_INTR_BYTE) == 0 ) {
-			return;
-		}
-		set_irq_state(adapter, byte);
-
-		while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
-			cpu_relax();
-		}
-		adapter->mbox->numstatus = 0xFF;
-
-		for (i = 0; i < nstatus; i++) {
-			while ((completed[i] = adapter->mbox->completed[i])
-					== 0xFF) {
-				cpu_relax();
-			}
-
-			adapter->mbox->completed[i] = 0xFF;
-		}
-
-		// we must read the valid status now
-		if ((status = adapter->mbox->status) == 0xFF) {
-			printk(KERN_WARNING
-			"megaraid critical: status 0xFF from firmware.\n");
-		}
-		adapter->mbox->status = 0xFF;
-
-		/*
-		 * decrement the pending queue counter
-		 */
-		atomic_sub(nstatus, &adapter->pend_cmds);
-
-		/* Acknowledge interrupt */
-		irq_ack(adapter);
-
-		mega_cmd_done(adapter, completed, nstatus, status);
-
-	} while(1);
-}
-
-
 
 /*
  * megaraid_queue()
@@ -1755,8 +1681,8 @@
 	pthru = scb->pthru;
 	memset(pthru, 0, sizeof (mega_passthru));
 
-	/* 0=6sec/1=60sec/2=10min/3=3hrs */
-	pthru->timeout = 2;
+	/* 0=6sec/1=60sec/2=10min/3=3hrs/4=NO timeout */
+	pthru->timeout = 4;
 
 	pthru->ars = 1;
 	pthru->reqsenselen = 14;
@@ -1819,8 +1745,8 @@
 	epthru = scb->epthru;
 	memset(epthru, 0, sizeof(mega_ext_passthru));
 
-	/* 0=6sec/1=60sec/2=10min/3=3hrs */
-	epthru->timeout = 2;
+	/* 0=6sec/1=60sec/2=10min/3=3hrs/4=NO timeout */
+	epthru->timeout = 4;
 
 	epthru->ars = 1;
 	epthru->reqsenselen = 14;
@@ -1862,6 +1788,32 @@
 }
 
 
+/*
+ * Wait until the controller's mailbox is available
+ */
+static inline int
+mega_busywait_mbox (adapter_t *adapter)
+{
+	if (adapter->mbox->busy)
+		return __mega_busywait_mbox(adapter);
+	return 0;
+}
+
+static int
+__mega_busywait_mbox (adapter_t *adapter)
+{
+	volatile mbox_t *mbox = adapter->mbox;
+	long counter;
+
+	for (counter = 0; counter < 10000; counter++) {
+		if (!mbox->busy)
+			return 0;
+		udelay(100); yield();
+	}
+	return -1;		/* give up after 1 second */
+}
+
+
 /**
  * issue_scb_block()
  * @adapter - pointer to our soft state
@@ -1962,137 +1914,7 @@
 	return -1;
 }
 
-
-/**
- * megaraid_isr_iomapped()
- * @irq - irq
- * @devp - pointer to our soft state
- * @regs - unused
- *
- * Interrupt service routine for io-mapped controllers.
- * Find out if our device is interrupting. If yes, acknowledge the interrupt
- * and service the completed commands.
- */
-static void
-megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
-{
-	adapter_t	*adapter = devp;
-	unsigned long	flags;
-
-
-	spin_lock_irqsave(adapter->host_lock, flags);
-
-	megaraid_iombox_ack_sequence(adapter);
-
-	/* Loop through any pending requests */
-	if( atomic_read(&adapter->quiescent ) == 0) {
-		mega_runpendq(adapter);
-	}
-
-	spin_unlock_irqrestore(adapter->host_lock, flags);
-
-	return;
-}
-
-
-/**
- * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs
- * @adapter	- controller's soft state
- *
- * Interrupt ackrowledgement sequence for memory mapped HBAs
- */
-static inline void
-megaraid_memmbox_ack_sequence(adapter_t *adapter)
-{
-	u8	status;
-	u32	dword = 0;
-	u8	nstatus;
-	u8	completed[MAX_FIRMWARE_STATUS];
-	int	i;
-
-
-	/*
-	 * loop till F/W has more commands for us to complete.
-	 */
-	do {
-		/* Check if a valid interrupt is pending */
-		dword = RDOUTDOOR(adapter);
-		if( dword != 0x10001234 ) {
-			/*
-			 * No more pending commands
-			 */
-			return;
-		}
-		WROUTDOOR(adapter, 0x10001234);
-
-		while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
-			cpu_relax();
-		}
-		adapter->mbox->numstatus = 0xFF;
-
-		for (i = 0; i < nstatus; i++ ) {
-			while ((completed[i] = adapter->mbox->completed[i])
-					== 0xFF) {
-				cpu_relax();
-			}
-
-			adapter->mbox->completed[i] = 0xFF;
-		}
-
-		// we must read the valid status now
-		if ((status = adapter->mbox->status) == 0xFF) {
-			printk(KERN_WARNING
-			"megaraid critical: status 0xFF from firmware.\n");
-		}
-		adapter->mbox->status = 0xFF;
-
-		/*
-		 * decrement the pending queue counter
-		 */
-		atomic_sub(nstatus, &adapter->pend_cmds);
-
-		/* Acknowledge interrupt */
-		WRINDOOR(adapter, 0x2);
-
-		while( RDINDOOR(adapter) & 0x02 ) cpu_relax();
-
-		mega_cmd_done(adapter, completed, nstatus, status);
-
-	} while(1);
-}
-
-
-/**
- * megaraid_isr_memmapped()
- * @irq - irq
- * @devp - pointer to our soft state
- * @regs - unused
- *
- * Interrupt service routine for memory-mapped controllers.
- * Find out if our device is interrupting. If yes, acknowledge the interrupt
- * and service the completed commands.
- */
-static void
-megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs)
-{
-	adapter_t	*adapter = devp;
-	unsigned long	flags;
-
-
-	spin_lock_irqsave(adapter->host_lock, flags);
-
-	megaraid_memmbox_ack_sequence(adapter);
-
-	/* Loop through any pending requests */
-	if(atomic_read(&adapter->quiescent) == 0) {
-		mega_runpendq(adapter);
-	}
-
-	spin_unlock_irqrestore(adapter->host_lock, flags);
-
-	return;
-}
-
+
 /**
  * mega_cmd_done()
  * @adapter - pointer to our soft state
@@ -2102,7 +1924,7 @@
  *
  * Complete the comamnds and call the scsi mid-layer callback hooks.
  */
-static void
+static inline void
 mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
 {
 	mega_ext_passthru	*epthru = NULL;
@@ -2351,6 +2173,197 @@
 }
 
 
+/**
+ * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs
+ * @adapter	- controller's soft state
+ *
+ * Interrupt ackrowledgement sequence for IO mapped HBAs
+ */
+static inline void
+megaraid_iombox_ack_sequence(adapter_t *adapter)
+{
+	u8	status;
+	int	nstatus;
+	u8	completed[MAX_FIRMWARE_STATUS];
+	u8	byte;
+	int	i;
+
+
+	/*
+	 * loop till F/W has more commands for us to complete.
+	 */
+	do {
+		/* Check if a valid interrupt is pending */
+		byte = irq_state(adapter);
+		if( (byte & VALID_INTR_BYTE) == 0 ) {
+			return;
+		}
+		set_irq_state(adapter, byte);
+
+		while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
+			cpu_relax();
+		}
+		adapter->mbox->numstatus = 0xFF;
+
+		for (i = 0; i < nstatus; i++) {
+			while ((completed[i] = adapter->mbox->completed[i])
+					== 0xFF) {
+				cpu_relax();
+			}
+
+			adapter->mbox->completed[i] = 0xFF;
+		}
+
+		// we must read the valid status now
+		if ((status = adapter->mbox->status) == 0xFF) {
+			printk(KERN_WARNING
+			"megaraid critical: status 0xFF from firmware.\n");
+		}
+		adapter->mbox->status = 0xFF;
+
+		/*
+		 * decrement the pending queue counter
+		 */
+		atomic_sub(nstatus, &adapter->pend_cmds);
+
+		/* Acknowledge interrupt */
+		irq_ack(adapter);
+
+		mega_cmd_done(adapter, completed, nstatus, status);
+
+	} while(1);
+}
+
+
+/**
+ * megaraid_isr_iomapped()
+ * @irq - irq
+ * @devp - pointer to our soft state
+ * @regs - unused
+ *
+ * Interrupt service routine for io-mapped controllers.
+ * Find out if our device is interrupting. If yes, acknowledge the interrupt
+ * and service the completed commands.
+ */
+static void
+megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
+{
+	adapter_t	*adapter = devp;
+	unsigned long	flags;
+
+	spin_lock_irqsave(adapter->host_lock, flags);
+
+	megaraid_iombox_ack_sequence(adapter);
+
+	/* Loop through any pending requests */
+	if( atomic_read(&adapter->quiescent ) == 0) {
+		mega_runpendq(adapter);
+	}
+
+	spin_unlock_irqrestore(adapter->host_lock, flags);
+
+	return;
+}
+
+
+/**
+ * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs
+ * @adapter	- controller's soft state
+ *
+ * Interrupt ackrowledgement sequence for memory mapped HBAs
+ */
+static inline void
+megaraid_memmbox_ack_sequence(adapter_t *adapter)
+{
+	u8	status;
+	u32	dword = 0;
+	int	nstatus;
+	u8	completed[MAX_FIRMWARE_STATUS];
+	int	i;
+
+
+	/*
+	 * loop till F/W has more commands for us to complete.
+	 */
+	do {
+		/* Check if a valid interrupt is pending */
+		dword = RDOUTDOOR(adapter);
+		if( dword != 0x10001234 ) {
+			/*
+			 * No more pending commands
+			 */
+			return;
+		}
+		WROUTDOOR(adapter, 0x10001234);
+
+		while ((nstatus = adapter->mbox->numstatus) == 0xFF) {
+			cpu_relax();
+		}
+		adapter->mbox->numstatus = 0xFF;
+
+		for (i = 0; i < nstatus; i++ ) {
+			while ((completed[i] = adapter->mbox->completed[i])
+					== 0xFF) {
+				cpu_relax();
+			}
+
+			adapter->mbox->completed[i] = 0xFF;
+		}
+
+		// we must read the valid status now
+		if ((status = adapter->mbox->status) == 0xFF) {
+			printk(KERN_WARNING
+			"megaraid critical: status 0xFF from firmware.\n");
+		}
+		adapter->mbox->status = 0xFF;
+
+		/*
+		 * decrement the pending queue counter
+		 */
+		atomic_sub(nstatus, &adapter->pend_cmds);
+
+		/* Acknowledge interrupt */
+		WRINDOOR(adapter, 0x2);
+
+		while( RDINDOOR(adapter) & 0x02 ) cpu_relax();
+
+		mega_cmd_done(adapter, completed, nstatus, status);
+
+	} while(1);
+}
+
+
+/**
+ * megaraid_isr_memmapped()
+ * @irq - irq
+ * @devp - pointer to our soft state
+ * @regs - unused
+ *
+ * Interrupt service routine for memory-mapped controllers.
+ * Find out if our device is interrupting. If yes, acknowledge the interrupt
+ * and service the completed commands.
+ */
+static void
+megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs)
+{
+	adapter_t	*adapter = devp;
+	unsigned long	flags;
+
+	spin_lock_irqsave(adapter->host_lock, flags);
+
+	megaraid_memmbox_ack_sequence(adapter);
+
+	/* Loop through any pending requests */
+	if(atomic_read(&adapter->quiescent) == 0) {
+		mega_runpendq(adapter);
+	}
+
+	spin_unlock_irqrestore(adapter->host_lock, flags);
+
+	return;
+}
+
+
 /*
  * Free a SCB structure
  * Note: We assume the scsi commands associated with this scb is not free yet.
@@ -2404,19 +2417,6 @@
 	list_add(&scb->list, &adapter->free_list);
 }
 
-static int
-__mega_busywait_mbox (adapter_t *adapter)
-{
-	volatile mbox_t *mbox = adapter->mbox;
-	long counter;
-
-	for (counter = 0; counter < 10000; counter++) {
-		if (!mbox->busy)
-			return 0;
-		udelay(100); yield();
-	}
-	return -1;		/* give up after 1 second */
-}
 
 /*
  * Copies data to SGLIST
@@ -2434,7 +2434,7 @@
 
 	cmd = scb->cmd;
 
-	/* return 0 elements if no data transfer */
+	// return 0 elements if no data transfer
 	if (!cmd->request_buffer || !cmd->request_bufflen)
 		return 0;
 
@@ -2561,6 +2561,7 @@
 		enquiry3->pdrv_state[i] = inquiry->pdrv_info.pdrv_state[i];
 }
 
+
 static inline void
 mega_free_sgl(adapter_t *adapter)
 {
@@ -2726,7 +2727,7 @@
 	 */
 	scsi_unregister(host);
 
-#if defined(__x86_64__)
+#ifdef LSI_CONFIG_COMPAT
 	unregister_ioctl32_conversion(MEGAIOCCMD);
 #endif
 
@@ -2835,7 +2836,6 @@
 	return SUCCESS;
 }
 
-
 static int
 megaraid_reset(Scsi_Cmnd *cmd)
 {
@@ -2903,12 +2903,10 @@
 		/*
 		 * Perform the ack sequence, since interrupts are unavailable
 		 */
-		if( adapter->flag & BOARD_MEMMAP ) {
+		if (adapter->flag & BOARD_MEMMAP)
 			megaraid_memmbox_ack_sequence(adapter);
-		}
-		else {
+		else
 			megaraid_iombox_ack_sequence(adapter);
-		}
 
 		spin_unlock(adapter->host_lock);
 
@@ -2941,7 +2939,6 @@
 	return rval;
 }
 
-
 #ifdef CONFIG_PROC_FS
 /* Following code handles /proc fs  */
 
@@ -3200,6 +3197,7 @@
 	return len;
 }
 
+
 /**
  * mega_allocate_inquiry()
  * @dma_handle - handle returned for dma address
@@ -3582,7 +3580,7 @@
 		 * Check for overflow. We print less than 240
 		 * characters for inquiry
 		 */
-		if( (len + 240) >= PAGE_SIZE ) break;
+		if( (len + 240) >= ((int) PAGE_SIZE) ) break;
 
 		len += sprintf(page+len, "%s.\n", str);
 
@@ -3886,7 +3884,7 @@
 		 * Check for overflow. We print less than 240 characters for
 		 * information about each logical drive.
 		 */
-		if( (len + 240) >= PAGE_SIZE ) break;
+		if( (len + 240) >= ((int) PAGE_SIZE) ) break;
 
 		len += sprintf(page+len, "Logical drive:%2d:, ", i);
 
@@ -4172,7 +4170,7 @@
 }
 
 
-#if defined(__x86_64__)
+#ifdef LSI_CONFIG_COMPAT
 static int
 megadev_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
 		struct file *filep)
@@ -4221,7 +4219,7 @@
 	megacmd_t	mc;
 	megastat_t	*ustats;
 	int		num_ldrv;
-	u32		uxferaddr = 0;
+	caddr_t		uxferaddr=NULL;
 	struct pci_dev	*pdev;
 
 	ustats = NULL; /* avoid compilation warnings */
@@ -4251,13 +4249,13 @@
 	switch( uioc.opcode ) {
 
 	case GET_DRIVER_VER:
-		if( put_user(driver_ver, (u32 *)uioc.uioc_uaddr) )
+		if( put_user(driver_ver, (u32 *)uioc.u_dataaddr) )
 			return (-EFAULT);
 
 		break;
 
 	case GET_N_ADAP:
-		if( put_user(hba_count, (u32 *)uioc.uioc_uaddr) )
+		if( put_user(hba_count, (u32 *)uioc.u_dataaddr) )
 			return (-EFAULT);
 
 		/*
@@ -4275,7 +4273,7 @@
 		if( (adapno = GETADAP(uioc.adapno)) >= hba_count )
 			return (-ENODEV);
 
-		if( copy_to_user(uioc.uioc_uaddr, mcontroller+adapno,
+		if( copy_to_user(uioc.u_dataaddr, mcontroller+adapno,
 				sizeof(struct mcontroller)) )
 			return (-EFAULT);
 		break;
@@ -4291,7 +4289,7 @@
 
 		adapter = hba_soft_state[adapno];
 
-		ustats = (megastat_t *)uioc.uioc_uaddr;
+		ustats = (megastat_t *)uioc.u_dataaddr;
 
 		if( copy_from_user(&num_ldrv, &ustats->num_ldrv, sizeof(int)) )
 			return (-EFAULT);
@@ -4333,7 +4331,7 @@
 		/*
 		 * Which adapter
 		 */
-		if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) 
+		if( (adapno = GETADAP(uioc.adapno)) >= hba_count )
 			return (-ENODEV);
 
 		adapter = hba_soft_state[adapno];
@@ -4342,37 +4340,37 @@
 		 * Deletion of logical drive is a special case. The adapter
 		 * should be quiescent before this command is issued.
 		 */
-		if( uioc.uioc_rmbox[0] == FC_DEL_LOGDRV &&
-				uioc.uioc_rmbox[2] == OP_DEL_LOGDRV ) {
+		if( RMBOX(uioc)[0] == FC_DEL_LOGDRV ) {
+			if ( RMBOX(uioc)[2] == OP_DEL_LOGDRV ) {
+				/*
+				 * Do we support this feature
+				 */
+				if( !adapter->support_random_del ) {
+					printk(KERN_WARNING "megaraid: logdrv ");
+					printk("delete on non-supporting F/W.\n");
 
-			/*
-			 * Do we support this feature
-			 */
-			if( !adapter->support_random_del ) {
-				printk(KERN_WARNING "megaraid: logdrv ");
-				printk("delete on non-supporting F/W.\n");
+					return (-EINVAL);
+				}
 
-				return (-EINVAL);
-			}
+				rval = mega_del_logdrv( adapter, RMBOX(uioc)[3] );
 
-			rval = mega_del_logdrv( adapter, uioc.uioc_rmbox[3] );
+				if( rval == 0 ) {
+					memset(&mc, 0, sizeof(megacmd_t));
 
-			if( rval == 0 ) {
-				memset(&mc, 0, sizeof(megacmd_t));
+					mc.status = rval;
 
-				mc.status = rval;
+					rval = mega_n_to_m((void *)arg, &mc);
+				}
 
-				rval = mega_n_to_m((void *)arg, &mc);
+				return rval;
 			}
-
-			return rval;
 		}
 		/*
 		 * This interface only support the regular passthru commands.
 		 * Reject extended passthru and 64-bit passthru
 		 */
-		if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU64 ||
-			uioc.uioc_rmbox[0] == MEGA_MBOXCMD_EXTPTHRU ) {
+		if( RMBOX(uioc)[0] == MEGA_MBOXCMD_PASSTHRU64 ||
+			RMBOX(uioc)[0] == MEGA_MBOXCMD_EXTPTHRU ) {
 
 			printk(KERN_WARNING "megaraid: rejected passthru.\n");
 
@@ -4386,7 +4384,7 @@
 		pdev = adapter->dev;
 
 		/* Is it a passthru command or a DCMD */
-		if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
+		if( RMBOX(uioc)[0] == MEGA_MBOXCMD_PASSTHRU ) {
 			/* Passthru commands */
 
 			pthru = adapter->int_pthru;
@@ -4394,20 +4392,12 @@
 			/*
 			 * The user passthru structure
 			 */
-			upthru = (mega_passthru *)
-					((ulong)(MBOX(uioc)->xferaddr));
-			/*
-			 * Copy in the user passthru here.
-			 */
-			if( copy_from_user(pthru, (char *)upthru,
-						sizeof(mega_passthru)) ) {
-				return (-EFAULT);
-			}
-
+			 upthru = &uioc.pthru;
+			 memcpy(pthru, (char *)upthru,sizeof(mega_passthru));
 			/*
 			 * Is there a data transfer; If the data transfer
-			 * length is <= INT_MEMBLK_SZ, usr the buffer 
-			 * allocated at the load time. Otherwise, allocate it 
+			 * length is <= INT_MEMBLK_SZ, usr the buffer
+			 * allocated at the load time. Otherwise, allocate it
 			 * here.
 			 */
 			if (pthru->dataxferlen) {
@@ -4417,8 +4407,9 @@
 							pthru->dataxferlen,
 							&data_dma_hndl );
 
-					if (data == NULL)
+					if (data == NULL) {
 						return (-ENOMEM);
+					}
 				}
 				else {
 					data = adapter->int_data;
@@ -4428,11 +4419,11 @@
 				 * Save the user address and point the kernel
 				 * address at just allocated memory
 				 */
-				uxferaddr = pthru->dataxferaddr;
+				uxferaddr = (caddr_t) uioc.u_dataaddr;
 				if (data_dma_hndl)
 					pthru->dataxferaddr = data_dma_hndl;
 				else
-					pthru->dataxferaddr = 
+					pthru->dataxferaddr =
 						adapter->int_data_dma_hndl;
 			}
 
@@ -4440,12 +4431,12 @@
 			/*
 			 * Is data coming down-stream
 			 */
-			if( pthru->dataxferlen && (uioc.flags & UIOC_WR) ) {
+			if(pthru->dataxferlen  && (uioc.flags & UIOC_WR) ) {
 				/*
 				 * Get the user data
 				 */
 				if( copy_from_user(data,
-						(char *)((ulong)uxferaddr),
+						(char *)uxferaddr,
 						pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 					goto freedata_and_return;
@@ -4471,7 +4462,7 @@
 			 * Is data going up-stream
 			 */
 			if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char *)((ulong)uxferaddr),
+				if( copy_to_user((char *)uxferaddr,
 						data, pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 				}
@@ -4511,7 +4502,7 @@
 				else {
 					data = adapter->int_data;
 				}
-				uxferaddr = MBOX(uioc)->xferaddr;
+				uxferaddr = uioc.u_dataaddr;
 			}
 
 			/*
@@ -4559,7 +4550,7 @@
 			 * Is data going up-stream
 			 */
 			if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char *)((ulong)uxferaddr),
+				if( copy_to_user((char *)uxferaddr,
 						data, uioc.xferlen) ) {
 
 					rval = (-EFAULT);
@@ -4648,18 +4639,18 @@
 
 		case MEGAIOC_QDRVRVER:	/* Query driver version */
 			uioc->opcode = GET_DRIVER_VER;
-			uioc->uioc_uaddr = uioc_mimd.data;
+			uioc->u_dataaddr = uioc_mimd.data;
 			break;
 
 		case MEGAIOC_QNADAP:	/* Get # of adapters */
 			uioc->opcode = GET_N_ADAP;
-			uioc->uioc_uaddr = uioc_mimd.data;
+			uioc->u_dataaddr = uioc_mimd.data;
 			break;
 
 		case MEGAIOC_QADAPINFO:	/* Get adapter information */
 			uioc->opcode = GET_ADAP_INFO;
 			uioc->adapno = uioc_mimd.ui.fcs.adapno;
-			uioc->uioc_uaddr = uioc_mimd.data;
+			uioc->u_dataaddr = uioc_mimd.data;
 			break;
 
 		default:
@@ -4674,9 +4665,16 @@
 		uioc->opcode = MBOX_CMD;
 		uioc->adapno = uioc_mimd.ui.fcs.adapno;
 
-		memcpy(uioc->uioc_rmbox, uioc_mimd.mbox, 18);
+		memcpy(&uioc->u_mbox, uioc_mimd.mbox, 18);
 
 		uioc->xferlen = uioc_mimd.ui.fcs.length;
+		uioc->u_dataaddr = uioc_mimd.ui.fcs.buffer;
+
+		if (uioc_mimd.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
+			memcpy(&uioc->pthru,&uioc_mimd.pthru,
+				sizeof(mega_passthru));
+
+		}
 
 		if( uioc_mimd.outlen ) uioc->flags = UIOC_RD;
 		if( uioc_mimd.inlen ) uioc->flags |= UIOC_WR;
@@ -4688,13 +4686,20 @@
 		uioc->opcode = MBOX_CMD;
 		uioc->adapno = uioc_mimd.ui.fcs.adapno;
 
-		memcpy(uioc->uioc_rmbox, uioc_mimd.mbox, 18);
+		memcpy(&uioc->u_mbox, uioc_mimd.mbox, 18);
 
 		/*
 		 * Choose the xferlen bigger of input and output data
 		 */
 		uioc->xferlen = uioc_mimd.outlen > uioc_mimd.inlen ?
 			uioc_mimd.outlen : uioc_mimd.inlen;
+		uioc->u_dataaddr = uioc_mimd.data;
+
+		if (uioc_mimd.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
+			memcpy(&uioc->pthru,&uioc_mimd.pthru,
+				sizeof(mega_passthru));
+
+		}
 
 		if( uioc_mimd.outlen ) uioc->flags = UIOC_RD;
 		if( uioc_mimd.inlen ) uioc->flags |= UIOC_WR;
@@ -4720,7 +4725,6 @@
 static int
 mega_n_to_m(void *arg, megacmd_t *mc)
 {
-	nitioctl_t	*uiocp;
 	megacmd_t	*umc;
 	megacmd_t	kmc;
 	mega_passthru	*upthru;
@@ -4735,20 +4739,14 @@
 
 	if( memcmp(signature, "MEGANIT", 7) == 0 ) {
 
-		uiocp = (nitioctl_t *)arg;
-
-		if( put_user(mc->status, (u8 *)&MBOX_P(uiocp)->status) )
-			return (-EFAULT);
-
-		if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) {
-
-			umc = MBOX_P(uiocp);
 
-			upthru = (mega_passthru *)((ulong)(umc->xferaddr));
-
-			if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
-				return (-EFAULT);
-		}
+		/*
+		 * NOTE: The nit ioctl is still under flux because of
+		 * change of mailbox definition, in HPE. No applications yet
+		 * use this interface and let's not have applications use this
+		 * interface till the new specifitions are in place.
+		 */
+		return -EINVAL;
 	}
 	else {
 		uioc_mimd = (struct uioctl_t *)arg;
@@ -4763,8 +4761,7 @@
 			if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) {
 				return -EFAULT;
 			}
-
-			upthru = (mega_passthru *)((ulong)kmc.xferaddr);
+			upthru = (mega_passthru *)((ulong)&uioc_mimd->pthru);
 
 			if( put_user(mc->status, (u8 *)&upthru->scsistatus) ){
 				return (-EFAULT);
@@ -5179,6 +5176,7 @@
 }
 
 
+
 /**
  * mega_reorder_hosts()
  *
@@ -5393,7 +5391,6 @@
 }
 
 
-
 /** mega_internal_dev_inquiry()
  * @adapter - pointer to our soft state
  * @ch - channel for this device
diff -urN linux-2.4.32-pre2/drivers/scsi/megaraid2.h linux-2.4.32-pre3/drivers/scsi/megaraid2.h
--- linux-2.4.32-pre2/drivers/scsi/megaraid2.h	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/megaraid2.h	2005-08-08 20:06:12.398629286 -0700
@@ -6,7 +6,7 @@
 
 
 #define MEGARAID_VERSION	\
-	"v2.10.8.2 (Release Date: Mon Jul 26 12:15:51 EDT 2004)\n"
+	"v2.10.10.1 (Release Date: Thu Jan 27 16:19:44 EDT 2005)\n"
 
 /*
  * Driver features - change the values to enable or disable features in the
@@ -83,6 +83,7 @@
 #define INTEL_SUBSYS_VID		0x8086
 #define FSC_SUBSYS_VID			0x1734
 #define ACER_SUBSYS_VID			0x1025
+#define NEC_SUBSYS_VID			0x1033
 
 #define HBA_SIGNATURE	      		0x3344
 #define HBA_SIGNATURE_471	  	0xCCCC
@@ -707,15 +708,15 @@
 	char		signature[8];	/* Must contain "MEGANIT" */
 	u32		opcode;		/* opcode for the command */
 	u32		adapno;		/* adapter number */
-	union {
-		u8	__raw_mbox[18];
-		caddr_t	__uaddr; /* xferaddr for non-mbox cmds */
-	}__ua;
-
-#define uioc_rmbox	__ua.__raw_mbox
-#define MBOX(uioc)	((megacmd_t *)&((uioc).__ua.__raw_mbox[0]))
-#define MBOX_P(uioc)	((megacmd_t *)&((uioc)->__ua.__raw_mbox[0]))
-#define uioc_uaddr	__ua.__uaddr
+	mbox_t  	u_mbox;		/* user mailbox */
+	caddr_t		u_dataaddr;	/* xferaddr for DCMD and non-mbox
+					   commands */
+	mega_passthru	pthru;
+
+#define RMBOX(uioc) 	((u8 *)&(uioc).u_mbox)
+#define MBOX(uioc)	((megacmd_t *)&(uioc).u_mbox)
+#define MBOX_P(uioc) 	((megacmd_t *)&(uioc)->u_mbox)
+
 
 	u32		xferlen;	/* xferlen for DCMD and non-mbox
 					   commands */
@@ -1128,7 +1129,7 @@
 			      u32 *buffer, u32 *length);
 static inline int mega_busywait_mbox (adapter_t *);
 static int __mega_busywait_mbox (adapter_t *);
-static void mega_cmd_done(adapter_t *, u8 [], int, int);
+static inline void mega_cmd_done(adapter_t *, u8 [], int, int);
 static inline void mega_free_sgl (adapter_t *adapter);
 static void mega_8_to_40ld (mraid_inquiry *inquiry,
 		mega_inquiry3 *enquiry3, mega_product_info *);
@@ -1137,7 +1138,14 @@
 				   unsigned long, void *);
 static int megadev_open (struct inode *, struct file *);
 
-#if defined(__x86_64__)
+#if defined( __x86_64__) || defined(IA32_EMULATION)
+#ifndef __ia64__
+#define LSI_CONFIG_COMPAT
+#endif
+#endif
+
+
+#ifdef LSI_CONFIG_COMPAT
 static int megadev_compat_ioctl(unsigned int, unsigned int, unsigned long,
 	struct file *);
 #endif
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_nv.c linux-2.4.32-pre3/drivers/scsi/sata_nv.c
--- linux-2.4.32-pre2/drivers/scsi/sata_nv.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_nv.c	2005-08-08 20:06:12.398629286 -0700
@@ -329,6 +329,8 @@
 		host->host_desc->disable_hotplug(host_set);
 
 	kfree(host);
+
+	ata_host_stop(host_set);
 }
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_promise.c linux-2.4.32-pre3/drivers/scsi/sata_promise.c
--- linux-2.4.32-pre2/drivers/scsi/sata_promise.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_promise.c	2005-08-08 20:06:12.399629330 -0700
@@ -42,6 +42,7 @@
 #define DRV_NAME	"sata_promise"
 #define DRV_VERSION	"1.01"
 
+
 enum {
 	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
 	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
@@ -58,6 +59,7 @@
 
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
+	board_20619		= 2,	/* FastTrak TX4000 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
 
@@ -121,6 +123,7 @@
 	.scr_write		= pdc_sata_scr_write,
 	.port_start		= pdc_port_start,
 	.port_stop		= pdc_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info pdc_port_info[] = {
@@ -145,11 +148,24 @@
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_ata_ops,
 	},
+
+	/* board_20619 */
+	{
+		.sht		= &pdc_ata_sht,
+		.host_flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+				  ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_ata_ops,
+	},
 };
 
 static struct pci_device_id pdc_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -168,6 +184,9 @@
 	{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
 
+	{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20619 },
+
 	{ }	/* terminate list */
 };
 
@@ -629,6 +648,15 @@
 	case board_2037x:
        		probe_ent->n_ports = 2;
 		break;
+	case board_20619:
+		probe_ent->n_ports = 4;
+
+		pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+		pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+		probe_ent->port[2].scr_addr = base + 0x600;
+		probe_ent->port[3].scr_addr = base + 0x700;
+		break;
 	default:
 		BUG();
 		break;
@@ -684,7 +712,7 @@
 
 
 MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver");
+MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_qstor.c linux-2.4.32-pre3/drivers/scsi/sata_qstor.c
--- linux-2.4.32-pre2/drivers/scsi/sata_qstor.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_qstor.c	2005-08-08 20:06:12.399629330 -0700
@@ -537,6 +537,8 @@
 
 	writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
 	writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+
+	ata_host_stop(host_set);
 }
 
 static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_sil.c linux-2.4.32-pre3/drivers/scsi/sata_sil.c
--- linux-2.4.32-pre2/drivers/scsi/sata_sil.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_sil.c	2005-08-08 20:06:12.400629374 -0700
@@ -82,6 +82,7 @@
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
 	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ }	/* terminate list */
 };
 
@@ -160,6 +161,7 @@
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info sil_port_info[] = {
@@ -427,7 +429,13 @@
 		writeb(cls, mmio_base + SIL_FIFO_R0);
 		writeb(cls, mmio_base + SIL_FIFO_W0);
 		writeb(cls, mmio_base + SIL_FIFO_R1);
-		writeb(cls, mmio_base + SIL_FIFO_W2);
+		writeb(cls, mmio_base + SIL_FIFO_W1);
+		if (ent->driver_data == sil_3114) {
+			writeb(cls, mmio_base + SIL_FIFO_R2);
+			writeb(cls, mmio_base + SIL_FIFO_W2);
+			writeb(cls, mmio_base + SIL_FIFO_R3);
+			writeb(cls, mmio_base + SIL_FIFO_W3);
+		}
 	} else
 		printk(KERN_WARNING DRV_NAME "(%s): cache line size not set.  Driver may not function\n",
 			pci_name(pdev));
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_sis.c linux-2.4.32-pre3/drivers/scsi/sata_sis.c
--- linux-2.4.32-pre2/drivers/scsi/sata_sis.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_sis.c	2005-08-08 20:06:12.400629374 -0700
@@ -114,6 +114,7 @@
 	.scr_write		= sis_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info sis_port_info = {
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_svw.c linux-2.4.32-pre3/drivers/scsi/sata_svw.c
--- linux-2.4.32-pre2/drivers/scsi/sata_svw.c	2005-05-31 17:56:56.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_svw.c	2005-08-08 20:06:12.400629374 -0700
@@ -49,7 +49,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME	"sata_svw"
-#define DRV_VERSION	"1.05"
+#define DRV_VERSION	"1.06"
 
 /* Taskfile registers offsets */
 #define K2_SATA_TF_CMD_OFFSET		0x00
@@ -313,6 +313,7 @@
 	.scr_write		= k2_sata_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -343,6 +344,7 @@
 	void *mmio_base;
 	int pci_dev_busy = 0;
 	int rc;
+	int i;
 
 	if (!printed_version++)
 		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -417,11 +419,11 @@
 	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 
-	/* We have 4 ports per PCI function */
-	k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET);
+	/* different controllers have different number of ports - currently 4 or 8 */
+	/* All ports are on the same function. Multi-function device is no
+	 * longer available. This should not be seen in any system. */
+	for (i = 0; i < ent->driver_data; i++)
+		k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
 
 	pci_set_master(pdev);
 
@@ -439,11 +441,17 @@
 	return rc;
 }
 
-
+/* 0x240 is device ID for Apple K2 device
+ * 0x241 is device ID for Serverworks Frodo4
+ * 0x242 is device ID for Serverworks Frodo8
+ * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
+ * controller
+ * */
 static struct pci_device_id k2_sata_pci_tbl[] = {
-	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+	{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ }
 };
 
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_sx4.c linux-2.4.32-pre3/drivers/scsi/sata_sx4.c
--- linux-2.4.32-pre2/drivers/scsi/sata_sx4.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_sx4.c	2005-08-08 20:06:12.401629418 -0700
@@ -245,6 +245,8 @@
 
 	iounmap(dimm_mmio);
 	kfree(hpriv);
+
+	ata_host_stop(host_set);
 }
 
 static int pdc_port_start(struct ata_port *ap)
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_uli.c linux-2.4.32-pre3/drivers/scsi/sata_uli.c
--- linux-2.4.32-pre2/drivers/scsi/sata_uli.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_uli.c	2005-08-08 20:06:12.401629418 -0700
@@ -113,6 +113,7 @@
 
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info uli_port_info = {
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_via.c linux-2.4.32-pre3/drivers/scsi/sata_via.c
--- linux-2.4.32-pre2/drivers/scsi/sata_via.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_via.c	2005-08-08 20:06:12.402629462 -0700
@@ -134,6 +134,7 @@
 
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static struct ata_port_info svia_port_info = {
diff -urN linux-2.4.32-pre2/drivers/scsi/sata_vsc.c linux-2.4.32-pre3/drivers/scsi/sata_vsc.c
--- linux-2.4.32-pre2/drivers/scsi/sata_vsc.c	2005-04-03 18:42:19.000000000 -0700
+++ linux-2.4.32-pre3/drivers/scsi/sata_vsc.c	2005-08-08 20:06:12.402629462 -0700
@@ -230,6 +230,7 @@
 	.scr_write		= vsc_sata_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
 };
 
 static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
diff -urN linux-2.4.32-pre2/drivers/sound/i810_audio.c linux-2.4.32-pre3/drivers/sound/i810_audio.c
--- linux-2.4.32-pre2/drivers/sound/i810_audio.c	2004-11-17 03:54:21.000000000 -0800
+++ linux-2.4.32-pre3/drivers/sound/i810_audio.c	2005-08-08 20:06:12.405629594 -0700
@@ -458,12 +458,38 @@
 /* extract register offset from codec struct */
 #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
 
-#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN)
-#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN)
+#define I810_IOREAD(size, type, card, off)				\
+({									\
+	type val;							\
+	if (card->use_mmio)						\
+		val=read##size(card->iobase_mmio+off);			\
+	else								\
+		val=in##size(card->iobase+off);				\
+	val;								\
+})
+
+#define I810_IOREADL(card, off)		I810_IOREAD(l, u32, card, off)
+#define I810_IOREADW(card, off)		I810_IOREAD(w, u16, card, off)
+#define I810_IOREADB(card, off)		I810_IOREAD(b, u8,  card, off)
+
+#define I810_IOWRITE(size, val, card, off)				\
+({									\
+	if (card->use_mmio)						\
+		write##size(val, card->iobase_mmio+off);		\
+	else								\
+		out##size(val, card->iobase+off);			\
+})
+
+#define I810_IOWRITEL(val, card, off)	I810_IOWRITE(l, val, card, off)
+#define I810_IOWRITEW(val, card, off)	I810_IOWRITE(w, val, card, off)
+#define I810_IOWRITEB(val, card, off)	I810_IOWRITE(b, val, card, off)
+
+#define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN)
+#define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN)
 
 /* set LVI from CIV */
-#define CIV_TO_LVI(port, off) \
-	outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI)
+#define CIV_TO_LVI(card, port, off) \
+	I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI)
 
 static struct i810_card *devs = NULL;
 
@@ -722,9 +748,9 @@
 		return 0;
 
 	if (rec)
-		port = state->card->iobase + dmabuf->read_channel->port;
+		port = dmabuf->read_channel->port;
 	else
-		port = state->card->iobase + dmabuf->write_channel->port;
+		port = dmabuf->write_channel->port;
 
 	if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) {
 		port_picb = port + OFF_SR;
@@ -733,8 +759,8 @@
 		port_picb = port + OFF_PICB;
 
 	do {
-		civ = GET_CIV(port);
-		offset = inw(port_picb);
+		civ = GET_CIV(state->card, port);
+		offset = I810_IOREADW(state->card, port_picb);
 		/* Must have a delay here! */ 
 		if(offset == 0)
 			udelay(1);
@@ -753,7 +779,7 @@
 		 * that we won't have to worry about the chip still being
 		 * out of sync with reality ;-)
 		 */
-	} while (civ != GET_CIV(port) || offset != inw(port_picb));
+	} while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb));
 		 
 	return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
 		% dmabuf->dmasize);
@@ -766,15 +792,15 @@
 	struct i810_card *card = state->card;
 
 	dmabuf->enable &= ~ADC_RUNNING;
-	outb(0, card->iobase + PI_CR);
+	I810_IOWRITEB(0, card, PI_CR);
 	// wait for the card to acknowledge shutdown
-	while( inb(card->iobase + PI_CR) != 0 ) ;
+	while( I810_IOREADB(card, PI_CR) != 0 ) ;
 	// now clear any latent interrupt bits (like the halt bit)
 	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB );
+		I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB );
 	else
-		outb( inb(card->iobase + PI_SR), card->iobase + PI_SR );
-	outl( inl(card->iobase + GLOB_STA) & INT_PI, card->iobase + GLOB_STA);
+		I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR );
+	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA);
 }
 
 static void stop_adc(struct i810_state *state)
@@ -795,7 +821,7 @@
 	    (dmabuf->trigger & PCM_ENABLE_INPUT)) {
 		dmabuf->enable |= ADC_RUNNING;
 		// Interrupt enable, LVI enable, DMA enable
-		outb(0x10 | 0x04 | 0x01, state->card->iobase + PI_CR);
+		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR);
 	}
 }
 
@@ -816,15 +842,15 @@
 	struct i810_card *card = state->card;
 
 	dmabuf->enable &= ~DAC_RUNNING;
-	outb(0, card->iobase + PO_CR);
+	I810_IOWRITEB(0, card, PO_CR);
 	// wait for the card to acknowledge shutdown
-	while( inb(card->iobase + PO_CR) != 0 ) ;
+	while( I810_IOREADB(card, PO_CR) != 0 ) ;
 	// now clear any latent interrupt bits (like the halt bit)
 	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB );
+		I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB );
 	else
-		outb( inb(card->iobase + PO_SR), card->iobase + PO_SR );
-	outl( inl(card->iobase + GLOB_STA) & INT_PO, card->iobase + GLOB_STA);
+		I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR );
+	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA);
 }
 
 static void stop_dac(struct i810_state *state)
@@ -845,7 +871,7 @@
 	    (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
 		dmabuf->enable |= DAC_RUNNING;
 		// Interrupt enable, LVI enable, DMA enable
-		outb(0x10 | 0x04 | 0x01, state->card->iobase + PO_CR);
+		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR);
 	}
 }
 static void start_dac(struct i810_state *state)
@@ -1008,12 +1034,12 @@
 			sg++;
 		}
 		spin_lock_irqsave(&state->card->lock, flags);
-		outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
-		while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ;
-		outl((u32)state->card->chandma +
+		I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
+		while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ;
+		I810_IOWRITEL((u32)state->card->chandma +
 		    c->num*sizeof(struct i810_channel),
-		    state->card->iobase+c->port+OFF_BDBAR);
-		CIV_TO_LVI(state->card->iobase+c->port, 0);
+		    state->card, c->port+OFF_BDBAR);
+		CIV_TO_LVI(state->card, c->port, 0);
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
 
@@ -1045,14 +1071,13 @@
 	void (*start)(struct i810_state *);
 
 	count = dmabuf->count;
-	port = state->card->iobase;
 	if (rec) {
-		port += dmabuf->read_channel->port;
+		port = dmabuf->read_channel->port;
 		trigger = PCM_ENABLE_INPUT;
 		start = __start_adc;
 		count = dmabuf->dmasize - count;
 	} else {
-		port += dmabuf->write_channel->port;
+		port = dmabuf->write_channel->port;
 		trigger = PCM_ENABLE_OUTPUT;
 		start = __start_dac;
 	}
@@ -1062,19 +1087,32 @@
 	if (count < fragsize)
 		return;
 
+	/* if we are currently stopped, then our CIV is actually set to our
+	 * *last* sg segment and we are ready to wrap to the next.  However,
+	 * if we set our LVI to the last sg segment, then it won't wrap to
+	 * the next sg segment, it won't even get a start.  So, instead, when
+	 * we are stopped, we set both the LVI value and also we increment
+	 * the CIV value to the next sg segment to be played so that when
+	 * we call start, things will operate properly.  Since the CIV can't
+	 * be written to directly for this purpose, we set the LVI to CIV + 1
+	 * temporarily.  Once the engine has started we set the LVI to its
+	 * final value.
+	 */
 	if (!dmabuf->enable && dmabuf->ready) {
 		if (!(dmabuf->trigger & trigger))
 			return;
 
+		CIV_TO_LVI(state->card, port, 1);
+
 		start(state);
-		while (!(inb(port + OFF_CR) & ((1<<4) | (1<<2))))
+		while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2))))
 			;
 	}
 
 	/* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
 	x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
 	x >>= dmabuf->fragshift;
-	outb(x, port + OFF_LVI);
+	I810_IOWRITEB(x, state->card, port + OFF_LVI);
 }
 
 static void i810_update_lvi(struct i810_state *state, int rec)
@@ -1116,8 +1154,8 @@
 			/* this is normal for the end of a read */
 			/* only give an error if we went past the */
 			/* last valid sg entry */
-			if (GET_CIV(state->card->iobase + PI_BASE) !=
-			    GET_LVI(state->card->iobase + PI_BASE)) {
+			if (GET_CIV(state->card, PI_BASE) !=
+			    GET_LVI(state->card, PI_BASE)) {
 				printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
 				dmabuf->error++;
 			}
@@ -1141,13 +1179,13 @@
 			/* this is normal for the end of a write */
 			/* only give an error if we went past the */
 			/* last valid sg entry */
-			if (GET_CIV(state->card->iobase + PO_BASE) !=
-			    GET_LVI(state->card->iobase + PO_BASE)) {
+			if (GET_CIV(state->card, PO_BASE) !=
+			    GET_LVI(state->card, PO_BASE)) {
 				printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
 				printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
 					"count %d\n",
-					GET_CIV(state->card->iobase + PO_BASE),
-					GET_LVI(state->card->iobase + PO_BASE),
+					GET_CIV(state->card, PO_BASE),
+					GET_LVI(state->card, PO_BASE),
 					dmabuf->hwptr, dmabuf->count);
 				dmabuf->error++;
 			}
@@ -1295,7 +1333,7 @@
 		struct i810_state *state = card->states[i];
 		struct i810_channel *c;
 		struct dmabuf *dmabuf;
-		unsigned long port = card->iobase;
+		unsigned long port;
 		u16 status;
 		
 		if(!state)
@@ -1310,12 +1348,12 @@
 		} else	/* This can occur going from R/W to close */
 			continue;
 		
-		port+=c->port;
+		port = c->port;
 
 		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			status = inw(port + OFF_PICB);
+			status = I810_IOREADW(card, port + OFF_PICB);
 		else
-			status = inw(port + OFF_SR);
+			status = I810_IOREADW(card, port + OFF_SR);
 
 #ifdef DEBUG_INTERRUPTS
 		printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status);
@@ -1348,7 +1386,7 @@
 			if(dmabuf->enable & ADC_RUNNING)
 				count = dmabuf->dmasize - count;
 			if (count >= (int)dmabuf->fragsize) {
-				outb(inb(port+OFF_CR) | 1, port+OFF_CR);
+				I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR);
 #ifdef DEBUG_INTERRUPTS
 				printk(" CONTINUE ");
 #endif
@@ -1364,9 +1402,9 @@
 			}
 		}
 		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			outw(status & DMA_INT_MASK, port + OFF_PICB);
+			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB);
 		else
-			outw(status & DMA_INT_MASK, port + OFF_SR);
+			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR);
 	}
 #ifdef DEBUG_INTERRUPTS
 	printk(")\n");
@@ -1380,7 +1418,7 @@
 
 	spin_lock(&card->lock);
 
-	status = inl(card->iobase + GLOB_STA);
+	status = I810_IOREADL(card, GLOB_STA);
 
 	if(!(status & INT_MASK)) 
 	{
@@ -1392,7 +1430,7 @@
 		i810_channel_interrupt(card);
 
  	/* clear 'em */
-	outl(status & INT_MASK, card->iobase + GLOB_STA);
+	I810_IOWRITEL(status & INT_MASK, card, GLOB_STA);
 	spin_unlock(&card->lock);
 	return IRQ_HANDLED;
 }
@@ -1790,13 +1828,13 @@
 			__stop_adc(state);
 		}
 		if (c != NULL) {
-			outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
-			while ( inb(state->card->iobase+c->port+OFF_CR) & 2 )
+			I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
+			while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 )
 				cpu_relax();
-			outl((u32)state->card->chandma +
+			I810_IOWRITEL((u32)state->card->chandma +
 			    c->num*sizeof(struct i810_channel),
-			    state->card->iobase+c->port+OFF_BDBAR);
-			CIV_TO_LVI(state->card->iobase+c->port, 0);
+			    state->card, c->port+OFF_BDBAR);
+			CIV_TO_LVI(state->card, c->port, 0);
 		}
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1926,7 +1964,7 @@
 		/* Global Status and Global Control register are now  */
 		/* used to indicate this.                             */
 
-                i_glob_cnt = inl(state->card->iobase + GLOB_CNT);
+                i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT);
 
 		/* Current # of channels enabled */
 		if ( i_glob_cnt & 0x0100000 )
@@ -1938,14 +1976,14 @@
 
 		switch ( val ) {
 			case 2: /* 2 channels is always supported */
-				outl(i_glob_cnt & 0xffcfffff,
-				     state->card->iobase + GLOB_CNT);
+				I810_IOWRITEL(i_glob_cnt & 0xffcfffff,
+				     state->card, GLOB_CNT);
 				/* Do we need to change mixer settings????  */
 				break;
 			case 4: /* Supported on some chipsets, better check first */
 				if ( state->card->channels >= 4 ) {
-					outl((i_glob_cnt & 0xffcfffff) | 0x100000,
-					      state->card->iobase + GLOB_CNT);
+					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000,
+					      state->card, GLOB_CNT);
 					/* Do we need to change mixer settings??? */
 				} else {
 					val = ret;
@@ -1953,8 +1991,8 @@
 				break;
 			case 6: /* Supported on some chipsets, better check first */
 				if ( state->card->channels >= 6 ) {
-					outl((i_glob_cnt & 0xffcfffff) | 0x200000,
-					      state->card->iobase + GLOB_CNT);
+					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000,
+					      state->card, GLOB_CNT);
 					/* Do we need to change mixer settings??? */
 				} else {
 					val = ret;
@@ -2483,8 +2521,8 @@
 		} else {
 			i810_set_dac_rate(state, 8000);
 			/* Put the ACLink in 2 channel mode by default */
-			i = inl(card->iobase + GLOB_CNT);
-			outl(i & 0xffcfffff, card->iobase + GLOB_CNT);
+			i = I810_IOREADL(card, GLOB_CNT);
+			I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT);
 		}
 	}
 		
@@ -2575,7 +2613,7 @@
 	int count = 100;
 	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
-	while(count-- && (inb(card->iobase + CAS) & 1)) 
+	while(count-- && (I810_IOREADB(card, CAS) & 1))
 		udelay(1);
 	
 	return inw(card->ac97base + reg_set);
@@ -2603,7 +2641,7 @@
 	int count = 100;
 	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
-	while(count-- && (inb(card->iobase + CAS) & 1)) 
+	while(count-- && (I810_IOREADB(card, CAS) & 1))
 		udelay(1);
 	
         outw(data, card->ac97base + reg_set);
@@ -2692,7 +2730,7 @@
 
 static inline int i810_ac97_exists(struct i810_card *card, int ac97_number)
 {
-	u32 reg = inl(card->iobase + GLOB_STA);
+	u32 reg = I810_IOREADL(card, GLOB_STA);
 	switch (ac97_number) {
 	case 0:
 		return reg & (1<<8);
@@ -2763,7 +2801,7 @@
  
 static int i810_ac97_power_up_bus(struct i810_card *card)
 {	
-	u32 reg = inl(card->iobase + GLOB_CNT);
+	u32 reg = I810_IOREADL(card, GLOB_CNT);
 	int i;
 	int primary_codec_id = 0;
 
@@ -2775,14 +2813,14 @@
 	reg&=~8;	/* ACLink on */
 	
 	/* At this point we deassert AC_RESET # */
-	outl(reg , card->iobase + GLOB_CNT);
+	I810_IOWRITEL(reg , card, GLOB_CNT);
 
 	/* We must now allow time for the Codec initialisation.
 	   600mS is the specified time */
 	   	
 	for(i=0;i<10;i++)
 	{
-		if((inl(card->iobase+GLOB_CNT)&4)==0)
+		if((I810_IOREADL(card, GLOB_CNT)&4)==0)
 			break;
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -2801,8 +2839,11 @@
 	 *	See if the primary codec comes ready. This must happen
 	 *	before we start doing DMA stuff
 	 */	
-	/* see i810_ac97_init for the next 7 lines (jsaw) */
-	inw(card->ac97base);
+	/* see i810_ac97_init for the next 10 lines (jsaw) */
+	if (card->use_mmio)
+		readw(card->ac97base_mmio);
+	else
+		inw(card->ac97base);
 	if (ich_use_mmio(card)) {
 		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
@@ -2820,7 +2861,10 @@
 		else 
 			printk("no response.\n");
 	}
-	inw(card->ac97base);
+	if (card->use_mmio)
+		readw(card->ac97base_mmio);
+	else
+		inw(card->ac97base);
 	return 1;
 }
 
@@ -2845,15 +2889,15 @@
 	/* to check....                                         */
 
 	card->channels = 2;
-	reg = inl(card->iobase + GLOB_STA);
+	reg = I810_IOREADL(card, GLOB_STA);
 	if ( reg & 0x0200000 )
 		card->channels = 6;
 	else if ( reg & 0x0100000 )
 		card->channels = 4;
 	printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels);
 	printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n");
-	reg = inl(card->iobase + GLOB_CNT);
-	outl(reg & 0xffcfffff, card->iobase + GLOB_CNT);
+	reg = I810_IOREADL(card, GLOB_CNT);
+	I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT);
 		
 	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) 
 		card->ac97_codec[num_ac97] = NULL;
@@ -2864,8 +2908,10 @@
 	for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
 		/* codec reset */
 		printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
-		if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97);
-		else inw(card->ac97base + 0x80*num_ac97);
+		if (card->use_mmio)
+			readw(card->ac97base_mmio + 0x80*num_ac97);
+		else
+			inw(card->ac97base + 0x80*num_ac97);
 
 		/* If we have the SDATA_IN Map Register, as on ICH4, we
 		   do not loop thru all possible codec IDs but thru all 
@@ -3068,7 +3114,7 @@
 			goto config_out;
 		}
 		dmabuf->count = dmabuf->dmasize;
-		CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
+		CIV_TO_LVI(card, dmabuf->write_channel->port, -1);
 		local_irq_save(flags);
 		start_dac(state);
 		offset = i810_get_dma_addr(state, 0);
@@ -3112,13 +3158,6 @@
 		return -ENODEV;
 	}
 	
-	if( pci_resource_start(pci_dev, 1) == 0)
-	{
-		/* MMIO only ICH5 .. here be dragons .. */
-		printk(KERN_ERR "i810_audio: Pure MMIO interfaces not yet supported.\n");
-		return -ENODEV;
-	}
-
 	if ((card = kmalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "i810_audio: out of memory\n");
 		return -ENOMEM;
@@ -3131,6 +3170,11 @@
 	card->ac97base = pci_resource_start (pci_dev, 0);
 	card->iobase = pci_resource_start (pci_dev, 1);
 
+	if (!(card->ac97base) || !(card->iobase)) {
+		card->ac97base = 0;
+		card->iobase = 0;
+	}
+
 	/* if chipset could have mmio capability, check it */ 
 	if (card_cap[pci_id->driver_data].flags & CAP_MMIO) {
 		card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2);
@@ -3145,6 +3189,11 @@
 		}
 	}
 
+	if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) {
+		printk(KERN_ERR "i810_audio: No I/O resources available.\n");
+		goto out_mem;
+	}
+
 	card->irq = pci_dev->irq;
 	card->next = devs;
 	card->magic = I810_CARD_MAGIC;
@@ -3190,8 +3239,14 @@
 	}
 
 	/* claim our iospace and irq */
-	request_region(card->iobase, 64, card_names[pci_id->driver_data]);
-	request_region(card->ac97base, 256, card_names[pci_id->driver_data]);
+	if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
+		goto out_region1;
+	}
+	if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
+		goto out_region2;
+	}
 
 	if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
 			card_names[pci_id->driver_data], card)) {
@@ -3264,8 +3319,10 @@
 		release_mem_region(card->iobase_mmio_phys, 256);
 	}
 out_pio:	
-	release_region(card->iobase, 64);
 	release_region(card->ac97base, 256);
+out_region2:
+	release_region(card->iobase, 64);
+out_region1:
 	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
 	    card->channel, card->chandma);
 out_mem:
diff -urN linux-2.4.32-pre2/drivers/usb/host/uhci.c linux-2.4.32-pre3/drivers/usb/host/uhci.c
--- linux-2.4.32-pre2/drivers/usb/host/uhci.c	2005-08-08 20:06:10.586549516 -0700
+++ linux-2.4.32-pre3/drivers/usb/host/uhci.c	2003-06-13 07:51:36.000000000 -0700
@@ -2924,7 +2924,7 @@
 		}
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = uhci->skeltd[irq]->dma_handle | UHCI_PTR_QH;
+		uhci->fl->frame[i] =  uhci->skeltd[irq]->dma_handle;
 	}
 
 	start_hc(uhci);
diff -urN linux-2.4.32-pre2/fs/isofs/compress.c linux-2.4.32-pre3/fs/isofs/compress.c
--- linux-2.4.32-pre2/fs/isofs/compress.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.32-pre3/fs/isofs/compress.c	2005-08-08 20:06:12.414629990 -0700
@@ -147,8 +147,14 @@
 	cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
 	brelse(bh);
 
+	if (cstart > cend)
+		goto eio;
+
 	csize = cend-cstart;
 
+	if (csize > deflateBound(1UL << zisofs_block_shift))
+		goto eio;
+
 	/* Now page[] contains an array of pages, any of which can be NULL,
 	   and the locks on which we hold.  We should now read the data and
 	   release the pages.  If the pages are NULL the decompressed data
diff -urN linux-2.4.32-pre2/include/linux/ata.h linux-2.4.32-pre3/include/linux/ata.h
--- linux-2.4.32-pre2/include/linux/ata.h	2005-04-03 18:42:20.000000000 -0700
+++ linux-2.4.32-pre3/include/linux/ata.h	2005-08-08 20:06:12.416630078 -0700
@@ -224,6 +224,7 @@
 };
 
 #define ata_id_is_ata(id)	(((id)[0] & (1 << 15)) == 0)
+#define ata_id_is_sata(id)	((id)[93] == 0)
 #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
 #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
 #define ata_id_has_flush(id) ((id)[83] & (1 << 12))
diff -urN linux-2.4.32-pre2/include/linux/libata-compat.h linux-2.4.32-pre3/include/linux/libata-compat.h
--- linux-2.4.32-pre2/include/linux/libata-compat.h	2005-04-03 18:42:20.000000000 -0700
+++ linux-2.4.32-pre3/include/linux/libata-compat.h	2005-08-08 20:06:12.416630078 -0700
@@ -23,6 +23,9 @@
 	return (struct pci_dev *) dev;
 }
 
+static inline int pci_enable_msi(struct pci_dev *dev) { return -1; }
+static inline void pci_disable_msi(struct pci_dev *dev) {}
+
 #define pci_set_consistent_dma_mask(pdev,mask) (0)
 
 #define DMA_FROM_DEVICE PCI_DMA_FROMDEVICE
diff -urN linux-2.4.32-pre2/include/linux/libata.h linux-2.4.32-pre3/include/linux/libata.h
--- linux-2.4.32-pre2/include/linux/libata.h	2005-04-03 18:42:20.000000000 -0700
+++ linux-2.4.32-pre3/include/linux/libata.h	2005-08-08 20:06:12.417630122 -0700
@@ -411,6 +411,7 @@
 extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
+extern void ata_host_stop (struct ata_host_set *host_set);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -421,6 +422,7 @@
 extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
 extern void ata_dev_id_string(u16 *id, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
+extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_port *ap);
@@ -465,12 +467,34 @@
 	return ap->ops->check_status(ap);
 }
 
+
+/**
+ *	ata_pause - Flush writes and pause 400 nanoseconds.
+ *	@ap: Port to wait for.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static inline void ata_pause(struct ata_port *ap)
 {
 	ata_altstatus(ap);
 	ndelay(400);
 }
 
+
+/**
+ *	ata_busy_wait - Wait for a port status register
+ *	@ap: Port to wait for.
+ *
+ *	Waits up to max*10 microseconds for the selected bits in the port's
+ *	status register to be cleared.
+ *	Returns final value of status register.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
 			       unsigned int max)
 {
@@ -485,6 +509,18 @@
 	return status;
 }
 
+
+/**
+ *	ata_wait_idle - Wait for a port to be idle.
+ *	@ap: Port to wait for.
+ *
+ *	Waits up to 10ms for port's BUSY and DRQ signals to clear.
+ *	Returns final value of status register.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static inline u8 ata_wait_idle(struct ata_port *ap)
 {
 	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
@@ -523,6 +559,18 @@
 		tf->device = ATA_DEVICE_OBS | ATA_DEV1;
 }
 
+
+/**
+ *	ata_irq_on - Enable interrupts on a port.
+ *	@ap: Port on which interrupts are enabled.
+ *
+ *	Enable interrupts on a legacy IDE device using MMIO or PIO,
+ *	wait for idle, clear any pending interrupts.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
 static inline u8 ata_irq_on(struct ata_port *ap)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -542,6 +590,18 @@
 	return tmp;
 }
 
+
+/**
+ *	ata_irq_ack - Acknowledge a device interrupt.
+ *	@ap: Port on which interrupts are enabled.
+ *
+ *	Wait up to 10 ms for legacy IDE device to become idle (BUSY
+ *	or BUSY+DRQ clear).  Obtain dma status and port status from
+ *	device.  Clear the interrupt.  Return port status.
+ *
+ *	LOCKING:
+ */
+
 static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
 {
 	unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
@@ -583,6 +643,13 @@
 	ap->ops->scr_write(ap, reg, val);
 }
 
+static inline void scr_write_flush(struct ata_port *ap, unsigned int reg, 
+				   u32 val)
+{
+	ap->ops->scr_write(ap, reg, val);
+	(void) ap->ops->scr_read(ap, reg);
+}
+
 static inline unsigned int sata_dev_present(struct ata_port *ap)
 {
 	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
diff -urN linux-2.4.32-pre2/include/linux/netfilter_ipv4/ip_tables.h linux-2.4.32-pre3/include/linux/netfilter_ipv4/ip_tables.h
--- linux-2.4.32-pre2/include/linux/netfilter_ipv4/ip_tables.h	2005-04-03 18:42:20.000000000 -0700
+++ linux-2.4.32-pre3/include/linux/netfilter_ipv4/ip_tables.h	2005-08-08 20:06:12.417630122 -0700
@@ -283,8 +283,6 @@
 	struct ipt_entry entrytable[0];
 };
 
-extern struct semaphore ipt_mutex;
-
 /* Standard return verdict, or do jump. */
 #define IPT_STANDARD_TARGET ""
 /* Error verdict. */
diff -urN linux-2.4.32-pre2/include/linux/zlib.h linux-2.4.32-pre3/include/linux/zlib.h
--- linux-2.4.32-pre2/include/linux/zlib.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.32-pre3/include/linux/zlib.h	2005-08-08 20:06:12.418630166 -0700
@@ -516,6 +516,11 @@
    stream state was inconsistent (such as zalloc or state being NULL).
 */
 
+static inline unsigned long deflateBound(unsigned long s)
+{
+	return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
+}
+
 ZEXTERN int ZEXPORT zlib_deflateParams OF((z_streamp strm,
 					      int level,
 					      int strategy));
diff -urN linux-2.4.32-pre2/lib/rbtree.c linux-2.4.32-pre3/lib/rbtree.c
--- linux-2.4.32-pre2/lib/rbtree.c	2004-11-17 03:54:22.000000000 -0800
+++ linux-2.4.32-pre3/lib/rbtree.c	2005-08-08 20:06:12.419630210 -0700
@@ -332,6 +332,7 @@
 		node = node->rb_right;
 		while (node->rb_left)
 			node = node->rb_left;
+		return node;
 	}
 
 	/* No right-hand children.  Everything down and left is
@@ -355,6 +356,7 @@
 		node = node->rb_left;
 		while (node->rb_right)
 			node = node->rb_right;	 
+		return node;
 	}
 
 	/* No left-hand children. Go up till we find an ancestor which
diff -urN linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_icmp.c linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_icmp.c
--- linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_icmp.c	2000-03-17 10:56:20.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_icmp.c	2005-08-08 20:06:12.422630342 -0700
@@ -26,16 +26,17 @@
 		  const struct ip_conntrack *conntrack)
 {
 	static u_int16_t id = 0;
-	unsigned int range_size
-		= (unsigned int)range->max.icmp.id - range->min.icmp.id + 1;
+	unsigned int range_size;
 	unsigned int i;
 
+	range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
 	/* If no range specified... */
 	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))
 		range_size = 0xFFFF;
 
 	for (i = 0; i < range_size; i++, id++) {
-		tuple->src.u.icmp.id = range->min.icmp.id + (id % range_size);
+		tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
+		                             (id % range_size));
 		if (!ip_nat_used_tuple(tuple, conntrack))
 			return 1;
 	}
diff -urN linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_tcp.c
--- linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_tcp.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_tcp.c	2005-08-08 20:06:12.422630342 -0700
@@ -31,7 +31,8 @@
 		 enum ip_nat_manip_type maniptype,
 		 const struct ip_conntrack *conntrack)
 {
-	static u_int16_t port = 0, *portptr;
+	static u_int16_t port = 0;
+	u_int16_t *portptr;
 	unsigned int range_size, min, i;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
diff -urN linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_udp.c
--- linux-2.4.32-pre2/net/ipv4/netfilter/ip_nat_proto_udp.c	2000-08-04 13:07:24.000000000 -0700
+++ linux-2.4.32-pre3/net/ipv4/netfilter/ip_nat_proto_udp.c	2005-08-08 20:06:12.422630342 -0700
@@ -32,7 +32,8 @@
 		 enum ip_nat_manip_type maniptype,
 		 const struct ip_conntrack *conntrack)
 {
-	static u_int16_t port = 0, *portptr;
+	static u_int16_t port = 0;
+	u_int16_t *portptr;
 	unsigned int range_size, min, i;
 
 	if (maniptype == IP_NAT_MANIP_SRC)
diff -urN linux-2.4.32-pre2/net/ipv4/netfilter/ip_queue.c linux-2.4.32-pre3/net/ipv4/netfilter/ip_queue.c
--- linux-2.4.32-pre2/net/ipv4/netfilter/ip_queue.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv4/netfilter/ip_queue.c	2005-08-08 20:06:12.423630386 -0700
@@ -62,7 +62,9 @@
 static void
 ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
 {
+	local_bh_disable();
 	nf_reinject(entry->skb, entry->info, verdict);
+	local_bh_enable();
 	kfree(entry);
 }
 
diff -urN linux-2.4.32-pre2/net/ipv4/netfilter/ipt_unclean.c linux-2.4.32-pre3/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.32-pre2/net/ipv4/netfilter/ipt_unclean.c	2004-08-07 16:26:06.000000000 -0700
+++ linux-2.4.32-pre3/net/ipv4/netfilter/ipt_unclean.c	2005-08-08 20:06:12.423630386 -0700
@@ -264,6 +264,7 @@
 {
 	[TH_SYN]			= 1,
 	[TH_SYN|TH_ACK]			= 1,
+	[TH_SYN|TH_ACK|TH_PUSH]		= 1,
 	[TH_RST]			= 1,
 	[TH_RST|TH_ACK]			= 1,
 	[TH_RST|TH_ACK|TH_PUSH]		= 1,
diff -urN linux-2.4.32-pre2/net/ipv6/mcast.c linux-2.4.32-pre3/net/ipv6/mcast.c
--- linux-2.4.32-pre2/net/ipv6/mcast.c	2005-01-19 06:10:14.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv6/mcast.c	2005-08-08 20:06:12.424630430 -0700
@@ -1243,15 +1243,6 @@
 		return 0;
 
 	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-	if (dev->hard_header) {
-		unsigned char ha[MAX_ADDR_LEN];
-
-		ndisc_mc_map(&mld2_all_mcr, ha, dev, 1);
-		if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) {
-			kfree_skb(skb);
-			return 0;
-		}
-	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-02.txt>:
@@ -1275,6 +1266,30 @@
 	return skb;
 }
 
+static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+
+	if (dev->hard_header) {
+		unsigned char ha[MAX_ADDR_LEN];
+		int err;
+
+		ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1);
+		err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len);
+		if (err < 0) {
+			kfree_skb(skb);
+			return err;
+		}
+	}
+	return dev_queue_xmit(skb);
+}
+
+static inline int mld_dev_queue_xmit(struct sk_buff *skb)
+{
+	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev,
+	               mld_dev_queue_xmit2);
+}
+
 static void mld_sendpack(struct sk_buff *skb)
 {
 	struct ipv6hdr *pip6 = skb->nh.ipv6h;
@@ -1289,7 +1304,7 @@
 	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
 		IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
-		      dev_queue_xmit);
+		      mld_dev_queue_xmit);
 	if (!err)
 		ICMP6_INC_STATS(Icmp6OutMsgs);
 }
@@ -1585,12 +1600,6 @@
 		return;
 
 	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-	if (dev->hard_header) {
-		unsigned char ha[MAX_ADDR_LEN];
-		ndisc_mc_map(snd_addr, ha, dev, 1);
-		if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)
-			goto out;
-	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-02.txt>:
@@ -1616,7 +1625,7 @@
 					   csum_partial((__u8 *) hdr, len, 0));
 
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
-		      dev_queue_xmit);
+		      mld_dev_queue_xmit);
 	if (!err) {
 		if (type == ICMPV6_MGM_REDUCTION)
 			ICMP6_INC_STATS(Icmp6OutGroupMembReductions);
@@ -1626,9 +1635,6 @@
 	}
 
 	return;
-
-out:
-	kfree_skb(skb);
 }
 
 static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
diff -urN linux-2.4.32-pre2/net/ipv6/netfilter/ip6_queue.c linux-2.4.32-pre3/net/ipv6/netfilter/ip6_queue.c
--- linux-2.4.32-pre2/net/ipv6/netfilter/ip6_queue.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv6/netfilter/ip6_queue.c	2005-08-08 20:06:12.425630474 -0700
@@ -68,7 +68,9 @@
 static void
 ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
 {
+	local_bh_disable();
 	nf_reinject(entry->skb, entry->info, verdict);
+	local_bh_enable();
 	kfree(entry);
 }
 
diff -urN linux-2.4.32-pre2/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.32-pre3/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.4.32-pre2/net/ipv6/netfilter/ip6t_LOG.c	2005-01-19 06:10:14.000000000 -0800
+++ linux-2.4.32-pre3/net/ipv6/netfilter/ip6t_LOG.c	2005-08-08 20:06:12.425630474 -0700
@@ -363,7 +363,6 @@
 		const void *targinfo,
 		void *userinfo)
 {
-	struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
 	const struct ip6t_log_info *loginfo = targinfo;
 	char level_string[4] = "< >";
 
@@ -375,41 +374,32 @@
 		in ? in->name : "",
 		out ? out->name : "");
 	if (in && !out) {
+		unsigned int len;
 		/* MAC logging for input chain only. */
 		printk("MAC=");
-		if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
-			if ((*pskb)->dev->type != ARPHRD_SIT){
-			  int i;
-			  unsigned char *p = (*pskb)->mac.raw;
-			  for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
-				printk("%02x%c", *p,
-			       		i==(*pskb)->dev->hard_header_len - 1
-			       		? ' ':':');
-			} else {
-			  int i;
-			  unsigned char *p = (*pskb)->mac.raw;
-			  if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
-			    p -= (ETH_ALEN+2);
-			    for (i = 0; i < (ETH_ALEN); i++,p++)
-				printk("%02x%s", *p,
-					i == ETH_ALEN-1 ? "->" : ":");
-			    p -= (ETH_ALEN*2);
-			    for (i = 0; i < (ETH_ALEN); i++,p++)
-				printk("%02x%c", *p,
-					i == ETH_ALEN-1 ? ' ' : ':');
-			  }
-			  
-			  if (((*pskb)->dev->addr_len == 4) &&
-			      (*pskb)->dev->hard_header_len > 20){
-			    printk("TUNNEL=");
-			    p = (*pskb)->mac.raw + 12;
-			    for (i = 0; i < 4; i++,p++)
-				printk("%3d%s", *p,
-					i == 3 ? "->" : ".");
-			    for (i = 0; i < 4; i++,p++)
-				printk("%3d%c", *p,
-					i == 3 ? ' ' : '.');
-			  }
+		if ((*pskb)->dev && (len = (*pskb)->dev->hard_header_len) &&
+		    (*pskb)->mac.raw != (*pskb)->nh.raw) {
+			unsigned char *p = (*pskb)->mac.raw;
+			int i;
+
+			if ((*pskb)->dev->type == ARPHRD_SIT &&
+			    (p -= ETH_HLEN) < (*pskb)->head)
+				p = NULL;
+
+			if (p != NULL) {
+				for (i = 0; i < len; i++)
+					printk("%02x%s", p[i],
+					       i == len - 1 ? "" : ":");
+			}
+			printk(" ");
+
+			if ((*pskb)->dev->type == ARPHRD_SIT) {
+				struct iphdr *iph;
+				
+				iph = (struct iphdr *)(*pskb)->mac.raw;
+				printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
+				       NIPQUAD(iph->saddr),
+				       NIPQUAD(iph->daddr));
 			}
 		} else
 			printk(" ");
