diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/CREDITS 001-linus.patch/CREDITS
--- 000-virgin/CREDITS	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/CREDITS	Tue Dec 30 16:38:56 2003
@@ -2669,6 +2669,13 @@ S: Kasarmikatu 11 A4
 S: 70110 Kuopio
 S: Finland
 
+N: Luca Risolia
+E: luca_ing@libero.it
+D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chip
+S: Via LibertÃ  41/a
+S: Osio Sotto, 24046, Bergamo
+S: Italy
+
 N: William E. Roadcap
 E: roadcapw@cfw.com
 W: http://www.cfw.com/~roadcapw
@@ -3569,4 +3576,4 @@ S: France
 # alphabetically. Leonard used to be very proud of being the 
 # last entry, and he'll get positively pissed if he can't even
 # be second-to-last.  (and this file really _is_ supposed to be
-# in alphabetic order) 
+# in alphabetic order)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/MAINTAINERS 001-linus.patch/MAINTAINERS
--- 000-virgin/MAINTAINERS	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/MAINTAINERS	Tue Dec 30 16:38:56 2003
@@ -73,7 +73,7 @@ S: Status, one of the following:
 3C359 NETWORK DRIVER
 P:	Mike Phillips
 M:	mikep@linuxtr.net
-L:	linux-net@vger.rutgers.edu
+L:	linux-net@vger.kernel.org
 L:	linux-tr@linuxtr.net
 W:	http://www.linuxtr.net
 S:	Maintained
@@ -929,8 +929,9 @@ W:	http://www.linuxia64.org/
 S:	Maintained
 
 SN-IA64 (Itanium) SUB-PLATFORM
-P:	John Hesterberg
-M:	jh@sgi.com
+P:	Jesse Barnes
+M:	jbarnes@sgi.com
+L:	linux-altix@sgi.com
 L:	linux-ia64@linuxia64.org
 W:	http://www.sgi.com/altix
 S:	Maintained
@@ -1468,7 +1469,7 @@ ONSTREAM SCSI TAPE DRIVER
 P:	Willem Riede
 M:	osst@riede.org
 L:	osst@linux1.onstream.nl
-L:	linux-scsi@vger.rutgers.edu
+L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
 OPL3-SA2, SA3, and SAx DRIVER
@@ -1852,8 +1853,10 @@ L:	ultralinux@vger.kernel.org
 S:	Maintained
 
 SPARC (sparc32):
+P:	Keith M. Wesolowski
+M:	wesolows@foobazco.org
 L:	sparclinux@vger.kernel.org
-S:	Unmaintained - please send patches to mailing list
+S:	Maintained
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
 P:	Roger Wolff
@@ -2218,6 +2221,13 @@ M:	dbrownell@users.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB W996[87]CF DRIVER
+P:	Luca Risolia
+M:	luca_ing@libero.it
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://go.lamarinapunto.com
+S:	Maintained
+
 USER-MODE LINUX
 P:	Jeff Dike
 M:	jdike@karaya.com
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/Makefile 001-linus.patch/Makefile
--- 000-virgin/Makefile	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/Makefile	Tue Dec 30 16:38:56 2003
@@ -275,7 +275,7 @@ NOSTDINC_FLAGS  = -nostdinc -iwithprefix
 CPPFLAGS        := -D__KERNEL__ -Iinclude \
 		   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
 
-CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
+CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
 	  	   -fno-strict-aliasing -fno-common
 AFLAGS		:= -D__ASSEMBLY__
 
@@ -431,6 +431,12 @@ libs-y		:= $(libs-y1) $(libs-y2)
 # ---------------------------------------------------------------------------
 
 
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+CFLAGS		+= -Os
+else
+CFLAGS		+= -O2
+endif
+
 ifndef CONFIG_FRAME_POINTER
 CFLAGS		+= -fomit-frame-pointer
 endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/alpha/kernel/irq.c 001-linus.patch/arch/alpha/kernel/irq.c
--- 000-virgin/arch/alpha/kernel/irq.c	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/arch/alpha/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -252,9 +252,11 @@ static int
 irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%016lx\n", irq_affinity[(long)data]);
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static unsigned int
@@ -331,10 +333,11 @@ static int
 prof_cpu_mask_read_proc(char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	unsigned long *mask = (unsigned long *) data;
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%016lx\n", *mask);
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static int
@@ -529,19 +532,21 @@ show_interrupts(struct seq_file *p, void
 #ifdef CONFIG_SMP
 	int j;
 #endif
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 
 #ifdef CONFIG_SMP
-	seq_puts(p, "           ");
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i))
-			seq_printf(p, "CPU%d       ", i);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i))
+				seq_printf(p, "CPU%d       ", i);
+		seq_putc(p, '\n');
+	}
 #endif
 
-	for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+	if (i < ACTUAL_NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
@@ -568,15 +573,16 @@ show_interrupts(struct seq_file *p, void
 		seq_putc(p, '\n');
 unlock:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
+	} else if (i == ACTUAL_NR_IRQS) {
 #ifdef CONFIG_SMP
-	seq_puts(p, "IPI: ");
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i))
-			seq_printf(p, "%10lu ", cpu_data[i].ipi_count);
-	seq_putc(p, '\n');
+		seq_puts(p, "IPI: ");
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i))
+				seq_printf(p, "%10lu ", cpu_data[i].ipi_count);
+		seq_putc(p, '\n');
 #endif
-	seq_printf(p, "ERR: %10lu\n", irq_err_count);
+		seq_printf(p, "ERR: %10lu\n", irq_err_count);
+	}
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/Makefile 001-linus.patch/arch/arm/Makefile
--- 000-virgin/arch/arm/Makefile	Wed Dec 17 18:58:41 2003
+++ 001-linus.patch/arch/arm/Makefile	Tue Dec 30 16:38:56 2003
@@ -14,8 +14,6 @@ OBJCOPYFLAGS	:=-O binary -R .note -R .co
 GZFLAGS		:=-9
 #CFLAGS		+=-pipe
 
-CFLAGS		:=$(CFLAGS:-O2=-Os)
-
 ifeq ($(CONFIG_FRAME_POINTER),y)
 CFLAGS		+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
 endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/boot/compressed/Makefile 001-linus.patch/arch/arm/boot/compressed/Makefile
--- 000-virgin/arch/arm/boot/compressed/Makefile	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/arch/arm/boot/compressed/Makefile	Tue Dec 30 16:38:56 2003
@@ -23,10 +23,6 @@ ifeq ($(CONFIG_ARCH_SHARK),y)
 OBJS		+= head-shark.o ofw-shark.o
 endif
 
-ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
-OBJS		+= head-integrator.o
-endif
-
 ifeq ($(CONFIG_ARCH_CAMELOT),y)
 OBJS		+= head-epxa10db.o
 endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/boot/compressed/head-integrator.S 001-linus.patch/arch/arm/boot/compressed/head-integrator.S
--- 000-virgin/arch/arm/boot/compressed/head-integrator.S	Wed Dec 17 18:59:04 2003
+++ 001-linus.patch/arch/arm/boot/compressed/head-integrator.S	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#include <asm/mach-types.h>
-
-		.section	".start", "ax"
-		mov	r7, #MACH_TYPE_INTEGRATOR
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/boot/compressed/head.S 001-linus.patch/arch/arm/boot/compressed/head.S
--- 000-virgin/arch/arm/boot/compressed/head.S	Wed Dec 17 18:59:36 2003
+++ 001-linus.patch/arch/arm/boot/compressed/head.S	Tue Dec 30 16:38:56 2003
@@ -503,12 +503,6 @@ proc_types:
 
 		@ Everything from here on will be the new ID system.
 
-		.word	0x41129200		@ ARM920T
-		.word	0xff00fff0
-		b	__armv4_cache_on
-		b	__armv4_cache_off
-		b	__armv4_cache_flush
-
 		.word	0x4401a100		@ sa110 / sa1100
 		.word	0xffffffe0
 		b	__armv4_cache_on
@@ -523,6 +517,12 @@ proc_types:
 
 		@ These match on the architecture ID
 
+		.word	0x00020000		@ ARMv4T
+		.word	0x000f0000
+		b	__armv4_cache_on
+		b	__armv4_cache_off
+		b	__armv4_cache_flush
+
 		.word	0x00050000		@ ARMv5TE
 		.word	0x000f0000
 		b	__armv4_cache_on
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/common/sa1111.c 001-linus.patch/arch/arm/common/sa1111.c
--- 000-virgin/arch/arm/common/sa1111.c	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/arch/arm/common/sa1111.c	Tue Dec 30 16:38:56 2003
@@ -34,6 +34,8 @@
 
 #include <asm/hardware/sa1111.h>
 
+extern void __init sa1110_mb_enable(void);
+
 /*
  * We keep the following data for the overall SA1111.  Note that the
  * struct device and struct resource are "fake"; they should be supplied
@@ -561,6 +563,8 @@ sa1111_init_one_child(struct sa1111 *sac
 	dev->res.name    = dev->dev.bus_id;
 	dev->res.flags   = IORESOURCE_MEM;
 	dev->mapbase     = sachip->base + info->offset;
+	dev->skpcr_mask  = info->skpcr_mask;
+	memmove(dev->irq, info->irq, sizeof(dev->irq));
 
 	ret = request_resource(parent, &dev->res);
 	if (ret) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/configs/netwinder_defconfig 001-linus.patch/arch/arm/configs/netwinder_defconfig
--- 000-virgin/arch/arm/configs/netwinder_defconfig	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/arm/configs/netwinder_defconfig	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,968 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ADIFCC is not set
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+CONFIG_ARCH_FOOTBRIDGE=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+
+#
+# Epxa10db
+#
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+CONFIG_ARCH_NETWINDER=y
+
+#
+# IOP3xx Implementation Options
+#
+# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IOP321 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Intel PXA250/210 Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+CONFIG_FOOTBRIDGE=y
+CONFIG_FOOTBRIDGE_HOST=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_SA110=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WB=y
+
+#
+# Processor Features
+#
+
+#
+# General setup
+#
+CONFIG_PCI=y
+CONFIG_ISA=y
+CONFIG_ISA_DMA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=0x301"
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+CONFIG_PARPORT_PC_SUPERIO=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_FTP=y
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_QUEUE=y
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
+# CONFIG_IP_NF_MATCH_HELPER is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_IDEDMA_PCI_WIP is not set
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_TSLIBDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2_SYNAPTICS is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_DZ is not set
+# CONFIG_SERIAL_21285 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_21285_WATCHDOG is not set
+CONFIG_977_WATCHDOG=y
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_SCx200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_MACHZ_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_AMD7XX_TCO is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_ALIM1535_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_WAFER_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_DS1620=y
+CONFIG_NWBUTTON=y
+CONFIG_NWBUTTON_REBOOT=y
+CONFIG_NWFLASH=y
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SMB_NLS=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=y
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_AD1889 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_MAUI is not set
+CONFIG_SOUND_YM3812=y
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_WAVEARTIST=y
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+# CONFIG_MCP is not set
+
+#
+# Console Switches
+#
+# CONFIG_SWITCHES is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/configs/shark_defconfig 001-linus.patch/arch/arm/configs/shark_defconfig
--- 000-virgin/arch/arm/configs/shark_defconfig	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/arm/configs/shark_defconfig	Tue Dec 30 16:38:56 2003
@@ -10,6 +10,10 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+# CONFIG_STANDALONE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
@@ -19,6 +23,14 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
 
 #
 # Loadable module support
@@ -35,7 +47,6 @@ CONFIG_KMOD=y
 #
 # CONFIG_ARCH_ADIFCC is not set
 # CONFIG_ARCH_ANAKIN is not set
-# CONFIG_ARCH_ARCA5K is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
@@ -44,21 +55,13 @@ CONFIG_KMOD=y
 # CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 CONFIG_ARCH_SHARK=y
 
 #
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-
-#
 # CLPS711X/EP721X Implementations
 #
 
@@ -71,11 +74,13 @@ CONFIG_ARCH_SHARK=y
 #
 
 #
-# IOP310 Implementation Options
+# IOP3xx Implementation Options
 #
+# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IOP321 is not set
 
 #
-# IOP310 Chipset Features
+# IOP3xx Chipset Features
 #
 
 #
@@ -92,6 +97,10 @@ CONFIG_ARCH_SHARK=y
 CONFIG_CPU_32=y
 CONFIG_CPU_SA110=y
 CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WB=y
 
 #
 # Processor Features
@@ -116,11 +125,13 @@ CONFIG_PCI_LEGACY_PROC=y
 #
 # CONFIG_FPE_NWFPE is not set
 CONFIG_FPE_FASTFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
 # CONFIG_PM is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ARTHUR is not set
@@ -164,6 +175,7 @@ CONFIG_PARPORT_PC_CML1=y
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -185,7 +197,6 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -199,8 +210,11 @@ CONFIG_INET=y
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
 # CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -209,9 +223,9 @@ CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -239,13 +253,13 @@ CONFIG_NETDEVICES=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
+# CONFIG_SMC91X is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -294,8 +308,14 @@ CONFIG_CS89x0=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
@@ -306,10 +326,12 @@ CONFIG_CS89x0=y
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_HOSTAP is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
+# CONFIG_TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -320,47 +342,54 @@ CONFIG_CS89x0=y
 # CONFIG_WAN is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
 #
-# Amateur Radio support
+# Bluetooth support
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_BT is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 # CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
 # CONFIG_BLK_DEV_IDEPCI is not set
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -395,7 +424,6 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
@@ -407,15 +435,13 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
@@ -425,6 +451,7 @@ CONFIG_CHR_DEV_SG=m
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
@@ -486,6 +513,7 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_NEWTON is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2_SYNAPTICS is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_INPORT is not set
 # CONFIG_MOUSE_LOGIBM is not set
@@ -497,7 +525,9 @@ CONFIG_MOUSE_PS2=y
 #
 # Character devices
 #
-# CONFIG_VT is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -505,6 +535,7 @@ CONFIG_MOUSE_PS2=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -526,12 +557,17 @@ CONFIG_PRINTER=m
 # CONFIG_I2C is not set
 
 #
-# I2C Hardware Sensors Mainboard support
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
 #
 
 #
 # I2C Hardware Sensors Chip support
 #
+# CONFIG_I2C_SENSOR is not set
 
 #
 # L3 serial bus support
@@ -566,7 +602,6 @@ CONFIG_RTC=y
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # Multimedia devices
@@ -574,6 +609,16 @@ CONFIG_RTC=y
 # CONFIG_VIDEO_DEV is not set
 
 #
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -581,6 +626,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -618,6 +664,8 @@ CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -642,6 +690,7 @@ CONFIG_RAMFS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
 # CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 # CONFIG_EXPORTFS is not set
@@ -740,9 +789,24 @@ CONFIG_FB_CYBER2000=y
 # CONFIG_FB_VIRTUAL is not set
 
 #
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
 # Logo configuration
 #
-# CONFIG_LOGO is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
 
 #
 # Sound
@@ -769,7 +833,6 @@ CONFIG_SOUND_PRIME=m
 # CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_MAESTRO3 is not set
 # CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -779,6 +842,7 @@ CONFIG_SOUND_OSS=m
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_AD1889 is not set
 # CONFIG_SOUND_SGALAXY is not set
 CONFIG_SOUND_ADLIB=m
 # CONFIG_SOUND_ACI_MIXER is not set
@@ -803,6 +867,11 @@ CONFIG_SOUND_SB=m
 # CONFIG_SOUND_YMFPCI is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_KAHLUA is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
 
 #
 # Misc devices
@@ -822,11 +891,7 @@ CONFIG_SOUND_SB=m
 # USB support
 #
 # CONFIG_USB is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # Kernel hacking
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/kernel/armksyms.c 001-linus.patch/arch/arm/kernel/armksyms.c
--- 000-virgin/arch/arm/kernel/armksyms.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/arch/arm/kernel/armksyms.c	Tue Dec 30 16:38:56 2003
@@ -68,8 +68,8 @@ extern void __umoddi3(void);
 extern void __udivmoddi4(void);
 extern void __udivsi3(void);
 extern void __umodsi3(void);
+extern void __do_div64(void);
 extern void abort(void);
-extern void do_div64(void);
 
 extern void ret_from_exception(void);
 extern void fpundefinstr(void);
@@ -223,7 +223,7 @@ EXPORT_SYMBOL_NOVERS(__umoddi3);
 EXPORT_SYMBOL_NOVERS(__udivmoddi4);
 EXPORT_SYMBOL_NOVERS(__udivsi3);
 EXPORT_SYMBOL_NOVERS(__umodsi3);
-EXPORT_SYMBOL_NOVERS(do_div64);
+EXPORT_SYMBOL_NOVERS(__do_div64);
 
 	/* bitops */
 EXPORT_SYMBOL(_set_bit_le);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/kernel/calls.S 001-linus.patch/arch/arm/kernel/calls.S
--- 000-virgin/arch/arm/kernel/calls.S	Wed Dec 17 19:00:01 2003
+++ 001-linus.patch/arch/arm/kernel/calls.S	Tue Dec 30 16:38:56 2003
@@ -271,6 +271,20 @@ __syscall_start:
 		.long	sys_ni_syscall	/* sys_set_thread_area */
 /* 255 */	.long	sys_ni_syscall	/* sys_get_thread_area */
  		.long	sys_ni_syscall	/* sys_set_tid_address */
+		.long	sys_timer_create
+		.long	sys_timer_settime
+		.long	sys_timer_gettime
+/* 260 */	.long	sys_timer_getoverrun
+		.long	sys_timer_delete
+		.long	sys_clock_settime
+		.long	sys_clock_gettime
+		.long	sys_clock_getres
+/* 265 */	.long	sys_clock_nanosleep
+		.long	sys_statfs64
+		.long	sys_fstatfs64
+		.long	sys_tgkill
+		.long	sys_utimes
+/* 270 */	.long	sys_fadvise64_64
 __syscall_end:
 
 		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/kernel/irq.c 001-linus.patch/arch/arm/kernel/irq.c
--- 000-virgin/arch/arm/kernel/irq.c	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/arch/arm/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -169,11 +169,11 @@ void disable_irq_wake(unsigned int irq)
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_controller_lock, flags);
 	    	action = irq_desc[i].action;
 		if (!action)
@@ -187,12 +187,12 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 unlock:
 		spin_unlock_irqrestore(&irq_controller_lock, flags);
-	}
-
+	} else if (i == NR_IRQS) {
 #ifdef CONFIG_ARCH_ACORN
-	show_fiq_list(p, v);
+		show_fiq_list(p, v);
 #endif
-	seq_printf(p, "Err: %10lu\n", irq_err_count);
+		seq_printf(p, "Err: %10lu\n", irq_err_count);
+	}
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/lib/div64.S 001-linus.patch/arch/arm/lib/div64.S
--- 000-virgin/arch/arm/lib/div64.S	Wed Dec 17 18:59:53 2003
+++ 001-linus.patch/arch/arm/lib/div64.S	Tue Dec 30 16:38:56 2003
@@ -1,59 +1,200 @@
+/*
+ *  linux/arch/arm/lib/div64.S
+ *
+ *  Optimized computation of 64-bit dividend / 32-bit divisor
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Oct 5, 2003
+ *  Copyright:	Monta Vista Software, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
 #include <linux/linkage.h>
 
-#ifndef __ARMEB__
-ql	.req	r0			@ quotient low
-qh	.req	r1			@ quotient high
-onl	.req	r0			@ original dividend low
-onh	.req	r1			@ original dividend high
-nl	.req	r4			@ dividend low
-nh	.req	r5			@ dividend high
-res	.req	r4			@ result
+#ifdef __ARMEB__
+#define xh r0
+#define xl r1
+#define yh r2
+#define yl r3
+#else
+#define xl r0
+#define xh r1
+#define yl r2
+#define yh r3
+#endif
+
+/*
+ * __do_div64: perform a division with 64-bit dividend and 32-bit divisor.
+ *
+ * Note: Calling convention is totally non standard for optimal code.
+ *       This is meant to be used by do_div() from include/asm/div64.h only.
+ *
+ * Input parameters:
+ * 	xh-xl	= dividend (clobbered)
+ * 	r4	= divisor (preserved)
+ *
+ * Output values:
+ * 	yh-yl	= result
+ * 	xh	= remainder
+ *
+ * Clobbered regs: xl, ip
+ */
+
+ENTRY(__do_div64)
+
+	@ Test for easy paths first.
+	subs	ip, r4, #1
+	bls	9f			@ divisor is 0 or 1
+	tst	ip, r4
+	beq	8f			@ divisor is power of 2
+
+	@ See if we need to handle upper 32-bit result.
+	cmp	xh, r4
+	mov	yh, #0
+	blo	3f
+
+	@ Align divisor with upper part of dividend.
+	@ The aligned divisor is stored in yl preserving the original.
+	@ The bit position is stored in ip.
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+	clz	yl, r4
+	clz	ip, xh
+	sub	yl, yl, ip
+	mov	ip, #1
+	mov	ip, ip, lsl yl
+	mov	yl, r4, lsl yl
+
+#else
+
+	mov	yl, r4
+	mov	ip, #1
+1:	cmp	yl, #0x80000000
+	cmpcc	yl, xh
+	movcc	yl, yl, lsl #1
+	movcc	ip, ip, lsl #1
+	bcc	1b
+
+#endif
+
+	@ The division loop for needed upper bit positions.
+ 	@ Break out early if dividend reaches 0.
+2:	cmp	xh, yl
+	orrcs	yh, yh, ip
+	subcss	xh, xh, yl
+	movnes	ip, ip, lsr #1
+	mov	yl, yl, lsr #1
+	bne	2b
+
+	@ See if we need to handle lower 32-bit result.
+3:	cmp	xh, #0
+	mov	yl, #0
+	cmpeq	xl, r4
+	movlo	xh, xl
+	movlo	pc, lr
+
+	@ The division loop for lower bit positions.
+	@ Here we shift remainer bits leftwards rather than moving the
+	@ divisor for comparisons, considering the carry-out bit as well.
+	mov	ip, #0x80000000
+4:	movs	xl, xl, lsl #1
+	adcs	xh, xh, xh
+	beq	6f
+	cmpcc	xh, r4
+5:	orrcs	yl, yl, ip
+	subcs	xh, xh, r4
+	movs	ip, ip, lsr #1
+	bne	4b
+	mov	pc, lr
+
+	@ The top part of remainder became zero.  If carry is set
+	@ (the 33th bit) this is a false positive so resume the loop.
+	@ Otherwise, if lower part is also null then we are done.
+6:	bcs	5b
+	cmp	xl, #0
+	moveq	pc, lr
+
+	@ We still have remainer bits in the low part.  Bring them up.
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+	clz	xh, xl			@ we know xh is zero here so...
+	add	xh, xh, #1
+	mov	xl, xl, lsl xh
+	mov	ip, ip, lsr xh
+
 #else
-ql	.req	r1
-qh	.req	r0
-onl	.req	r1
-onh	.req	r0
-nl	.req	r5
-nh	.req	r4
-res	.req	r5
+
+7:	movs	xl, xl, lsl #1
+	mov	ip, ip, lsr #1
+	bcc	7b
+
 #endif
 
-dl	.req	r3			@ divisor low
-dh	.req	r2			@ divsor high
+	@ Current remainder is now 1.  It is worthless to compare with
+	@ divisor at this point since divisor can not be smaller than 3 here.
+	@ If possible, branch for another shift in the division loop.
+	@ If no bit position left then we are done.
+	movs	ip, ip, lsr #1
+	mov	xh, #1
+	bne	4b
+	mov	pc, lr
+
+8:	@ Division by a power of 2: determine what that divisor order is
+	@ then simply shift values around
+
+#if __LINUX_ARM_ARCH__ >= 5
 
+	clz	ip, r4
+	rsb	ip, ip, #31
+
+#else
+
+	mov	yl, r4
+	cmp	r4, #(1 << 16)
+	mov	ip, #0
+	movhs	yl, yl, lsr #16
+	movhs	ip, #16
+
+	cmp	yl, #(1 << 8)
+	movhs	yl, yl, lsr #8
+	addhs	ip, ip, #8
+
+	cmp	yl, #(1 << 4)
+	movhs	yl, yl, lsr #4
+	addhs	ip, ip, #4
+
+	cmp	yl, #(1 << 2)
+	addhi	ip, ip, #3
+	addls	ip, ip, yl, lsr #1
+
+#endif
 
-ENTRY(do_div64)
-	stmfd	sp!, {r4, r5, lr}
-	mov	nl, onl
-	movs	nh, onh			@ if high bits are zero
-	movne	lr, #33
-	moveq	lr, #1			@ only divide low bits
-	moveq	nh, onl
-
-	tst	dh, #0x80000000
-	bne	2f
-1:	cmp	nh, dh
-	bls	2f
-	add	lr, lr, #1
-	movs	dh, dh, lsl #1		@ left justify disor
-	bpl	1b
-
-2:	movs	nh, onh
-	moveq	dl, dh
-	moveq	dh, #0
-	movne	dl, #0
-	mov	ql, #0
-	mov	qh, #0
-3:	subs	ip, nl, dl		@ trial subtraction
-	sbcs	ip, nh, dh
-	movcs	nh, ip			@ only update if successful
-	subcs	nl, nl, dl		@ (repeat the subtraction)
-	adcs	ql, ql, ql		@ C=1 if successful, shift into
-	adc	qh, qh, qh		@ quotient
-	movs	dh, dh, lsr #1		@ shift base high part right
-	mov	dl, dl, rrx		@ shift base low part right
-	subs	lr, lr, #1
-	bne	3b
+	mov	yh, xh, lsr ip
+	mov	yl, xl, lsr ip
+	rsb	ip, ip, #32
+	orr	yl, yl, xh, lsl ip
+	mov	xh, xl, lsl ip
+	mov	xh, xh, lsr ip
+	mov	pc, lr
+
+	@ eq -> division by 1: obvious enough...
+9:	moveq	yl, xl
+	moveq	yh, xh
+	moveq	xh, #0
+	moveq	pc, lr
+
+	@ Division by 0:
+	str	lr, [sp, #-4]!
+	bl	__div0
+
+	@ as wrong as it could be...
+	mov	yl, #0
+	mov	yh, #0
+	mov	xh, #0
+	ldr	pc, [sp], #4
 
-	mov	r2, res
-	ldmfd	sp!, {r4, r5, pc}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mach-clps711x/time.c 001-linus.patch/arch/arm/mach-clps711x/time.c
--- 000-virgin/arch/arm/mach-clps711x/time.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/arm/mach-clps711x/time.c	Tue Dec 30 16:38:56 2003
@@ -40,6 +40,7 @@ static unsigned long clps711x_gettimeoff
 
 void __init clps711x_setup_timer(void)
 {
+	struct timespec tv;
 	unsigned int syscon;
 
 	gettimeoffset = clps711x_gettimeoffset;
@@ -50,5 +51,7 @@ void __init clps711x_setup_timer(void)
 
 	clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
 
-	xtime.tv_sec = clps_readl(RTCDR);
+	tv.tv_nsec = 0;
+	tv.tv_sec = clps_readl(RTCDR);
+	do_settimeofday(&tv);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mach-integrator/integrator_ap.c 001-linus.patch/arch/arm/mach-integrator/integrator_ap.c
--- 000-virgin/arch/arm/mach-integrator/integrator_ap.c	Wed Dec 17 18:59:27 2003
+++ 001-linus.patch/arch/arm/mach-integrator/integrator_ap.c	Tue Dec 30 16:38:56 2003
@@ -126,7 +126,7 @@ static void __init ap_init_irq(void)
 	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 
 	for (i = 0; i < NR_IRQS; i++) {
-		if (((1 << i) && INTEGRATOR_SC_VALID_INT) != 0) {
+		if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
 			set_irq_chip(i, &sc_chip);
 			set_irq_handler(i, do_level_IRQ);
 			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mm/cache-v3.S 001-linus.patch/arch/arm/mm/cache-v3.S
--- 000-virgin/arch/arm/mm/cache-v3.S	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/arch/arm/mm/cache-v3.S	Tue Dec 30 16:38:56 2003
@@ -32,14 +32,14 @@ ENTRY(v3_flush_kern_cache_all)
 	/* FALLTHROUGH */
 
 /*
- *	flush_user_cache_range(start, end, vm_flags)
+ *	flush_user_cache_range(start, end, flags)
  *
  *	Invalidate a range of cache entries in the specified
  *	address space.
  *
  *	- start - start address (may not be aligned)
  *	- end	- end address (exclusive, may not be aligned)
- *	- vma	- vma_area_struct describing address space
+ *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v3_flush_user_cache_range)
 	mov	ip, #0
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mm/cache-v4.S 001-linus.patch/arch/arm/mm/cache-v4.S
--- 000-virgin/arch/arm/mm/cache-v4.S	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/arch/arm/mm/cache-v4.S	Tue Dec 30 16:38:56 2003
@@ -34,14 +34,14 @@ ENTRY(v4_flush_kern_cache_all)
 	mov	pc, lr
 
 /*
- *	flush_user_cache_range(start, end, vma)
+ *	flush_user_cache_range(start, end, flags)
  *
  *	Invalidate a range of cache entries in the specified
  *	address space.
  *
  *	- start - start address (may not be aligned)
  *	- end	- end address (exclusive, may not be aligned)
- *	- vma	- vma_area_struct describing address space
+ *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v4_flush_user_cache_range)
 	mov	ip, #0
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mm/cache-v4wb.S 001-linus.patch/arch/arm/mm/cache-v4wb.S
--- 000-virgin/arch/arm/mm/cache-v4wb.S	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/arch/arm/mm/cache-v4wb.S	Tue Dec 30 16:38:56 2003
@@ -72,14 +72,14 @@ __flush_whole_cache:
 	mov	pc, lr
 
 /*
- *	flush_user_cache_range(start, end, vm_flags)
+ *	flush_user_cache_range(start, end, flags)
  *
  *	Invalidate a range of cache entries in the specified
  *	address space.
  *
  *	- start - start address (inclusive, page aligned)
  *	- end	- end address (exclusive, page aligned)
- *	- vma	- vma_area_struct describing address space
+ *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v4wb_flush_user_cache_range)
 	sub	r3, r1, r0			@ calculate total size
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm/mm/cache-v4wt.S 001-linus.patch/arch/arm/mm/cache-v4wt.S
--- 000-virgin/arch/arm/mm/cache-v4wt.S	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/arch/arm/mm/cache-v4wt.S	Tue Dec 30 16:38:56 2003
@@ -64,14 +64,14 @@ __flush_whole_cache:
 	mov	pc, lr
 
 /*
- *	flush_user_cache_range(start, end, vm_flags)
+ *	flush_user_cache_range(start, end, flags)
  *
  *	Clean and invalidate a range of cache entries in the specified
  *	address space.
  *
  *	- start - start address (inclusive, page aligned)
  *	- end	- end address (exclusive, page aligned)
- *	- vma	- vma_area_struct describing address space
+ *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v4wt_flush_user_cache_range)
 	sub	r3, r1, r0			@ calculate total size
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/arm26/kernel/irq.c 001-linus.patch/arch/arm26/kernel/irq.c
--- 000-virgin/arch/arm26/kernel/irq.c	Wed Dec 17 18:59:36 2003
+++ 001-linus.patch/arch/arm26/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -135,10 +135,10 @@ void enable_irq(unsigned int irq)
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 	    	action = irq_desc[i].action;
 		if (!action)
 			continue;
@@ -148,10 +148,10 @@ int show_interrupts(struct seq_file *p, 
 			seq_printf(p, ", %s", action->name);
 		}
 		seq_putc(p, '\n');
+	} else if (i == NR_IRQS) {
+		show_fiq_list(p, v);
+		seq_printf(p, "Err: %10lu\n", irq_err_count);
 	}
-
-	show_fiq_list(p, v);
-	seq_printf(p, "Err: %10lu\n", irq_err_count);
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/cris/kernel/irq.c 001-linus.patch/arch/cris/kernel/irq.c
--- 000-virgin/arch/cris/kernel/irq.c	Wed Dec 17 18:59:54 2003
+++ 001-linus.patch/arch/cris/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -89,11 +89,11 @@ static struct irqaction *irq_action[NR_I
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/h8300/Kconfig 001-linus.patch/arch/h8300/Kconfig
--- 000-virgin/arch/h8300/Kconfig	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/arch/h8300/Kconfig	Tue Dec 30 16:38:56 2003
@@ -5,6 +5,10 @@
 
 mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration"
 
+config H8300
+	bool
+	default y
+
 config MMU
 	bool
 	default n
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/h8300/Makefile 001-linus.patch/arch/h8300/Makefile
--- 000-virgin/arch/h8300/Makefile	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/arch/h8300/Makefile	Tue Dec 30 16:38:56 2003
@@ -34,7 +34,7 @@ cflags-$(CONFIG_CPU_H8S)	:= -ms
 ldflags-$(CONFIG_CPU_H8S)	:= -mh8300self
 
 CFLAGS += $(cflags-y)
-CFLAGS += -mint32 -fno-builtin -Os
+CFLAGS += -mint32 -fno-builtin
 CFLAGS += -g
 CFLAGS += -D__linux__
 CFLAGS += -DUTS_SYSNAME=\"uClinux\"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/h8300/platform/h8300h/ints.c 001-linus.patch/arch/h8300/platform/h8300h/ints.c
--- 000-virgin/arch/h8300/platform/h8300h/ints.c	Wed Dec 17 18:58:38 2003
+++ 001-linus.patch/arch/h8300/platform/h8300h/ints.c	Tue Dec 30 16:38:56 2003
@@ -228,9 +228,9 @@ asmlinkage void process_int(int vec, str
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		if (irq_list[i]) {
 			seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
 			seq_printf(p, "%s\n", irq_list[i]->devname);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/h8300/platform/h8s/ints.c 001-linus.patch/arch/h8300/platform/h8s/ints.c
--- 000-virgin/arch/h8300/platform/h8s/ints.c	Wed Dec 17 18:58:44 2003
+++ 001-linus.patch/arch/h8300/platform/h8s/ints.c	Tue Dec 30 16:38:56 2003
@@ -280,9 +280,9 @@ asmlinkage void process_int(unsigned lon
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		if (irq_list[i]) {
 			seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
 			seq_printf(p, "%s\n", irq_list[i]->devname);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/Kconfig 001-linus.patch/arch/i386/Kconfig
--- 000-virgin/arch/i386/Kconfig	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/arch/i386/Kconfig	Tue Dec 30 16:38:56 2003
@@ -784,6 +784,25 @@ config MTRR
 
 	  See <file:Documentation/mtrr.txt> for more information.
 
+config EFI
+	bool "Boot from EFI support (EXPERIMENTAL)"
+	depends on ACPI
+	default n
+	---help---
+
+	This enables the the kernel to boot on EFI platforms using
+	system configuration information passed to it from the firmware.
+	This also enables the kernel to use any EFI runtime services that are
+	available (such as the EFI variable services).
+
+	This option is only useful on systems that have EFI firmware
+	and will result in a kernel image that is ~8k larger.  In addition,
+	you must use the latest ELILO loader available at
+	ftp.hpl.hp.com/pub/linux-ia64/ in order to take advantage of kernel
+	initialization using EFI information (neither GRUB nor LILO know
+	anything about EFI).  However, even with this option, the resultant
+	kernel should continue to boot on existing non-EFI platforms.
+
 config HAVE_DEC_LOCK
 	bool
 	depends on (SMP || PREEMPT) && X86_CMPXCHG
@@ -793,7 +812,7 @@ config HAVE_DEC_LOCK
 # Summit needs it only when NUMA is on
 config BOOT_IOREMAP
 	bool
-	depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA)
+	depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
 	default y
 
 endmenu
@@ -1030,6 +1049,25 @@ config PCI_DIRECT
  	depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
 	default y
 
+config PCI_USE_VECTOR
+	bool "Vector-based interrupt indexing"
+	depends on X86_LOCAL_APIC
+	default n
+	help
+	   This replaces the current existing IRQ-based index interrupt scheme
+	   with the vector-base index scheme. The advantages of vector base
+	   over IRQ base are listed below:
+	   1) Support MSI implementation.
+	   2) Support future IOxAPIC hotplug
+
+	   Note that this enables MSI, Message Signaled Interrupt, on all
+	   MSI capable device functions detected if users also install the
+	   MSI patch. Message Signal Interrupt enables an MSI-capable
+	   hardware device to send an inbound Memory Write on its PCI bus
+	   instead of asserting IRQ signal on device IRQ pin.
+
+	   If you don't know what to do here, say N.
+
 source "drivers/pci/Kconfig"
 
 config ISA
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/Makefile 001-linus.patch/arch/i386/kernel/Makefile
--- 000-virgin/arch/i386/kernel/Makefile	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/arch/i386/kernel/Makefile	Tue Dec 30 16:38:56 2003
@@ -30,6 +30,7 @@ obj-$(CONFIG_MODULES)		+= module.o
 obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
+obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
 
 EXTRA_AFLAGS   := -traditional
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/acpi/boot.c 001-linus.patch/arch/i386/kernel/acpi/boot.c
--- 000-virgin/arch/i386/kernel/acpi/boot.c	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/i386/kernel/acpi/boot.c	Tue Dec 30 16:38:56 2003
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/config.h>
 #include <linux/acpi.h>
+#include <linux/efi.h>
 #include <asm/pgalloc.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
@@ -331,6 +332,12 @@ acpi_find_rsdp (void)
 {
 	unsigned long		rsdp_phys = 0;
 
+	if (efi_enabled) {
+		if (efi.acpi20)
+			return __pa(efi.acpi20);
+		else if (efi.acpi)
+			return __pa(efi.acpi);
+	}
 	/*
 	 * Scan memory looking for the RSDP signature. First search EBDA (low
 	 * memory) paragraphs and then search upper memory (E0000-FFFFF).
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/cpu/common.c 001-linus.patch/arch/i386/kernel/cpu/common.c
--- 000-virgin/arch/i386/kernel/cpu/common.c	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/arch/i386/kernel/cpu/common.c	Tue Dec 30 16:38:56 2003
@@ -510,7 +510,7 @@ void __init cpu_init (void)
 		BUG();
 	enter_lazy_tlb(&init_mm, current);
 
-	load_esp0(t, thread->esp0);
+	load_esp0(t, thread);
 	set_tss_desc(cpu,t);
 	cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
 	load_TR_desc();
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 001-linus.patch/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
--- 000-virgin/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	Tue Dec 30 16:38:56 2003
@@ -73,6 +73,16 @@ static struct cpufreq_frequency_table op
 	{ .frequency = CPUFREQ_TABLE_END }
 };
 
+/* Ultra Low Voltage Intel Pentium M processor 1000MHz */
+static struct cpufreq_frequency_table op_1000[] =
+  {
+    OP(600,  844),
+    OP(800,  972),
+    OP(900, 988),
+    OP(1000, 1004),
+    { .frequency = CPUFREQ_TABLE_END }
+  };
+
 /* Low Voltage Intel Pentium M processor 1.10GHz */
 static struct cpufreq_frequency_table op_1100[] =
 {
@@ -165,6 +175,7 @@ static struct cpufreq_frequency_table op
 static const struct cpu_model models[] = 
 {
        _CPU( 900, " 900"),
+       CPU(1000),
 	CPU(1100),
 	CPU(1200),
 	CPU(1300),
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/efi.c 001-linus.patch/arch/i386/kernel/efi.c
--- 000-virgin/arch/i386/kernel/efi.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/i386/kernel/efi.c	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,645 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 1.0
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *	Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * All EFI Runtime Services are not implemented yet as EFI only
+ * supports physical mode addressing on SoftSDV. This is to be fixed
+ * in a future version.  --drummond 1999-07-20
+ *
+ * Implemented EFI runtime services and virtual mode calls.  --davidm
+ *
+ * Goutham Rao: <goutham.rao@intel.com>
+ *	Skip non-WB memory and ignore empty memory ranges.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/spinlock.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <linux/proc_fs.h>
+#include <linux/efi.h>
+
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/desc.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+#define EFI_DEBUG	0
+#define PFX 		"EFI: "
+
+extern efi_status_t asmlinkage efi_call_phys(void *, ...);
+
+struct efi efi;
+struct efi efi_phys __initdata;
+struct efi_memory_map memmap __initdata;
+
+/*
+ * We require an early boot_ioremap mapping mechanism initially
+ */
+extern void * boot_ioremap(unsigned long, unsigned long);
+
+/*
+ * efi_dir is allocated here, but the directory isn't created
+ * here, as proc_mkdir() doesn't work this early in the bootup
+ * process.  Therefore, each module, like efivars, must test for
+ *    if (!efi_dir) efi_dir = proc_mkdir("efi", NULL);
+ * prior to creating their own entries under /proc/efi.
+ */
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *efi_dir;
+#endif
+
+
+/*
+ * To make EFI call EFI runtime service in physical addressing mode we need
+ * prelog/epilog before/after the invocation to disable interrupt, to
+ * claim EFI runtime service handler exclusively and to duplicate a memory in
+ * low memory space say 0 - 3G.
+ */
+
+static unsigned long efi_rt_eflags;
+static spinlock_t efi_rt_lock = SPIN_LOCK_UNLOCKED;
+static pgd_t efi_bak_pg_dir_pointer[2];
+
+static void efi_call_phys_prelog(void)
+{
+	unsigned long cr4;
+	unsigned long temp;
+
+	spin_lock(&efi_rt_lock);
+	local_irq_save(efi_rt_eflags);
+
+	/*
+	 * If I don't have PSE, I should just duplicate two entries in page
+	 * directory. If I have PSE, I just need to duplicate one entry in
+	 * page directory.
+	 */
+	__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
+
+	if (cr4 & X86_CR4_PSE) {
+		efi_bak_pg_dir_pointer[0].pgd =
+		    swapper_pg_dir[pgd_index(0)].pgd;
+		swapper_pg_dir[0].pgd =
+		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
+	} else {
+		efi_bak_pg_dir_pointer[0].pgd =
+		    swapper_pg_dir[pgd_index(0)].pgd;
+		efi_bak_pg_dir_pointer[1].pgd =
+		    swapper_pg_dir[pgd_index(0x400000)].pgd;
+		swapper_pg_dir[pgd_index(0)].pgd =
+		    swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
+		temp = PAGE_OFFSET + 0x400000;
+		swapper_pg_dir[pgd_index(0x400000)].pgd =
+		    swapper_pg_dir[pgd_index(temp)].pgd;
+	}
+
+	/*
+	 * After the lock is released, the original page table is restored.
+	 */
+	local_flush_tlb();
+
+	cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
+	__asm__ __volatile__("lgdt %0":"=m"
+			    (*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
+}
+
+static void efi_call_phys_epilog(void)
+{
+	unsigned long cr4;
+
+	cpu_gdt_descr[0].address =
+		(unsigned long) __va(cpu_gdt_descr[0].address);
+	__asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
+	__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
+
+	if (cr4 & X86_CR4_PSE) {
+		swapper_pg_dir[pgd_index(0)].pgd =
+		    efi_bak_pg_dir_pointer[0].pgd;
+	} else {
+		swapper_pg_dir[pgd_index(0)].pgd =
+		    efi_bak_pg_dir_pointer[0].pgd;
+		swapper_pg_dir[pgd_index(0x400000)].pgd =
+		    efi_bak_pg_dir_pointer[1].pgd;
+	}
+
+	/*
+	 * After the lock is released, the original page table is restored.
+	 */
+	local_flush_tlb();
+
+	local_irq_restore(efi_rt_eflags);
+	spin_unlock(&efi_rt_lock);
+}
+
+static efi_status_t
+phys_efi_set_virtual_address_map(unsigned long memory_map_size,
+				 unsigned long descriptor_size,
+				 u32 descriptor_version,
+				 efi_memory_desc_t *virtual_map)
+{
+	efi_status_t status;
+
+	efi_call_phys_prelog();
+	status = efi_call_phys(efi_phys.set_virtual_address_map,
+				     memory_map_size, descriptor_size,
+				     descriptor_version, virtual_map);
+	efi_call_phys_epilog();
+	return status;
+}
+
+efi_status_t
+phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+	efi_status_t status;
+
+	efi_call_phys_prelog();
+	status = efi_call_phys(efi_phys.get_time, tm, tc);
+	efi_call_phys_epilog();
+	return status;
+}
+
+int inline efi_set_rtc_mmss(unsigned long nowtime)
+{
+	int real_seconds, real_minutes;
+	efi_status_t 	status;
+	efi_time_t 	eft;
+	efi_time_cap_t 	cap;
+
+	spin_lock(&efi_rt_lock);
+	status = efi.get_time(&eft, &cap);
+	spin_unlock(&efi_rt_lock);
+	if (status != EFI_SUCCESS)
+		panic("Ooops, efitime: can't read time!\n");
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+
+	if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
+		real_minutes += 30;
+	real_minutes %= 60;
+
+	eft.minute = real_minutes;
+	eft.second = real_seconds;
+
+	if (status != EFI_SUCCESS) {
+		printk("Ooops: efitime: can't read time!\n");
+		return -1;
+	}
+	return 0;
+}
+/*
+ * This should only be used during kernel init and before runtime
+ * services have been remapped, therefore, we'll need to call in physical
+ * mode.  Note, this call isn't used later, so mark it __init.
+ */
+unsigned long inline __init efi_get_time(void)
+{
+	efi_status_t status;
+	efi_time_t eft;
+	efi_time_cap_t cap;
+
+	status = phys_efi_get_time(&eft, &cap);
+	if (status != EFI_SUCCESS)
+		printk("Oops: efitime: can't read time status: 0x%lx\n",status);
+
+	return mktime(eft.year, eft.month, eft.day, eft.hour,
+			eft.minute, eft.second);
+}
+
+int is_available_memory(efi_memory_desc_t * md)
+{
+	if (!(md->attribute & EFI_MEMORY_WB))
+		return 0;
+
+	switch (md->type) {
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
+		case EFI_BOOT_SERVICES_CODE:
+		case EFI_BOOT_SERVICES_DATA:
+		case EFI_CONVENTIONAL_MEMORY:
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * We need to map the EFI memory map again after paging_init().
+ */
+void __init efi_map_memmap(void)
+{
+	memmap.map = NULL;
+
+	memmap.map = (efi_memory_desc_t *)
+		bt_ioremap((unsigned long) memmap.phys_map,
+			(memmap.nr_map * sizeof(efi_memory_desc_t)));
+
+	if (memmap.map == NULL)
+		printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
+}
+
+void __init print_efi_memmap(void)
+{
+	efi_memory_desc_t *md;
+	int i;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+		printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
+			"range=[0x%016llx-0x%016llx) (%lluMB)\n",
+			i, md->type, md->attribute, md->phys_addr,
+			md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
+			(md->num_pages >> (20 - EFI_PAGE_SHIFT)));
+	}
+}
+
+/*
+ * Walks the EFI memory map and calls CALLBACK once for each EFI
+ * memory descriptor that has memory that is available for kernel use.
+ */
+void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
+{
+	int prev_valid = 0;
+	struct range {
+		unsigned long start;
+		unsigned long end;
+	} prev, curr;
+	efi_memory_desc_t *md;
+	unsigned long start, end;
+	int i;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+
+		if ((md->num_pages == 0) || (!is_available_memory(md)))
+			continue;
+
+		curr.start = md->phys_addr;
+		curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
+
+		if (!prev_valid) {
+			prev = curr;
+			prev_valid = 1;
+		} else {
+			if (curr.start < prev.start)
+				printk(KERN_INFO PFX "Unordered memory map\n");
+			if (prev.end == curr.start)
+				prev.end = curr.end;
+			else {
+				start =
+				    (unsigned long) (PAGE_ALIGN(prev.start));
+				end = (unsigned long) (prev.end & PAGE_MASK);
+				if ((end > start)
+				    && (*callback) (start, end, arg) < 0)
+					return;
+				prev = curr;
+			}
+		}
+	}
+	if (prev_valid) {
+		start = (unsigned long) PAGE_ALIGN(prev.start);
+		end = (unsigned long) (prev.end & PAGE_MASK);
+		if (end > start)
+			(*callback) (start, end, arg);
+	}
+}
+
+void __init efi_init(void)
+{
+	efi_config_table_t *config_tables;
+	efi_runtime_services_t *runtime;
+	efi_char16_t *c16;
+	char vendor[100] = "unknown";
+	unsigned long num_config_tables;
+	int i = 0;
+
+	memset(&efi, 0, sizeof(efi) );
+	memset(&efi_phys, 0, sizeof(efi_phys));
+
+	efi_phys.systab = EFI_SYSTAB;
+	memmap.phys_map = EFI_MEMMAP;
+	memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
+	memmap.desc_version = EFI_MEMDESC_VERSION;
+
+	efi.systab = (efi_system_table_t *)
+		boot_ioremap((unsigned long) efi_phys.systab,
+			sizeof(efi_system_table_t));
+	/*
+	 * Verify the EFI Table
+	 */
+	if (efi.systab == NULL)
+		printk(KERN_ERR PFX "Woah! Couldn't map the EFI system table.\n");
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+		printk(KERN_ERR PFX "Woah! EFI system table signature incorrect\n");
+	if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
+		printk(KERN_ERR PFX
+		       "Warning: EFI system table major version mismatch: "
+		       "got %d.%02d, expected %d.%02d\n",
+		       efi.systab->hdr.revision >> 16,
+		       efi.systab->hdr.revision & 0xffff,
+		       EFI_SYSTEM_TABLE_REVISION >> 16,
+		       EFI_SYSTEM_TABLE_REVISION & 0xffff);
+	/*
+	 * Grab some details from the system table
+	 */
+	num_config_tables = efi.systab->nr_tables;
+	config_tables = (efi_config_table_t *)efi.systab->tables;
+	runtime = efi.systab->runtime;
+
+	/*
+	 * Show what we know for posterity
+	 */
+	c16 = (efi_char16_t *) boot_ioremap(efi.systab->fw_vendor, 2);
+	if (c16) {
+		for (i = 0; i < sizeof(vendor) && *c16; ++i)
+			vendor[i] = *c16++;
+		vendor[i] = '\0';
+	} else
+		printk(KERN_ERR PFX "Could not map the firmware vendor!\n");
+
+	printk(KERN_INFO PFX "EFI v%u.%.02u by %s \n",
+	       efi.systab->hdr.revision >> 16,
+	       efi.systab->hdr.revision & 0xffff, vendor);
+
+	/*
+	 * Let's see what config tables the firmware passed to us.
+	 */
+	config_tables = (efi_config_table_t *)
+				boot_ioremap((unsigned long) config_tables,
+			        num_config_tables * sizeof(efi_config_table_t));
+
+	if (config_tables == NULL)
+		printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
+
+	for (i = 0; i < num_config_tables; i++) {
+		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
+			efi.mps = (void *)config_tables[i].table;
+			printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
+		} else
+		    if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
+			efi.acpi20 = __va(config_tables[i].table);
+			printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
+		} else
+		    if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
+			efi.acpi = __va(config_tables[i].table);
+			printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
+		} else
+		    if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
+			efi.smbios = (void *) config_tables[i].table;
+			printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
+		} else
+		    if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
+			efi.hcdp = (void *)config_tables[i].table;
+			printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table);
+		} else
+		    if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) {
+			efi.uga = (void *)config_tables[i].table;
+			printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table);
+		}
+	}
+	printk("\n");
+
+	/*
+	 * Check out the runtime services table. We need to map
+	 * the runtime services table so that we can grab the physical
+	 * address of several of the EFI runtime functions, needed to
+	 * set the firmware into virtual mode.
+	 */
+
+	runtime = (efi_runtime_services_t *) boot_ioremap((unsigned long)
+						runtime,
+				      		sizeof(efi_runtime_services_t));
+	if (runtime != NULL) {
+		/*
+	 	 * We will only need *early* access to the following
+		 * two EFI runtime services before set_virtual_address_map
+		 * is invoked.
+ 	 	 */
+		efi_phys.get_time = (efi_get_time_t *) runtime->get_time;
+		efi_phys.set_virtual_address_map =
+			(efi_set_virtual_address_map_t *)
+				runtime->set_virtual_address_map;
+	} else
+		printk(KERN_ERR PFX "Could not map the runtime service table!\n");
+
+	/* Map the EFI memory map for use until paging_init() */
+
+	memmap.map = (efi_memory_desc_t *)
+		boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
+
+	if (memmap.map == NULL)
+		printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
+
+	if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
+		printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
+			   "match the one from EFI!\n");
+	}
+#if EFI_DEBUG
+	print_efi_memmap();
+#endif
+}
+
+/*
+ * This function will switch the EFI runtime services to virtual mode.
+ * Essentially, look through the EFI memmap and map every region that
+ * has the runtime attribute bit set in its memory descriptor and update
+ * that memory descriptor with the virtual address obtained from ioremap().
+ * This enables the runtime services to be called without having to
+ * thunk back into physical mode for every invocation.
+ */
+
+void __init efi_enter_virtual_mode(void)
+{
+	efi_memory_desc_t *md;
+	efi_status_t status;
+	int i;
+
+	efi.systab = NULL;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+
+		if (md->attribute & EFI_MEMORY_RUNTIME) {
+			md->virt_addr =
+				(unsigned long)ioremap(md->phys_addr,
+					md->num_pages << EFI_PAGE_SHIFT);
+			if (!(unsigned long)md->virt_addr) {
+				printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
+					(unsigned long)md->phys_addr);
+			}
+
+			if (((unsigned long)md->phys_addr <=
+					(unsigned long)efi_phys.systab) &&
+				((unsigned long)efi_phys.systab <
+					md->phys_addr +
+					((unsigned long)md->num_pages <<
+						EFI_PAGE_SHIFT))) {
+				unsigned long addr;
+
+				addr = md->virt_addr - md->phys_addr +
+						(unsigned long)efi_phys.systab;
+				efi.systab = (efi_system_table_t *)addr;
+			}
+		}
+	}
+
+	if (!efi.systab)
+		BUG();
+
+	status = phys_efi_set_virtual_address_map(
+			sizeof(efi_memory_desc_t) * memmap.nr_map,
+			sizeof(efi_memory_desc_t),
+			memmap.desc_version,
+		       	memmap.phys_map);
+
+	if (status != EFI_SUCCESS) {
+		printk (KERN_ALERT "You are screwed! "
+			"Unable to switch EFI into virtual mode "
+			"(status=%lx)\n", status);
+		panic("EFI call to SetVirtualAddressMap() failed!");
+	}
+
+	/*
+	 * Now that EFI is in virtual mode, update the function
+	 * pointers in the runtime service table to the new virtual addresses.
+	 */
+
+	efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
+	efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
+	efi.get_wakeup_time = (efi_get_wakeup_time_t *)
+					efi.systab->runtime->get_wakeup_time;
+	efi.set_wakeup_time = (efi_set_wakeup_time_t *)
+					efi.systab->runtime->set_wakeup_time;
+	efi.get_variable = (efi_get_variable_t *)
+					efi.systab->runtime->get_variable;
+	efi.get_next_variable = (efi_get_next_variable_t *)
+					efi.systab->runtime->get_next_variable;
+	efi.set_variable = (efi_set_variable_t *)
+					efi.systab->runtime->set_variable;
+	efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
+					efi.systab->runtime->get_next_high_mono_count;
+	efi.reset_system = (efi_reset_system_t *)
+					efi.systab->runtime->reset_system;
+}
+
+void __init
+efi_initialize_iomem_resources(struct resource *code_resource,
+			       struct resource *data_resource)
+{
+	struct resource *res;
+	efi_memory_desc_t *md;
+	int i;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+
+		if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
+		    0x100000000ULL)
+			continue;
+		res = alloc_bootmem_low(sizeof(struct resource));
+		switch (md->type) {
+		case EFI_RESERVED_TYPE:
+			res->name = "Reserved Memory";
+			break;
+		case EFI_LOADER_CODE:
+			res->name = "Loader Code";
+			break;
+		case EFI_LOADER_DATA:
+			res->name = "Loader Data";
+			break;
+		case EFI_BOOT_SERVICES_DATA:
+			res->name = "BootServices Data";
+			break;
+		case EFI_BOOT_SERVICES_CODE:
+			res->name = "BootServices Code";
+			break;
+		case EFI_RUNTIME_SERVICES_CODE:
+			res->name = "Runtime Service Code";
+			break;
+		case EFI_RUNTIME_SERVICES_DATA:
+			res->name = "Runtime Service Data";
+			break;
+		case EFI_CONVENTIONAL_MEMORY:
+			res->name = "Conventional Memory";
+			break;
+		case EFI_UNUSABLE_MEMORY:
+			res->name = "Unusable Memory";
+			break;
+		case EFI_ACPI_RECLAIM_MEMORY:
+			res->name = "ACPI Reclaim";
+			break;
+		case EFI_ACPI_MEMORY_NVS:
+			res->name = "ACPI NVS";
+			break;
+		case EFI_MEMORY_MAPPED_IO:
+			res->name = "Memory Mapped IO";
+			break;
+		case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+			res->name = "Memory Mapped IO Port Space";
+			break;
+		default:
+			res->name = "Reserved";
+			break;
+		}
+		res->start = md->phys_addr;
+		res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1);
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		if (request_resource(&iomem_resource, res) < 0)
+			printk(KERN_ERR PFX "Failed to allocate res %s : 0x%lx-0x%lx\n",
+				res->name, res->start, res->end);
+		/*
+		 * We don't know which region contains kernel data so we try
+		 * it repeatedly and let the resource manager test it.
+		 */
+		if (md->type == EFI_CONVENTIONAL_MEMORY) {
+			request_resource(res, code_resource);
+			request_resource(res, data_resource);
+		}
+	}
+}
+
+/*
+ * Convenience functions to obtain memory types and attributes
+ */
+
+u32 efi_mem_type(unsigned long phys_addr)
+{
+	efi_memory_desc_t *md;
+	int i;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+		if ((md->phys_addr <= phys_addr) && (phys_addr <
+			(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
+			return md->type;
+	}
+	return 0;
+}
+
+u64 efi_mem_attributes(unsigned long phys_addr)
+{
+	efi_memory_desc_t *md;
+	int i;
+
+	for (i = 0; i < memmap.nr_map; i++) {
+		md = &memmap.map[i];
+		if ((md->phys_addr <= phys_addr) && (phys_addr <
+			(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
+			return md->attribute;
+	}
+	return 0;
+}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/efi_stub.S 001-linus.patch/arch/i386/kernel/efi_stub.S
--- 000-virgin/arch/i386/kernel/efi_stub.S	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/i386/kernel/efi_stub.S	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,124 @@
+/*
+ * EFI call stub for IA32.
+ *
+ * This stub allows us to make EFI calls in physical mode with interrupts
+ * turned off.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+/*
+ * efi_call_phys(void *, ...) is a function with variable parameters.
+ * All the callers of this function assure that all the parameters are 4-bytes.
+ */
+
+/*
+ * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
+ * So we'd better save all of them at the beginning of this function and restore
+ * at the end no matter how many we use, because we can not assure EFI runtime
+ * service functions will comply with gcc calling convention, too.
+ */
+
+.text
+ENTRY(efi_call_phys)
+	/*
+	 * 0. The function can only be called in Linux kernel. So CS has been
+	 * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
+	 * the values of these registers are the same. And, the corresponding
+	 * GDT entries are identical. So I will do nothing about segment reg
+	 * and GDT, but change GDT base register in prelog and epilog.
+	 */
+
+	/*
+	 * 1. Now I am running with EIP = <physical address> + PAGE_OFFSET.
+	 * But to make it smoothly switch from virtual mode to flat mode.
+	 * The mapping of lower virtual memory has been created in prelog and
+	 * epilog.
+	 */
+	movl	$1f, %edx
+	subl	$__PAGE_OFFSET, %edx
+	jmp	*%edx
+1:
+
+	/*
+	 * 2. Now on the top of stack is the return
+	 * address in the caller of efi_call_phys(), then parameter 1,
+	 * parameter 2, ..., param n. To make things easy, we save the return
+	 * address of efi_call_phys in a global variable.
+	 */
+	popl	%edx
+	movl	%edx, saved_return_addr
+	/* get the function pointer into ECX*/
+	popl	%ecx
+	movl	%ecx, efi_rt_function_ptr
+	movl	$2f, %edx
+	subl	$__PAGE_OFFSET, %edx
+	pushl	%edx
+
+	/*
+	 * 3. Clear PG bit in %CR0.
+	 */
+	movl	%cr0, %edx
+	andl	$0x7fffffff, %edx
+	movl	%edx, %cr0
+	jmp	1f
+1:
+
+	/*
+	 * 4. Adjust stack pointer.
+	 */
+	subl	$__PAGE_OFFSET, %esp
+
+	/*
+	 * 5. Call the physical function.
+	 */
+	jmp	*%ecx
+
+2:
+	/*
+	 * 6. After EFI runtime service returns, control will return to
+	 * following instruction. We'd better readjust stack pointer first.
+	 */
+	addl	$__PAGE_OFFSET, %esp
+
+	/*
+	 * 7. Restore PG bit
+	 */
+	movl	%cr0, %edx
+	orl	$0x80000000, %edx
+	movl	%edx, %cr0
+	jmp	1f
+1:
+	/*
+	 * 8. Now restore the virtual mode from flat mode by
+	 * adding EIP with PAGE_OFFSET.
+	 */
+	movl	$1f, %edx
+	jmp	*%edx
+1:
+
+	/*
+	 * 9. Balance the stack. And because EAX contain the return value,
+	 * we'd better not clobber it.
+	 */
+	leal	efi_rt_function_ptr, %edx
+	movl	(%edx), %ecx
+	pushl	%ecx
+
+	/*
+	 * 10. Push the saved return address onto the stack and return.
+	 */
+	leal	saved_return_addr, %edx
+	movl	(%edx), %ecx
+	pushl	%ecx
+	ret
+.previous
+
+.data
+saved_return_addr:
+	.long 0
+efi_rt_function_ptr:
+	.long 0
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/i8259.c 001-linus.patch/arch/i386/kernel/i8259.c
--- 000-virgin/arch/i386/kernel/i8259.c	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/arch/i386/kernel/i8259.c	Tue Dec 30 16:38:56 2003
@@ -419,8 +419,10 @@ void __init init_IRQ(void)
 	 * us. (some of these will be overridden and become
 	 * 'special' SMP interrupts)
 	 */
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
+		if (i >= NR_IRQS)
+			break;
 		if (vector != SYSCALL_VECTOR) 
 			set_intr_gate(vector, interrupt[i]);
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/io_apic.c 001-linus.patch/arch/i386/kernel/io_apic.c
--- 000-virgin/arch/i386/kernel/io_apic.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/i386/kernel/io_apic.c	Tue Dec 30 16:38:56 2003
@@ -76,6 +76,14 @@ static struct irq_pin_list {
 	int apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
 
+#ifdef CONFIG_PCI_USE_VECTOR
+int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};
+#define vector_to_irq(vector) 	\
+	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
+#else
+#define vector_to_irq(vector)	(vector)
+#endif
+
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
@@ -249,7 +257,7 @@ static void clear_IO_APIC (void)
 			clear_IO_APIC_pin(apic, pin);
 }
 
-static void set_ioapic_affinity(unsigned int irq, cpumask_t cpumask)
+static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 {
 	unsigned long flags;
 	int pin;
@@ -288,7 +296,7 @@ static void set_ioapic_affinity(unsigned
 
 extern cpumask_t irq_affinity[NR_IRQS];
 
-static cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
+cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
 
 #define IRQBALANCE_CHECK_ARCH -999
 static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
@@ -670,13 +678,11 @@ static int __init irqbalance_disable(cha
 
 __setup("noirqbalance", irqbalance_disable);
 
-static void set_ioapic_affinity(unsigned int irq, cpumask_t mask);
-
 static inline void move_irq(int irq)
 {
 	/* note - we hold the desc->lock */
 	if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
-		set_ioapic_affinity(irq, pending_irq_balance_cpumask[irq]);
+		set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
 		cpus_clear(pending_irq_balance_cpumask[irq]);
 	}
 }
@@ -853,7 +859,7 @@ void __init setup_ioapic_dest(cpumask_t 
 			if (irq_entry == -1)
 				continue;
 			irq = pin_2_irq(irq_entry, ioapic, pin);
-			set_ioapic_affinity(irq, mask);
+			set_ioapic_affinity_irq(irq, mask);
 		}
 
 	}
@@ -1141,7 +1147,8 @@ static inline int IO_APIC_irq_trigger(in
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
 u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
 
-static int __init assign_irq_vector(int irq)
+#ifndef CONFIG_PCI_USE_VECTOR
+int __init assign_irq_vector(int irq)
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 	BUG_ON(irq >= NR_IRQ_VECTORS);
@@ -1158,11 +1165,36 @@ next:
 	}
 
 	IO_APIC_VECTOR(irq) = current_vector;
+
 	return current_vector;
 }
+#endif
 
-static struct hw_interrupt_type ioapic_level_irq_type;
-static struct hw_interrupt_type ioapic_edge_irq_type;
+static struct hw_interrupt_type ioapic_level_type;
+static struct hw_interrupt_type ioapic_edge_type;
+
+#define IOAPIC_AUTO	-1
+#define IOAPIC_EDGE	0
+#define IOAPIC_LEVEL	1
+
+static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+{
+	if (use_pci_vector() && !platform_legacy_irq(irq)) {
+		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+				trigger == IOAPIC_LEVEL)
+			irq_desc[vector].handler = &ioapic_level_type;
+		else
+			irq_desc[vector].handler = &ioapic_edge_type;
+		set_intr_gate(vector, interrupt[vector]);
+	} else	{
+		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+				trigger == IOAPIC_LEVEL)
+			irq_desc[irq].handler = &ioapic_level_type;
+		else
+			irq_desc[irq].handler = &ioapic_edge_type;
+		set_intr_gate(vector, interrupt[irq]);
+	}
+}
 
 void __init setup_IO_APIC_irqs(void)
 {
@@ -1220,13 +1252,7 @@ void __init setup_IO_APIC_irqs(void)
 		if (IO_APIC_IRQ(irq)) {
 			vector = assign_irq_vector(irq);
 			entry.vector = vector;
-
-			if (IO_APIC_irq_trigger(irq))
-				irq_desc[irq].handler = &ioapic_level_irq_type;
-			else
-				irq_desc[irq].handler = &ioapic_edge_irq_type;
-
-			set_intr_gate(vector, interrupt[irq]);
+			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
 		
 			if (!apic && (irq < 16))
 				disable_8259A_irq(irq);
@@ -1273,7 +1299,7 @@ void __init setup_ExtINT_IRQ0_pin(unsign
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we have a 8259A-master in AEOI mode ...
 	 */
-	irq_desc[0].handler = &ioapic_edge_irq_type;
+	irq_desc[0].handler = &ioapic_edge_type;
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -1763,9 +1789,6 @@ static int __init timer_irq_works(void)
  * that was delayed but this is now handled in the device
  * independent code.
  */
-#define enable_edge_ioapic_irq unmask_IO_APIC_irq
-
-static void disable_edge_ioapic_irq (unsigned int irq) { /* nothing */ }
 
 /*
  * Starting up a edge-triggered IO-APIC interrupt is
@@ -1776,7 +1799,6 @@ static void disable_edge_ioapic_irq (uns
  * This is not complete - we should be able to fake
  * an edge even if it isn't on the 8259A...
  */
-
 static unsigned int startup_edge_ioapic_irq(unsigned int irq)
 {
 	int was_pending = 0;
@@ -1794,8 +1816,6 @@ static unsigned int startup_edge_ioapic_
 	return was_pending;
 }
 
-#define shutdown_edge_ioapic_irq	disable_edge_ioapic_irq
-
 /*
  * Once we have recorded IRQ_PENDING already, we can mask the
  * interrupt for real. This prevents IRQ storms from unhandled
@@ -1810,9 +1830,6 @@ static void ack_edge_ioapic_irq(unsigned
 	ack_APIC_irq();
 }
 
-static void end_edge_ioapic_irq (unsigned int i) { /* nothing */ }
-
-
 /*
  * Level triggered interrupts can just be masked,
  * and shutting down and starting up the interrupt
@@ -1834,10 +1851,6 @@ static unsigned int startup_level_ioapic
 	return 0; /* don't check for pending */
 }
 
-#define shutdown_level_ioapic_irq	mask_IO_APIC_irq
-#define enable_level_ioapic_irq		unmask_IO_APIC_irq
-#define disable_level_ioapic_irq	mask_IO_APIC_irq
-
 static void end_level_ioapic_irq (unsigned int irq)
 {
 	unsigned long v;
@@ -1864,6 +1877,7 @@ static void end_level_ioapic_irq (unsign
  * The idea is from Manfred Spraul.  --macro
  */
 	i = IO_APIC_VECTOR(irq);
+
 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
 	ack_APIC_irq();
@@ -1898,7 +1912,57 @@ static void end_level_ioapic_irq (unsign
 	}
 }
 
-static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
+#ifdef CONFIG_PCI_USE_VECTOR
+static unsigned int startup_edge_ioapic_vector(unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	return startup_edge_ioapic_irq(irq);
+}
+
+static void ack_edge_ioapic_vector(unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	ack_edge_ioapic_irq(irq);
+}
+
+static unsigned int startup_level_ioapic_vector (unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	return startup_level_ioapic_irq (irq);
+}
+
+static void end_level_ioapic_vector (unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	end_level_ioapic_irq(irq);
+}
+
+static void mask_IO_APIC_vector (unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	mask_IO_APIC_irq(irq);
+}
+
+static void unmask_IO_APIC_vector (unsigned int vector)
+{
+	int irq = vector_to_irq(vector);
+
+	unmask_IO_APIC_irq(irq);
+}
+
+static void set_ioapic_affinity_vector (unsigned int vector,
+					cpumask_t cpu_mask)
+{
+	int irq = vector_to_irq(vector);
+
+	set_ioapic_affinity_irq(irq, cpu_mask);
+}
+#endif
 
 /*
  * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1908,26 +1972,25 @@ static void mask_and_ack_level_ioapic_ir
  * edge-triggered handler, without risking IRQ storms and other ugly
  * races.
  */
-
-static struct hw_interrupt_type ioapic_edge_irq_type = {
+static struct hw_interrupt_type ioapic_edge_type = {
 	.typename 	= "IO-APIC-edge",
-	.startup 	= startup_edge_ioapic_irq,
-	.shutdown 	= shutdown_edge_ioapic_irq,
-	.enable 	= enable_edge_ioapic_irq,
-	.disable 	= disable_edge_ioapic_irq,
-	.ack 		= ack_edge_ioapic_irq,
-	.end 		= end_edge_ioapic_irq,
+	.startup 	= startup_edge_ioapic,
+	.shutdown 	= shutdown_edge_ioapic,
+	.enable 	= enable_edge_ioapic,
+	.disable 	= disable_edge_ioapic,
+	.ack 		= ack_edge_ioapic,
+	.end 		= end_edge_ioapic,
 	.set_affinity 	= set_ioapic_affinity,
 };
 
-static struct hw_interrupt_type ioapic_level_irq_type = {
+static struct hw_interrupt_type ioapic_level_type = {
 	.typename 	= "IO-APIC-level",
-	.startup 	= startup_level_ioapic_irq,
-	.shutdown 	= shutdown_level_ioapic_irq,
-	.enable 	= enable_level_ioapic_irq,
-	.disable 	= disable_level_ioapic_irq,
-	.ack 		= mask_and_ack_level_ioapic_irq,
-	.end 		= end_level_ioapic_irq,
+	.startup 	= startup_level_ioapic,
+	.shutdown 	= shutdown_level_ioapic,
+	.enable 	= enable_level_ioapic,
+	.disable 	= disable_level_ioapic,
+	.ack 		= mask_and_ack_level_ioapic,
+	.end 		= end_level_ioapic,
 	.set_affinity 	= set_ioapic_affinity,
 };
 
@@ -1947,7 +2010,13 @@ static inline void init_IO_APIC_traps(vo
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	for (irq = 0; irq < NR_IRQS ; irq++) {
-		if (IO_APIC_IRQ(irq) && !IO_APIC_VECTOR(irq)) {
+		int tmp = irq;
+		if (use_pci_vector()) {
+			if (!platform_legacy_irq(tmp))
+				if ((tmp = vector_to_irq(tmp)) == -1)
+					continue;
+		}
+		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
 			/*
 			 * Hmm.. We don't have an entry for this,
 			 * so default to an old-fashioned 8259
@@ -2379,10 +2448,12 @@ int io_apic_set_pci_routing (int ioapic,
 		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
 		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
 
+ 	if (use_pci_vector() && !platform_legacy_irq(irq))
+		irq = IO_APIC_VECTOR(irq);
 	if (edge_level) {
-	irq_desc[irq].handler = &ioapic_level_irq_type;
+		irq_desc[irq].handler = &ioapic_level_type;
 	} else {
-		irq_desc[irq].handler = &ioapic_edge_irq_type;
+		irq_desc[irq].handler = &ioapic_edge_type;
 	}
 
 	set_intr_gate(entry.vector, interrupt[irq]);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/irq.c 001-linus.patch/arch/i386/kernel/irq.c
--- 000-virgin/arch/i386/kernel/irq.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/i386/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -138,17 +138,19 @@ atomic_t irq_mis_count;
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_printf(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ",j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
@@ -170,28 +172,32 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	seq_printf(p, "NMI: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "%10u ", nmi_count(j));
-	seq_putc(p, '\n');
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
-	seq_printf(p, "LOC: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
-	seq_putc(p, '\n');
+		seq_printf(p, "LOC: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+		seq_putc(p, '\n');
 #endif
-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 #ifdef CONFIG_X86_IO_APIC
 #ifdef APIC_MISMATCH_DEBUG
-	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
 #endif
+	}
 	return 0;
 }
 
+
+
+
 #ifdef CONFIG_SMP
 inline void synchronize_irq(unsigned int irq)
 {
@@ -505,6 +511,20 @@ out:
 	return 1;
 }
 
+int can_request_irq(unsigned int irq, unsigned long irqflags)
+{
+	struct irqaction *action;
+
+	if (irq >= NR_IRQS)
+		return 0;
+	action = irq_desc[irq].action;
+	if (action) {
+		if (irqflags & action->flags & SA_SHIRQ)
+			action = NULL;
+	}
+	return !action;
+}
+
 /**
  *	request_irq - allocate an interrupt line
  *	@irq: Interrupt line to allocate
@@ -898,48 +918,6 @@ int setup_irq(unsigned int irq, struct i
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
-static unsigned int parse_hex_value(const char __user *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum[HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	int i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first HEX_DIGITS characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-
-	for (i = 0; i < count; i++) {
-		unsigned int c = hexnum[i];
-		int k;
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 4);
-		for (k = 0; k < 4; ++k)
-			if (test_bit(k, (unsigned long *)&c))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 #ifdef CONFIG_SMP
 
 static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
@@ -949,20 +927,10 @@ cpumask_t irq_affinity[NR_IRQS] = { [0 .
 static int irq_affinity_read_proc(char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int k, len;
-	cpumask_t tmp = irq_affinity[(long)data];
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-
-	len = 0;
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -975,7 +943,7 @@ static int irq_affinity_write_proc(struc
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
@@ -1000,10 +968,11 @@ static int irq_affinity_write_proc(struc
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	unsigned long *mask = (unsigned long *) data;
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%08lx\n", *mask);
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
@@ -1013,7 +982,7 @@ static int prof_cpu_mask_write_proc (str
 	unsigned long full_count = count, err;
 	cpumask_t new_value;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/mpparse.c 001-linus.patch/arch/i386/kernel/mpparse.c
--- 000-virgin/arch/i386/kernel/mpparse.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/i386/kernel/mpparse.c	Tue Dec 30 16:38:56 2003
@@ -1147,15 +1147,19 @@ void __init mp_parse_prt (void)
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
 			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-			entry->irq = irq;
+ 			if (use_pci_vector() && !platform_legacy_irq(irq))
+ 				irq = IO_APIC_VECTOR(irq);
+ 			entry->irq = irq;
 			continue;
 		}
 
 		mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
-		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low))
-			entry->irq = irq;
-
+		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low)) {
+ 			if (use_pci_vector() && !platform_legacy_irq(irq))
+ 				irq = IO_APIC_VECTOR(irq);
+ 			entry->irq = irq;
+ 		}
 		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
 			entry->id.segment, entry->id.bus, 
 			entry->id.device, ('A' + entry->pin), 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/process.c 001-linus.patch/arch/i386/kernel/process.c
--- 000-virgin/arch/i386/kernel/process.c	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/arch/i386/kernel/process.c	Tue Dec 30 16:38:56 2003
@@ -507,7 +507,7 @@ struct task_struct * __switch_to(struct 
 	/*
 	 * Reload esp0, LDT and the page table pointer:
 	 */
-	load_esp0(tss, next->esp0);
+	load_esp0(tss, next);
 
 	/*
 	 * Load the per-thread Thread-Local Storage descriptor.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/reboot.c 001-linus.patch/arch/i386/kernel/reboot.c
--- 000-virgin/arch/i386/kernel/reboot.c	Wed Dec 17 18:58:38 2003
+++ 001-linus.patch/arch/i386/kernel/reboot.c	Tue Dec 30 16:38:56 2003
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
+#include <linux/efi.h>
 #include <asm/uaccess.h>
 #include <asm/apic.h>
 #include "mach_reboot.h"
@@ -263,7 +264,12 @@ void machine_restart(char * __unused)
 	disable_IO_APIC();
 #endif
 
-	if(!reboot_thru_bios) {
+	if (!reboot_thru_bios) {
+		if (efi_enabled) {
+			efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, 0);
+			__asm__ __volatile__("lidt %0": :"m" (no_idt));
+			__asm__ __volatile__("int3");
+		}
 		/* rebooting needs to touch the page at absolute addr 0 */
 		*((unsigned short *)__va(0x472)) = reboot_mode;
 		for (;;) {
@@ -273,6 +279,8 @@ void machine_restart(char * __unused)
 			__asm__ __volatile__("int3");
 		}
 	}
+	if (efi_enabled)
+		efi.reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, 0);
 
 	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
 }
@@ -287,6 +295,8 @@ EXPORT_SYMBOL(machine_halt);
 
 void machine_power_off(void)
 {
+	if (efi_enabled)
+		efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, 0);
 	if (pm_power_off)
 		pm_power_off();
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/setup.c 001-linus.patch/arch/i386/kernel/setup.c
--- 000-virgin/arch/i386/kernel/setup.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/i386/kernel/setup.c	Tue Dec 30 16:38:56 2003
@@ -36,6 +36,8 @@
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/efi.h>
+#include <linux/init.h>
 #include <video/edid.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
@@ -56,6 +58,10 @@ static inline char * __init machine_spec
  * Machine setup..
  */
 
+#ifdef CONFIG_EFI
+int efi_enabled = 0;
+#endif
+
 /* cpu data as detected by the assembly code in head.S */
 struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 /* common cpu data for all cpus */
@@ -144,6 +150,20 @@ static void __init limit_regions(unsigne
 	unsigned long long current_addr = 0;
 	int i;
 
+	if (efi_enabled) {
+		for (i = 0; i < memmap.nr_map; i++) {
+			current_addr = memmap.map[i].phys_addr +
+				       (memmap.map[i].num_pages << 12);
+			if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
+				if (current_addr >= size) {
+					memmap.map[i].num_pages -=
+						(((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
+					memmap.nr_map = i + 1;
+					return;
+				}
+			}
+		}
+	}
 	for (i = 0; i < e820.nr_map; i++) {
 		if (e820.map[i].type == E820_RAM) {
 			current_addr = e820.map[i].addr + e820.map[i].size;
@@ -159,17 +179,21 @@ static void __init limit_regions(unsigne
 static void __init add_memory_region(unsigned long long start,
                                   unsigned long long size, int type)
 {
-	int x = e820.nr_map;
+	int x;
 
-	if (x == E820MAX) {
-	    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
-	    return;
-	}
+	if (!efi_enabled) {
+       		x = e820.nr_map;
 
-	e820.map[x].addr = start;
-	e820.map[x].size = size;
-	e820.map[x].type = type;
-	e820.nr_map++;
+		if (x == E820MAX) {
+		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+		    return;
+		}
+
+		e820.map[x].addr = start;
+		e820.map[x].size = size;
+		e820.map[x].type = type;
+		e820.nr_map++;
+	}
 } /* add_memory_region */
 
 #define E820_DEBUG	1
@@ -446,7 +470,6 @@ static inline void copy_edd(void)
 static void __init setup_memory_region(void)
 {
 	char *who = machine_specific_memory_setup();
-
 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 	print_memory_map(who);
 } /* setup_memory_region */
@@ -584,6 +607,23 @@ static void __init parse_cmdline_early (
 }
 
 /*
+ * Callback for efi_memory_walk.
+ */
+static int __init
+efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+{
+	unsigned long *max_pfn = arg, pfn;
+
+	if (start < end) {
+		pfn = PFN_UP(end -1);
+		if (pfn > *max_pfn)
+			*max_pfn = pfn;
+	}
+	return 0;
+}
+
+
+/*
  * Find the highest page frame number we have available
  */
 void __init find_max_pfn(void)
@@ -591,6 +631,11 @@ void __init find_max_pfn(void)
 	int i;
 
 	max_pfn = 0;
+	if (efi_enabled) {
+		efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+		return;
+	}
+
 	for (i = 0; i < e820.nr_map; i++) {
 		unsigned long start, end;
 		/* RAM? */
@@ -665,6 +710,25 @@ unsigned long __init find_max_low_pfn(vo
 }
 
 #ifndef CONFIG_DISCONTIGMEM
+
+/*
+ * Free all available memory for boot time allocation.  Used
+ * as a callback function by efi_memory_walk()
+ */
+
+static int __init
+free_available_memory(unsigned long start, unsigned long end, void *arg)
+{
+	/* check max_low_pfn */
+	if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
+		return 0;
+	if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
+		end = (max_low_pfn + 1) << PAGE_SHIFT;
+	if (start < end)
+		free_bootmem(start, end - start);
+
+	return 0;
+}
 /*
  * Register fully available low RAM pages with the bootmem allocator.
  */
@@ -672,6 +736,10 @@ static void __init register_bootmem_low_
 {
 	int i;
 
+	if (efi_enabled) {
+		efi_memmap_walk(free_available_memory, NULL);
+		return;
+	}
 	for (i = 0; i < e820.nr_map; i++) {
 		unsigned long curr_pfn, last_pfn, size;
 		/*
@@ -799,9 +867,9 @@ extern unsigned long setup_memory(void);
  * Request address space for all standard RAM and ROM resources
  * and also for regions reported as reserved by the e820.
  */
-static void __init register_memory(unsigned long max_low_pfn)
+static void __init
+legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
 {
-	unsigned long low_mem_size;
 	int i;
 
 	probe_roms();
@@ -826,11 +894,26 @@ static void __init register_memory(unsig
 			 *  so we try it repeatedly and let the resource manager
 			 *  test it.
 			 */
-			request_resource(res, &code_resource);
-			request_resource(res, &data_resource);
+			request_resource(res, code_resource);
+			request_resource(res, data_resource);
 		}
 	}
+}
 
+/*
+ * Request address space for all standard resources
+ */
+static void __init register_memory(unsigned long max_low_pfn)
+{
+	unsigned long low_mem_size;
+	int i;
+
+	if (efi_enabled)
+		efi_initialize_iomem_resources(&code_resource, &data_resource);
+	else
+		legacy_init_iomem_resources(&code_resource, &data_resource);
+
+ 	 /* EFI systems may still have VGA */
 	request_graphics_resource();
 
 	/* request I/O space for devices used on all i[345]86 PCs */
@@ -950,6 +1033,13 @@ static int __init noreplacement_setup(ch
 
 __setup("noreplacement", noreplacement_setup); 
 
+/*
+ * Determine if we were loaded by an EFI loader.  If so, then we have also been
+ * passed the efi memmap, systab, etc., so we should use these data structures
+ * for initialization.  Note, the efi init code path is determined by the
+ * global efi_enabled. This allows the same kernel image to be used on existing
+ * systems (with a traditional BIOS) as well as on EFI systems.
+ */
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long max_low_pfn;
@@ -958,6 +1048,18 @@ void __init setup_arch(char **cmdline_p)
 	pre_setup_arch_hook();
 	early_cpu_init();
 
+	/*
+	 * FIXME: This isn't an official loader_type right
+	 * now but does currently work with elilo.
+	 * If we were configured as an EFI kernel, check to make
+	 * sure that we were loaded correctly from elilo and that
+	 * the system table is valid.  If not, then initialize normally.
+	 */
+#ifdef CONFIG_EFI
+	if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
+		efi_enabled = 1;
+#endif
+
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
@@ -979,7 +1081,11 @@ void __init setup_arch(char **cmdline_p)
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
 	ARCH_SETUP
-	setup_memory_region();
+	if (efi_enabled)
+		efi_init();
+	else
+		setup_memory_region();
+
 	copy_edd();
 
 	if (!MOUNT_ROOT_RDONLY)
@@ -1013,6 +1119,8 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_X86_GENERICARCH
 	generic_apic_probe(*cmdline_p);
 #endif	
+	if (efi_enabled)
+		efi_map_memmap();
 
 	/*
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
@@ -1028,7 +1136,8 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-	conswitchp = &vga_con;
+	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+		conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/time.c 001-linus.patch/arch/i386/kernel/time.c
--- 000-virgin/arch/i386/kernel/time.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/i386/kernel/time.c	Tue Dec 30 16:38:56 2003
@@ -44,6 +44,7 @@
 #include <linux/module.h>
 #include <linux/sysdev.h>
 #include <linux/bcd.h>
+#include <linux/efi.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -94,7 +95,7 @@ void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long seq;
 	unsigned long usec, sec;
-	unsigned long max_ntp_tick = tick_usec - tickadj;
+	unsigned long max_ntp_tick;
 
 	do {
 		unsigned long lost;
@@ -110,13 +111,14 @@ void do_gettimeofday(struct timeval *tv)
 		 * Better to lose some accuracy than have time go backwards..
 		 */
 		if (unlikely(time_adjust < 0)) {
+			max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
 			usec = min(usec, max_ntp_tick);
 
 			if (lost)
 				usec += lost * max_ntp_tick;
 		}
 		else if (unlikely(lost))
-			usec += lost * tick_usec;
+			usec += lost * (USEC_PER_SEC / HZ);
 
 		sec = xtime.tv_sec;
 		usec += (xtime.tv_nsec / 1000);
@@ -174,7 +176,10 @@ static int set_rtc_mmss(unsigned long no
 
 	/* gets recalled with irq locally disabled */
 	spin_lock(&rtc_lock);
-	retval = mach_set_rtc_mmss(nowtime);
+	if (efi_enabled)
+		retval = efi_set_rtc_mmss(nowtime);
+	else
+		retval = mach_set_rtc_mmss(nowtime);
 	spin_unlock(&rtc_lock);
 
 	return retval;
@@ -232,7 +237,13 @@ static inline void do_timer_interrupt(in
 			>= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
 	    (xtime.tv_nsec / 1000)
 			<= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) {
-		if (set_rtc_mmss(xtime.tv_sec) == 0)
+		/* horrible...FIXME */
+		if (efi_enabled) {
+	 		if (efi_set_rtc_mmss(xtime.tv_sec) == 0)
+				last_rtc_update = xtime.tv_sec;
+			else
+				last_rtc_update = xtime.tv_sec - 600;
+		} else if (set_rtc_mmss(xtime.tv_sec) == 0)
 			last_rtc_update = xtime.tv_sec;
 		else
 			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
@@ -286,7 +297,10 @@ unsigned long get_cmos_time(void)
 
 	spin_lock(&rtc_lock);
 
-	retval = mach_get_cmos_time();
+	if (efi_enabled)
+		retval = efi_get_time();
+	else
+		retval = mach_get_cmos_time();
 
 	spin_unlock(&rtc_lock);
 
@@ -297,6 +311,7 @@ static struct sysdev_class pit_sysclass 
 	set_kset_name("pit"),
 };
 
+
 /* XXX this driverfs stuff should probably go elsewhere later -john */
 static struct sys_device device_i8253 = {
 	.id	= 0,
@@ -328,6 +343,8 @@ void __init hpet_time_init(void)
 	}
 
 	cur_timer = select_timer();
+	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
+
 	time_init_hook();
 }
 #endif
@@ -344,12 +361,13 @@ void __init time_init(void)
 		return;
 	}
 #endif
-
 	xtime.tv_sec = get_cmos_time();
 	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
 	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
 
 	cur_timer = select_timer();
+	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
+
 	time_init_hook();
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/timers/timer_cyclone.c 001-linus.patch/arch/i386/kernel/timers/timer_cyclone.c
--- 000-virgin/arch/i386/kernel/timers/timer_cyclone.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/i386/kernel/timers/timer_cyclone.c	Tue Dec 30 16:38:56 2003
@@ -253,6 +253,7 @@ static void delay_cyclone(unsigned long 
 
 /* cyclone timer_opts struct */
 struct timer_opts timer_cyclone = {
+	.name = "cyclone",
 	.init = init_cyclone, 
 	.mark_offset = mark_offset_cyclone, 
 	.get_offset = get_offset_cyclone,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/timers/timer_hpet.c 001-linus.patch/arch/i386/kernel/timers/timer_hpet.c
--- 000-virgin/arch/i386/kernel/timers/timer_hpet.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/arch/i386/kernel/timers/timer_hpet.c	Tue Dec 30 16:38:56 2003
@@ -178,6 +178,7 @@ static int __init init_hpet(char* overri
 
 /* tsc timer_opts struct */
 struct timer_opts timer_hpet = {
+	.name = 		"hpet",
 	.init =			init_hpet,
 	.mark_offset =		mark_offset_hpet,
 	.get_offset =		get_offset_hpet,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/timers/timer_none.c 001-linus.patch/arch/i386/kernel/timers/timer_none.c
--- 000-virgin/arch/i386/kernel/timers/timer_none.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/arch/i386/kernel/timers/timer_none.c	Tue Dec 30 16:38:56 2003
@@ -36,6 +36,7 @@ static void delay_none(unsigned long loo
 
 /* tsc timer_opts struct */
 struct timer_opts timer_none = {
+	.name = 	"none",
 	.init =		init_none, 
 	.mark_offset =	mark_offset_none, 
 	.get_offset =	get_offset_none,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/timers/timer_pit.c 001-linus.patch/arch/i386/kernel/timers/timer_pit.c
--- 000-virgin/arch/i386/kernel/timers/timer_pit.c	Wed Dec 17 18:59:27 2003
+++ 001-linus.patch/arch/i386/kernel/timers/timer_pit.c	Tue Dec 30 16:38:56 2003
@@ -149,6 +149,7 @@ static unsigned long get_offset_pit(void
 
 /* tsc timer_opts struct */
 struct timer_opts timer_pit = {
+	.name = 	"pit",
 	.init =		init_pit, 
 	.mark_offset =	mark_offset_pit, 
 	.get_offset =	get_offset_pit,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/timers/timer_tsc.c 001-linus.patch/arch/i386/kernel/timers/timer_tsc.c
--- 000-virgin/arch/i386/kernel/timers/timer_tsc.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/i386/kernel/timers/timer_tsc.c	Tue Dec 30 16:38:56 2003
@@ -472,6 +472,7 @@ __setup("notsc", tsc_setup);
 
 /* tsc timer_opts struct */
 struct timer_opts timer_tsc = {
+	.name = 	"tsc",
 	.init =		init_tsc,
 	.mark_offset =	mark_offset_tsc, 
 	.get_offset =	get_offset_tsc,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/kernel/vm86.c 001-linus.patch/arch/i386/kernel/vm86.c
--- 000-virgin/arch/i386/kernel/vm86.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/i386/kernel/vm86.c	Tue Dec 30 16:38:56 2003
@@ -124,7 +124,8 @@ struct pt_regs * save_v86_state(struct k
 
 	tss = init_tss + get_cpu();
 	current->thread.esp0 = current->thread.saved_esp0;
-	load_esp0(tss, current->thread.esp0);
+	current->thread.sysenter_cs = __KERNEL_CS;
+	load_esp0(tss, &current->thread);
 	current->thread.saved_esp0 = 0;
 	put_cpu();
 
@@ -301,8 +302,10 @@ static void do_sys_vm86(struct kernel_vm
 	asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
 
 	tss = init_tss + get_cpu();
-	tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
-	disable_sysenter(tss);
+	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
+	if (cpu_has_sep)
+		tsk->thread.sysenter_cs = 0;
+	load_esp0(tss, &tsk->thread);
 	put_cpu();
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/lib/usercopy.c 001-linus.patch/arch/i386/lib/usercopy.c
--- 000-virgin/arch/i386/lib/usercopy.c	Wed Dec 17 18:57:59 2003
+++ 001-linus.patch/arch/i386/lib/usercopy.c	Tue Dec 30 16:38:56 2003
@@ -541,8 +541,10 @@ survive:
 				goto survive;
 			}
 
-			if (retval != 1)
+			if (retval != 1) {
+				up_read(&current->mm->mmap_sem);
 		       		break;
+		       	}
 
 			maddr = kmap_atomic(pg, KM_USER0);
 			memcpy(maddr + offset, from, len);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/mm/hugetlbpage.c 001-linus.patch/arch/i386/mm/hugetlbpage.c
--- 000-virgin/arch/i386/mm/hugetlbpage.c	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/arch/i386/mm/hugetlbpage.c	Tue Dec 30 16:38:56 2003
@@ -534,7 +534,7 @@ int is_hugepage_mem_enough(size_t size)
  * this far.
  */
 static struct page *hugetlb_nopage(struct vm_area_struct *vma,
-				unsigned long address, int unused)
+				unsigned long address, int *unused)
 {
 	BUG();
 	return NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/mm/init.c 001-linus.patch/arch/i386/mm/init.c
--- 000-virgin/arch/i386/mm/init.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/arch/i386/mm/init.c	Tue Dec 30 16:38:56 2003
@@ -26,6 +26,7 @@
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/efi.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -165,12 +166,30 @@ static inline int page_kills_ppro(unsign
 	return 0;
 }
 
+extern int is_available_memory(efi_memory_desc_t *);
+
 static inline int page_is_ram(unsigned long pagenr)
 {
 	int i;
+	unsigned long addr, end;
+
+	if (efi_enabled) {
+		efi_memory_desc_t *md;
+
+		for (i = 0; i < memmap.nr_map; i++) {
+			md = &memmap.map[i];
+			if (!is_available_memory(md))
+				continue;
+			addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
+			end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT;
+
+			if ((pagenr >= addr) && (pagenr < end))
+				return 1;
+		}
+		return 0;
+	}
 
 	for (i = 0; i < e820.nr_map; i++) {
-		unsigned long addr, end;
 
 		if (e820.map[i].type != E820_RAM)	/* not usable memory */
 			continue;
@@ -388,12 +407,6 @@ void __init paging_init(void)
 
 void __init test_wp_bit(void)
 {
-	if (cpu_has_pse) {
-		/* Ok, all PSE-capable CPUs are definitely handling the WP bit right. */
-		boot_cpu_data.wp_works_ok = 1;
-		return;
-	}
-
 	printk("Checking if this processor honours the WP bit even in supervisor mode... ");
 
 	/* Any page-aligned address will do, the test is non-destructive */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/i386/pci/irq.c 001-linus.patch/arch/i386/pci/irq.c
--- 000-virgin/arch/i386/pci/irq.c	Wed Dec 17 18:59:57 2003
+++ 001-linus.patch/arch/i386/pci/irq.c	Tue Dec 30 16:38:56 2003
@@ -455,7 +455,10 @@ static __init int intel_router_probe(str
 #if 0 /* Let's see what chip this is supposed to be ... */
 	/* We must not touch 440GX even if we have tables. 440GX has
 	   different IRQ routing weirdness */
-	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82440GX, NULL))
+	if (	pci_find_device(PCI_VENDOR_ID_INTEL,
+				PCI_DEVICE_ID_INTEL_82443GX_0, NULL) ||
+		pci_find_device(PCI_VENDOR_ID_INTEL,
+				PCI_DEVICE_ID_INTEL_82443GX_2, NULL))
 		return 0;
 #endif
 
@@ -695,11 +698,6 @@ static struct irq_info *pirq_get_info(st
 	return NULL;
 }
 
-static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-	return IRQ_NONE;
-}
-
 static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 {
 	u8 pin;
@@ -761,11 +759,8 @@ static int pcibios_lookup_irq(struct pci
 		for (i = 0; i < 16; i++) {
 			if (!(mask & (1 << i)))
 				continue;
-			if (pirq_penalty[i] < pirq_penalty[newirq] &&
-			    !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
-				free_irq(i, dev);
+			if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ))
 				newirq = i;
-			}
 		}
 	}
 	DBG(" -> newirq=%d", newirq);
@@ -813,8 +808,10 @@ static int pcibios_lookup_irq(struct pci
 		    	if ( dev2->irq && dev2->irq != irq && \
 			(!(pci_probe & PCI_USE_PIRQ_MASK) || \
 			((1 << dev2->irq) & mask)) ) {
+#ifndef CONFIG_PCI_USE_VECTOR
 		    		printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
 				       pci_name(dev2), dev2->irq, irq);
+#endif
 		    		continue;
 		    	}
 			dev2->irq = irq;
@@ -878,6 +875,10 @@ static void __init pcibios_fixup_irqs(vo
 							bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
 				}
 				if (irq >= 0) {
+					if (use_pci_vector() &&
+						!platform_legacy_irq(irq))
+						irq = IO_APIC_VECTOR(irq);
+
 					printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
 						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
 					dev->irq = irq;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/Kconfig 001-linus.patch/arch/ia64/Kconfig
--- 000-virgin/arch/ia64/Kconfig	Wed Dec 17 18:59:41 2003
+++ 001-linus.patch/arch/ia64/Kconfig	Tue Dec 30 16:38:56 2003
@@ -164,11 +164,6 @@ config ACPI
 	  The ACPI Sourceforge project may also be of interest:
 	  <http://sf.net/projects/acpi/>
 
-config ACPI_EFI
-	bool
-	depends on !IA64_HP_SIM
-	default y
-
 config ACPI_INTERPRETER
 	bool
 	depends on !IA64_HP_SIM
@@ -375,6 +370,11 @@ config COMPAT
 	depends on IA32_SUPPORT
 	default y
 
+config HAVE_DEC_LOCK
+	bool
+	depends on (SMP || PREEMPT)
+	default y
+
 config PERFMON
 	bool "Performance monitor support"
 	help
@@ -394,15 +394,11 @@ config IA64_PALINFO
 	  To use this option, you have to ensure that the "/proc file system
 	  support" (CONFIG_PROC_FS) is enabled, too.
 
-config IA64_SALINFO
-	tristate "/proc/sal support"
-	help
-	  The /proc/sal directory exports the SAL (system abstraction layer)
-	  feature bits, like whether the platform is subject to ITC drift.  It
-	  is intended to be used by user programs that care about such things.
 
-	  To use this option, you have to ensure that the "/proc file system
-	  support" (CONFIG_PROC_FS) is enabled, too.
+config EFI
+	bool
+	depends on !IA64_HP_SIM
+	default y
 
 config EFI_VARS
 	tristate "/proc/efi/vars support"
@@ -579,6 +575,7 @@ config IA64_GRANULE_16MB
 
 config IA64_GRANULE_64MB
 	bool "64MB"
+	depends on !(IA64_GENERIC || IA64_HP_ZX1)
 
 endchoice
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/Makefile 001-linus.patch/arch/ia64/Makefile
--- 000-virgin/arch/ia64/Makefile	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/arch/ia64/Makefile	Tue Dec 30 16:38:56 2003
@@ -14,7 +14,7 @@ export AWK
 
 OBJCOPYFLAGS	:= --strip-all
 LDFLAGS_vmlinux	:= -static
-LDFLAGS_MODULE	+= -T arch/ia64/module.lds
+LDFLAGS_MODULE	+= -T $(srctree)/arch/ia64/module.lds
 AFLAGS_KERNEL	:= -mconstant-gp
 EXTRA		:=
 
@@ -25,9 +25,9 @@ CFLAGS_KERNEL	:= -mconstant-gp
 GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
 GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.')
 
-GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
+GAS_STATUS=$(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
 
-CPPFLAGS	+= $(shell arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP))
+CPPFLAGS	+= $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP))
 
 ifeq ($(GAS_STATUS),buggy)
 $(error Sorry, you need a newer version of the assember, one that is built from	\
@@ -88,12 +88,15 @@ CLEAN_FILES += include/asm-ia64/.offsets
 
 prepare: include/asm-ia64/offsets.h
 
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
+arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h
+
+include/asm-ia64/offsets.h: arch/ia64/kernel/asm-offsets.s
 	$(call filechk,gen-asm-offsets)
 
 arch/ia64/kernel/asm-offsets.s: include/asm-ia64/.offsets.h.stamp
 
 include/asm-ia64/.offsets.h.stamp:
+	mkdir -p include/asm-ia64
 	[ -s include/asm-ia64/offsets.h ] \
 	 || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/offsets.h
 	touch $@
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/configs/sn2_defconfig 001-linus.patch/arch/ia64/configs/sn2_defconfig
--- 000-virgin/arch/ia64/configs/sn2_defconfig	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/ia64/configs/sn2_defconfig	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,693 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_PAGG=y
+CONFIG_PAGG_JOB=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=20
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_GENERIC is not set
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_IA64_HP_ZX1 is not set
+CONFIG_IA64_SGI_SN2=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_EFI=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_KERNEL_CONFIG=y
+CONFIG_IA64_L1_CACHE_SHIFT=7
+# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
+CONFIG_NUMA=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_IA64_MCA=y
+CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_SIM is not set
+CONFIG_FORCE_MAX_ZONEORDER=18
+# CONFIG_IA64_PAL_IDLE is not set
+CONFIG_SMP=y
+# CONFIG_PREEMPT is not set
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_IA64_SALINFO=y
+# CONFIG_EFI_VARS is not set
+CONFIG_NR_CPUS=512
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_PROCESSOR is not set
+CONFIG_ACPI_NUMA=y
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_RELAXED_AML is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_HOTPLUG=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_REPORT_LUNS=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+CONFIG_TIGON3=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+CONFIG_SGI_L1_SERIAL=y
+CONFIG_SGI_L1_SERIAL_CONSOLE=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_IA64_GRANULE_16MB is not set
+CONFIG_IA64_GRANULE_64MB=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_IA64_EARLY_PRINTK=y
+# CONFIG_IA64_EARLY_PRINTK_UART is not set
+# CONFIG_IA64_EARLY_PRINTK_VGA is not set
+CONFIG_IA64_EARLY_PRINTK_SGI_SN=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/defconfig 001-linus.patch/arch/ia64/defconfig
--- 000-virgin/arch/ia64/defconfig	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/ia64/defconfig	Tue Dec 30 16:38:56 2003
@@ -48,7 +48,6 @@ CONFIG_IA64_HP_ZX1=y
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
 CONFIG_ACPI=y
-CONFIG_ACPI_EFI=y
 CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_KERNEL_CONFIG=y
 CONFIG_IA64_L1_CACHE_SHIFT=7
@@ -76,6 +75,7 @@ CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+CONFIG_EFI=y
 CONFIG_EFI_VARS=y
 CONFIG_NR_CPUS=16
 CONFIG_BINFMT_ELF=y
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/ia32/binfmt_elf32.c 001-linus.patch/arch/ia64/ia32/binfmt_elf32.c
--- 000-virgin/arch/ia64/ia32/binfmt_elf32.c	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/arch/ia64/ia32/binfmt_elf32.c	Tue Dec 30 16:38:56 2003
@@ -60,10 +60,12 @@ extern struct page *ia32_shared_page[];
 extern unsigned long *ia32_gdt;
 
 struct page *
-ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int no_share)
+ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type)
 {
 	struct page *pg = ia32_shared_page[smp_processor_id()];
 	get_page(pg);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return pg;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/ia32/sys_ia32.c 001-linus.patch/arch/ia64/ia32/sys_ia32.c
--- 000-virgin/arch/ia64/ia32/sys_ia32.c	Wed Dec 17 18:58:58 2003
+++ 001-linus.patch/arch/ia64/ia32/sys_ia32.c	Tue Dec 30 16:38:56 2003
@@ -2267,7 +2267,7 @@ sys32_sigaltstack (ia32_stack_t *uss32, 
 	uss.ss_flags = buf32.ss_flags;
 	/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the 
            check and set it to the user requested value later */
-	if (buf32.ss_size < MINSIGSTKSZ_IA32) {
+	if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/Makefile 001-linus.patch/arch/ia64/kernel/Makefile
--- 000-virgin/arch/ia64/kernel/Makefile	Wed Dec 17 18:59:56 2003
+++ 001-linus.patch/arch/ia64/kernel/Makefile	Tue Dec 30 16:38:56 2003
@@ -6,7 +6,7 @@ extra-y	:= head.o init_task.o vmlinux.ld
 
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
-	 semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o
+	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o
 
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
@@ -14,7 +14,6 @@ obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1)	+= acpi-ext.o
 obj-$(CONFIG_IA64_MCA)		+= mca.o mca_asm.o
 obj-$(CONFIG_IA64_PALINFO)	+= palinfo.o
-obj-$(CONFIG_IA64_SALINFO)	+= salinfo.o
 obj-$(CONFIG_IOSAPIC)		+= iosapic.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/acpi.c 001-linus.patch/arch/ia64/kernel/acpi.c
--- 000-virgin/arch/ia64/kernel/acpi.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/ia64/kernel/acpi.c	Tue Dec 30 16:38:56 2003
@@ -413,7 +413,7 @@ acpi_numa_memory_affinity_init (struct a
 			break;
 	}
 	if (p < pend) {
-		for (q = pend; q >= p; q--)
+		for (q = pend - 1; q >= p; q--)
 			*(q + 1) = *q;
 	}
 	p->start_paddr = paddr;
@@ -610,66 +610,6 @@ acpi_boot_init (void)
 	return 0;
 }
 
-/*
- * PCI Interrupt Routing
- */
-
-#ifdef CONFIG_PCI
-int __init
-acpi_get_prt (struct pci_vector_struct **vectors, int *count)
-{
-	struct pci_vector_struct *vector;
-	struct list_head *node;
-	struct acpi_prt_entry *entry;
-	int i = 0;
-
-	if (!vectors || !count)
-		return -EINVAL;
-
-	*vectors = NULL;
-	*count = 0;
-
-	if (acpi_prt.count < 0) {
-		printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n");
-		return -ENODEV;
-	}
-
-	/* Allocate vectors */
-
-	*vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL);
-	if (!(*vectors))
-		return -ENOMEM;
-
-	/* Convert PRT entries to IOSAPIC PCI vectors */
-
-	vector = *vectors;
-
-	list_for_each(node, &acpi_prt.entries) {
-		entry = (struct acpi_prt_entry *)node;
-		vector[i].segment = entry->id.segment;
-		vector[i].bus    = entry->id.bus;
-		vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff;
-		vector[i].pin    = entry->pin;
-		vector[i].irq    = entry->link.index;
-		i++;
-	}
-	*count = acpi_prt.count;
-	return 0;
-}
-#endif /* CONFIG_PCI */
-
-/* Assume IA64 always use I/O SAPIC */
-
-int __init
-acpi_get_interrupt_model (int *type)
-{
-        if (!type)
-                return -EINVAL;
-
-	*type = ACPI_IRQ_MODEL_IOSAPIC;
-        return 0;
-}
-
 int
 acpi_irq_to_vector (u32 gsi)
 {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/asm-offsets.c 001-linus.patch/arch/ia64/kernel/asm-offsets.c
--- 000-virgin/arch/ia64/kernel/asm-offsets.c	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/arch/ia64/kernel/asm-offsets.c	Tue Dec 30 16:38:56 2003
@@ -12,6 +12,7 @@
 #include <asm-ia64/ptrace.h>
 #include <asm-ia64/siginfo.h>
 #include <asm-ia64/sigcontext.h>
+#include <asm-ia64/mca.h>
 
 #include "../kernel/sigframe.h"
 
@@ -204,4 +205,7 @@ void foo(void)
 # error "CLONE_SETTLS_BIT incorrect, please fix"
 #endif
 
+	BLANK();
+	DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info));
+
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/efi.c 001-linus.patch/arch/ia64/kernel/efi.c
--- 000-virgin/arch/ia64/kernel/efi.c	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/arch/ia64/kernel/efi.c	Tue Dec 30 16:38:56 2003
@@ -30,6 +30,7 @@
 #include <asm/kregs.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
+#include <asm/mca.h>
 
 #define EFI_DEBUG	0
 
@@ -395,6 +396,9 @@ efi_map_pal_code (void)
 	int pal_code_count = 0;
 	u64 mask, psr;
 	u64 vaddr;
+#ifdef CONFIG_IA64_MCA
+	int cpu;
+#endif
 
 	efi_map_start = __va(ia64_boot_param->efi_memmap);
 	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -455,6 +459,14 @@ efi_map_pal_code (void)
 			 IA64_GRANULE_SHIFT);
 		ia64_set_psr(psr);		/* restore psr */
 		ia64_srlz_i();
+
+#ifdef CONFIG_IA64_MCA
+		cpu = smp_processor_id();
+
+		/* insert this TR into our list for MCA recovery purposes */
+		ia64_mca_tlb_list[cpu].pal_base = vaddr & mask;
+		ia64_mca_tlb_list[cpu].pal_paddr = pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL));
+#endif
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/gate.S 001-linus.patch/arch/ia64/kernel/gate.S
--- 000-virgin/arch/ia64/kernel/gate.S	Wed Dec 17 18:59:20 2003
+++ 001-linus.patch/arch/ia64/kernel/gate.S	Tue Dec 30 16:38:56 2003
@@ -195,10 +195,10 @@ GLOBAL_ENTRY(__kernel_sigtramp)
 	ld8 r15=[base1]					// get address of new RBS base (or NULL)
 	cover				// push args in interrupted frame onto backing store
 	;;
-	cmp.ne p8,p0=r15,r0		// do we need to switch the rbs?
+	cmp.ne p1,p0=r15,r0		// do we need to switch rbs? (note: pr is saved by kernel)
 	mov.m r9=ar.bsp			// fetch ar.bsp
-	.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-(p8)	br.cond.spnt setup_rbs		// yup -> (clobbers p8, r14-r16, and r18-r20)
+	.spillsp.p p1, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+(p1)	br.cond.spnt setup_rbs		// yup -> (clobbers p8, r14-r16, and r18-r20)
 back_from_setup_rbs:
 	alloc r8=ar.pfs,0,0,3,0
 	ld8 out0=[base0],16		// load arg0 (signum)
@@ -237,8 +237,8 @@ back_from_setup_rbs:
 	ld8 r15=[base0],(CFM_OFF-BSP_OFF)	// fetch sc_ar_bsp and advance to CFM_OFF
 	mov r14=ar.bsp
 	;;
-	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
-(p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
+	cmp.ne p1,p0=r14,r15			// do we need to restore the rbs?
+(p1)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
 	;;
 back_from_restore_rbs:
 	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/head.S 001-linus.patch/arch/ia64/kernel/head.S
--- 000-virgin/arch/ia64/kernel/head.S	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/ia64/kernel/head.S	Tue Dec 30 16:38:56 2003
@@ -864,7 +864,7 @@ SET_REG(b5);
 	 * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h.
 	 */
 
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 
 GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4)
 	.prologue
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/ia64_ksyms.c 001-linus.patch/arch/ia64/kernel/ia64_ksyms.c
--- 000-virgin/arch/ia64/kernel/ia64_ksyms.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/ia64/kernel/ia64_ksyms.c	Tue Dec 30 16:38:56 2003
@@ -189,7 +189,7 @@ EXPORT_SYMBOL(unw_access_ar);
 EXPORT_SYMBOL(unw_access_pr);
 
 #ifdef CONFIG_SMP
-# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 /*
  * This is not a normal routine and we don't want a function descriptor for it, so we use
  * a fake declaration here.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/iosapic.c 001-linus.patch/arch/ia64/kernel/iosapic.c
--- 000-virgin/arch/ia64/kernel/iosapic.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/ia64/kernel/iosapic.c	Tue Dec 30 16:38:56 2003
@@ -628,9 +628,6 @@ iosapic_init (unsigned long phys_addr, u
 	iosapic_lists[num_iosapic].num_rte = num_rte;
 	num_iosapic++;
 
-	printk(KERN_INFO "  IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
-	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
-
 	if ((gsi_base == 0) && pcat_compat) {
 		/*
 		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/irq.c 001-linus.patch/arch/ia64/kernel/irq.c
--- 000-virgin/arch/ia64/kernel/irq.c	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/ia64/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -27,6 +27,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/ctype.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
@@ -160,18 +161,20 @@ atomic_t irq_mis_count;
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int j, i = *(loff_t *) v;
 	struct irqaction * action;
 	irq_desc_t *idesc;
 	unsigned long flags;
 
-	seq_puts(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ",j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		idesc = irq_descp(i);
 		spin_lock_irqsave(&idesc->lock, flags);
 		action = idesc->action;
@@ -194,25 +197,26 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&idesc->lock, flags);
-	}
-	seq_puts(p, "NMI: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "%10u ", nmi_count(j));
-	seq_putc(p, '\n');
+	} else if (i == NR_IRQS) {
+		seq_puts(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
-	seq_puts(p, "LOC: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
-	seq_putc(p, '\n');
+		seq_puts(p, "LOC: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+		seq_putc(p, '\n');
 #endif
-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 #ifdef CONFIG_X86_IO_APIC
 #ifdef APIC_MISMATCH_DEBUG
-	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
 #endif
+	}
 	return 0;
 }
 
@@ -910,47 +914,6 @@ int setup_irq(unsigned int irq, struct i
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
-static unsigned int parse_hex_value(const char *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum[HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	unsigned long i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first 8 characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-	for (i = 0; i < count; i++) {
-		unsigned int c = hexnum[i];
-		int k;
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 4);
-		for (k = 0; k < 4; ++k)
-			if (test_bit(k, (unsigned long *)&c))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 #ifdef CONFIG_SMP
 
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
@@ -974,20 +937,10 @@ void set_irq_affinity_info (unsigned int
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int k, len;
-	cpumask_t tmp = irq_affinity[(long)data];
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-
-	len = 0;
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -997,21 +950,37 @@ static int irq_affinity_write_proc (stru
 	unsigned int irq = (unsigned long) data;
 	int full_count = count, err;
 	cpumask_t new_value, tmp;
-	const char *buf = buffer;
+#	define R_PREFIX_LEN 16
+	char rbuf[R_PREFIX_LEN];
+	int rlen;
+	int prelen;
 	irq_desc_t *desc = irq_descp(irq);
-	int redir;
 
 	if (!desc->handler->set_affinity)
 		return -EIO;
 
-	if (buf[0] == 'r' || buf[0] == 'R') {
-		++buf;
-		while (*buf == ' ') ++buf;
-		redir = 1;
-	} else
-		redir = 0;
+	/*
+	 * If string being written starts with a prefix of 'r' or 'R'
+	 * and some limited number of spaces, set IA64_IRQ_REDIRECTED.
+	 * If more than (R_PREFIX_LEN - 2) spaces are passed, they won't
+	 * all be trimmed as part of prelen, the untrimmed spaces will
+	 * cause the hex parsing to fail, and this write() syscall will
+	 * fail with EINVAL.
+	 */
+
+	if (!count)
+		return -EINVAL;
+	rlen = min(sizeof(rbuf)-1, count);
+	if (copy_from_user(rbuf, buffer, rlen))
+		return -EFAULT;
+	rbuf[rlen] = 0;
+	prelen = 0;
+	if (tolower(*rbuf) == 'r') {
+		prelen = strspn(rbuf, "Rr ");
+		irq |= IA64_IRQ_REDIRECTED;
+	}
 
-	err = parse_hex_value(buf, count, &new_value);
+	err = cpumask_parse(buffer+prelen, count-prelen, new_value);
 	if (err)
 		return err;
 
@@ -1024,7 +993,7 @@ static int irq_affinity_write_proc (stru
 	if (cpus_empty(tmp))
 		return -EINVAL;
 
-	desc->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value);
+	desc->handler->set_affinity(irq, new_value);
 	return full_count;
 }
 
@@ -1033,19 +1002,10 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	cpumask_t *mask = (cpumask_t *)data;
-	int k, len = 0;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(*mask));
-		len += j;
-		page += j;
-		cpus_shift_right(*mask, *mask, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -1056,7 +1016,7 @@ static int prof_cpu_mask_write_proc (str
 	unsigned long full_count = count, err;
 	cpumask_t new_value;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/ivt.S 001-linus.patch/arch/ia64/kernel/ivt.S
--- 000-virgin/arch/ia64/kernel/ivt.S	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/arch/ia64/kernel/ivt.S	Tue Dec 30 16:38:56 2003
@@ -360,33 +360,6 @@ ENTRY(alt_dtlb_miss)
 	rfi
 END(alt_dtlb_miss)
 
-	//-----------------------------------------------------------------------------------
-	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-ENTRY(page_fault)
-	ssm psr.dt
-	;;
-	srlz.i
-	;;
-	SAVE_MIN_WITH_COVER
-	alloc r15=ar.pfs,0,0,3,0
-	mov out0=cr.ifa
-	mov out1=cr.isr
-	adds r3=8,r2				// set up second base pointer
-	;;
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i					// guarantee that interruption collectin is on
-	;;
-(p15)	ssm psr.i				// restore psr.i
-	movl r14=ia64_leave_kernel
-	;;
-	SAVE_REST
-	mov rp=r14
-	;;
-	adds out2=16,r12			// out2 = pointer to pt_regs
-	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
-END(page_fault)
-
 	.org ia64_ivt+0x1400
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
@@ -459,6 +432,33 @@ ENTRY(ikey_miss)
 	FAULT(6)
 END(ikey_miss)
 
+	//-----------------------------------------------------------------------------------
+	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+	ssm psr.dt
+	;;
+	srlz.i
+	;;
+	SAVE_MIN_WITH_COVER
+	alloc r15=ar.pfs,0,0,3,0
+	mov out0=cr.ifa
+	mov out1=cr.isr
+	adds r3=8,r2				// set up second base pointer
+	;;
+	ssm psr.ic | PSR_DEFAULT_BITS
+	;;
+	srlz.i					// guarantee that interruption collectin is on
+	;;
+(p15)	ssm psr.i				// restore psr.i
+	movl r14=ia64_leave_kernel
+	;;
+	SAVE_REST
+	mov rp=r14
+	;;
+	adds out2=16,r12			// out2 = pointer to pt_regs
+	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
+END(page_fault)
+
 	.org ia64_ivt+0x1c00
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/mca.c 001-linus.patch/arch/ia64/kernel/mca.c
--- 000-virgin/arch/ia64/kernel/mca.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/ia64/kernel/mca.c	Tue Dec 30 16:38:56 2003
@@ -36,6 +36,10 @@
  *                      SAL 3.0 spec.
  * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
  *                           added min save state dump, added INIT handler.
+ *
+ * 2003-12-08 Keith Owens <kaos@sgi.com>
+ *            smp_call_function() must not be called from interrupt context (can
+ *            deadlock on tasklist_lock).  Use keventd to call smp_call_function().
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -51,6 +55,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
+#include <linux/workqueue.h>
 
 #include <asm/delay.h>
 #include <asm/machvec.h>
@@ -78,17 +83,19 @@ u64				ia64_mca_stack[1024] __attribute_
 u64				ia64_mca_stackframe[32];
 u64				ia64_mca_bspstore[1024];
 u64				ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16)));
-u64				ia64_mca_sal_data_area[1356];
-u64				ia64_tlb_functional;
 u64				ia64_os_mca_recovery_successful;
+u64				ia64_mca_serialize;
 static void			ia64_mca_wakeup_ipi_wait(void);
 static void			ia64_mca_wakeup(int cpu);
 static void			ia64_mca_wakeup_all(void);
 static void			ia64_log_init(int);
 extern void			ia64_monarch_init_handler (void);
 extern void			ia64_slave_init_handler (void);
+static u64			ia64_log_get(int sal_info_type, u8 **buffer);
 extern struct hw_interrupt_type	irq_type_iosapic_level;
 
+struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
+
 static struct irqaction cmci_irqaction = {
 	.handler =	ia64_mca_cmc_int_handler,
 	.flags =	SA_INTERRUPT,
@@ -149,12 +156,14 @@ static int cmc_polling_enabled = 1;
  */
 static int cpe_poll_enabled = 1;
 
+extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size);
+
 /*
  *  ia64_mca_log_sal_error_record
  *
- *  This function retrieves a specified error record type from SAL, sends it to
- *  the system log, and notifies SALs to clear the record from its non-volatile
- *  memory.
+ *  This function retrieves a specified error record type from SAL,
+ *  wakes up any processes waiting for error records, and sends it to
+ *  the system log.
  *
  *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
  *  Outputs :   platform error status
@@ -162,11 +171,13 @@ static int cpe_poll_enabled = 1;
 int
 ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
 {
-	int platform_err = 0;
+	u8 *buffer;
+	u64 size;
+	int platform_err;
 
-	/* Get the MCA error record */
-	if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
-		return platform_err;		/* no record retrieved */
+	size = ia64_log_get(sal_info_type, &buffer);
+	if (!size)
+		return 0;
 
 	/* TODO:
 	 * 1. analyze error logs to determine recoverability
@@ -174,10 +185,10 @@ ia64_mca_log_sal_error_record(int sal_in
 	 * 3. set ia64_os_mca_recovery_successful flag, if applicable
 	 */
 
+	salinfo_log_wakeup(sal_info_type, buffer, size);
 	platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
-	/* temporary: only clear SAL logs on hardware-corrected errors
-		or if we're logging an error after an MCA-initiated reboot */
-	if ((sal_info_type > 1) || (called_from_init))
+	/* Clear logs from corrected errors in case there's no user-level logger */
+	if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC)
 		ia64_sal_clear_state_info(sal_info_type);
 
 	return platform_err;
@@ -450,7 +461,10 @@ static void
 ia64_mca_register_cpev (int cpev)
 {
 	/* Register the CPE interrupt vector with SAL */
-	if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {
+	struct ia64_sal_retval isrv;
+
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0);
+	if (isrv.status) {
 		printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected "
 		       "Platform Error interrupt vector with SAL.\n");
 		return;
@@ -602,6 +616,30 @@ verify_guid (efi_guid_t *test, efi_guid_
 }
 
 /*
+ * ia64_mca_cmc_vector_disable_keventd
+ *
+ * Called via keventd (smp_call_function() is not safe in interrupt context) to
+ * disable the cmc interrupt vector.
+ */
+static void
+ia64_mca_cmc_vector_disable_keventd(void *unused)
+{
+	on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0);
+}
+
+/*
+ * ia64_mca_cmc_vector_enable_keventd
+ *
+ * Called via keventd (smp_call_function() is not safe in interrupt context) to
+ * enable the cmc interrupt vector.
+ */
+static void
+ia64_mca_cmc_vector_enable_keventd(void *unused)
+{
+	on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0);
+}
+
+/*
  * ia64_mca_init
  *
  *  Do all the system level mca specific initialization.
@@ -629,6 +667,8 @@ ia64_mca_init(void)
 	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
 	int i;
 	s64 rc;
+	struct ia64_sal_retval isrv;
+	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
 
 	IA64_MCA_DEBUG("ia64_mca_init: begin\n");
 
@@ -644,23 +684,33 @@ ia64_mca_init(void)
 	 */
 
 	/* Register the rendezvous interrupt vector with SAL */
-	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
-					 SAL_MC_PARAM_MECHANISM_INT,
-					 IA64_MCA_RENDEZ_VECTOR,
-					 IA64_MCA_RENDEZ_TIMEOUT,
-					 SAL_MC_PARAM_RZ_ALWAYS)))
-	{
+	while (1) {
+		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+					      SAL_MC_PARAM_MECHANISM_INT,
+					      IA64_MCA_RENDEZ_VECTOR,
+					      timeout,
+					      SAL_MC_PARAM_RZ_ALWAYS);
+		rc = isrv.status;
+		if (rc == 0)
+			break;
+		if (rc == -2) {
+			printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from "
+				"%ld to %ld\n", timeout, isrv.v0);
+			timeout = isrv.v0;
+			continue;
+		}
 		printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt "
 		       "with SAL.  rc = %ld\n", rc);
 		return;
 	}
 
 	/* Register the wakeup interrupt vector with SAL */
-	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
-					 SAL_MC_PARAM_MECHANISM_INT,
-					 IA64_MCA_WAKEUP_VECTOR,
-					 0, 0)))
-	{
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+				      SAL_MC_PARAM_MECHANISM_INT,
+				      IA64_MCA_WAKEUP_VECTOR,
+				      0, 0);
+	rc = isrv.status;
+	if (rc) {
 		printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL.  "
 		       "rc = %ld\n", rc);
 		return;
@@ -924,6 +974,9 @@ ia64_mca_wakeup_int_handler(int wakeup_i
 void
 ia64_return_to_sal_check(void)
 {
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
+		&ia64_sal_to_os_handoff_state.proc_state_param;
+
 	/* Copy over some relevant stuff from the sal_to_os_mca_handoff
 	 * so that it can be used at the time of os_mca_to_sal_handoff
 	 */
@@ -933,14 +986,22 @@ ia64_return_to_sal_check(void)
 	ia64_os_to_sal_handoff_state.imots_sal_check_ra =
 		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
 
-	/* Cold Boot for uncorrectable MCA */
-	ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
+	/*
+	 * Did we correct the error? At the moment the only error that
+	 * we fix is a TLB error, if any other kind of error occurred
+	 * we must reboot.
+	 */
+	if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1)
+		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
+	else
+		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
 
 	/* Default = tell SAL to return to same context */
 	ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
 
 	ia64_os_to_sal_handoff_state.imots_new_min_state =
 		(u64 *)ia64_sal_to_os_handoff_state.pal_min_state;
+
 }
 
 /*
@@ -983,6 +1044,9 @@ ia64_mca_ucmc_handler(void)
 	ia64_return_to_sal_check();
 }
 
+static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL);
+static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL);
+
 /*
  * ia64_mca_cmc_int_handler
  *
@@ -1029,14 +1093,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, vo
 
 			cmc_polling_enabled = 1;
 			spin_unlock(&cmc_history_lock);
-
-			/*
-			 * We rely on the local_irq_enable() above so
-			 * that this can't deadlock.
-			 */
-			ia64_mca_cmc_vector_disable(NULL);
-
-			smp_call_function(ia64_mca_cmc_vector_disable, NULL, 1, 0);
+			schedule_work(&cmc_disable_work);
 
 			/*
 			 * Corrected errors will still be corrected, but
@@ -1131,19 +1188,7 @@ ia64_mca_cmc_int_caller(int cpe_irq, voi
 		if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
 
 			printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__);
-
-			/*
-			 * The cmc interrupt handler enabled irqs, so
-			 * this can't deadlock.
-			 */
-			smp_call_function(ia64_mca_cmc_vector_enable, NULL, 1, 0);
-
-			/*
-			 * Turn off interrupts before re-enabling the
-			 * cmc vector locally.  Make sure we get out.
-			 */
-			local_irq_disable();
-			ia64_mca_cmc_vector_enable(NULL);
+			schedule_work(&cmc_enable_work);
 			cmc_polling_enabled = 0;
 
 		} else {
@@ -1399,12 +1444,12 @@ ia64_log_init(int sal_info_type)
  *	Get the current MCA log from SAL and copy it into the OS log buffer.
  *
  *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *              prfunc      (fn ptr of log output function)
  *  Outputs :   size        (total record length)
+ *              *buffer     (ptr to error record)
  *
  */
-u64
-ia64_log_get(int sal_info_type, prfunc_t prfunc)
+static u64
+ia64_log_get(int sal_info_type, u8 **buffer)
 {
 	sal_log_record_header_t     *log_buffer;
 	u64                         total_len = 0;
@@ -1422,6 +1467,7 @@ ia64_log_get(int sal_info_type, prfunc_t
 		IA64_LOG_UNLOCK(sal_info_type);
 		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
 			       "Record length = %ld\n", sal_info_type, total_len);
+		*buffer = (u8 *) log_buffer;
 		return total_len;
 	} else {
 		IA64_LOG_UNLOCK(sal_info_type);
@@ -1466,7 +1512,7 @@ ia64_log_prt_oem_data (int header_len, i
 void
 ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
 {
-	prfunc("+Err Record ID: %d    SAL Rev: %2x.%02x\n", lh->id,
+	prfunc("+Err Record ID: %ld    SAL Rev: %2x.%02x\n", lh->id,
 			lh->revision.major, lh->revision.minor);
 	prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x    Severity %d\n",
 			lh->timestamp.slh_month, lh->timestamp.slh_day,
@@ -1589,13 +1635,13 @@ ia64_log_cache_check_info_print (int    
 	if (info->dl)
 		prfunc(" Line: Data,");
 	prfunc(" Operation: %s,", pal_cache_op[info->op]);
-	if (info->wv)
+	if (info->wiv)
 		prfunc(" Way: %d,", info->way);
 	if (cache_check_info->valid.target_identifier)
 		/* Hope target address is saved in target_identifier */
 		if (info->tv)
 			prfunc(" Target Addr: 0x%lx,", target_addr);
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" MC: Corrected");
 	prfunc("\n");
 }
@@ -1631,13 +1677,13 @@ ia64_log_tlb_check_info_print (int      
 		prfunc("  Failure: Data Translation Cache");
 	if (info->itr) {
 		prfunc("  Failure: Instruction Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
 	if (info->dtr) {
 		prfunc("  Failure: Data Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	prfunc("\n");
 }
@@ -1683,7 +1729,7 @@ ia64_log_bus_check_info_print (int      
 		prfunc(" ,Error: Internal");
 	if (info->eb)
 		prfunc(" ,Error: External");
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	if (info->tv)
 		prfunc(" ,Target Address: 0x%lx", targ_addr);
@@ -1970,9 +2016,9 @@ ia64_log_plat_specific_err_info_print (s
 		ia64_log_prt_guid(&psei->guid, prfunc);
 	}
 	if (psei->valid.oem_data) {
-		platform_plat_specific_err_print((int)psei->header.len,
-				      (int)sizeof(sal_log_plat_specific_err_info_t) - 1,
-				      &(psei->oem_data[0]), prfunc);
+		platform_plat_specific_err_print((int) psei->header.len,
+				      (char *) psei->oem_data - (char *) psei,
+				      &psei->oem_data[0], prfunc);
 	}
 	prfunc("\n");
 }
@@ -2352,13 +2398,12 @@ ia64_log_print(int sal_info_type, prfunc
 
 	switch(sal_info_type) {
 	      case SAL_INFO_TYPE_MCA:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n");
-		platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type),
-							    prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT MCA\n");
+		prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id());
+		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_INIT:
-		prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n");
+		prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id());
+		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_CMC:
 		prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/mca_asm.S 001-linus.patch/arch/ia64/kernel/mca_asm.S
--- 000-virgin/arch/ia64/kernel/mca_asm.S	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/ia64/kernel/mca_asm.S	Tue Dec 30 16:38:56 2003
@@ -14,6 +14,7 @@
 //		   3. Move stack ptr 16 bytes to conform to C calling convention
 //
 #include <linux/config.h>
+#include <linux/threads.h>
 
 #include <asm/asmmacro.h>
 #include <asm/pgtable.h>
@@ -22,20 +23,15 @@
 #include <asm/mca.h>
 
 /*
- * When we get an machine check, the kernel stack pointer is no longer
+ * When we get a machine check, the kernel stack pointer is no longer
  * valid, so we need to set a new stack pointer.
  */
 #define	MINSTATE_PHYS	/* Make sure stack access is physical for MINSTATE */
 
 /*
- * Needed for ia64_sal call
- */
-#define SAL_GET_STATE_INFO      0x01000001
-
-/*
  * Needed for return context to SAL
  */
-#define IA64_MCA_SAME_CONTEXT	0x0
+#define IA64_MCA_SAME_CONTEXT	0
 #define IA64_MCA_COLD_BOOT	-2
 
 #include "minstate.h"
@@ -71,19 +67,36 @@
  *	returns ptr to SAL rtn save loc in _tmp
  */
 #define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp)	\
-	LOAD_PHYSICAL(p6, _tmp, ia64_sal_to_os_handoff_state);; \
-	LOAD_PHYSICAL(p7, _tmp, ia64_os_to_sal_handoff_state);; \
-(p6)	movl	r8=IA64_MCA_COLD_BOOT;			\
-(p6)	movl	r10=IA64_MCA_SAME_CONTEXT;		\
-(p6)	add     _tmp=0x18,_tmp;;			\
-(p6)	ld8	r9=[_tmp],0x10;				\
-(p6)	mov	r22=r0;;				\
-(p7)	ld8	r8=[_tmp],0x08;;			\
-(p7)	ld8	r9=[_tmp],0x08;;			\
-(p7)	ld8     r10=[_tmp],0x08;;			\
-(p7)	ld8     r22=[_tmp],0x08;;
+	movl	_tmp=ia64_os_to_sal_handoff_state;;	\
+	DATA_VA_TO_PA(_tmp);;				\
+	ld8	r8=[_tmp],0x08;;			\
+	ld8	r9=[_tmp],0x08;;			\
+	ld8	r10=[_tmp],0x08;;			\
+	ld8	r22=[_tmp],0x08;;
 	// now _tmp is pointing to SAL rtn save location
 
+/*
+ * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state
+ *	imots_os_status=IA64_MCA_COLD_BOOT
+ *	imots_sal_gp=SAL GP
+ *	imots_context=IA64_MCA_SAME_CONTEXT
+ *	imots_new_min_state=Min state save area pointer
+ *	imots_sal_check_ra=Return address to location within SAL_CHECK
+ *
+ */
+#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\
+	movl	tmp=IA64_MCA_COLD_BOOT;					\
+	movl	sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state);	\
+	movl	os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);;	\
+	st8	[os_to_sal_handoff]=tmp,8;;				\
+	ld8	tmp=[sal_to_os_handoff],48;;				\
+	st8	[os_to_sal_handoff]=tmp,8;;				\
+	movl	tmp=IA64_MCA_SAME_CONTEXT;;				\
+	st8	[os_to_sal_handoff]=tmp,8;;				\
+	ld8	tmp=[sal_to_os_handoff],-8;;				\
+	st8     [os_to_sal_handoff]=tmp,8;;				\
+	ld8	tmp=[sal_to_os_handoff];;				\
+	st8     [os_to_sal_handoff]=tmp;;
 
 	.global ia64_os_mca_dispatch
 	.global ia64_os_mca_dispatch_end
@@ -94,20 +107,19 @@
 	.global	ia64_mca_stackframe
 	.global	ia64_mca_bspstore
 	.global ia64_init_stack
-	.global ia64_mca_sal_data_area
-	.global ia64_tlb_functional
 
 	.text
 	.align 16
 
 ia64_os_mca_dispatch:
 
-#if defined(MCA_TEST)
-	// Pretend that we are in interrupt context
-	mov		r2=psr
-	dep		r2=0, r2, PSR_IC, 2;
-	mov		psr.l = r2
-#endif	/* #if defined(MCA_TEST) */
+	// Serialize all MCA processing
+	mov	r3=1;;
+	LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
+ia64_os_mca_spin:
+	xchg8	r4=[r2],r3;;
+	cmp.ne	p6,p0=r4,r0
+(p6)	br ia64_os_mca_spin
 
 	// Save the SAL to OS MCA handoff state as defined
 	// by SAL SPEC 3.0
@@ -124,6 +136,187 @@ begin_os_mca_dump:
 
 ia64_os_mca_done_dump:
 
+	LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
+	;;
+	ld8 r18=[r16]		// Get processor state parameter on existing PALE_CHECK.
+	;;
+	tbit.nz p6,p7=r18,60
+(p7)	br.spnt done_tlb_purge_and_reload
+
+	// The following code purges TC and TR entries. Then reload all TC entries.
+	// Purge percpu data TC entries.
+begin_tlb_purge_and_reload:
+	mov r16=cr.lid
+	LOAD_PHYSICAL(p0,r17,ia64_mca_tlb_list) // Physical address of ia64_mca_tlb_list
+	mov r19=0
+	mov r20=NR_CPUS
+	;;
+1:	cmp.eq p6,p7=r19,r20
+(p6)	br.spnt.few err
+	ld8 r18=[r17],IA64_MCA_TLB_INFO_SIZE
+	;;
+	add r19=1,r19
+	cmp.eq p6,p7=r18,r16
+(p7)	br.sptk.few 1b
+	;;
+	adds r17=-IA64_MCA_TLB_INFO_SIZE,r17
+	;;
+	mov r23=r17		// save current ia64_mca_percpu_info addr pointer.
+	adds r17=16,r17
+	;;
+	ld8 r18=[r17],8		// r18=ptce_base
+  	;;
+	ld4 r19=[r17],4		// r19=ptce_count[0]
+	;;
+	ld4 r20=[r17],4		// r20=ptce_count[1]
+	;;
+	ld4 r21=[r17],4		// r21=ptce_stride[0]
+	mov r24=0
+	;;
+	ld4 r22=[r17],4		// r22=ptce_stride[1]
+	adds r20=-1,r20
+	;;
+2:
+	cmp.ltu p6,p7=r24,r19
+(p7)	br.cond.dpnt.few 4f
+	mov ar.lc=r20
+3:
+	ptc.e r18
+	;;
+	add r18=r22,r18
+	br.cloop.sptk.few 3b
+	;;
+	add r18=r21,r18
+	add r24=1,r24
+	;;
+	br.sptk.few 2b
+4:
+	srlz.i 			// srlz.i implies srlz.d
+	;;
+
+        // Now purge addresses formerly mapped by TR registers
+	// 1. Purge ITR&DTR for kernel.
+	movl r16=KERNEL_START
+	mov r18=KERNEL_TR_PAGE_SHIFT<<2
+	;;
+	ptr.i r16, r18
+	ptr.d r16, r18
+	;;
+	srlz.i
+	;;
+	srlz.d
+	;;
+	// 2. Purge DTR for PERCPU data.
+	movl r16=PERCPU_ADDR
+	mov r18=PERCPU_PAGE_SHIFT<<2
+	;;
+	ptr.d r16,r18
+	;;
+	srlz.d
+	;;
+	// 3. Purge ITR for PAL code.
+	adds r17=48,r23
+	;;
+	ld8 r16=[r17]
+	mov r18=IA64_GRANULE_SHIFT<<2
+	;;
+	ptr.i r16,r18
+	;;
+	srlz.i
+	;;
+	// 4. Purge DTR for stack.
+	mov r16=IA64_KR(CURRENT_STACK)
+	;;
+	shl r16=r16,IA64_GRANULE_SHIFT
+	movl r19=PAGE_OFFSET
+	;;
+	add r16=r19,r16
+	mov r18=IA64_GRANULE_SHIFT<<2
+	;;
+	ptr.d r16,r18
+	;;
+	srlz.i
+	;;
+	// Finally reload the TR registers.
+	// 1. Reload DTR/ITR registers for kernel.
+	mov r18=KERNEL_TR_PAGE_SHIFT<<2
+	movl r17=KERNEL_START
+	;;
+	mov cr.itir=r18
+	mov cr.ifa=r17
+        mov r16=IA64_TR_KERNEL
+	mov r19=ip
+	movl r18=PAGE_KERNEL
+	;;
+        dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT
+	;;
+	or r18=r17,r18
+	;;
+        itr.i itr[r16]=r18
+	;;
+        itr.d dtr[r16]=r18
+        ;;
+	srlz.i
+	srlz.d
+	;;
+	// 2. Reload DTR register for PERCPU data.
+	adds r17=8,r23
+	movl r16=PERCPU_ADDR		// vaddr
+	movl r18=PERCPU_PAGE_SHIFT<<2
+	;;
+	mov cr.itir=r18
+	mov cr.ifa=r16
+	;;
+	ld8 r18=[r17]			// pte
+	mov r16=IA64_TR_PERCPU_DATA;
+	;;
+	itr.d dtr[r16]=r18
+	;;
+	srlz.d
+	;;
+	// 3. Reload ITR for PAL code.
+	adds r17=40,r23
+	;;
+	ld8 r18=[r17],8			// pte
+	;;
+	ld8 r16=[r17]			// vaddr
+	mov r19=IA64_GRANULE_SHIFT<<2
+	;;
+	mov cr.itir=r19
+	mov cr.ifa=r16
+	mov r20=IA64_TR_PALCODE
+	;;
+	itr.i itr[r20]=r18
+	;;
+	srlz.i
+	;;
+	// 4. Reload DTR for stack.
+	mov r16=IA64_KR(CURRENT_STACK)
+	;;
+	shl r16=r16,IA64_GRANULE_SHIFT
+	movl r19=PAGE_OFFSET
+	;;
+	add r18=r19,r16
+	movl r20=PAGE_KERNEL
+	;;
+	add r16=r20,r16
+	mov r19=IA64_GRANULE_SHIFT<<2
+	;;
+	mov cr.itir=r19
+	mov cr.ifa=r18
+	mov r20=IA64_TR_CURRENT_STACK
+	;;
+	itr.d dtr[r20]=r16
+	;;
+	srlz.d
+	;;
+	br.sptk.many done_tlb_purge_and_reload
+err:
+	COLD_BOOT_HANDOFF_STATE(r20,r21,r22)
+	br.sptk.many ia64_os_mca_done_restore
+
+done_tlb_purge_and_reload:
+
 	// Setup new stack frame for OS_MCA handling
 	movl	r2=ia64_mca_bspstore;;	// local bspstore area location in r2
 	DATA_VA_TO_PA(r2);;
@@ -137,17 +330,11 @@ ia64_os_mca_done_dump:
 					// (C calling convention)
 	DATA_VA_TO_PA(r12);;
 
-	// Check to see if the MCA resulted from a TLB error
-begin_tlb_error_check:
-        br      ia64_os_mca_tlb_error_check;;
-
-done_tlb_error_check:
-
-        // If TLB is functional, enter virtual mode from physical mode
+        // Enter virtual mode from physical mode
 	VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
 ia64_os_mca_virtual_begin:
 
-	// call our handler
+	// Call virtual mode handler
 	movl		r2=ia64_mca_ucmc_handler;;
 	mov		b6=r2;;
 	br.call.sptk.many    b0=b6;;
@@ -156,13 +343,6 @@ ia64_os_mca_virtual_begin:
 	PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
 ia64_os_mca_virtual_end:
 
-#if defined(MCA_TEST)
-	// Pretend that we are in interrupt context
-	mov	r2=psr;;
-	dep	r2=0, r2, PSR_IC, 2;;
-	mov	psr.l = r2;;
-#endif	/* #if defined(MCA_TEST) */
-
 	// restore the original stack frame here
 	movl    r2=ia64_mca_stackframe	// restore stack frame from memory at r2
 	;;
@@ -178,14 +358,16 @@ begin_os_mca_restore:
 	br	ia64_os_mca_proc_state_restore;;
 
 ia64_os_mca_done_restore:
-	movl	r3=ia64_tlb_functional;;
-	DATA_VA_TO_PA(r3);;
-	ld8	r3=[r3];;
-	cmp.eq	p6,p7=r0,r3;;
 	OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);;
 	// branch back to SALE_CHECK
 	ld8		r3=[r2];;
 	mov		b0=r3;;		// SAL_CHECK return address
+
+	// release lock
+	movl		r3=ia64_mca_serialize;;
+	DATA_VA_TO_PA(r3);;
+	st8.rel		[r3]=r0
+
 	br		b0
 	;;
 ia64_os_mca_dispatch_end:
@@ -205,8 +387,7 @@ ia64_os_mca_dispatch_end:
 ia64_os_mca_proc_state_dump:
 // Save bank 1 GRs 16-31 which will be used by c-language code when we switch
 //  to virtual addressing mode.
-	movl		r2=ia64_mca_proc_state_dump;;           // Os state dump area
-        DATA_VA_TO_PA(r2)                   // convert to to physical address
+	LOAD_PHYSICAL(p0,r2,ia64_mca_proc_state_dump)// convert OS state dump area to physical address
 
 // save ar.NaT
 	mov		r5=ar.unat                  // ar.unat
@@ -658,79 +839,6 @@ end_os_mca_restore:
 
 //EndStub//////////////////////////////////////////////////////////////////////
 
-//++
-// Name:
-//	ia64_os_mca_tlb_error_check()
-//
-// Stub Description:
-//
-//	This stub checks to see if the MCA resulted from a TLB error
-//
-//--
-
-ia64_os_mca_tlb_error_check:
-
-	// Retrieve sal data structure for uncorrected MCA
-
-	// Make the ia64_sal_get_state_info() call
-	movl	r4=ia64_mca_sal_data_area;;
-	movl	r7=ia64_sal;;
-	mov	r6=r1			// save gp
-	DATA_VA_TO_PA(r4)		// convert to physical address
-	DATA_VA_TO_PA(r7);;		// convert to physical address
-	ld8	r7=[r7]			// get addr of pdesc from ia64_sal
-	movl	r3=SAL_GET_STATE_INFO;;
-	DATA_VA_TO_PA(r7);;		// convert to physical address
-	ld8	r8=[r7],8;;		// get pdesc function pointer
-	dep	r8=0,r8,61,3;;		// convert SAL VA to PA
-	ld8	r1=[r7];;		// set new (ia64_sal) gp
-	dep	r1=0,r1,61,3;;		// convert SAL VA to PA
-	mov	b6=r8
-
-	alloc	r5=ar.pfs,8,0,8,0;;	// allocate stack frame for SAL call
-	mov	out0=r3			// which SAL proc to call
-	mov	out1=r0			// error type == MCA
-	mov	out2=r0			// null arg
-	mov	out3=r4			// data copy area
-	mov	out4=r0			// null arg
-	mov	out5=r0			// null arg
-	mov	out6=r0			// null arg
-	mov	out7=r0;;		// null arg
-
-	br.call.sptk.few	b0=b6;;
-
-	mov	r1=r6			// restore gp
-	mov	ar.pfs=r5;;		// restore ar.pfs
-
-	movl	r6=ia64_tlb_functional;;
-	DATA_VA_TO_PA(r6)		// needed later
-
-	cmp.eq	p6,p7=r0,r8;;		// check SAL call return address
-(p7)	st8	[r6]=r0			// clear tlb_functional flag
-(p7)    br	tlb_failure		// error; return to SAL
-
-	// examine processor error log for type of error
-	add	r4=40+24,r4;;		// parse past record header (length=40)
-					// and section header (length=24)
-	ld4	r4=[r4]			// get valid field of processor log
-	mov	r5=0xf00;;
-	and	r5=r4,r5;;		// read bits 8-11 of valid field
-					// to determine if we have a TLB error
-	movl	r3=0x1
-	cmp.eq	p6,p7=r0,r5;;
-	// if no TLB failure, set tlb_functional flag
-(p6)	st8	[r6]=r3
-	// else clear flag
-(p7)	st8	[r6]=r0
-
-	// if no TLB failure, continue with normal virtual mode logging
-(p6)    br	done_tlb_error_check
-	// else no point in entering virtual mode for logging
-tlb_failure:
-	br      ia64_os_mca_virtual_end
-
-//EndStub//////////////////////////////////////////////////////////////////////
-
 
 // ok, the issue here is that we need to save state information so
 // it can be useable by the kernel debugger and show regs routines.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/perfmon.c 001-linus.patch/arch/ia64/kernel/perfmon.c
--- 000-virgin/arch/ia64/kernel/perfmon.c	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/arch/ia64/kernel/perfmon.c	Tue Dec 30 16:38:56 2003
@@ -5475,7 +5475,7 @@ pfm_interrupt_handler(int irq, void *arg
 	int this_cpu;
 	int ret;
 
-	this_cpu = smp_processor_id();
+	this_cpu = get_cpu();
 	min      = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
 	max      = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/salinfo.c 001-linus.patch/arch/ia64/kernel/salinfo.c
--- 000-virgin/arch/ia64/kernel/salinfo.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/arch/ia64/kernel/salinfo.c	Tue Dec 30 16:38:56 2003
@@ -3,18 +3,31 @@
  *
  * Creates entries in /proc/sal for various system features.
  *
- * Copyright (c) 2001 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2003 Hewlett-Packard Co
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
- * 09/11/2003	jbarnes@sgi.com		updated for 2.6
  * 10/30/2001	jbarnes@sgi.com		copied much of Stephane's palinfo
  *					code to create this file
+ * Oct 23 2003	kaos@sgi.com
+ *   Replace IPI with set_cpus_allowed() to read a record from the required cpu.
+ *   Redesign salinfo log processing to separate interrupt and user space
+ *   contexts.
+ *   Cache the record across multi-block reads from user space.
+ *   Support > 64 cpus.
+ *   Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
  */
 
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
 
+#include <asm/semaphore.h>
 #include <asm/sal.h>
+#include <asm/uaccess.h>
 
 MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
 MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
@@ -41,42 +54,516 @@ static salinfo_entry_t salinfo_entries[]
 
 #define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
 
-/*
- * One for each feature and one more for the directory entry...
+static char *salinfo_log_name[] = {
+	"mca",
+	"init",
+	"cmc",
+	"cpe",
+};
+
+static struct proc_dir_entry *salinfo_proc_entries[
+	ARRAY_SIZE(salinfo_entries) +			/* /proc/sal/bus_lock */
+	ARRAY_SIZE(salinfo_log_name) +			/* /proc/sal/{mca,...} */
+	(2 * ARRAY_SIZE(salinfo_log_name)) +		/* /proc/sal/mca/{event,data} */
+	1];						/* /proc/sal */
+
+/* Some records we get ourselves, some are accessed as saved data in buffers
+ * that are owned by mca.c.
+ */
+struct salinfo_data_saved {
+	u8*			buffer;
+	u64			size;
+	u64			id;
+	int			cpu;
+};
+
+/* State transitions.  Actions are :-
+ *   Write "read <cpunum>" to the data file.
+ *   Write "clear <cpunum>" to the data file.
+ *   Write "oemdata <cpunum> <offset> to the data file.
+ *   Read from the data file.
+ *   Close the data file.
+ *
+ * Start state is NO_DATA.
+ *
+ * NO_DATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> return -EINVAL.
+ *    read data -> return EOF.
+ *    close -> unchanged.  Free record areas.
+ *
+ * LOG_RECORD
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the INIT/MCA/CMC/CPE record.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * OEMDATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the formatted oemdata.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * Closing the data file does not change the state.  This allows shell scripts
+ * to manipulate salinfo data, each shell redirection opens the file, does one
+ * action then closes it again.  The record areas are only freed at close when
+ * the state is NO_DATA.
+ */
+enum salinfo_state {
+	STATE_NO_DATA,
+	STATE_LOG_RECORD,
+	STATE_OEMDATA,
+};
+
+struct salinfo_data {
+	volatile cpumask_t	cpu_event;	/* which cpus have outstanding events */
+	struct semaphore	sem;		/* count of cpus with outstanding events (bits set in cpu_event) */
+	u8			*log_buffer;
+	u64			log_size;
+	u8			*oemdata;	/* decoded oem data */
+	u64			oemdata_size;
+	int			open;		/* single-open to prevent races */
+	u8			type;
+	u8			saved_num;	/* using a saved record? */
+	enum salinfo_state	state :8;	/* processing state */
+	u8			padding;
+	int			cpu_check;	/* next CPU to check */
+	struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */
+};
+
+static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)];
+
+static spinlock_t data_lock, data_saved_lock;
+
+/** salinfo_platform_oemdata - optional callback to decode oemdata from an error
+ * record.
+ * @sect_header: pointer to the start of the section to decode.
+ * @oemdata: returns vmalloc area containing the decded output.
+ * @oemdata_size: returns length of decoded output (strlen).
+ *
+ * Description: If user space asks for oem data to be decoded by the kernel
+ * and/or prom and the platform has set salinfo_platform_oemdata to the address
+ * of a platform specific routine then call that routine.  salinfo_platform_oemdata
+ * vmalloc's and formats its output area, returning the address of the text
+ * and its strlen.  Returns 0 for success, -ve for error.  The callback is
+ * invoked on the cpu that generated the error record.
  */
-static struct proc_dir_entry *salinfo_proc_entries[NR_SALINFO_ENTRIES + 1];
+int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size);
+
+struct salinfo_platform_oemdata_parms {
+	const u8 *efi_guid;
+	u8 **oemdata;
+	u64 *oemdata_size;
+	int ret;
+};
+
+static void
+salinfo_platform_oemdata_cpu(void *context)
+{
+	struct salinfo_platform_oemdata_parms *parms = context;
+	parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
+}
+
+static void
+shift1_data_saved (struct salinfo_data *data, int shift)
+{
+	memcpy(data->data_saved+shift, data->data_saved+shift+1,
+	       (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
+	memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
+	       sizeof(data->data_saved[0]));
+}
+
+/* This routine is invoked in interrupt context.  Note: mca.c enables
+ * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
+ * not irq safe, do not call any routines that use spinlocks, they may deadlock.
+ *
+ * The buffer passed from mca.c points to the output from ia64_log_get. This is
+ * a persistent buffer but its contents can change between the interrupt and
+ * when user space processes the record.  Save the record id to identify
+ * changes.
+ */
+void
+salinfo_log_wakeup(int type, u8 *buffer, u64 size)
+{
+	struct salinfo_data *data = salinfo_data + type;
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags = 0;
+	int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
+
+	if (irqsafe)
+		spin_lock_irqsave(&data_saved_lock, flags);
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (!data_saved->buffer)
+			break;
+	}
+	if (i == saved_size) {
+		if (!data->saved_num) {
+			shift1_data_saved(data, 0);
+			data_saved = data->data_saved + saved_size - 1;
+		} else
+			data_saved = NULL;
+	}
+	if (data_saved) {
+		data_saved->cpu = smp_processor_id();
+		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
+		data_saved->size = size;
+		data_saved->buffer = buffer;
+	}
+	if (irqsafe)
+		spin_unlock_irqrestore(&data_saved_lock, flags);
+
+	if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
+		if (irqsafe)
+			up(&data->sem);
+	}
+}
+
+static int
+salinfo_event_open(struct inode *inode, struct file *file)
+{
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
+static ssize_t
+salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	char cmd[32];
+	size_t size;
+	int i, n, cpu = -1;
+
+retry:
+	if (down_trylock(&data->sem)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		if (down_interruptible(&data->sem))
+			return -ERESTARTSYS;
+	}
+
+	n = data->cpu_check;
+	for (i = 0; i < NR_CPUS; i++) {
+		if (test_bit(n, &data->cpu_event)) {
+			cpu = n;
+			break;
+		}
+		if (++n == NR_CPUS)
+			n = 0;
+	}
+
+	if (cpu == -1)
+		goto retry;
+
+	/* events are sticky until the user says "clear" */
+	up(&data->sem);
+
+	/* for next read, start checking at next CPU */
+	data->cpu_check = cpu;
+	if (++data->cpu_check == NR_CPUS)
+		data->cpu_check = 0;
+
+	snprintf(cmd, sizeof(cmd), "read %d\n", cpu);
+
+	size = strlen(cmd);
+	if (size > count)
+		size = count;
+	if (copy_to_user(buffer, cmd, size))
+		return -EFAULT;
+
+	return size;
+}
+
+static struct file_operations salinfo_event_fops = {
+	.open  = salinfo_event_open,
+	.read  = salinfo_event_read,
+};
+
+static int
+salinfo_log_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	spin_lock(&data_lock);
+	if (data->open) {
+		spin_unlock(&data_lock);
+		return -EBUSY;
+	}
+	data->open = 1;
+	spin_unlock(&data_lock);
+
+	if (data->state == STATE_NO_DATA &&
+	    !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) {
+		data->open = 0;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int
+salinfo_log_release(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+
+	if (data->state == STATE_NO_DATA) {
+		vfree(data->log_buffer);
+		vfree(data->oemdata);
+		data->log_buffer = NULL;
+		data->oemdata = NULL;
+	}
+	spin_lock(&data_lock);
+	data->open = 0;
+	spin_unlock(&data_lock);
+	return 0;
+}
+
+static void
+call_on_cpu(int cpu, void (*fn)(void *), void *arg)
+{
+	cpumask_t save_cpus_allowed, new_cpus_allowed;
+	memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed));
+	memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
+	set_bit(cpu, &new_cpus_allowed);
+	set_cpus_allowed(current, new_cpus_allowed);
+	(*fn)(arg);
+	set_cpus_allowed(current, save_cpus_allowed);
+}
+
+static void
+salinfo_log_read_cpu(void *context)
+{
+	struct salinfo_data *data = context;
+	data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);
+	if (data->type == SAL_INFO_TYPE_CPE || data->type == SAL_INFO_TYPE_CMC)
+		ia64_sal_clear_state_info(data->type);
+}
+
+static void
+salinfo_log_new_read(int cpu, struct salinfo_data *data)
+{
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags;
+	int i;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	data->saved_num = 0;
+	spin_lock_irqsave(&data_saved_lock, flags);
+retry:
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (data_saved->buffer && data_saved->cpu == cpu) {
+			sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer);
+			data->log_size = data_saved->size;
+			memcpy(data->log_buffer, rh, data->log_size);
+			barrier();	/* id check must not be moved */
+			if (rh->id == data_saved->id) {
+				data->saved_num = i+1;
+				break;
+			}
+			/* saved record changed by mca.c since interrupt, discard it */
+			shift1_data_saved(data, i);
+			goto retry;
+		}
+	}
+	spin_unlock_irqrestore(&data_saved_lock, flags);
+
+	if (!data->saved_num)
+		call_on_cpu(cpu, salinfo_log_read_cpu, data);
+	data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
+}
+
+static ssize_t
+salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	void *saldata;
+	size_t size;
+	u8 *buf;
+	u64 bufsize;
+
+	if (data->state == STATE_LOG_RECORD) {
+		buf = data->log_buffer;
+		bufsize = data->log_size;
+	} else if (data->state == STATE_OEMDATA) {
+		buf = data->oemdata;
+		bufsize = data->oemdata_size;
+	} else {
+		buf = NULL;
+		bufsize = 0;
+	}
+	if (*ppos >= bufsize)
+		return 0;
+
+	saldata = buf + file->f_pos;
+	size = bufsize - file->f_pos;
+	if (size > count)
+		size = count;
+	if (copy_to_user(buffer, saldata, size))
+		return -EFAULT;
+
+	*ppos += size;
+	return size;
+}
+
+static void
+salinfo_log_clear_cpu(void *context)
+{
+	struct salinfo_data *data = context;
+	ia64_sal_clear_state_info(data->type);
+}
+
+static int
+salinfo_log_clear(struct salinfo_data *data, int cpu)
+{
+	data->state = STATE_NO_DATA;
+	if (!test_bit(cpu, &data->cpu_event))
+		return 0;
+	down(&data->sem);
+	clear_bit(cpu, &data->cpu_event);
+	if (data->saved_num) {
+		unsigned long flags;
+		spin_lock_irqsave(&data_saved_lock, flags);
+		shift1_data_saved(data, data->saved_num - 1 );
+		data->saved_num = 0;
+		spin_unlock_irqrestore(&data_saved_lock, flags);
+	}
+	/* ia64_mca_log_sal_error_record or salinfo_log_read_cpu already cleared
+	 * CPE and CMC errors
+	 */
+	if (data->type != SAL_INFO_TYPE_CPE && data->type != SAL_INFO_TYPE_CMC)
+		call_on_cpu(cpu, salinfo_log_clear_cpu, data);
+	/* clearing a record may make a new record visible */
+	salinfo_log_new_read(cpu, data);
+	if (data->state == STATE_LOG_RECORD &&
+	    !test_and_set_bit(cpu,  &data->cpu_event))
+		up(&data->sem);
+	return 0;
+}
+
+static ssize_t
+salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	char cmd[32];
+	size_t size;
+	u32 offset;
+	int cpu;
+
+	size = sizeof(cmd);
+	if (count < size)
+		size = count;
+	if (copy_from_user(cmd, buffer, size))
+		return -EFAULT;
+
+	if (sscanf(cmd, "read %d", &cpu) == 1) {
+		salinfo_log_new_read(cpu, data);
+	} else if (sscanf(cmd, "clear %d", &cpu) == 1) {
+		int ret;
+		if ((ret = salinfo_log_clear(data, cpu)))
+			count = ret;
+	} else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) {
+		if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA)
+			return -EINVAL;
+		if (offset > data->log_size - sizeof(efi_guid_t))
+			return -EINVAL;
+		data->state = STATE_OEMDATA;
+		if (salinfo_platform_oemdata) {
+			struct salinfo_platform_oemdata_parms parms = {
+				.efi_guid = data->log_buffer + offset,
+				.oemdata = &data->oemdata,
+				.oemdata_size = &data->oemdata_size
+			};
+			call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms);
+			if (parms.ret)
+				count = parms.ret;
+		} else
+			data->oemdata_size = 0;
+	} else
+		return -EINVAL;
+
+	return count;
+}
+
+static struct file_operations salinfo_data_fops = {
+	.open    = salinfo_log_open,
+	.release = salinfo_log_release,
+	.read    = salinfo_log_read,
+	.write   = salinfo_log_write,
+};
 
 static int __init
 salinfo_init(void)
 {
 	struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */
 	struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
-	int i;
+	struct proc_dir_entry *dir, *entry;
+	struct salinfo_data *data;
+	int i, j, online;
 
 	salinfo_dir = proc_mkdir("sal", NULL);
+	if (!salinfo_dir)
+		return 0;
 
 	for (i=0; i < NR_SALINFO_ENTRIES; i++) {
 		/* pass the feature bit in question as misc data */
-		*sdir = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
+		*sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
 						  salinfo_read, (void *)salinfo_entries[i].feature);
-		if (*sdir)
-			(*sdir)->owner = THIS_MODULE;
-		sdir++;
 	}
-	*sdir++ = salinfo_dir;
-
-	return 0;
-}
 
-static void __exit
-salinfo_exit(void)
-{
-	int i = 0;
+	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
+		data = salinfo_data + i;
+		data->type = i;
+		sema_init(&data->sem, 0);
+		dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
+		if (!dir)
+			continue;
+
+		entry = create_proc_entry("event", S_IRUSR, dir);
+		if (!entry)
+			continue;
+		entry->data = data;
+		entry->proc_fops = &salinfo_event_fops;
+		*sdir++ = entry;
+
+		entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);
+		if (!entry)
+			continue;
+		entry->data = data;
+		entry->proc_fops = &salinfo_data_fops;
+		*sdir++ = entry;
+
+		/* we missed any events before now */
+		online = 0;
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j)) {
+				set_bit(j, &data->cpu_event);
+				++online;
+			}
+		sema_init(&data->sem, online);
 
-	for (i = 0; i < NR_SALINFO_ENTRIES ; i++) {
-		if (salinfo_proc_entries[i])
-			remove_proc_entry (salinfo_proc_entries[i]->name, NULL);
+		*sdir++ = dir;
 	}
+
+	*sdir++ = salinfo_dir;
+
+	return 0;
 }
 
 /*
@@ -102,4 +589,3 @@ salinfo_read(char *page, char **start, o
 }
 
 module_init(salinfo_init);
-module_exit(salinfo_exit);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/setup.c 001-linus.patch/arch/ia64/kernel/setup.c
--- 000-virgin/arch/ia64/kernel/setup.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/arch/ia64/kernel/setup.c	Tue Dec 30 16:38:56 2003
@@ -54,6 +54,10 @@
 # error "struct cpuinfo_ia64 too big!"
 #endif
 
+#ifdef CONFIG_EFI
+int efi_enabled = 1;
+#endif
+
 #ifdef CONFIG_SMP
 unsigned long __per_cpu_offset[NR_CPUS];
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/smpboot.c 001-linus.patch/arch/ia64/kernel/smpboot.c
--- 000-virgin/arch/ia64/kernel/smpboot.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/arch/ia64/kernel/smpboot.c	Tue Dec 30 16:38:56 2003
@@ -466,7 +466,7 @@ smp_build_cpu_map (void)
 #ifdef CONFIG_NUMA
 
 /* on which node is each logical CPU (one cacheline even for 64 CPUs) */
-volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
 /* which logical CPUs are on which nodes */
 volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/kernel/vmlinux.lds.S 001-linus.patch/arch/ia64/kernel/vmlinux.lds.S
--- 000-virgin/arch/ia64/kernel/vmlinux.lds.S	Wed Dec 17 18:59:27 2003
+++ 001-linus.patch/arch/ia64/kernel/vmlinux.lds.S	Tue Dec 30 16:38:56 2003
@@ -151,7 +151,7 @@ SECTIONS
 	{ *(.con_initcall.init) }
   __con_initcall_end = .;
   __security_initcall_start = .;
-  .security_initcall.init : AT(ADDR(.security_initcall.init) - PAGE_OFFSET)
+  .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET)
 	{ *(.security_initcall.init) }
   __security_initcall_end = .;
   . = ALIGN(PAGE_SIZE);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/lib/Makefile 001-linus.patch/arch/ia64/lib/Makefile
--- 000-virgin/arch/ia64/lib/Makefile	Wed Dec 17 18:59:42 2003
+++ 001-linus.patch/arch/ia64/lib/Makefile	Tue Dec 30 16:38:56 2003
@@ -13,6 +13,7 @@ lib-$(CONFIG_ITANIUM)	+= copy_page.o cop
 lib-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
 lib-$(CONFIG_PERFMON)	+= carta_random.o
 lib-$(CONFIG_MD_RAID5)	+= xor.o
+lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
 
 AFLAGS___divdi3.o	=
 AFLAGS___udivdi3.o	= -DUNSIGNED
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/lib/dec_and_lock.c 001-linus.patch/arch/ia64/lib/dec_and_lock.c
--- 000-virgin/arch/ia64/lib/dec_and_lock.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/ia64/lib/dec_and_lock.c	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2003 Jerome Marchand, Bull S.A.
+ *	Cleaned up by David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * This file is released under the GPLv2, or at your option any later version.
+ *
+ * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction.  This
+ * code is an adaptation of the x86 version of "atomic_dec_and_lock()".
+ */
+
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+/*
+ * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock.  Both of these
+ * operations have to be done atomically, so that the count doesn't drop to zero without
+ * acquiring the spinlock first.
+ */
+int
+atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock)
+{
+	int old, new;
+
+	do {
+		old = atomic_read(refcount);
+		new = old - 1;
+
+		if (unlikely (old == 1)) {
+			/* oops, we may be decrementing to zero, do it the slow way... */
+			spin_lock(lock);
+			if (atomic_dec_and_test(refcount))
+				return 1;
+			spin_unlock(lock);
+			return 0;
+		}
+	} while (cmpxchg(&refcount->counter, old, new) != old);
+	return 0;
+}
+
+EXPORT_SYMBOL(atomic_dec_and_lock);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/mm/discontig.c 001-linus.patch/arch/ia64/mm/discontig.c
--- 000-virgin/arch/ia64/mm/discontig.c	Wed Dec 17 18:59:28 2003
+++ 001-linus.patch/arch/ia64/mm/discontig.c	Tue Dec 30 16:38:56 2003
@@ -134,94 +134,69 @@ static int __init find_pernode_space(uns
 				     int node)
 {
 	unsigned long epfn, cpu, cpus;
-	unsigned long pernodesize = 0, pernode;
-       	void *cpu_data;
+	unsigned long pernodesize = 0, pernode, pages, mapsize;
+	void *cpu_data;
 	struct bootmem_data *bdp = &mem_data[node].bootmem_data;
 
 	epfn = (start + len) >> PAGE_SHIFT;
 
+	pages = bdp->node_low_pfn - (bdp->node_boot_start >> PAGE_SHIFT);
+	mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
+
 	/*
 	 * Make sure this memory falls within this node's usable memory
 	 * since we may have thrown some away in build_maps().
 	 */
-	if (start < bdp->node_boot_start ||
-	    epfn > bdp->node_low_pfn)
+	if (start < bdp->node_boot_start || epfn > bdp->node_low_pfn)
 		return 0;
 
 	/* Don't setup this node's local space twice... */
-	if (!mem_data[node].pernode_addr) {
-		/*
-		 * Calculate total size needed, incl. what's necessary
-		 * for good alignment and alias prevention.
-		 */
-		cpus = early_nr_cpus_node(node);
-		pernodesize += PERCPU_PAGE_SIZE * cpus;
-		pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
-		pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-		pernodesize = PAGE_ALIGN(pernodesize);
-		pernode = NODEDATA_ALIGN(start, node);
-
-		/* Is this range big enough for what we want to store here? */
-		if (start + len > (pernode + pernodesize)) {
-			mem_data[node].pernode_addr = pernode;
-			mem_data[node].pernode_size = pernodesize;
-			memset(__va(pernode), 0, pernodesize);
-
-			cpu_data = (void *)pernode;
-			pernode += PERCPU_PAGE_SIZE * cpus;
-
-			mem_data[node].pgdat = __va(pernode);
-			pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
-			mem_data[node].node_data = __va(pernode);
-			pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-
-			mem_data[node].pgdat->bdata = bdp;
-			pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
-			/*
-			 * Copy the static per-cpu data into the region we
-			 * just set aside and then setup __per_cpu_offset
-			 * for each CPU on this node.
-			 */
-			for (cpu = 0; cpu < NR_CPUS; cpu++) {
-				if (node == node_cpuid[cpu].nid) {
-					memcpy(__va(cpu_data), __phys_per_cpu_start,
-					       __per_cpu_end-__per_cpu_start);
-					__per_cpu_offset[cpu] =
-						(char*)__va(cpu_data) -
-						__per_cpu_start;
-					cpu_data += PERCPU_PAGE_SIZE;
-				}
-			}
-		}
-	}
+	if (mem_data[node].pernode_addr)
+		return 0;
+
+	/*
+	 * Calculate total size needed, incl. what's necessary
+	 * for good alignment and alias prevention.
+	 */
+	cpus = early_nr_cpus_node(node);
+	pernodesize += PERCPU_PAGE_SIZE * cpus;
+	pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+	pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+	pernodesize = PAGE_ALIGN(pernodesize);
+	pernode = NODEDATA_ALIGN(start, node);
+
+	/* Is this range big enough for what we want to store here? */
+	if (start + len > (pernode + pernodesize + mapsize)) {
+		mem_data[node].pernode_addr = pernode;
+		mem_data[node].pernode_size = pernodesize;
+		memset(__va(pernode), 0, pernodesize);
+
+		cpu_data = (void *)pernode;
+		pernode += PERCPU_PAGE_SIZE * cpus;
+
+		mem_data[node].pgdat = __va(pernode);
+		pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
-	pernode = mem_data[node].pernode_addr;
-	pernodesize = mem_data[node].pernode_size;
-	if (pernode && !bdp->node_bootmem_map) {
-		unsigned long pages, mapsize, map = 0;
-
-		pages = bdp->node_low_pfn -
-			(bdp->node_boot_start >> PAGE_SHIFT);
-		mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
+		mem_data[node].node_data = __va(pernode);
+		pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+
+		mem_data[node].pgdat->bdata = bdp;
+		pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
 		/*
-		 * The map will either contain the pernode area or begin
-		 * after it.
+		 * Copy the static per-cpu data into the region we
+		 * just set aside and then setup __per_cpu_offset
+		 * for each CPU on this node.
 		 */
-		if (pernode - start > mapsize)
-			map = start;
-		else if (start + len - pernode - pernodesize > mapsize)
-			map = pernode + pernodesize;
-
-		if (map) {
-			init_bootmem_node(mem_data[node].pgdat,
-					  map>>PAGE_SHIFT,
-					  bdp->node_boot_start>>PAGE_SHIFT,
-					  bdp->node_low_pfn);
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			if (node == node_cpuid[cpu].nid) {
+				memcpy(__va(cpu_data), __phys_per_cpu_start,
+				       __per_cpu_end - __per_cpu_start);
+				__per_cpu_offset[cpu] = (char*)__va(cpu_data) -
+					__per_cpu_start;
+				cpu_data += PERCPU_PAGE_SIZE;
+			}
 		}
-
 	}
 
 	return 0;
@@ -314,6 +289,8 @@ static void __init initialize_pernode_da
  */
 void __init find_memory(void)
 {
+	int node;
+
 	reserve_memory();
 
 	if (numnodes == 0) {
@@ -327,6 +304,31 @@ void __init find_memory(void)
 	/* These actually end up getting called by call_pernode_memory() */
 	efi_memmap_walk(filter_rsvd_memory, build_node_maps);
 	efi_memmap_walk(filter_rsvd_memory, find_pernode_space);
+
+	/*
+	 * Initialize the boot memory maps in reverse order since that's
+	 * what the bootmem allocator expects
+	 */
+	for (node = numnodes - 1; node >= 0; node--) {
+		unsigned long pernode, pernodesize, map;
+		struct bootmem_data *bdp;
+
+		bdp = &mem_data[node].bootmem_data;
+		pernode = mem_data[node].pernode_addr;
+		pernodesize = mem_data[node].pernode_size;
+		map = pernode + pernodesize;
+
+		/* Sanity check... */
+		if (!pernode)
+			panic("pernode space for node %d "
+			      "could not be allocated!", node);
+
+		init_bootmem_node(mem_data[node].pgdat,
+				  map>>PAGE_SHIFT,
+				  bdp->node_boot_start>>PAGE_SHIFT,
+				  bdp->node_low_pfn);
+	}
+
 	efi_memmap_walk(filter_rsvd_memory, free_node_bootmem);
 
 	reserve_pernode_space();
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/mm/hugetlbpage.c 001-linus.patch/arch/ia64/mm/hugetlbpage.c
--- 000-virgin/arch/ia64/mm/hugetlbpage.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/arch/ia64/mm/hugetlbpage.c	Tue Dec 30 16:38:56 2003
@@ -144,17 +144,6 @@ int is_aligned_hugepage_range(unsigned l
 
 	return 0;
 }
-/* This function checks if the address and address+len falls out of HugeTLB region.  It
- * return -EINVAL if any part of address range falls in HugeTLB region.
- */
-int  check_valid_hugepage_range(unsigned long addr, unsigned long len)
-{
-	if (REGION_NUMBER(addr) == REGION_HPAGE)
-		return -EINVAL;
-	if (REGION_NUMBER(addr+len) == REGION_HPAGE)
-		return -EINVAL;
-	return 0;
-}
 
 int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
 			struct vm_area_struct *vma)
@@ -272,6 +261,59 @@ void huge_page_release(struct page *page
 	free_huge_page(page);
 }
 
+/*
+ * Same as generic free_pgtables(), except constant PGDIR_* and pgd_offset
+ * are hugetlb region specific.
+ */
+void hugetlb_free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev,
+	unsigned long start, unsigned long end)
+{
+	unsigned long first = start & HUGETLB_PGDIR_MASK;
+	unsigned long last = end + HUGETLB_PGDIR_SIZE - 1;
+	unsigned long start_index, end_index;
+	struct mm_struct *mm = tlb->mm;
+
+	if (!prev) {
+		prev = mm->mmap;
+		if (!prev)
+			goto no_mmaps;
+		if (prev->vm_end > start) {
+			if (last > prev->vm_start)
+				last = prev->vm_start;
+			goto no_mmaps;
+		}
+	}
+	for (;;) {
+		struct vm_area_struct *next = prev->vm_next;
+
+		if (next) {
+			if (next->vm_start < start) {
+				prev = next;
+				continue;
+			}
+			if (last > next->vm_start)
+				last = next->vm_start;
+		}
+		if (prev->vm_end > first)
+			first = prev->vm_end + HUGETLB_PGDIR_SIZE - 1;
+		break;
+	}
+no_mmaps:
+	if (last < first)	/* for arches with discontiguous pgd indices */
+		return;
+	/*
+	 * If the PGD bits are not consecutive in the virtual address, the
+	 * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
+	 */
+
+	start_index = pgd_index(htlbpage_to_page(first));
+	end_index = pgd_index(htlbpage_to_page(last));
+
+	if (end_index > start_index) {
+		clear_page_tables(tlb, start_index, end_index - start_index);
+	}
+}
+
 void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -518,7 +560,7 @@ int is_hugepage_mem_enough(size_t size)
 	return 1;
 }
 
-static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int unused)
+static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int *unused)
 {
 	BUG();
 	return NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/mm/init.c 001-linus.patch/arch/ia64/mm/init.c
--- 000-virgin/arch/ia64/mm/init.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/ia64/mm/init.c	Tue Dec 30 16:38:56 2003
@@ -34,6 +34,7 @@
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/mca.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -277,6 +278,10 @@ ia64_mmu_init (void *my_cpu_data)
 {
 	unsigned long psr, pta, impl_va_bits;
 	extern void __init tlb_init (void);
+#ifdef CONFIG_IA64_MCA
+	int cpu;
+#endif
+
 #ifdef CONFIG_DISABLE_VHPT
 #	define VHPT_ENABLE_BIT	0
 #else
@@ -335,6 +340,22 @@ ia64_mmu_init (void *my_cpu_data)
 	ia64_set_pta(pta | (0 << 8) | (vmlpt_bits << 2) | VHPT_ENABLE_BIT);
 
 	ia64_tlb_init();
+
+#ifdef	CONFIG_IA64_MCA
+	cpu = smp_processor_id();
+
+	/* mca handler uses cr.lid as key to pick the right entry */
+	ia64_mca_tlb_list[cpu].cr_lid = ia64_getreg(_IA64_REG_CR_LID);
+
+	/* insert this percpu data information into our list for MCA recovery purposes */
+	ia64_mca_tlb_list[cpu].percpu_paddr = pte_val(mk_pte_phys(__pa(my_cpu_data), PAGE_KERNEL));
+	/* Also save per-cpu tlb flush recipe for use in physical mode mca handler */
+	ia64_mca_tlb_list[cpu].ptce_base = local_cpu_data->ptce_base;
+	ia64_mca_tlb_list[cpu].ptce_count[0] = local_cpu_data->ptce_count[0];
+	ia64_mca_tlb_list[cpu].ptce_count[1] = local_cpu_data->ptce_count[1];
+	ia64_mca_tlb_list[cpu].ptce_stride[0] = local_cpu_data->ptce_stride[0];
+	ia64_mca_tlb_list[cpu].ptce_stride[1] = local_cpu_data->ptce_stride[1];
+#endif
 }
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ia64/pci/pci.c 001-linus.patch/arch/ia64/pci/pci.c
--- 000-virgin/arch/ia64/pci/pci.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/ia64/pci/pci.c	Tue Dec 30 16:38:56 2003
@@ -153,7 +153,7 @@ alloc_resource (char *name, struct resou
 	res->end = end;
 	res->flags = flags;
 
-	if (request_resource(root, res))
+	if (insert_resource(root, res))
 		return -EBUSY;
 
 	return 0;
@@ -260,7 +260,6 @@ pci_acpi_scan_root (struct acpi_device *
 	unsigned int windows = 0;
 	char *name;
 
-	printk("PCI: Probing PCI hardware on bus (%04x:%02x)\n", domain, bus);
 	controller = alloc_pci_controller(domain);
 	if (!controller)
 		goto out1;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/m68k/kernel/ints.c 001-linus.patch/arch/m68k/kernel/ints.c
--- 000-virgin/arch/m68k/kernel/ints.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/m68k/kernel/ints.c	Tue Dec 30 16:38:56 2003
@@ -253,19 +253,18 @@ asmlinkage void process_int(unsigned lon
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
 	/* autovector interrupts */
 	if (mach_default_handler) {
-		for (i = 0; i < SYS_IRQS; i++) {
+		if (i < SYS_IRQS) {
 			seq_printf(p, "auto %2d: %10u ", i,
 			               i ? kstat_cpu(0).irqs[i] : num_spurious);
 			seq_puts(p, "  ");
 			seq_printf(p, "%s\n", irq_list[i].devname);
 		}
-	}
-
-	mach_get_irq_list(p, v);
+	} else if (i == SYS_IRQS)
+		mach_get_irq_list(p, v);
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/m68knommu/platform/5307/ints.c 001-linus.patch/arch/m68knommu/platform/5307/ints.c
--- 000-virgin/arch/m68knommu/platform/5307/ints.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/m68knommu/platform/5307/ints.c	Tue Dec 30 16:38:56 2003
@@ -254,9 +254,9 @@ asmlinkage void process_int(unsigned lon
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		if (irq_list[i].flags & IRQ_FLG_STD)
 			continue;
 
@@ -269,7 +269,7 @@ int show_interrupts(struct seq_file *p, 
 		seq_printf(p, "%s\n", irq_list[i].devname);
 	}
 
-	if (mach_get_irq_list)
+	if (i == NR_IRQS && mach_get_irq_list)
 		mach_get_irq_list(p, v);
 	return(0);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/m68knommu/platform/68328/ints.c 001-linus.patch/arch/m68knommu/platform/68328/ints.c
--- 000-virgin/arch/m68knommu/platform/68328/ints.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/m68knommu/platform/68328/ints.c	Tue Dec 30 16:38:56 2003
@@ -198,9 +198,9 @@ EXPORT_SYMBOL(free_irq);
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		if (int_irq_list[i].flags & IRQ_FLG_STD)
 			continue;
 
@@ -211,7 +211,8 @@ int show_interrupts(struct seq_file *p, 
 			seq_printf(p, "  ");
 		seq_printf(p, "%s\n", int_irq_list[i].devname);
 	}
-	seq_printf(p, "   : %10u   spurious\n", num_spurious);
+	if (i == NR_IRQS)
+		seq_printf(p, "   : %10u   spurious\n", num_spurious);
 
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/m68knommu/platform/68360/ints.c 001-linus.patch/arch/m68knommu/platform/68360/ints.c
--- 000-virgin/arch/m68knommu/platform/68360/ints.c	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/arch/m68knommu/platform/68360/ints.c	Tue Dec 30 16:38:56 2003
@@ -278,9 +278,9 @@ void M68360_disable_irq(unsigned int irq
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	if (i < NR_IRQS) {
 		if (int_irq_list[i].flags & IRQ_FLG_STD)
 			continue;
 
@@ -291,7 +291,8 @@ int show_interrupts(struct seq_file *p, 
 			seq_printf(p, "  ");
 		seq_printf(p, "%s\n", int_irq_list[i].devname);
 	}
-	seq_printf(p, "   : %10u   spurious\n", num_spurious);
+	if (i == NR_IRQS)
+		seq_printf(p, "   : %10u   spurious\n", num_spurious);
 
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/mips/kernel/irq.c 001-linus.patch/arch/mips/kernel/irq.c
--- 000-virgin/arch/mips/kernel/irq.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/arch/mips/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -85,17 +85,19 @@ atomic_t irq_err_count;
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_printf(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ",j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
@@ -117,10 +119,10 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+	} else if (i == NR_IRQS) {
+		seq_putc(p, '\n');
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 	}
-	seq_putc(p, '\n');
-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-
 	return 0;
 }
 
@@ -825,45 +827,6 @@ EXPORT_SYMBOL(probe_irq_mask);
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 
-#define HEX_DIGITS 8
-
-static unsigned int parse_hex_value (const char *buffer,
-		unsigned long count, unsigned long *ret)
-{
-	unsigned char hexnum [HEX_DIGITS];
-	unsigned long value;
-	int i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first 8 characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-	value = 0;
-
-	for (i = 0; i < count; i++) {
-		unsigned int c = hexnum[i];
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		value = (value << 4) | c;
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 #ifdef CONFIG_SMP
 
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
@@ -872,18 +835,10 @@ static cpumask_t irq_affinity [NR_IRQS] 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len, k;
-	cpumask_t tmp = irq_affinity[(long)data];
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -896,7 +851,7 @@ static int irq_affinity_write_proc (stru
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
@@ -918,20 +873,10 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int len, k;
-	cpumask_t *mask = (cpumask_t *)data, tmp;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-	tmp = *mask;
-
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -941,7 +886,7 @@ static int prof_cpu_mask_write_proc (str
 	cpumask_t *mask = (cpumask_t *)data, new_value;
 	unsigned long full_count = count, err;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/Kconfig 001-linus.patch/arch/parisc/Kconfig
--- 000-virgin/arch/parisc/Kconfig	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/arch/parisc/Kconfig	Tue Dec 30 16:38:56 2003
@@ -169,51 +169,10 @@ source "fs/Kconfig.binfmt"
 
 endmenu
 
-source "drivers/base/Kconfig"
-
-# source "drivers/mtd/Kconfig"
-
-source "drivers/parport/Kconfig"
-
-# source "drivers/pnp/Kconfig"
-
-source "drivers/block/Kconfig"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-source drivers/message/fusion/Kconfig
-
-#source drivers/ieee1394/Kconfig
-
-#source drivers/message/i2o/Kconfig
-
-source "net/Kconfig"
-
-#source "drivers/isdn/Kconfig"
-
-#source "drivers/telephony/Kconfig"
-
-# input before char - char/joystick depends on it. As does USB.
-source "drivers/input/Kconfig"
-
-source "drivers/char/Kconfig"
-
-#source "drivers/misc/Kconfig"
-
-source "drivers/media/Kconfig"
+source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-source "drivers/video/Kconfig"
-
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
 source "arch/parisc/oprofile/Kconfig"
 
 menu "Kernel hacking"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/configs/712_defconfig 001-linus.patch/arch/parisc/configs/712_defconfig
--- 000-virgin/arch/parisc/configs/712_defconfig	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/parisc/configs/712_defconfig	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,637 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_PARISC=y
+CONFIG_MMU=y
+CONFIG_STACK_GROWSUP=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_KMOD is not set
+
+#
+# Processor type and features
+#
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
+# CONFIG_PA7200 is not set
+# CONFIG_PA8X00 is not set
+CONFIG_PA11=y
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+#
+CONFIG_GSC=y
+# CONFIG_HPPB is not set
+# CONFIG_IOMMU_CCIO is not set
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+# CONFIG_EISA is not set
+# CONFIG_PCI is not set
+# CONFIG_CHASSIS_LCD_LED is not set
+# CONFIG_PDC_CHASSIS is not set
+# CONFIG_HOTPLUG is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_MEM_MAPPED=y
+CONFIG_53C700_LE_ON_BE=y
+# CONFIG_SCSI_ZALON is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_INET_ECN=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_LASI_82596=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_PLIP is not set
+CONFIG_PPP=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Token Ring devices
+#
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_HP_SDC is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_HIL_OLD is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_GSC=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MUX is not set
+# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_STI=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=160
+CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_PARISC_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_INFO is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SELINUX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/defconfig 001-linus.patch/arch/parisc/defconfig
--- 000-virgin/arch/parisc/defconfig	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/arch/parisc/defconfig	Tue Dec 30 16:38:56 2003
@@ -3,7 +3,6 @@
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
-CONFIG_SWAP=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 
@@ -11,20 +10,27 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_LOG_BUF_SHIFT_17 is not set
-# CONFIG_LOG_BUF_SHIFT_16 is not set
-CONFIG_LOG_BUF_SHIFT_15=y
-# CONFIG_LOG_BUF_SHIFT_14 is not set
-# CONFIG_LOG_BUF_SHIFT_13 is not set
-# CONFIG_LOG_BUF_SHIFT_12 is not set
 CONFIG_LOG_BUF_SHIFT=15
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
 
 #
 # Loadable module support
@@ -34,6 +40,15 @@ CONFIG_LOG_BUF_SHIFT=15
 #
 # Processor type and features
 #
+CONFIG_PA7000=y
+# CONFIG_PA7100LC is not set
+# CONFIG_PA7200 is not set
+# CONFIG_PA8X00 is not set
+CONFIG_PA11=y
+# CONFIG_64BIT is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HPUX is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, GSC, ISA)
@@ -44,6 +59,8 @@ CONFIG_IOMMU_CCIO=y
 CONFIG_GSC_LASI=y
 CONFIG_GSC_WAX=y
 CONFIG_EISA=y
+CONFIG_EISA_NAMES=y
+# CONFIG_ISA is not set
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
@@ -52,17 +69,30 @@ CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
 CONFIG_SUPERIO=y
-# CONFIG_CHASSIS_LCD_LED is not set
+CONFIG_CHASSIS_LCD_LED=y
+CONFIG_PDC_CHASSIS=y
+# CONFIG_HOTPLUG is not set
 
 #
 # Executable file formats
 #
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_SOM=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Parallel port support
 #
 CONFIG_PARPORT=y
@@ -76,6 +106,11 @@ CONFIG_PARPORT_GSC=y
 # CONFIG_PARPORT_1284 is not set
 
 #
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -85,20 +120,22 @@ CONFIG_PARPORT_GSC=y
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -128,22 +165,17 @@ CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
@@ -160,15 +192,11 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
 CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -185,6 +213,21 @@ CONFIG_MD_RAID5=y
 # CONFIG_BLK_DEV_DM is not set
 
 #
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -195,8 +238,6 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-CONFIG_FILTER=y
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -213,8 +254,12 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
 # CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -223,9 +268,9 @@ CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -259,6 +304,7 @@ CONFIG_NETDEVICES=y
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
 CONFIG_LASI_82596=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
@@ -311,8 +357,14 @@ CONFIG_DL2K=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
@@ -323,19 +375,23 @@ CONFIG_DL2K=y
 # Wireless LAN (non-hamradio)
 #
 CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
 # CONFIG_STRIP is not set
-# CONFIG_AIRONET4500 is not set
 
 #
-# Wireless ISA/PCI cards support
+# Wireless 802.11b ISA/PCI cards support
 #
 CONFIG_AIRO=y
 # CONFIG_HERMES is not set
 CONFIG_NET_WIRELESS=y
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
+# CONFIG_TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -346,11 +402,31 @@ CONFIG_NET_WIRELESS=y
 # CONFIG_WAN is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
 # IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
 #
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
 # Input device support
 #
 CONFIG_INPUT=y
@@ -358,7 +434,10 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=y
@@ -370,11 +449,12 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
 CONFIG_HP_SDC=y
+# CONFIG_HIL_MLC is not set
+# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
@@ -384,11 +464,10 @@ CONFIG_INPUT_KEYBOARD=y
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_KEYBOARD_HIL_OLD is not set
 CONFIG_INPUT_MOUSE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_HIL is not set
 CONFIG_INPUT_JOYSTICK=y
 # CONFIG_JOYSTICK_IFORCE is not set
 # CONFIG_JOYSTICK_WARRIOR is not set
@@ -407,7 +486,7 @@ CONFIG_INPUT_MISC=y
 # CONFIG_INPUT_PCSPKR is not set
 # CONFIG_INPUT_UINPUT is not set
 CONFIG_INPUT_GSC=y
-# CONFIG_HP_SDC_RTC is not set
+CONFIG_HP_SDC_RTC=y
 
 #
 # Character devices
@@ -422,6 +501,7 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -432,8 +512,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_MUX=y
-CONFIG_SERIAL_MUX_CONSOLE=y
+# CONFIG_SERIAL_MUX is not set
+# CONFIG_PDC_CONSOLE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -449,12 +529,17 @@ CONFIG_PRINTER=y
 # CONFIG_I2C is not set
 
 #
-# I2C Hardware Sensors Mainboard support
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
 #
 
 #
 # I2C Hardware Sensors Chip support
 #
+# CONFIG_I2C_SENSOR is not set
 
 #
 # Mice
@@ -463,11 +548,15 @@ CONFIG_PRINTER=y
 # CONFIG_QIC02_TAPE is not set
 
 #
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -488,126 +577,17 @@ CONFIG_GEN_RTC=y
 # CONFIG_VIDEO_DEV is not set
 
 #
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-# CONFIG_CIFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
+# Digital Video Broadcasting Devices
 #
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_DVB is not set
 
 #
 # Graphics support
 #
 CONFIG_FB=y
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_STI is not set
+CONFIG_FB_STI=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON is not set
@@ -618,7 +598,6 @@ CONFIG_FB=y
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -632,12 +611,16 @@ CONFIG_DUMMY_CONSOLE_ROWS=64
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_PCI_CONSOLE=y
-# CONFIG_FBCON_ADVANCED is not set
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 
 #
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
 # Sound
 #
 CONFIG_SOUND=y
@@ -651,6 +634,7 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND_HARMONY is not set
 
 #
 # USB support
@@ -694,6 +678,7 @@ CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_XPAD is not set
 
@@ -718,7 +703,6 @@ CONFIG_USB_OHCI_HCD=y
 # USB Network adaptors
 #
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
@@ -742,11 +726,140 @@ CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_BRLVGER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_GADGET is not set
 
 #
-# Bluetooth support
+# File systems
 #
-# CONFIG_BT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Profiling support
@@ -760,7 +873,8 @@ CONFIG_OPROFILE=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_KALLSYMS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_INFO is not set
 
 #
 # Security options
@@ -770,9 +884,25 @@ CONFIG_MAGIC_SYSRQ=y
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Library routines
 #
-# CONFIG_CRC32 is not set
+CONFIG_CRC32=y
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/Makefile 001-linus.patch/arch/parisc/kernel/Makefile
--- 000-virgin/arch/parisc/kernel/Makefile	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/parisc/kernel/Makefile	Tue Dec 30 16:38:56 2003
@@ -8,6 +8,7 @@ extra-y			:= init_task.o $(head-y) vmlin
 
 AFLAGS_entry.o	:= -traditional
 AFLAGS_pacache.o := -traditional
+CFLAGS_ioctl32.o := -Ifs/
 
 obj-y	     	:= cache.o pacache.o setup.o traps.o time.o irq.o \
 		   pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/cache.c 001-linus.patch/arch/parisc/kernel/cache.c
--- 000-virgin/arch/parisc/kernel/cache.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/parisc/kernel/cache.c	Tue Dec 30 16:38:56 2003
@@ -292,5 +292,10 @@ void __flush_dcache_page(struct page *pa
 		break;
 	}
 }
-
 EXPORT_SYMBOL(__flush_dcache_page);
+
+/* Defined in arch/parisc/kernel/pacache.S */
+EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
+EXPORT_SYMBOL(flush_kernel_dcache_page);
+EXPORT_SYMBOL(flush_data_cache_local);
+EXPORT_SYMBOL(flush_kernel_icache_range_asm);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/drivers.c 001-linus.patch/arch/parisc/kernel/drivers.c
--- 000-virgin/arch/parisc/kernel/drivers.c	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/arch/parisc/kernel/drivers.c	Tue Dec 30 16:38:56 2003
@@ -560,9 +560,9 @@ static void print_parisc_device(struct p
 	static int count;
 
 	print_pa_hwpath(dev, hw_path);
-	printk(KERN_INFO "%d. %s (%d) at 0x%lx [%s], versions 0x%x, 0x%x, 0x%x",
-		++count, dev->name, dev->id.hw_type, dev->hpa, hw_path,
-		dev->id.hversion, dev->id.hversion_rev, dev->id.sversion);
+	printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
+		++count, dev->name, dev->hpa, hw_path, dev->id.hw_type,
+		dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
 
 	if (dev->num_addrs) {
 		int k;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/entry.S 001-linus.patch/arch/parisc/kernel/entry.S
--- 000-virgin/arch/parisc/kernel/entry.S	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/arch/parisc/kernel/entry.S	Tue Dec 30 16:38:56 2003
@@ -77,13 +77,13 @@
 	ldil	L%KERNEL_PSW, %r1
 	ldo	R%KERNEL_PSW(%r1), %r1
 	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17
-	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17	/* Clear IIASQ tail */
+	mtctl	%r0, %cr17	/* Clear IIASQ head */
 	ldil	L%4f, %r1
 	ldo	R%4f(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* Set IIAOQ tail */
 	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* Set IIAOQ head */
 	rfir
 	nop
 4:
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/firmware.c 001-linus.patch/arch/parisc/kernel/firmware.c
--- 000-virgin/arch/parisc/kernel/firmware.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/parisc/kernel/firmware.c	Tue Dec 30 16:38:56 2003
@@ -541,8 +541,8 @@ EXPORT_SYMBOL(pdc_lan_station_id);
  *    o cable too long (ie SE scsi 10Mhz won't support 6m length),
  *    o bus width exported is less than what the interface chip supports.
  */
-int pdc_get_initiator( struct hardware_path *hwpath, unsigned char *scsi_id,
-	unsigned long *period, char *width, char *mode)
+int pdc_get_initiator(struct hardware_path *hwpath, unsigned char *scsi_id,
+		unsigned long *period, char *width, char *mode)
 {
 	int retval;
 
@@ -550,53 +550,49 @@ int pdc_get_initiator( struct hardware_p
 
 /* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
 #define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
-	strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 9) == 0)
+	strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0)
 
 	retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, 
 			      __pa(pdc_result), __pa(hwpath));
 
+	if (retval < PDC_OK)
+		goto fail;
 
-	if (retval >= PDC_OK) {
-		*scsi_id = (unsigned char) pdc_result[0];
+	*scsi_id = (unsigned char) pdc_result[0];
 
-		/* convert Bus speed in Mhz to period (in 1/10 ns) */
-		switch(pdc_result[1]) {
+	/* convert Bus speed in Mhz to period (in 1/10 ns) */
+	switch (pdc_result[1]) {
 		/*
-		** case  0:   driver determines rate
-		** case -1:   Settings are uninitialized.
-		*/
+		 * case  0:   driver determines rate
+		 * case -1:   Settings are uninitialized.
+		 */
 		case  5:  *period = 2000; break;
 		case 10:  *period = 1000; break;
 		case 20:  *period = 500; break;
 		case 40:  *period = 250; break;
 		default: /* Do nothing */ break;
-		}
+	}
 
-		/* 
-		** pdc_result[2]	PDC suggested SCSI id
-		** pdc_result[3]	PDC suggested SCSI rate
-		*/
-
-		if (IS_SPROCKETS()) {
-			/*
-			** Revisit: PAT PDC do the same thing?
-			** A500 also exports 50-pin SE SCSI.
-			**	0 == 8-bit
-			**	1 == 16-bit
-			*/
-			*width = (char) pdc_result[4];
-
-			/* ...in case someone needs it in the future.
-			** sym53c8xx.c comments say it can't autodetect
-			** for 825/825A/875 chips.
-			**	0 == SE, 1 == HVD, 2 == LVD
-			*/
-			*mode = (char) pdc_result[5]; 
-		}
+	/* 
+	 * pdc_result[2]	PDC suggested SCSI id
+	 * pdc_result[3]	PDC suggested SCSI rate
+	 */
+
+	if (IS_SPROCKETS()) {
+		/* 0 == 8-bit, 1 == 16-bit */
+		*width = (char) pdc_result[4];
+
+		/* ...in case someone needs it in the future.
+		 * sym53c8xx.c comments say it can't autodetect
+		 * for 825/825A/875 chips.
+		 *	0 == SE, 1 == HVD, 2 == LVD
+		 */
+		*mode = (char) pdc_result[5]; 
 	}
 
+ fail:
 	spin_unlock_irq(&pdc_lock);
-	return retval >= PDC_OK;
+	return (retval >= PDC_OK);
 }
 EXPORT_SYMBOL(pdc_get_initiator);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/hardware.c 001-linus.patch/arch/parisc/kernel/hardware.c
--- 000-virgin/arch/parisc/kernel/hardware.c	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/arch/parisc/kernel/hardware.c	Tue Dec 30 16:38:56 2003
@@ -772,6 +772,7 @@ static struct hp_hardware hp_hardware_li
 	{HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"}, 
 	{HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"}, 
 	{HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"}, 
+	{HPHW_FIO, 0x015, 0x0007B, 0x0, "KittyHawk GSY Core Audio"}, 
 	{HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"}, 
 	{HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"}, 
 	{HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"}, 
@@ -824,6 +825,7 @@ static struct hp_hardware hp_hardware_li
 	{HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"}, 
 	{HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"}, 
 	{HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"}, 
+	{HPHW_FIO, 0x015, 0x00082, 0x0, "KittyHawk GSY Core SCSI"},
 	{HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"}, 
 	{HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"}, 
 	{HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"}, 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/head.S 001-linus.patch/arch/parisc/kernel/head.S
--- 000-virgin/arch/parisc/kernel/head.S	Wed Dec 17 18:59:20 2003
+++ 001-linus.patch/arch/parisc/kernel/head.S	Tue Dec 30 16:38:56 2003
@@ -221,13 +221,13 @@ $install_iva:
 	** Clear the two-level IIA Space Queue, effectively setting
 	** Kernel space.
 	*/
-	mtctl		%r0,%cr17
-	mtctl		%r0,%cr17
+	mtctl		%r0,%cr17	/* Clear IIASQ tail */
+	mtctl		%r0,%cr17	/* Clear IIASQ head */
 
 	/* Load RFI target into PC queue */
-	mtctl		%r11,%cr18
+	mtctl		%r11,%cr18	/* IIAOQ head */
 	ldo		4(%r11),%r11
-	mtctl		%r11,%cr18
+	mtctl		%r11,%cr18	/* IIAOQ tail */
 
 	/* Jump to hyperspace */
 	rfi
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/head64.S 001-linus.patch/arch/parisc/kernel/head64.S
--- 000-virgin/arch/parisc/kernel/head64.S	Wed Dec 17 18:57:59 2003
+++ 001-linus.patch/arch/parisc/kernel/head64.S	Tue Dec 30 16:38:56 2003
@@ -267,13 +267,13 @@ aligned_rfi:
 	** Clear the two-level IIA Space Queue, effectively setting
 	** Kernel space.
 	*/
-	mtctl		%r0,%cr17
-	mtctl		%r0,%cr17
+	mtctl		%r0,%cr17	/* Clear IIASQ tail */
+	mtctl		%r0,%cr17	/* Clear IIASQ head */
 
 	/* Load RFI target into PC queue */
-	mtctl		%r11,%cr18
+	mtctl		%r11,%cr18	/* IIAOQ head */
 	ldo		4(%r11),%r11
-	mtctl		%r11,%cr18
+	mtctl		%r11,%cr18	/* IIAOQ tail */
 
 	/* Jump to hyperspace */
 	rfi
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/inventory.c 001-linus.patch/arch/parisc/kernel/inventory.c
--- 000-virgin/arch/parisc/kernel/inventory.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/parisc/kernel/inventory.c	Tue Dec 30 16:38:56 2003
@@ -532,7 +532,12 @@ static void __init system_map_inventory(
 	 * Otherwise the machine might crash during iommu setup.
 	 */
 	pdc_io_reset();
-	pdc_io_reset_devices();
+
+	/*
+	 * Unfortunately if we reset devices here, serial console
+	 * stops working :-(
+	 */
+	/* pdc_io_reset_devices(); */
 #endif
 
 	for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/ioctl32.c 001-linus.patch/arch/parisc/kernel/ioctl32.c
--- 000-virgin/arch/parisc/kernel/ioctl32.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/arch/parisc/kernel/ioctl32.c	Tue Dec 30 16:38:56 2003
@@ -8,1783 +8,21 @@
  * ioctls.
  */
 
-#include <linux/config.h>
-#include <linux/compat.h>
-#include <linux/ioctl.h>
-#include <linux/ioctl32.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/ioctl.h>
-#include <linux/if.h>
-#include <linux/slab.h>
-#include <linux/hdreg.h>
-#include <linux/raid/md.h>
-#include <linux/kd.h>
-#include <linux/route.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/vt.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/fd.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/if_pppox.h>
-#include <linux/if_tun.h>
-#include <linux/mtio.h>
-#include <linux/cdrom.h>
-#include <linux/loop.h>
-#include <linux/auto_fs4.h>
-#include <linux/devfs_fs.h>
-#include <linux/ncp_fs.h>
-#include <linux/tty.h>
-#include <linux/vt_kern.h>
-#include <linux/fb.h>
-#include <linux/ext2_fs.h>
-#include <linux/videodev.h>
-#include <linux/netdevice.h>
-#include <linux/raw.h>
-#include <linux/smb_fs.h>
-#include <linux/blkpg.h>
-#include <linux/elevator.h>
-#include <linux/rtc.h>
-#include <linux/pci.h>
-#include <linux/serial.h>
-#include <linux/watchdog.h>
-#include <net/sock.h>		/* siocdevprivate_ioctl */
-
-#include <scsi/scsi.h>
-/* Ugly hack. */
-#undef __KERNEL__
-#include <scsi/scsi_ioctl.h>
-#define __KERNEL__
-#include <scsi/sg.h>
+#define INCLUDES
+#include "compat_ioctl.c"
 
-#include <linux/raid/md_u.h>
-#include <linux/dm-ioctl.h>
-
-#include <asm/types.h>
-#include <asm/uaccess.h>
 #include <asm/perf.h>
-#include <linux/ethtool.h>
-#include <linux/soundcard.h>
-#include <linux/lp.h>
-
-#include <linux/atm.h>
-#include <linux/atmarp.h>
-#include <linux/atmclip.h>
-#include <linux/atmdev.h>
-#include <linux/atmioc.h>
-#include <linux/atmlec.h>
-#include <linux/atmmpc.h>
-#include <linux/atmsvc.h>
-#include <linux/atm_tcp.h>
-#include <linux/sonet.h>
-#include <linux/atm_suni.h>
-#include <linux/mtd/mtd.h>
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci.h>
-
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-#include <linux/nbd.h>
-#include <linux/random.h>
-
 #include <asm/ioctls.h>
 
+#define CODE
+#include "compat_ioctl.c"
+
 /* Use this to get at 32-bit user passed pointers. 
    See sys_sparc32.c for description about these. */
 #define A(__x) ((unsigned long)(__x))
 /* The same for use with copy_from_user() and copy_to_user(). */
 #define B(__x) ((void *)(unsigned long)(__x))
 
-/* Aiee. Someone does not find a difference between int and long */
-#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
-#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
-#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
-#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
-
-static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	int err;
-	unsigned long val;
-	
-	set_fs (KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&val);
-	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)arg))
-		return -EFAULT;
-	return err;
-}
- 
-static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	int err;
-	unsigned long val;
-	
-	if(get_user(val, (u32 *)arg))
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&val);
-	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)arg))
-		return -EFAULT;
-	return err;
-}
-
-static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	/* These are just misnamed, they actually get/put from/to user an int */
-	switch (cmd) {
-	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
-	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
-	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
-	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
-	}
-	return sys_ioctl(fd, cmd, arg);
-}
- 
-static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct compat_timeval *up = (struct compat_timeval *)arg;
-	struct timeval ktv;
-	mm_segment_t old_fs = get_fs();
-	int err;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
-	set_fs(old_fs);
-	if(!err) {
-		err = put_user(ktv.tv_sec, &up->tv_sec);
-		err |= __put_user(ktv.tv_usec, &up->tv_usec);
-	}
-	return err;
-}
-
-struct ifmap32 {
-	u32 mem_start;
-	u32 mem_end;
-	unsigned short base_addr;
-	unsigned char irq;
-	unsigned char dma;
-	unsigned char port;
-};
-
-struct ifreq32 {
-#define IFHWADDRLEN     6
-#define IFNAMSIZ        16
-        union {
-                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
-        } ifr_ifrn;
-        union {
-                struct  sockaddr ifru_addr;
-                struct  sockaddr ifru_dstaddr;
-                struct  sockaddr ifru_broadaddr;
-                struct  sockaddr ifru_netmask;
-                struct  sockaddr ifru_hwaddr;
-                short   ifru_flags;
-                int     ifru_ivalue;
-                int     ifru_mtu;
-                struct  ifmap32 ifru_map;
-                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
-		char	ifru_newname[IFNAMSIZ];
-                compat_caddr_t ifru_data;
-        } ifr_ifru;
-};
-
-struct ifconf32 {
-        int		ifc_len;		/* size of buffer       */
-        compat_caddr_t	ifcbuf;
-};
-
-static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct net_device *dev;
-	struct ifreq32 ifr32;
-	int err;
-
-	if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-		return -EFAULT;
-
-	dev = dev_get_by_index(ifr32.ifr_ifindex);
-	if (!dev)
-		return -ENODEV;
-
-	strcpy(ifr32.ifr_name, dev->name);
-	dev_put(dev);
-
-	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
-	return (err ? -EFAULT : 0);
-}
-
-static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifconf32 ifc32;
-	struct ifconf ifc;
-	struct ifreq32 *ifr32;
-	struct ifreq *ifr;
-	mm_segment_t old_fs;
-	unsigned int i, j;
-	int err;
-
-	if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32)))
-		return -EFAULT;
-
-	if(ifc32.ifcbuf == 0) {
-		ifc32.ifc_len = 0;
-		ifc.ifc_len = 0;
-		ifc.ifc_buf = NULL;
-	} else {
-		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
-			sizeof (struct ifreq);
-		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
-		if (!ifc.ifc_buf)
-			return -ENOMEM;
-	}
-	ifr = ifc.ifc_req;
-	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
-	for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
-		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
-			kfree (ifc.ifc_buf);
-			return -EFAULT;
-		}
-	}
-	old_fs = get_fs(); set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
-	set_fs (old_fs);
-	if (!err) {
-		ifr = ifc.ifc_req;
-		ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
-		for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
-		     i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
-			if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
-				err = -EFAULT;
-				break;
-			}
-		}
-		if (!err) {
-			if (i <= ifc32.ifc_len)
-				ifc32.ifc_len = i;
-			else
-				ifc32.ifc_len = i - sizeof (struct ifreq32);
-			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
-				err = -EFAULT;
-		}
-	}
-	if(ifc.ifc_buf != NULL)
-		kfree (ifc.ifc_buf);
-	return err;
-}
-
-static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifreq ifr;
-	mm_segment_t old_fs;
-	int err;
-	
-	switch (cmd) {
-	case SIOCSIFMAP:
-		err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name));
-		err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
-		err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
-		err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
-		err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
-		err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
-		err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
-		if (err)
-			return -EFAULT;
-		break;
-	case SIOCGPPPSTATS:
-	case SIOCGPPPCSTATS:
-	case SIOCGPPPVER:
-	case SIOCETHTOOL:
-		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-			return -EFAULT;
-		ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
-		if (!ifr.ifr_data)
-			return -EAGAIN;
-		if(cmd == SIOCETHTOOL) {
-			u32 data;
-
-			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-			if(copy_from_user(ifr.ifr_data,
-					  (char *)A(data),
-					  sizeof(struct ethtool_cmd))) {
-				free_page((unsigned long)ifr.ifr_data);
-				return -EFAULT;
-			}
-		}
-		break;
-	default:
-		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-			return -EFAULT;
-		break;
-	}
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
-	if (!err) {
-		switch (cmd) {
-		case SIOCGIFFLAGS:
-		case SIOCGIFMETRIC:
-		case SIOCGIFMTU:
-		case SIOCGIFMEM:
-		case SIOCGIFHWADDR:
-		case SIOCGIFINDEX:
-		case SIOCGIFADDR:
-		case SIOCGIFBRDADDR:
-		case SIOCGIFDSTADDR:
-		case SIOCGIFNETMASK:
-		case SIOCGIFTXQLEN:
-			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
-				return -EFAULT;
-			break;
-		case SIOCGPPPSTATS:
-		case SIOCGPPPCSTATS:
-		case SIOCGPPPVER:
-		case SIOCETHTOOL:
-		{
-			u32 data;
-			int len;
-
-			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-			if(cmd == SIOCETHTOOL)
-				len = sizeof(struct ethtool_cmd);
-			if(cmd == SIOCGPPPVER)
-				len = strlen((char *)ifr.ifr_data) + 1;
-			else if(cmd == SIOCGPPPCSTATS)
-				len = sizeof(struct ppp_comp_stats);
-			else
-				len = sizeof(struct ppp_stats);
-
-			len = copy_to_user((char *)A(data), ifr.ifr_data, len);
-			free_page((unsigned long)ifr.ifr_data);
-			if(len)
-				return -EFAULT;
-			break;
-		}
-		case SIOCGIFMAP:
-			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
-			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
-			err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
-			err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
-			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
-			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
-			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
-			if (err)
-				err = -EFAULT;
-			break;
-		}
-	}
-	return err;
-}
-
-struct rtentry32 {
-        u32   		rt_pad1;
-        struct sockaddr rt_dst;         /* target address               */
-        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
-        struct sockaddr rt_genmask;     /* target network mask (IP)     */
-        unsigned short  rt_flags;
-        short           rt_pad2;
-        u32   		rt_pad3;
-        unsigned char   rt_tos;
-        unsigned char   rt_class;
-        short           rt_pad4;
-        short           rt_metric;      /* +1 for binary compatibility! */
-        /* char * */ u32 rt_dev;        /* forcing the device at add    */
-        u32   		rt_mtu;         /* per route MTU/Window         */
-        u32   		rt_window;      /* Window clamping              */
-        unsigned short  rt_irtt;        /* Initial RTT                  */
-
-};
-
-static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct rtentry r;
-	char devname[16];
-	u32 rtdev;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	
-	ret = copy_from_user (&r.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr));
-	ret |= __get_user (r.rt_flags, &(((struct rtentry32 *)arg)->rt_flags));
-	ret |= __get_user (r.rt_metric, &(((struct rtentry32 *)arg)->rt_metric));
-	ret |= __get_user (r.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu));
-	ret |= __get_user (r.rt_window, &(((struct rtentry32 *)arg)->rt_window));
-	ret |= __get_user (r.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt));
-	ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev));
-	if (rtdev) {
-		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
-		r.rt_dev = devname; devname[15] = 0;
-	} else
-		r.rt_dev = 0;
-	if (ret)
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl (fd, cmd, (long)&r);
-	set_fs (old_fs);
-	return ret;
-}
-
-struct hd_geometry32 {
-	unsigned char heads;
-	unsigned char sectors;
-	unsigned short cylinders;
-	u32 start;
-};
-                        
-static inline int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct hd_geometry geo;
-	int err;
-	
-	set_fs (KERNEL_DS);
-	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
-	set_fs (old_fs);
-	if (!err) {
-		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
-		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
-	}
-	return err ? -EFAULT : 0;
-}
-
-
-#if 0
-/* looks like SPARC only - eg sbus video */
-struct  fbcmap32 {
-	int             index;          /* first element (0 origin) */
-	int             count;
-	u32		red;
-	u32		green;
-	u32		blue;
-};
-
-
-static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct fbcmap f;
-	int ret;
-	char red[256], green[256], blue[256];
-	u32 r, g, b;
-	mm_segment_t old_fs = get_fs();
-	
-	ret = get_user(f.index, &(((struct fbcmap32 *)arg)->index));
-	ret |= __get_user(f.count, &(((struct fbcmap32 *)arg)->count));
-	ret |= __get_user(r, &(((struct fbcmap32 *)arg)->red));
-	ret |= __get_user(g, &(((struct fbcmap32 *)arg)->green));
-	ret |= __get_user(b, &(((struct fbcmap32 *)arg)->blue));
-	if (ret)
-		return -EFAULT;
-	if ((f.index < 0) || (f.index > 255)) return -EINVAL;
-	if (f.index + f.count > 256)
-		f.count = 256 - f.index;
-	if (cmd == FBIOPUTCMAP32) {
-		ret = copy_from_user (red, (char *)A(r), f.count);
-		ret |= copy_from_user (green, (char *)A(g), f.count);
-		ret |= copy_from_user (blue, (char *)A(b), f.count);
-		if (ret)
-			return -EFAULT;
-	}
-	f.red = red; f.green = green; f.blue = blue;
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f);
-	set_fs (old_fs);
-	if (!ret && cmd == FBIOGETCMAP32) {
-		ret = copy_to_user ((char *)A(r), red, f.count);
-		ret |= copy_to_user ((char *)A(g), green, f.count);
-		ret |= copy_to_user ((char *)A(b), blue, f.count);
-	}
-	return ret ? -EFAULT : 0;
-}
-
-struct fbcursor32 {
-	short set;		/* what to set, choose from the list above */
-	short enable;		/* cursor on/off */
-	struct fbcurpos pos;	/* cursor position */
-	struct fbcurpos hot;	/* cursor hot spot */
-	struct fbcmap32 cmap;	/* color map info */
-	struct fbcurpos size;	/* cursor bit map size */
-	u32	image;		/* cursor image bits */
-	u32	mask;		/* cursor mask bits */
-};
-	
-static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct fbcursor f;
-	int ret;
-	char red[2], green[2], blue[2];
-	char image[128], mask[128];
-	u32 r, g, b;
-	u32 m, i;
-	mm_segment_t old_fs = get_fs();
-	
-	ret = copy_from_user (&f, (struct fbcursor32 *)arg, 2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
-	ret |= __get_user(f.size.fbx, &(((struct fbcursor32 *)arg)->size.fbx));
-	ret |= __get_user(f.size.fby, &(((struct fbcursor32 *)arg)->size.fby));
-	ret |= __get_user(f.cmap.index, &(((struct fbcursor32 *)arg)->cmap.index));
-	ret |= __get_user(f.cmap.count, &(((struct fbcursor32 *)arg)->cmap.count));
-	ret |= __get_user(r, &(((struct fbcursor32 *)arg)->cmap.red));
-	ret |= __get_user(g, &(((struct fbcursor32 *)arg)->cmap.green));
-	ret |= __get_user(b, &(((struct fbcursor32 *)arg)->cmap.blue));
-	ret |= __get_user(m, &(((struct fbcursor32 *)arg)->mask));
-	ret |= __get_user(i, &(((struct fbcursor32 *)arg)->image));
-	if (ret)
-		return -EFAULT;
-	if (f.set & FB_CUR_SETCMAP) {
-		if ((uint) f.size.fby > 32)
-			return -EINVAL;
-		ret = copy_from_user (mask, (char *)A(m), f.size.fby * 4);
-		ret |= copy_from_user (image, (char *)A(i), f.size.fby * 4);
-		if (ret)
-			return -EFAULT;
-		f.image = image; f.mask = mask;
-	}
-	if (f.set & FB_CUR_SETCMAP) {
-		ret = copy_from_user (red, (char *)A(r), 2);
-		ret |= copy_from_user (green, (char *)A(g), 2);
-		ret |= copy_from_user (blue, (char *)A(b), 2);
-		if (ret)
-			return -EFAULT;
-		f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue;
-	}
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f);
-	set_fs (old_fs);
-	return ret;
-}
-#endif /* 0 */
-
-struct fb_fix_screeninfo32 {
-	char		id[16];
-        compat_caddr_t	smem_start;
-	__u32		smem_len;
-	__u32		type;
-	__u32		type_aux;
-	__u32		visual;
-	__u16		xpanstep;
-	__u16		ypanstep;
-	__u16		ywrapstep;
-	__u32		line_length;
-        compat_caddr_t	mmio_start;
-	__u32		mmio_len;
-	__u32		accel;
-	__u16		reserved[3];
-};
-
-struct fb_cmap32 {
-	__u32		start;
-	__u32		len;
-	compat_caddr_t	red;
-	compat_caddr_t	green;
-	compat_caddr_t	blue;
-	compat_caddr_t	transp;
-};
-
-static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	u32 red = 0, green = 0, blue = 0, transp = 0;
-	struct fb_fix_screeninfo fix;
-	struct fb_cmap cmap;
-	void *karg;
-	int err = 0;
-
-	memset(&cmap, 0, sizeof(cmap));
-	switch (cmd) {
-	case FBIOGET_FSCREENINFO:
-		karg = &fix;
-		break;
-	case FBIOGETCMAP:
-	case FBIOPUTCMAP:
-		karg = &cmap;
-		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
-		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
-		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
-		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
-		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
-		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-		err = -ENOMEM;
-		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.red)
-			goto out;
-		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.green)
-			goto out;
-		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.blue)
-			goto out;
-		if (transp) {
-			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-			if (!cmap.transp)
-				goto out;
-		}
-			
-		if (cmd == FBIOGETCMAP)
-			break;
-
-		err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
-		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-		break;
-	default:
-		do {
-			static int count = 0;
-			if (++count <= 20)
-				printk(KERN_WARNING
-					"%s: Unknown fb ioctl cmd fd(%d) "
-					"cmd(%08x) arg(%08lx)\n",
-					__FUNCTION__, fd, cmd, arg);
-		} while(0);
-		return -ENOSYS;
-	}
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)karg);
-	set_fs(old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-		struct fb_fix_screeninfo32 fix32;
-	case FBIOGET_FSCREENINFO:
-		memset(&fix32, 0, sizeof(fix32));
-		memcpy(fix32.id, fix.id, sizeof(fix32.id));
-		fix32.smem_start = (__u32)(unsigned long)fix.smem_start;
-		fix32.smem_len	= fix.smem_len;
-		fix32.type	= fix.type;
-		fix32.type_aux	= fix.type_aux;
-		fix32.visual	= fix.visual;
-		fix32.xpanstep	= fix.xpanstep;
-		fix32.ypanstep	= fix.ypanstep;
-		fix32.ywrapstep = fix.ywrapstep;
-		fix32.line_length = fix.line_length;
-		fix32.mmio_start = (__u32)(unsigned long)fix.mmio_start;
-		fix32.mmio_len	= fix.mmio_len;
-		fix32.accel	= fix.accel;
-		memcpy(fix32.reserved, fix.reserved, sizeof(fix32.reserved));
-		err = __copy_to_user((void *) arg, (const void *) &fix32, sizeof(fix32));
-
-printk("fix  : %lx %x  %x %x %x  %x %x %x %x  %lx %x %x\n",
-	fix.smem_start, fix.smem_len,
-	fix.type, fix.type_aux, fix.visual,
-	fix.xpanstep, fix.ypanstep, fix.ywrapstep, fix.line_length,
-	fix.mmio_start, fix.mmio_len, fix.accel);
-printk("fix32: %x %x  %x %x %x  %x %x %x %x  %x %x %x\n",
-	fix32.smem_start, fix32.smem_len,
-	fix32.type, fix32.type_aux, fix32.visual,
-	fix32.xpanstep, fix32.ypanstep, fix32.ywrapstep, fix32.line_length,
-	fix32.mmio_start, fix32.mmio_len, fix32.accel);
-
-		break;
-	case FBIOGETCMAP:
-		err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16));
-		if (cmap.transp)
-			err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16));
-		break;
-	case FBIOPUTCMAP:
-		break;
-	}
-	if (err)
-		err = -EFAULT;
-
-out:	if (cmap.red) kfree(cmap.red);
-	if (cmap.green) kfree(cmap.green);
-	if (cmap.blue) kfree(cmap.blue);
-	if (cmap.transp) kfree(cmap.transp);
-	return err;
-}
-
-static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	unsigned long kval;
-	unsigned int *uvp;
-	int error;
-
-	set_fs(KERNEL_DS);
-	error = sys_ioctl(fd, cmd, (long)&kval);
-	set_fs(old_fs);
-
-	if(error == 0) {
-		uvp = (unsigned int *)arg;
-		if(put_user(kval, uvp))
-			error = -EFAULT;
-	}
-	return error;
-}
-
-struct floppy_struct32 {
-	unsigned int	size;
-	unsigned int	sect;
-	unsigned int	head;
-	unsigned int	track;
-	unsigned int	stretch;
-	unsigned char	gap;
-	unsigned char	rate;
-	unsigned char	spec1;
-	unsigned char	fmt_gap;
-	const compat_caddr_t name;
-};
-
-struct floppy_drive_params32 {
-	char		cmos;
-	u32		max_dtr;
-	u32		hlt;
-	u32		hut;
-	u32		srt;
-	u32		spinup;
-	u32		spindown;
-	unsigned char	spindown_offset;
-	unsigned char	select_delay;
-	unsigned char	rps;
-	unsigned char	tracks;
-	u32		timeout;
-	unsigned char	interleave_sect;
-	struct floppy_max_errors max_errors;
-	char		flags;
-	char		read_track;
-	short		autodetect[8];
-	int		checkfreq;
-	int		native_format;
-};
-
-struct floppy_drive_struct32 {
-	signed char	flags;
-	u32		spinup_date;
-	u32		select_date;
-	u32		first_read_date;
-	short		probed_format;
-	short		track;
-	short		maxblock;
-	short		maxtrack;
-	int		generation;
-	int		keep_data;
-	int		fd_ref;
-	int		fd_device;
-	int		last_checked;
-	compat_caddr_t	dmabuf;
-	int		bufblocks;
-};
-
-struct floppy_fdc_state32 {
-	int		spec1;
-	int		spec2;
-	int		dtr;
-	unsigned char	version;
-	unsigned char	dor;
-	u32		address;
-	unsigned int	rawcmd:2;
-	unsigned int	reset:1;
-	unsigned int	need_configure:1;
-	unsigned int	perp_mode:2;
-	unsigned int	has_fifo:1;
-	unsigned int	driver_version;
-	unsigned char	track[4];
-};
-
-struct floppy_write_errors32 {
-	unsigned int	write_errors;
-	u32		first_error_sector;
-	int		first_error_generation;
-	u32		last_error_sector;
-	int		last_error_generation;
-	unsigned int	badness;
-};
-
-#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
-#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
-#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
-#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
-#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
-#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
-#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
-#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
-#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
-
-static struct {
-	unsigned int	cmd32;
-	unsigned int	cmd;
-} fd_ioctl_trans_table[] = {
-	{ FDSETPRM32, FDSETPRM },
-	{ FDDEFPRM32, FDDEFPRM },
-	{ FDGETPRM32, FDGETPRM },
-	{ FDSETDRVPRM32, FDSETDRVPRM },
-	{ FDGETDRVPRM32, FDGETDRVPRM },
-	{ FDGETDRVSTAT32, FDGETDRVSTAT },
-	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
-	{ FDGETFDCSTAT32, FDGETFDCSTAT },
-	{ FDWERRORGET32, FDWERRORGET }
-};
-
-#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
-
-static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	void *karg = NULL;
-	unsigned int kcmd = 0;
-	int i, err;
-
-	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
-		if (cmd == fd_ioctl_trans_table[i].cmd32) {
-			kcmd = fd_ioctl_trans_table[i].cmd;
-			break;
-		}
-	if (!kcmd)
-		return -EINVAL;
-
-	switch (cmd) {
-		case FDSETPRM32:
-		case FDDEFPRM32:
-		case FDGETPRM32:
-		{
-			struct floppy_struct *f;
-
-			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
-			if (!karg)
-				return -ENOMEM;
-			if (cmd == FDGETPRM32)
-				break;
-			err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size);
-			err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
-			err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head);
-			err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track);
-			err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
-			err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
-			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
-			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
-			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
-			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
-			if (err) {
-				err = -EFAULT;
-				goto out;
-			}
-			break;
-		}
-		case FDSETDRVPRM32:
-		case FDGETDRVPRM32:
-		{
-			struct floppy_drive_params *f;
-
-			f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
-			if (!karg)
-				return -ENOMEM;
-			if (cmd == FDGETDRVPRM32)
-				break;
-			err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
-			err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
-			err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
-			err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
-			err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
-			err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
-			err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
-			err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
-			err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
-			err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
-			err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
-			err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
-			err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
-			err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors));
-			err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
-			err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
-			err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect));
-			err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
-			err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
-			if (err) {
-				err = -EFAULT;
-				goto out;
-			}
-			break;
-		}
-		case FDGETDRVSTAT32:
-		case FDPOLLDRVSTAT32:
-			karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
-			if (!karg)
-				return -ENOMEM;
-			break;
-		case FDGETFDCSTAT32:
-			karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
-			if (!karg)
-				return -ENOMEM;
-			break;
-		case FDWERRORGET32:
-			karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
-			if (!karg)
-				return -ENOMEM;
-			break;
-		default:
-			return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-		case FDGETPRM32:
-		{
-			struct floppy_struct *f = karg;
-
-			err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size);
-			err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
-			err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head);
-			err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track);
-			err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
-			err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
-			err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
-			err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
-			err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
-			err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
-			break;
-		}
-		case FDGETDRVPRM32:
-		{
-			struct floppy_drive_params *f = karg;
-
-			err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
-			err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
-			err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
-			err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
-			err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
-			err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
-			err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
-			err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
-			err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
-			err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
-			err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
-			err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
-			err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
-			err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors));
-			err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
-			err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
-			err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect));
-			err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
-			err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
-			break;
-		}
-		case FDGETDRVSTAT32:
-		case FDPOLLDRVSTAT32:
-		{
-			struct floppy_drive_struct *f = karg;
-
-			err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags);
-			err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date);
-			err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date);
-			err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date);
-			err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format);
-			err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track);
-			err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock);
-			err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack);
-			err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation);
-			err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data);
-			err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref);
-			err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device);
-			err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked);
-			err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf);
-			err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks);
-			break;
-		}
-		case FDGETFDCSTAT32:
-		{
-			struct floppy_fdc_state *f = karg;
-
-			err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1);
-			err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2);
-			err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr);
-			err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version);
-			err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor);
-			err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address);
-			err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address
-			    		   + sizeof(((struct floppy_fdc_state32 *)arg)->address),
-					   (char *)&f->address + sizeof(f->address), sizeof(int));
-			err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version);
-			err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track));
-			break;
-		}
-		case FDWERRORGET32:
-		{
-			struct floppy_write_errors *f = karg;
-
-			err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors);
-			err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector);
-			err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation);
-			err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector);
-			err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation);
-			err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness);
-			break;
-		}
-		default:
-			break;
-	}
-	if (err)
-		err = -EFAULT;
-
-out:	if (karg) kfree(karg);
-	return err;
-}
-
-struct ppp_option_data32 {
-	compat_caddr_t	ptr;
-	__u32		length;
-	int		transmit;
-};
-#define PPPIOCSCOMPRESS32	_IOW('t', 77, struct ppp_option_data32)
-
-struct ppp_idle32 {
-	compat_time_t xmit_idle;
-	compat_time_t recv_idle;
-};
-#define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
-
-static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct ppp_option_data32 data32;
-	struct ppp_option_data data;
-	struct ppp_idle32 idle32;
-	struct ppp_idle idle;
-	unsigned int kcmd;
-	void *karg;
-	int err = 0;
-
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		kcmd = PPPIOCGIDLE;
-		karg = &idle;
-		break;
-	case PPPIOCSCOMPRESS32:
-		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
-			return -EFAULT;
-		data.ptr = kmalloc (data32.length, GFP_KERNEL);
-		if (!data.ptr)
-			return -ENOMEM;
-		if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) {
-			kfree(data.ptr);
-			return -EFAULT;
-		}
-		data.length = data32.length;
-		data.transmit = data32.transmit;
-		kcmd = PPPIOCSCOMPRESS;
-		karg = &data;
-		break;
-	default:
-		do {
-			static int count = 0;
-			if (++count <= 20)
-				printk(KERN_WARNING
-					"ppp_ioctl: Unknown cmd fd(%d) "
-					"cmd(%08x) arg(%08x)\n",
-					(int)fd, (unsigned int)cmd, (unsigned int)arg);
-		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		if (err)
-			return err;
-		idle32.xmit_idle = idle.xmit_idle;
-		idle32.recv_idle = idle.recv_idle;
-		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
-			return -EFAULT;
-		break;
-	case PPPIOCSCOMPRESS32:
-		kfree(data.ptr);
-		break;
-	default:
-		break;
-	}
-	return err;
-}
-
-
-struct mtget32 {
-	__u32	mt_type;
-	__u32	mt_resid;
-	__u32	mt_dsreg;
-	__u32	mt_gstat;
-	__u32	mt_erreg;
-	compat_daddr_t	mt_fileno;
-	compat_daddr_t	mt_blkno;
-};
-#define MTIOCGET32	_IOR('m', 2, struct mtget32)
-
-struct mtpos32 {
-	__u32	mt_blkno;
-};
-#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
-
-struct mtconfiginfo32 {
-	__u32	mt_type;
-	__u32	ifc_type;
-	__u16	irqnr;
-	__u16	dmanr;
-	__u16	port;
-	__u32	debug;
-	__u32	have_dens:1;
-	__u32	have_bsf:1;
-	__u32	have_fsr:1;
-	__u32	have_bsr:1;
-	__u32	have_eod:1;
-	__u32	have_seek:1;
-	__u32	have_tell:1;
-	__u32	have_ras1:1;
-	__u32	have_ras2:1;
-	__u32	have_ras3:1;
-	__u32	have_qfa:1;
-	__u32	pad1:5;
-	char	reserved[10];
-};
-#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
-#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
-
-static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct mtconfiginfo info;
-	struct mtget get;
-	struct mtpos pos;
-	unsigned long kcmd;
-	void *karg;
-	int err = 0;
-
-	switch(cmd) {
-	case MTIOCPOS32:
-		kcmd = MTIOCPOS;
-		karg = &pos;
-		break;
-	case MTIOCGET32:
-		kcmd = MTIOCGET;
-		karg = &get;
-		break;
-	case MTIOCGETCONFIG32:
-		kcmd = MTIOCGETCONFIG;
-		karg = &info;
-		break;
-	case MTIOCSETCONFIG32:
-		kcmd = MTIOCSETCONFIG;
-		karg = &info;
-		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
-		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
-		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
-		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
-		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
-		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
-		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
-				     (char *)&((struct mtconfiginfo32 *)arg)->debug
-				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
-		if (err)
-			return -EFAULT;
-		break;
-	default:
-		do {
-			static int count = 0;
-			if (++count <= 20)
-				printk(KERN_WARNING
-					"mt_ioctl: Unknown cmd fd(%d) "
-					"cmd(%08x) arg(%08x)\n",
-					(int)fd, (unsigned int)cmd, (unsigned int)arg);
-		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		return err;
-	switch (cmd) {
-	case MTIOCPOS32:
-		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
-		break;
-	case MTIOCGET32:
-		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
-		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
-		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
-		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
-		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
-		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
-		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
-		break;
-	case MTIOCGETCONFIG32:
-		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
-		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
-		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
-		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
-		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
-		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
-		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
-			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
-					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
-		break;
-	case MTIOCSETCONFIG32:
-		break;
-	}
-	return err ? -EFAULT: 0;
-}
-
-struct cdrom_read32 {
-	int		cdread_lba;
-	compat_caddr_t	cdread_bufaddr;
-	int		cdread_buflen;
-};
-
-struct cdrom_read_audio32 {
-	union cdrom_addr	addr;
-	u_char			addr_format;
-	int			nframes;
-	compat_caddr_t		buf;
-};
-
-struct cdrom_generic_command32 {
-	unsigned char	cmd[CDROM_PACKET_SIZE];
-	compat_caddr_t	buffer;
-	unsigned int	buflen;
-	int		stat;
-	compat_caddr_t	sense;
-	compat_caddr_t	reserved[3];
-};
-
-static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct cdrom_read cdread;
-	struct cdrom_read_audio cdreadaudio;
-	struct cdrom_generic_command cgc;
-	compat_caddr_t addr;
-	char *data = 0;
-	void *karg;
-	int err = 0;
-
-	switch(cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		karg = &cdread;
-		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
-		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
-		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdread.cdread_buflen, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdread.cdread_bufaddr = data;
-		break;
-	case CDROMREADAUDIO:
-		karg = &cdreadaudio;
-		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
-		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
-		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
-		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdreadaudio.buf = data;
-		break;
-	case CDROM_SEND_PACKET:
-		karg = &cgc;
-		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
-		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
-		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
-		if (err)
-			return -EFAULT;
-		if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
-			return -ENOMEM;
-		cgc.buffer = data;
-		break;
-	default:
-		do {
-			static int count = 0;
-			if (++count <= 20)
-				printk(KERN_WARNING
-					"cdrom_ioctl: Unknown cmd fd(%d) "
-					"cmd(%08x) arg(%08x)\n",
-					(int)fd, (unsigned int)cmd, (unsigned int)arg);
-		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen);
-		break;
-	case CDROMREADAUDIO:
-		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
-		break;
-	case CDROM_SEND_PACKET:
-		err = copy_to_user((char *)A(addr), data, cgc.buflen);
-		break;
-	default:
-		break;
-	}
-out:	if (data)
-		kfree(data);
-	return err ? -EFAULT : 0;
-}
-
-struct loop_info32 {
-	int		lo_number;      /* ioctl r/o */
-	compat_dev_t	lo_device;      /* ioctl r/o */
-	unsigned int	lo_inode;       /* ioctl r/o */
-	compat_dev_t	lo_rdevice;     /* ioctl r/o */
-	int		lo_offset;
-	int		lo_encrypt_type;
-	int		lo_encrypt_key_size;    /* ioctl w/o */
-	int		lo_flags;       /* ioctl r/o */
-	char		lo_name[LO_NAME_SIZE];
-	unsigned char	lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
-	unsigned int	lo_init[2];
-	char		reserved[4];
-};
-
-static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct loop_info l;
-	int err = -EINVAL;
-
-	switch(cmd) {
-	case LOOP_SET_STATUS:
-		err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
-		err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
-		err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
-		err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
-		err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
-					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
-		if (err) {
-			err = -EFAULT;
-		} else {
-			set_fs (KERNEL_DS);
-			err = sys_ioctl (fd, cmd, (unsigned long)&l);
-			set_fs (old_fs);
-		}
-		break;
-	case LOOP_GET_STATUS:
-		set_fs (KERNEL_DS);
-		err = sys_ioctl (fd, cmd, (unsigned long)&l);
-		set_fs (old_fs);
-		if (!err) {
-			err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
-			err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
-			err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
-			err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
-			err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset,
-					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
-			if (err)
-				err = -EFAULT;
-		}
-		break;
-	default: {
-		static int count = 0;
-		if (++count <= 20)
-			printk(KERN_WARNING
-				"%s: Unknown loop ioctl cmd, fd(%d) "
-				"cmd(%08x) arg(%08lx)\n",
-				__FUNCTION__, fd, cmd, arg);
-	}
-	}
-	return err;
-}
-
-#ifdef CONFIG_VT
-extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
-
-static int vt_check(struct file *file)
-{
-	struct tty_struct *tty;
-	struct inode *inode = file->f_dentry->d_inode;
-	
-	if (file->f_op->ioctl != tty_ioctl)
-		return -EINVAL;
-	                
-	tty = (struct tty_struct *)file->private_data;
-	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
-		return -EINVAL;
-	                                                
-	if (tty->driver->ioctl != vt_ioctl)
-		return -EINVAL;
-	
-	/*
-	 * To have permissions to do most of the vt ioctls, we either have
-	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG
-	 */
-	if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG))
-		return 1;
-	return 0;                                                    
-}
-
-struct consolefontdesc32 {
-	unsigned short charcount;       /* characters in font (256 or 512) */
-	unsigned short charheight;      /* scan lines per character (1-32) */
-	u32 chardata;			/* font data in expanded form */
-};
-
-static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file)
-{
-	struct consolefontdesc cfdarg;
-	struct console_font_op op;
-	int i, perm;
-
-	perm = vt_check(file);
-	if (perm < 0) return perm;
-	
-	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
-		return -EFAULT;
-	
-	cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata);
- 	
-	switch (cmd) {
-	case PIO_FONTX:
-		if (!perm)
-			return -EPERM;
-		op.op = KD_FONT_OP_SET;
-		op.flags = 0;
-		op.width = 8;
-		op.height = cfdarg.charheight;
-		op.charcount = cfdarg.charcount;
-		op.data = cfdarg.chardata;
-		return con_font_op(fg_console, &op);
-	case GIO_FONTX:
-		if (!cfdarg.chardata)
-			return 0;
-		op.op = KD_FONT_OP_GET;
-		op.flags = 0;
-		op.width = 8;
-		op.height = cfdarg.charheight;
-		op.charcount = cfdarg.charcount;
-		op.data = cfdarg.chardata;
-		i = con_font_op(fg_console, &op);
-		if (i)
-			return i;
-		cfdarg.charheight = op.height;
-		cfdarg.charcount = op.charcount;
-		((struct consolefontdesc32 *)&cfdarg)->chardata	= (unsigned long)cfdarg.chardata;
-		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32)))
-			return -EFAULT;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-struct console_font_op32 {
-	unsigned int op;        /* operation code KD_FONT_OP_* */
-	unsigned int flags;     /* KD_FONT_FLAG_* */
-	unsigned int width, height;     /* font size */
-	unsigned int charcount;
-	u32 data;    /* font data with height fixed to 32 */
-};
-                                        
-static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file)
-{
-	struct console_font_op op;
-	int perm = vt_check(file), i;
-	struct vt_struct *vt;
-	
-	if (perm < 0) return perm;
-	
-	if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32)))
-		return -EFAULT;
-	if (!perm && op.op != KD_FONT_OP_GET)
-		return -EPERM;
-	op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data);
-	op.flags |= KD_FONT_FLAG_OLD;
-	vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
-	i = con_font_op(vt->vc_num, &op);
-	if (i) return i;
-	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
-	if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32)))
-		return -EFAULT;
-	return 0;
-}
-
-struct unimapdesc32 {
-	unsigned short entry_ct;
-	u32 entries;
-};
-
-static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file)
-{
-	struct unimapdesc32 tmp;
-	int perm = vt_check(file);
-	
-	if (perm < 0) return perm;
-	if (copy_from_user(&tmp, user_ud, sizeof tmp))
-		return -EFAULT;
-	switch (cmd) {
-	case PIO_UNIMAP:
-		if (!perm) return -EPERM;
-		return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries));
-	case GIO_UNIMAP:
-		return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries));
-	}
-	return 0;
-}
-#endif
-
-#if 0
-static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	__kernel_uid_t kuid;
-	int err;
-
-	cmd = SMB_IOC_GETMOUNTUID;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
-	set_fs(old_fs);
-
-	if (err >= 0)
-		err = put_user(kuid, (compat_uid_t *)arg);
-
-	return err;
-}
-#endif
-
-struct atmif_sioc32 {
-        int		number;
-        int		length;
-        compat_caddr_t	arg;
-};
-
-struct atm_iobuf32 {
-	int		length;
-	compat_caddr_t	buffer;
-};
-
-#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
-#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
-#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
-#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
-#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
-#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
-#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
-#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
-#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
-#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
-#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
-#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
-#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
-#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
-#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
-#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
-#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
-
-static struct {
-        unsigned int cmd32;
-        unsigned int cmd;
-} atm_ioctl_map[] = {
-        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
-	{ ATM_GETNAMES32,    ATM_GETNAMES },
-        { ATM_GETTYPE32,     ATM_GETTYPE },
-        { ATM_GETESI32,      ATM_GETESI },
-        { ATM_GETADDR32,     ATM_GETADDR },
-        { ATM_RSTADDR32,     ATM_RSTADDR },
-        { ATM_ADDADDR32,     ATM_ADDADDR },
-        { ATM_DELADDR32,     ATM_DELADDR },
-        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
-	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
-	{ ATM_SETESI32,      ATM_SETESI },
-	{ ATM_SETESIF32,     ATM_SETESIF },
-	{ ATM_GETSTAT32,     ATM_GETSTAT },
-	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
-	{ ATM_GETLOOP32,     ATM_GETLOOP },
-	{ ATM_SETLOOP32,     ATM_SETLOOP },
-	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
-};
-
-#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
-
-
-static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct atm_iobuf32 iobuf32;
-	struct atm_iobuf   iobuf = { 0, NULL };
-	mm_segment_t old_fs;
-	int err;
-
-	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
-	    sizeof(struct atm_iobuf32));
-	if (err)
-		return -EFAULT;
-
-	iobuf.length = iobuf32.length;
-
-	if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
-		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
-	} else {
-		iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
-		if (iobuf.buffer == NULL) {
-			err = -ENOMEM;
-			goto out;
-		}
-
-		err = copy_from_user(iobuf.buffer, B(iobuf32.buffer), iobuf.length);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-	}
-
-	old_fs = get_fs(); set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
-	set_fs (old_fs);
-        if(err)
-		goto out;
-
-        if(iobuf.buffer && iobuf.length > 0) {
-		err = copy_to_user(B(iobuf32.buffer), iobuf.buffer, iobuf.length);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-	}
-	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
-
- out:
-        if(iobuf32.buffer && iobuf32.length > 0)
-		kfree(iobuf.buffer);
-
-	return err;
-}
-
-
-static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-        struct atmif_sioc32 sioc32;
-        struct atmif_sioc   sioc = { 0, 0, NULL };
-        mm_segment_t old_fs;
-        int err;
-        
-        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
-			     sizeof(struct atmif_sioc32));
-        if (err)
-                return -EFAULT;
-
-        sioc.number = sioc32.number;
-        sioc.length = sioc32.length;
-        
-	if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
-		sioc.arg = (void*)(unsigned long)sioc32.arg;
-        } else {
-                sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
-                if (sioc.arg == NULL) {
-                        err = -ENOMEM;
-			goto out;
-		}
-                
-                err = copy_from_user(sioc.arg, B(sioc32.arg), sioc32.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        
-        old_fs = get_fs(); set_fs (KERNEL_DS);
-        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
-        set_fs (old_fs);
-        if(err) {
-                goto out;
-	}
-        
-        if(sioc.arg && sioc.length > 0) {
-                err = copy_to_user(B(sioc32.arg), sioc.arg, sioc.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
-        
- out:
-        if(sioc32.arg && sioc32.length > 0)
-		kfree(sioc.arg);
-        
-	return err;
-}
-
-
-static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
-{
-        int i;
-        unsigned int cmd = 0;
-        
-	switch (cmd32) {
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atmif_sioc(fd, cmd32, arg);
-	}
-
-		for (i = 0; i < NR_ATM_IOCTL; i++) {
-			if (cmd32 == atm_ioctl_map[i].cmd32) {
-				cmd = atm_ioctl_map[i].cmd;
-				break;
-			}
-		}
-	        if (i == NR_ATM_IOCTL) {
-	        return -EINVAL;
-	        }
-        
-        switch (cmd) {
-	case ATM_GETNAMES:
-		return do_atm_iobuf(fd, cmd, arg);
-	    
-	case ATM_GETLINKRATE:
-        case ATM_GETTYPE:
-        case ATM_GETESI:
-        case ATM_GETADDR:
-        case ATM_RSTADDR:
-        case ATM_ADDADDR:
-        case ATM_DELADDR:
-        case ATM_GETCIRANGE:
-	case ATM_SETCIRANGE:
-	case ATM_SETESI:
-	case ATM_SETESIF:
-	case ATM_GETSTAT:
-	case ATM_GETSTATZ:
-	case ATM_GETLOOP:
-	case ATM_SETLOOP:
-	case ATM_QUERYLOOP:
-                return do_atmif_sioc(fd, cmd, arg);
-        }
-
-        return -EINVAL;
-}
-
 #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
 /* This really belongs in include/linux/drm.h -DaveM */
 #include "../../../drivers/char/drm/drm.h"
@@ -2323,137 +561,6 @@ static int drm32_res_ctx(unsigned int fd
 
 #endif
 
-static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return -EINVAL;
-}
-
-static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	/* The mkswap binary hard codes it to Intel value :-((( */
-	return w_long(fd, BLKGETSIZE, arg);
-}
-
-struct blkpg_ioctl_arg32 {
-	int op;
-	int flags;
-	int datalen;
-	u32 data;
-};
-                                
-static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg)
-{
-	struct blkpg_ioctl_arg a;
-	struct blkpg_partition p;
-	int err;
-	mm_segment_t old_fs = get_fs();
-	
-	err = get_user(a.op, &arg->op);
-	err |= __get_user(a.flags, &arg->flags);
-	err |= __get_user(a.datalen, &arg->datalen);
-	err |= __get_user((long)a.data, &arg->data);
-	if (err) return err;
-	switch (a.op) {
-	case BLKPG_ADD_PARTITION:
-	case BLKPG_DEL_PARTITION:
-		if (a.datalen < sizeof(struct blkpg_partition))
-			return -EINVAL;
-                if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
-			return -EFAULT;
-		a.data = &p;
-		set_fs (KERNEL_DS);
-		err = sys_ioctl(fd, cmd, (unsigned long)&a);
-		set_fs (old_fs);
-	default:
-		return -EINVAL;
-	}                                        
-	return err;
-}
-
-/* Fix sizeof(sizeof()) breakage */
-#define BLKBSZGET_32	_IOR(0x12,112,int)
-#define BLKBSZSET_32	_IOW(0x12,113,int)
-#define BLKGETSIZE64_32	_IOR(0x12,114,int)
-
-static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return sys_ioctl(fd, BLKBSZGET, arg);
-}
-
-static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return sys_ioctl(fd, BLKBSZSET, arg);
-}
-
-static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
-			   unsigned long arg)
-{
-	return sys_ioctl(fd, BLKGETSIZE64, arg);
-}
-
-static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
-}
-
-/* USB to be done */
-
-
-struct serial_struct32 {
-	int	type;
-	int	line;
-	unsigned int	port;
-	int	irq;
-	int	flags;
-	int	xmit_fifo_size;
-	int	custom_divisor;
-	int	baud_base;
-	unsigned short	close_delay;
-	char	io_type;
-	char	reserved_char[1];
-	int	hub6;
-	unsigned short	closing_wait; /* time to wait before closing */
-	unsigned short	closing_wait2; /* no longer used... */
-	unsigned int	iomem_base;	/* char * really */
-	unsigned short	iomem_reg_shift;
-	unsigned int	port_high;
-	int	reserved[1];
-};
-
-static int do_tiocgserial(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct serial_struct ss;
-	int ret;
-	struct serial_struct32 * uptr = (struct serial_struct32 *)arg;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl(fd, cmd, (unsigned long) &ss);
-	set_fs(old_fs);
-
-	if (!ret) {
-		/* structs match up to iomem_base */
-		ret = copy_to_user(uptr, &ss, sizeof(struct serial_struct32));
-		ret |= put_user(ss.iomem_base, &uptr->iomem_base);
-		ret |= put_user(ss.iomem_reg_shift, &uptr->iomem_reg_shift);
-		ret |= put_user(ss.port_high, &uptr->port_high);
-		if (ret)
-			ret = -EFAULT;
-	}
-	return ret;
-}
-
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	int err = sys_ioctl(fd, cmd, arg);
-	if ((unsigned) err > -4095)
-		printk(KERN_WARNING 
-			"ioctl(%d, 0x%x, %p) -- SIOCDEVPRIVATE-based ioctls aren't really\n"
-			"supported, though some will work by accident.\n",
-		    fd, cmd, (void *)arg);
-	return err;
-}
-
 #define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, 0 },
 #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) 
 
@@ -2463,6 +570,9 @@ int siocdevprivate_ioctl(unsigned int fd
 IOCTL_TABLE_START
 #include <linux/compat_ioctl.h>
 
+#define DECLARES
+#include "compat_ioctl.c"
+
 /* Might be moved to compat_ioctl.h with some ifdefs... */
 COMPATIBLE_IOCTL(TIOCSTART)
 COMPATIBLE_IOCTL(TIOCSTOP)
@@ -2474,132 +584,10 @@ COMPATIBLE_IOCTL(PA_PERF_OFF)
 COMPATIBLE_IOCTL(PA_PERF_VERSION)
 
 /* And these ioctls need translation */
-HANDLE_IOCTL(TIOCGSERIAL, do_tiocgserial)
-HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
-HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
-HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc)
-HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
-HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
-HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
-/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
-HANDLE_IOCTL(SIOCRTMSG, ret_einval)
-HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
-HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
-HANDLE_IOCTL(BLKGETSIZE, w_long)
-HANDLE_IOCTL(0x1260, broken_blkgetsize)
-HANDLE_IOCTL(BLKSECTGET, w_long)
-HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
-/* take care of sizeof(sizeof()) breakage */
-/* block stuff */
-HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
-HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
-HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
-
-HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans)
-HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans)
-HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans)
-
-HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans)
-HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans)
-HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans)
-HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans)
-HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans)
-HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans)
-HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans)
-HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans)
-HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
-HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
-HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
-HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
-HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
-HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
-HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
-#ifdef CONFIG_VT
-HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
-HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
-HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
-HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
-HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
-#endif
-HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
-#if 0
-/* One SMB ioctl needs translations. */
-#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
-HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
-#endif
-HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
+
 #if defined(CONFIG_GEN_RTC)
 COMPATIBLE_IOCTL(RTC_AIE_ON)
 COMPATIBLE_IOCTL(RTC_AIE_OFF)
@@ -2618,6 +606,7 @@ COMPATIBLE_IOCTL(RTC_IRQP_SET)
 HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
 COMPATIBLE_IOCTL(RTC_EPOCH_SET)
 #endif
+
 #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
 HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
 HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/irq.c 001-linus.patch/arch/parisc/kernel/irq.c
--- 000-virgin/arch/parisc/kernel/irq.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/arch/parisc/kernel/irq.c	Tue Dec 30 16:38:56 2003
@@ -215,29 +215,30 @@ EXPORT_SYMBOL(enable_irq);
 int show_interrupts(struct seq_file *p, void *v)
 {
 #ifdef CONFIG_PROC_FS
-	unsigned int regnr = 0;
+	unsigned int regnr = *(loff_t *) v, i;
 
-	seq_puts(p, "     ");
+	if (regnr == 0) {
+		seq_puts(p, "     ");
 #ifdef CONFIG_SMP
-	for (regnr = 0; regnr < NR_CPUS; regnr++)
+		for (i = 0; i < NR_CPUS; i++)
 #endif
-		seq_printf(p, "      CPU%02d ", regnr);
+			seq_printf(p, "      CPU%02d ", i);
 
 #ifdef PARISC_IRQ_CR16_COUNTS
-	seq_printf(p, "[min/avg/max] (CPU cycle counts)");
+		seq_printf(p, "[min/avg/max] (CPU cycle counts)");
 #endif
-	seq_putc(p, '\n');
+		seq_putc(p, '\n');
+	}
 
 	/* We don't need *irqsave lock variants since this is
 	** only allowed to change while in the base context.
 	*/
 	spin_lock(&irq_lock);
-	for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
-	    unsigned int i;
+	if (regnr < NR_IRQ_REGS) {
 	    struct irq_region *region = irq_region[regnr];
 
             if (!region || !region->action)
-		continue;
+		    goto skip;
 
 	    for (i = 0; i <= MAX_CPU_IRQ; i++) {
 		struct irqaction *action = &region->action[i];
@@ -286,9 +287,9 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 	    }
 	}
+  skip:
 	spin_unlock(&irq_lock);
 
-	seq_putc(p, '\n');
 #endif	/* CONFIG_PROC_FS */
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/pacache.S 001-linus.patch/arch/parisc/kernel/pacache.S
--- 000-virgin/arch/parisc/kernel/pacache.S	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/arch/parisc/kernel/pacache.S	Tue Dec 30 16:38:56 2003
@@ -79,13 +79,13 @@ flush_tlb_all_local:
 	ldil    L%REAL_MODE_PSW, %r1
 	ldo     R%REAL_MODE_PSW(%r1), %r1
 	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17
-	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17	/* Clear IIASQ tail */
+	mtctl	%r0, %cr17	/* Clear IIASQ head */
 	ldil    L%PA(1f),%r1
 	ldo     R%PA(1f)(%r1),%r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ head */
 	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ tail */
 	rfi
 	nop
 
@@ -185,13 +185,13 @@ fdtdone:
 	ldo	R%KERNEL_PSW(%r1), %r1
 	or      %r1,%r19,%r1    /* Set I bit if set on entry */
 	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17
-	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17	/* Clear IIASQ tail */
+	mtctl	%r0, %cr17	/* Clear IIASQ head */
 	ldil    L%(2f), %r1
 	ldo     R%(2f)(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ head */
 	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ tail */
 	rfi
 	nop
 
@@ -837,13 +837,13 @@ disable_sr_hashing_asm:
 	ldil    L%REAL_MODE_PSW, %r1
 	ldo     R%REAL_MODE_PSW(%r1), %r1
 	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17
-	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17	/* Clear IIASQ tail */
+	mtctl	%r0, %cr17	/* Clear IIASQ head */
 	ldil    L%PA(1f),%r1
 	ldo     R%PA(1f)(%r1),%r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ head */
 	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ tail */
 	rfi
 	nop
 
@@ -889,13 +889,13 @@ srdis_done:
 	ldil	L%KERNEL_PSW, %r1
 	ldo	R%KERNEL_PSW(%r1), %r1
 	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17
-	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17	/* Clear IIASQ tail */
+	mtctl	%r0, %cr17	/* Clear IIASQ head */
 	ldil    L%(2f), %r1
 	ldo     R%(2f)(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ head */
 	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18
+	mtctl	%r1, %cr18	/* IIAOQ tail */
 	rfi
 	nop
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/parisc_ksyms.c 001-linus.patch/arch/parisc/kernel/parisc_ksyms.c
--- 000-virgin/arch/parisc/kernel/parisc_ksyms.c	Wed Dec 17 18:59:58 2003
+++ 001-linus.patch/arch/parisc/kernel/parisc_ksyms.c	Tue Dec 30 16:38:56 2003
@@ -26,10 +26,6 @@ EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strpbrk);
 
-#include <asm/processor.h>
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(boot_cpu_data);
-
 #include <linux/pm.h>
 EXPORT_SYMBOL(pm_power_off);
 
@@ -64,15 +60,6 @@ EXPORT_SYMBOL(__memcpy_toio);
 EXPORT_SYMBOL(__memcpy_fromio);
 EXPORT_SYMBOL(__memset_io);
 
-#include <asm/cache.h>
-EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
-EXPORT_SYMBOL(flush_kernel_dcache_page);
-EXPORT_SYMBOL(flush_data_cache_local);
-EXPORT_SYMBOL(flush_kernel_icache_range_asm);
-EXPORT_SYMBOL(flush_all_caches);
-EXPORT_SYMBOL(dcache_stride);
-EXPORT_SYMBOL(flush_cache_all_local);
-
 #include <asm/unistd.h>
 extern long sys_open(const char *, int, int);
 extern off_t sys_lseek(int, off_t, int);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/pdc_chassis.c 001-linus.patch/arch/parisc/kernel/pdc_chassis.c
--- 000-virgin/arch/parisc/kernel/pdc_chassis.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/parisc/kernel/pdc_chassis.c	Tue Dec 30 16:38:56 2003
@@ -2,7 +2,7 @@
  *		arch/parisc/kernel/pdc_chassis.c
  *
  * 		Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- *		Copyright (C) 2002 Thibaut Varene <varenet@esiee.fr>
+ *		Copyright (C) 2002-2003 Thibaut Varene <varenet@esiee.fr>
  *
  *
  *		This program is free software; you can redistribute it and/or modify
@@ -35,6 +35,8 @@
 #include <asm/pdc_chassis.h>
 #include <asm/processor.h>
 
+
+#ifdef CONFIG_PDC_CHASSIS
 static int pdc_chassis_old = 0;	
 
 
@@ -102,6 +104,7 @@ static struct notifier_block pdc_chassis
 	.notifier_call = pdc_chassis_reboot_event,
 	.priority = INT_MAX,
 };
+#endif /* CONFIG_PDC_CHASSIS */
 
 
 /**
@@ -110,16 +113,33 @@ static struct notifier_block pdc_chassis
 
 void __init parisc_pdc_chassis_init(void)
 {
-	DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
-
-	/* initialize panic notifier chain */
-	notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
+#ifdef CONFIG_PDC_CHASSIS
+	int handle = 0;
 
-	/* initialize reboot notifier chain */
-	register_reboot_notifier(&pdc_chassis_reboot_block);
+	DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
 
-	/* Check for old LED Panel */
+	/* Let see if we have something to handle... */
+	/* Check for PDC_PAT or old LED Panel */
 	pdc_chassis_checkold();
+	if (is_pdc_pat()) {
+#ifdef __LP64__	/* see pdc_chassis_send_status() */
+		printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
+		handle = 1;
+#endif /* __LP64__ */
+	}
+	else if (pdc_chassis_old) {
+		printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
+		handle = 1;
+	}
+	
+	if (handle) {
+		/* initialize panic notifier chain */
+		notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
+
+		/* initialize reboot notifier chain */
+		register_reboot_notifier(&pdc_chassis_reboot_block);
+	}
+#endif /* CONFIG_PDC_CHASSIS */
 }
 
 
@@ -128,7 +148,8 @@ void __init parisc_pdc_chassis_init(void
  * and changes the front panel LEDs according to the new system state
  * @retval: PDC call return value.
  *
- * Only machines with 64 bits PDC PAT and E-class are supported atm.
+ * Only machines with 64 bits PDC PAT and those reported in
+ * pdc_chassis_checkold() are supported atm.
  * 
  * returns 0 if no error, -1 if no supported PDC is present or invalid message,
  * else returns the appropriate PDC error code.
@@ -140,7 +161,7 @@ int pdc_chassis_send_status(int message)
 {
 	/* Maybe we should do that in an other way ? */
 	int retval = 0;
-
+#ifdef CONFIG_PDC_CHASSIS
 	DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
 
 #ifdef __LP64__	/* pdc_pat_chassis_send_log is defined only when #ifdef __LP64__ */
@@ -199,7 +220,7 @@ int pdc_chassis_send_status(int message)
 				retval = -1;
 		}
 	} else retval = -1;
-#endif
-		
+#endif /* __LP64__ */
+#endif /* CONFIG_PDC_CHASSIS */
 	return retval;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/pdc_cons.c 001-linus.patch/arch/parisc/kernel/pdc_cons.c
--- 000-virgin/arch/parisc/kernel/pdc_cons.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/arch/parisc/kernel/pdc_cons.c	Tue Dec 30 16:38:56 2003
@@ -61,16 +61,6 @@ static struct tty_driver * pdc_console_d
 	*index = c->index ? c->index-1 : fg_console;
 	return &console_driver;
 }
-
-#elif defined(CONFIG_SERIAL_MUX)
-#warning CONFIG_SERIAL_MUX
-#define PDC_CONSOLE_DEVICE pdc_console_device
-#warning "FIXME - should be: static struct tty_driver * pdc_console_device (struct console *c, int *index)"
-static kdev_t pdc_console_device (struct console *c, int *index)
-{
-        return mk_kdev(MUX_MAJOR, 0);
-}
-
 #else
 #define PDC_CONSOLE_DEVICE NULL
 #endif
@@ -105,7 +95,7 @@ static void pdc_console_init_force(void)
 
 void __init pdc_console_init(void)
 {
-#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) || defined(CONFIG_SERIAL_MUX)
+#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
 	pdc_console_init_force();
 #endif
 #ifdef EARLY_BOOTUP_DEBUG
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/process.c 001-linus.patch/arch/parisc/kernel/process.c
--- 000-virgin/arch/parisc/kernel/process.c	Wed Dec 17 18:59:55 2003
+++ 001-linus.patch/arch/parisc/kernel/process.c	Tue Dec 30 16:38:56 2003
@@ -179,6 +179,7 @@ pid_t kernel_thread(int (*fn)(void *), v
 
 	return __kernel_thread(fn, arg, flags);
 }
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Free current thread data structures etc..
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/processor.c 001-linus.patch/arch/parisc/kernel/processor.c
--- 000-virgin/arch/parisc/kernel/processor.c	Wed Dec 17 18:59:46 2003
+++ 001-linus.patch/arch/parisc/kernel/processor.c	Tue Dec 30 16:38:56 2003
@@ -27,14 +27,12 @@
  *
  */
 #include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#define PCI_DEBUG
-#include <linux/pci.h>
-#undef PCI_DEBUG
+#include <linux/slab.h>
 
 #include <asm/cache.h>
 #include <asm/hardware.h>	/* for register_parisc_driver() stuff */
@@ -45,6 +43,8 @@
 #include <asm/parisc-device.h>
 
 struct system_cpuinfo_parisc boot_cpu_data;
+EXPORT_SYMBOL(boot_cpu_data);
+
 struct cpuinfo_parisc cpu_data[NR_CPUS];
 
 /*
@@ -105,11 +105,11 @@ static int __init processor_probe(struct
 		status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
 			dev->mod_index, PA_VIEW, &pa_pdc_cell);
 
-		ASSERT(PDC_OK == status);
+		BUG_ON(PDC_OK != status);
 
 		/* verify it's the same as what do_pat_inventory() found */
-		ASSERT(dev->mod_info == pa_pdc_cell.mod_info);
-		ASSERT(dev->pmod_loc == pa_pdc_cell.mod_location);
+		BUG_ON(dev->mod_info != pa_pdc_cell.mod_info);
+		BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location);
 
 		txn_addr = pa_pdc_cell.mod[0];   /* id_eid for IO sapic */
 
@@ -122,7 +122,7 @@ static int __init processor_probe(struct
 		/* get the cpu number */
 		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa);
 
-		ASSERT(PDC_OK == status);
+		BUG_ON(PDC_OK != status);
 
 		if (cpu_info.cpu_num >= NR_CPUS) {
 			printk(KERN_WARNING "IGNORING CPU at 0x%x,"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/real2.S 001-linus.patch/arch/parisc/kernel/real2.S
--- 000-virgin/arch/parisc/kernel/real2.S	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/arch/parisc/kernel/real2.S	Tue Dec 30 16:38:56 2003
@@ -154,12 +154,12 @@ rfi_virt2real:
 	nop
 	
 	rsm             (PSW_SM_Q|PSW_SM_I),%r0  /* disable Q & I bits to load iia queue */
-	mtctl		0, %cr17	/* space 0 */
-	mtctl		0, %cr17
+	mtctl		%r0, %cr17	/* Clear IIASQ tail */
+	mtctl		%r0, %cr17	/* Clear IIASQ head */
 	load32		PA(rfi_v2r_1), %r1
-	mtctl		%r1, %cr18
+	mtctl		%r1, %cr18	/* IIAOQ head */
 	ldo		4(%r1), %r1
-	mtctl		%r1, %cr18
+	mtctl		%r1, %cr18	/* IIAOQ tail */
 	load32          REAL_MODE_PSW, %r1
 	mtctl		%r1, %cr22
 	rfi
@@ -191,12 +191,12 @@ rfi_real2virt:
 	nop
 	
 	rsm             PSW_SM_Q,%r0    /* disable Q bit to load iia queue */
-	mtctl		0, %cr17	/* space 0 */
-	mtctl		0, %cr17
+	mtctl		%r0, %cr17	/* Clear IIASQ tail */
+	mtctl		%r0, %cr17	/* Clear IIASQ head */
 	load32		(rfi_r2v_1), %r1
-	mtctl		%r1, %cr18
+	mtctl		%r1, %cr18	/* IIAOQ head */
 	ldo		4(%r1), %r1
-	mtctl		%r1, %cr18
+	mtctl		%r1, %cr18	/* IIAOQ tail */
 	load32		KERNEL_PSW, %r1
 	mtctl		%r1, %cr22
 	rfi
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/signal.c 001-linus.patch/arch/parisc/kernel/signal.c
--- 000-virgin/arch/parisc/kernel/signal.c	Wed Dec 17 18:59:53 2003
+++ 001-linus.patch/arch/parisc/kernel/signal.c	Tue Dec 30 16:38:56 2003
@@ -33,13 +33,22 @@
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 
-#define DEBUG_SIG 0
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#include "signal32.h"
+#endif
+
+#define DEBUG_SIG 0 
+#define DEBUG_SIG_LEVEL 2
 
 #if DEBUG_SIG
-#define DBG(x)	printk x
+#define DBG(LEVEL, ...) \
+        ((DEBUG_SIG_LEVEL >= LEVEL) \
+	? printk(__VA_ARGS__) : (void) 0)
 #else
-#define DBG(x)
+#define DBG(LEVEL, ...)
 #endif
+	
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -52,43 +61,6 @@
 
 int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
 
-int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
-{
-	if (from->si_code < 0)
-		return __copy_to_user(to, from, sizeof(siginfo_t));
-	else {
-		int err;
-
-		/*
-		 * If you change siginfo_t structure, please be sure
-		 * this code is fixed accordingly.  It should never
-		 * copy any pad contained in the structure to avoid
-		 * security leaks, but must copy the generic 3 ints
-		 * plus the relevant union member.
-		 */
-		err = __put_user(from->si_signo, &to->si_signo);
-		err |= __put_user(from->si_errno, &to->si_errno);
-		err |= __put_user((short)from->si_code, &to->si_code);
-		switch (from->si_code >> 16) {
-		      case __SI_FAULT >> 16:
-			/* FIXME: should we put the interruption code here? */
-		      case __SI_POLL >> 16:
-			err |= __put_user(from->si_addr, &to->si_addr);
-			break;
-		      case __SI_CHLD >> 16:
-			err |= __put_user(from->si_utime, &to->si_utime);
-			err |= __put_user(from->si_stime, &to->si_stime);
-			err |= __put_user(from->si_status, &to->si_status);
-		      default:
-			err |= __put_user(from->si_uid, &to->si_uid);
-			err |= __put_user(from->si_pid, &to->si_pid);
-			break;
-		      /* case __SI_RT: This is not generated by the kernel as of now.  */
-		}
-		return err;
-	}
-}
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -101,26 +73,27 @@ sys_rt_sigsuspend(sigset_t *unewset, siz
 {
 	sigset_t saveset, newset;
 #ifdef __LP64__
-	/* XXX FIXME -- assumes 32-bit user app! */
 	compat_sigset_t newset32;
 
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(compat_sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset32, (compat_sigset_t *)unewset, sizeof(newset32)))
-		return -EFAULT;
-
-	newset.sig[0] = newset32.sig[0] | ((unsigned long)newset32.sig[1] << 32);
-#else
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
+	if(personality(current->personality) == PER_LINUX32){
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&newset32, (compat_sigset_t *)unewset, sizeof(newset32)))
+			return -EFAULT;
+		sigset_32to64(&newset,&newset32);
+		
+	} else 
 #endif
+	{
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+	
+		if (copy_from_user(&newset, unewset, sizeof(newset)))
+			return -EFAULT;
+	}
+
 	sigdelsetmask(&newset, ~_BLOCKABLE);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -161,7 +134,9 @@ restore_sigcontext(struct sigcontext *sc
 	err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
 	err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
 	err |= __get_user(regs->sar, &sc->sc_sar);
-	DBG(("restore_sigcontext: r28 is %ld\n", regs->gr[28]));
+	DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n", 
+			regs->iaoq[0],regs->iaoq[1]);
+	DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
 	return err;
 }
 
@@ -174,6 +149,9 @@ sys_rt_sigreturn(struct pt_regs *regs, i
 	unsigned long usp = (regs->gr[30] & ~(0x01UL));
 	unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 #ifdef __LP64__
+	compat_sigset_t compat_set;
+	struct compat_rt_sigframe * compat_frame;
+	
 	if(personality(current->personality) == PER_LINUX32)
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
@@ -182,11 +160,23 @@ sys_rt_sigreturn(struct pt_regs *regs, i
 	/* Unwind the user stack to get the rt_sigframe structure. */
 	frame = (struct rt_sigframe *)
 		(usp - sigframe_size);
-	DBG(("in sys_rt_sigreturn, frame is %p\n", frame));
-
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto give_sigsegv;
+	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
 
+#ifdef __LP64__
+	compat_frame = (struct compat_rt_sigframe *)frame;
+	
+	if(personality(current->personality) == PER_LINUX32){
+		DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
+		if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
+			goto give_sigsegv;
+		sigset_32to64(&set,&compat_set);
+	} else
+#endif
+	{
+		if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+			goto give_sigsegv;
+	}
+		
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sighand->siglock);
 	current->blocked = set;
@@ -194,17 +184,32 @@ sys_rt_sigreturn(struct pt_regs *regs, i
 	spin_unlock_irq(&current->sighand->siglock);
 
 	/* Good thing we saved the old gr[30], eh? */
-	if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
-		goto give_sigsegv;
-
-	DBG(("usp: %#08lx stack %p", usp, &frame->uc.uc_stack));
+#ifdef __LP64__
+	if(personality(current->personality) == PER_LINUX32){
+		DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
+				&compat_frame->uc.uc_mcontext);
+// FIXME: Load upper half from register file
+		if (restore_sigcontext32(&compat_frame->uc.uc_mcontext, 
+					&compat_frame->regs, regs))
+			goto give_sigsegv;
+		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
+				usp, &compat_frame->uc.uc_stack);
+		if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
+			goto give_sigsegv;
+	} else
+#endif
+	{
+		DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
+				&frame->uc.uc_mcontext);
+		if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
+			goto give_sigsegv;
+		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
+				usp, &frame->uc.uc_stack);
+		if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
+			goto give_sigsegv;
+	}
+		
 
-	/* I don't know why everyone else assumes they can call this
-           with a pointer to a stack_t on the kernel stack.  That
-           makes no sense.  Anyway we'll do it like m68k, since we
-           also are using segmentation in the same way as them. */
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
-		goto give_sigsegv;
 
 	/* If we are on the syscall path IAOQ will not be restored, and
 	 * if we are on the interrupt path we must not corrupt gr31.
@@ -212,14 +217,13 @@ sys_rt_sigreturn(struct pt_regs *regs, i
 	if (in_syscall)
 		regs->gr[31] = regs->iaoq[0];
 #if DEBUG_SIG
-	DBG(("returning to %#lx\n", regs->iaoq[0]));
-	DBG(("in sys_rt_sigreturn:\n"));
+	DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
 	show_regs(regs);
 #endif
 	return;
 
 give_sigsegv:
-	DBG(("sys_rt_sigreturn sending SIGSEGV\n"));
+	DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
 	si.si_signo = SIGSEGV;
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
@@ -237,9 +241,16 @@ give_sigsegv:
 static inline void *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
+	/*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
+	  don't use the parameter it doesn't matter */
+
+	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
+			(unsigned long)ka, sp, frame_size);
+	
 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
 		sp = current->sas_ss_sp; /* Stacks grow up! */
 
+	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
 	return (void *) sp; /* Stacks grow up.  Fun. */
 }
 
@@ -259,20 +270,20 @@ setup_sigcontext(struct sigcontext *sc, 
 		err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
 		err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
 		err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
-		DBG(("setup_sigcontext: iaoq %#lx/%#lx\n",
-			regs->gr[31], regs->gr[31]));
+		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
+			regs->gr[31], regs->gr[31]+4);
 	} else {
 		err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
 		err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
-		DBG(("setup_sigcontext: iaoq %#lx/%#lx\n", 
-			regs->iaoq[0], regs->iaoq[1]));
+		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n", 
+			regs->iaoq[0], regs->iaoq[1]);
 	}
 
 	err |= __put_user(flags, &sc->sc_flags);
 	err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
 	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
 	err |= __put_user(regs->sar, &sc->sc_sar);
-	DBG(("setup_sigcontext: r28 is %ld\n", regs->gr[28]));
+	DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
 
 	return err;
 }
@@ -286,46 +297,85 @@ setup_rt_frame(int sig, struct k_sigacti
 	unsigned long haddr, sigframe_size;
 	struct siginfo si;
 	int err = 0;
-
+#ifdef __LP64__
+	compat_int_t compat_val;
+	struct compat_rt_sigframe * compat_frame;
+	compat_sigset_t compat_set;
+#endif
+	
 	usp = (regs->gr[30] & ~(0x01UL));
+	/*FIXME: frame_size parameter is unused, remove it. */
 	frame = get_sigframe(ka, usp, sizeof(*frame));
 
-	DBG(("setup_rt_frame 1: frame %p info %p\n", frame, info));
+	DBG(1,"SETUP_RT_FRAME: START\n");
+	DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
 
-	err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= __put_user(sas_ss_flags(regs->gr[30]),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	
+#ifdef __LP64__
+
+	compat_frame = (struct compat_rt_sigframe *)frame;
+	
+	if(personality(current->personality) == PER_LINUX32) {
+		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
+		err |= compat_copy_siginfo_to_user(&compat_frame->info, info);
+		DBG(1,"SETUP_RT_FRAME: 1\n");
+		compat_val = (compat_int_t)current->sas_ss_sp;
+		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
+		DBG(1,"SETUP_RT_FRAME: 2\n");
+		compat_val = (compat_int_t)current->sas_ss_size;
+		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
+		DBG(1,"SETUP_RT_FRAME: 3\n");
+		compat_val = sas_ss_flags(regs->gr[30]);		
+		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);		
+		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
+		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
+		err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, 
+					&compat_frame->regs, regs, in_syscall);
+		sigset_64to32(&compat_set,set);
+		err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
+	} else
+#endif
+	{	
+		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
+		err |= copy_siginfo_to_user(&frame->info, info);
+		err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+		err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+		err |= __put_user(sas_ss_flags(regs->gr[30]),
+				  &frame->uc.uc_stack.ss_flags);
+		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
+		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
+		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
+		/* FIXME: Should probably be converted aswell for the compat case */
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	}
+	
 	if (err)
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
 	err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
-			&frame->tramp[0]);
-	err |= __put_user(INSN_LDI_R20, &frame->tramp[1]);
-	err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[2]);
-	err |= __put_user(INSN_NOP, &frame->tramp[3]);
+			&frame->tramp[SIGRETURN_TRAMP+0]);
+	err |= __put_user(INSN_LDI_R20, &frame->tramp[SIGRETURN_TRAMP+1]);
+	err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[SIGRETURN_TRAMP+2]);
+	err |= __put_user(INSN_NOP, &frame->tramp[SIGRETURN_TRAMP+3]);
 
 #if DEBUG_SIG
 	/* Assert that we're flushing in the correct space... */
 	{
 		int sid;
 		asm ("mfsp %%sr3,%0" : "=r" (sid));
-		DBG(("flushing 64 bytes at space %#x offset %p\n",
-		       sid, frame->tramp));
+		DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
+		       sid, frame->tramp);
 	}
 #endif
 
-	flush_user_dcache_range((unsigned long) &frame->tramp[0],
-			   (unsigned long) &frame->tramp[4]);
-	flush_user_icache_range((unsigned long) &frame->tramp[0],
-			   (unsigned long) &frame->tramp[4]);
+	flush_user_dcache_range((unsigned long) &frame->tramp[SIGRETURN_TRAMP],
+			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
+	flush_user_icache_range((unsigned long) &frame->tramp[SIGRETURN_TRAMP],
+			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
 
-	rp = (unsigned long) frame->tramp;
+	rp = (unsigned long) &frame->tramp[SIGRETURN_TRAMP];
 
 	if (err)
 		goto give_sigsegv;
@@ -359,8 +409,8 @@ setup_rt_frame(int sig, struct k_sigacti
 		
 		haddr = fdesc.addr;
 		regs->gr[19] = fdesc.gp;
-		DBG(("64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
-		     haddr, regs->gr[19], in_syscall));
+		DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
+		     haddr, regs->gr[19], in_syscall);
 	}
 #endif
 
@@ -391,24 +441,33 @@ setup_rt_frame(int sig, struct k_sigacti
 
 	regs->gr[2]  = rp;                /* userland return pointer */
 	regs->gr[26] = sig;               /* signal number */
-	regs->gr[25] = A(&frame->info); /* siginfo pointer */
-	regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
 	
-	DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",
+#ifdef __LP64__
+	if(personality(current->personality) == PER_LINUX32){
+		regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
+		regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
+	} else
+#endif
+	{		
+		regs->gr[25] = A(&frame->info); /* siginfo pointer */
+		regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
+	}
+	
+	DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
 	       regs->gr[30], sigframe_size,
-	       regs->gr[30] + sigframe_size));
+	       regs->gr[30] + sigframe_size);
 	/* Raise the user stack pointer to make a proper call frame. */
 	regs->gr[30] = (A(frame) + sigframe_size);
 
 
-	DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+	DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
 	       current->comm, current->pid, frame, regs->gr[30],
-	       regs->iaoq[0], regs->iaoq[1], rp));
+	       regs->iaoq[0], regs->iaoq[1], rp);
 
 	return 1;
 
 give_sigsegv:
-	DBG(("setup_rt_frame sending SIGSEGV\n"));
+	DBG(1,"setup_rt_frame: sending SIGSEGV\n");
 	if (sig == SIGSEGV)
 		ka->sa.sa_handler = SIG_DFL;
 	si.si_signo = SIGSEGV;
@@ -431,8 +490,8 @@ handle_signal(unsigned long sig, siginfo
 {
 	struct k_sigaction *ka = &current->sighand->action[sig-1];
 
-	DBG(("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
-	       sig, ka, info, oldset, regs));
+	DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
+	       sig, ka, info, oldset, regs);
 	
 	/* Set up the stack frame */
 	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
@@ -470,8 +529,8 @@ do_signal(sigset_t *oldset, struct pt_re
 	struct k_sigaction *ka;
 	int signr;
 
-	DBG(("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
-	       oldset, regs, regs->sr[7], current->sigpending, in_syscall));
+	DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
+	       oldset, regs, regs->sr[7], in_syscall);
 
 	/* Everyone else checks to see if they are in kernel mode at
 	   this point and exits if that's the case.  I'm not sure why
@@ -481,11 +540,13 @@ do_signal(sigset_t *oldset, struct pt_re
 	if (!oldset)
 		oldset = &current->blocked;
 
-	DBG(("do_signal: oldset %08lx:%08lx\n", 
-		oldset->sig[0], oldset->sig[1]));
+	DBG(1,"do_signal: oldset %08lx / %08lx\n", 
+		oldset->sig[0], oldset->sig[1]);
 
 
 	signr = get_signal_to_deliver(&info, regs, NULL);
+	DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
+	
 	if (signr > 0) {
 		/* Restart a system call if necessary. */
 		if (in_syscall) {
@@ -494,14 +555,14 @@ do_signal(sigset_t *oldset, struct pt_re
 		        case -ERESTART_RESTARTBLOCK:
 				current_thread_info()->restart_block.fn = do_no_restart_syscall;
 			case -ERESTARTNOHAND:
-				DBG(("ERESTARTNOHAND: returning -EINTR\n"));
+				DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
 				regs->gr[28] = -EINTR;
 				break;
 
 			case -ERESTARTSYS:
 				ka = &current->sighand->action[signr-1];
 				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					DBG(("ERESTARTSYS: putting -EINTR\n"));
+					DBG(1,"ERESTARTSYS: putting -EINTR\n");
 					regs->gr[28] = -EINTR;
 					break;
 				}
@@ -520,9 +581,8 @@ do_signal(sigset_t *oldset, struct pt_re
 		   delivery failed, we need to continue to iterate in
 		   this loop so we can deliver the SIGSEGV... */
 		if (handle_signal(signr, &info, oldset, regs, in_syscall)) {
-			DBG((KERN_DEBUG
-				"Exiting do_signal (success), regs->gr[28] = %ld\n",
-				regs->gr[28]));
+			DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
+				regs->gr[28]);
 			return 1;
 		}
 	}
@@ -530,10 +590,42 @@ do_signal(sigset_t *oldset, struct pt_re
 	/* Did we come from a system call? */
 	if (in_syscall) {
 		/* Restart the system call - no handlers present */
-		if (regs->gr[28] == -ERESTART_RESTARTBLOCK ||
-		    regs->gr[28] == -ERESTARTNOHAND ||
-		    regs->gr[28] == -ERESTARTSYS ||
-		    regs->gr[28] == -ERESTARTNOINTR) {
+		if (regs->gr[28] == -ERESTART_RESTARTBLOCK) {
+			unsigned int *usp = (unsigned int *)regs->gr[30];
+
+			/* Setup a trampoline to restart the syscall
+			 * with __NR_restart_syscall
+			 *
+			 *  0: <return address (orig r31)>
+			 *  4: <2nd half for 64-bit>
+			 *  8: ldw 0(%sp), %r31
+			 * 12: be 0x100(%sr2, %r0)
+			 * 16: ldi __NR_restart_syscall, %r20
+			 */
+#ifndef __LP64__
+			put_user(regs->gr[31], &usp[0]);
+			put_user(0x0fc0109f, &usp[2]);
+#else
+			put_user(regs->gr[31] >> 32, &usp[0]);
+			put_user(regs->gr[31] & 0xffffffff, &usp[1]);
+			put_user(0x0fc010df, &usp[2]);
+#endif
+			put_user(0xe0008200, &usp[3]);
+			put_user(0x34140000, &usp[4]);
+
+			/* Stack is 64-byte aligned, and we only 
+			 * need to flush 1 cache line */
+			asm("fdc 0(%%sr3, %0)\n"
+			    "fic 0(%%sr3, %0)\n"
+			    "sync\n"
+			    : : "r"(regs->gr[30]));
+
+			regs->gr[31] = regs->gr[30] + 8;
+			/* Preserve original r28. */
+			regs->gr[28] = regs->orig_r28;
+		} else if (regs->gr[28] == -ERESTARTNOHAND ||
+		           regs->gr[28] == -ERESTARTSYS ||
+		           regs->gr[28] == -ERESTARTNOINTR) {
 			/* Hooray for delayed branching.  We don't
                            have to restore %r20 (the system call
                            number) because it gets loaded in the delay
@@ -544,8 +636,8 @@ do_signal(sigset_t *oldset, struct pt_re
 		}
 	}
 	
-	DBG(("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", 
-		regs->gr[28]));
+	DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
+		regs->gr[28]);
 
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/signal32.c 001-linus.patch/arch/parisc/kernel/signal32.c
--- 000-virgin/arch/parisc/kernel/signal32.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/arch/parisc/kernel/signal32.c	Tue Dec 30 16:38:56 2003
@@ -10,20 +10,32 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 
+#include <asm/compat_signal.h>
 #include <asm/uaccess.h>
+
+#include "signal32.h"
 #include "sys32.h"
 
-struct k_sigaction32 {
-	struct sigaction32 sa;
-};
+#define DEBUG_COMPAT_SIG 0 
+#define DEBUG_COMPAT_SIG_LEVEL 2
+
+#if DEBUG_COMPAT_SIG
+#define DBG(LEVEL, ...) \
+	((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
+	? printk(__VA_ARGS__) : (void) 0)
+#else
+#define DBG(LEVEL, ...)
+#endif
 
-static inline void
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+inline void
 sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
 {
 	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
 }
 
-static inline void
+inline void
 sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
 {
 	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
@@ -120,16 +132,10 @@ sys32_rt_sigaction(int sig, const struct
 	return ret;
 }
 
-typedef struct {
-	unsigned int ss_sp;
-	int ss_flags;
-	compat_size_t ss_size;
-} stack_t32;
-
 int 
-do_sigaltstack32 (const stack_t32 *uss32, stack_t32 *uoss32, unsigned long sp)
+do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned long sp)
 {
-	stack_t32 ss32, oss32;
+	compat_stack_t ss32, oss32;
 	stack_t ss, oss;
 	stack_t *ssp = NULL, *ossp = NULL;
 	int ret;
@@ -160,3 +166,218 @@ do_sigaltstack32 (const stack_t32 *uss32
 
 	return ret;
 }
+
+long
+restore_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
+		struct pt_regs *regs)
+{
+	long err = 0;
+	compat_uint_t compat_reg;
+	compat_uint_t compat_regt;
+	int regn;
+	
+	/* When loading 32-bit values into 64-bit registers make
+	   sure to clear the upper 32-bits */
+	DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
+	DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
+	DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
+	for(regn=0; regn < 32; regn++){
+		err |= __get_user(compat_reg,&sc->sc_gr[regn]);
+		regs->gr[regn] = compat_reg;
+		/* Load upper half */
+		err |= __get_user(compat_regt,&rf->rf_gr[regn]);
+		regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
+		DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", 
+				regn, regs->gr[regn], compat_regt, compat_reg);
+	}
+	DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
+	/* XXX: BE WARNED FR's are 64-BIT! */
+	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
+		
+	/* Better safe than sorry, pass __get_user two things of
+	   the same size and let gcc do the upward conversion to 
+	   64-bits */		
+	err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
+	/* Load upper half */
+	err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
+	regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
+	DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
+	DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", 
+			&sc->sc_iaoq[0], compat_reg);
+
+	err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
+	/* Load upper half */
+	err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
+	regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
+	DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
+	DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", 
+			&sc->sc_iaoq[1],compat_reg);	
+	DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", 
+			regs->iaoq[0],regs->iaoq[1]);		
+		
+	err |= __get_user(compat_reg, &sc->sc_iasq[0]);
+	/* Load the upper half for iasq */
+	err |= __get_user(compat_regt, &rf->rf_iasq[0]);
+	regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
+	DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
+	
+	err |= __get_user(compat_reg, &sc->sc_iasq[1]);
+	/* Load the upper half for iasq */
+	err |= __get_user(compat_regt, &rf->rf_iasq[1]);
+	regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
+	DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
+	DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", 
+		regs->iasq[0],regs->iasq[1]);		
+
+	err |= __get_user(compat_reg, &sc->sc_sar);
+	/* Load the upper half for sar */
+	err |= __get_user(compat_regt, &rf->rf_sar);
+	regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;	
+	DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);	
+	DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);		
+	DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
+	
+	return err;
+}
+
+/*
+ * Set up the sigcontext structure for this process.
+ * This is not an easy task if the kernel is 64-bit, it will require
+ * that we examine the process personality to determine if we need to
+ * truncate for a 32-bit userspace.
+ */
+long
+setup_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf, 
+		struct pt_regs *regs, int in_syscall)		 
+{
+	compat_int_t flags = 0;
+	long err = 0;
+	compat_uint_t compat_reg;
+	compat_uint_t compat_regb;
+	int regn;
+	
+	if (on_sig_stack((unsigned long) sc))
+		flags |= PARISC_SC_FLAG_ONSTACK;
+	
+	if (in_syscall) {
+		
+		DBG(1,"setup_sigcontext32: in_syscall\n");
+		
+		flags |= PARISC_SC_FLAG_IN_SYSCALL;
+		/* Truncate gr31 */
+		compat_reg = (compat_uint_t)(regs->gr[31]);
+		/* regs->iaoq is undefined in the syscall return path */
+		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
+		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
+				&sc->sc_iaoq[0], compat_reg);
+		
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->gr[32] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
+		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
+		
+		
+		compat_reg = (compat_uint_t)(regs->gr[31]+4);
+		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
+		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
+				&sc->sc_iaoq[1], compat_reg);
+		/* Store upper half */
+		compat_reg = (compat_uint_t)((regs->gr[32]+4) >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
+		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
+		
+		/* Truncate sr3 */
+		compat_reg = (compat_uint_t)(regs->sr[3]);
+		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
+		err |= __put_user(compat_reg, &sc->sc_iasq[1]);		
+		
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
+		err |= __put_user(compat_reg, &rf->rf_iasq[1]);		
+		
+		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
+		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);		
+		DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",				
+			regs->gr[31], regs->gr[31]+4);
+		
+	} else {
+		
+		compat_reg = (compat_uint_t)(regs->iaoq[0]);
+		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
+		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
+				&sc->sc_iaoq[0], compat_reg);
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);	
+		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
+		
+		compat_reg = (compat_uint_t)(regs->iaoq[1]);
+		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
+		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
+				&sc->sc_iaoq[1], compat_reg);
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
+		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
+		
+		
+		compat_reg = (compat_uint_t)(regs->iasq[0]);
+		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
+		DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
+				&sc->sc_iasq[0], compat_reg);
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
+		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
+		
+		
+		compat_reg = (compat_uint_t)(regs->iasq[1]);
+		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
+		DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
+				&sc->sc_iasq[1], compat_reg);
+		/* Store upper half */
+		compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
+		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
+		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
+
+		/* Print out the IAOQ for debugging */		
+		DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", 
+			regs->iaoq[0], regs->iaoq[1]);
+	}
+
+	err |= __put_user(flags, &sc->sc_flags);
+	
+	DBG(1,"setup_sigcontext32: Truncating general registers.\n");
+	
+	for(regn=0; regn < 32; regn++){
+		/* Truncate a general register */
+		compat_reg = (compat_uint_t)(regs->gr[regn]);
+		err |= __put_user(compat_reg, &sc->sc_gr[regn]);
+		/* Store upper half */
+		compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
+		err |= __put_user(compat_regb, &rf->rf_gr[regn]);
+
+		/* DEBUG: Write out the "upper / lower" register data */
+		DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, 
+				compat_regb, compat_reg);
+	}
+	
+	/* Copy the floating point registers (same size)
+	   XXX: BE WARNED FR's are 64-BIT! */	
+	DBG(1,"setup_sigcontext32: Copying from regs to sc, "
+	      "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
+		sizeof(regs->fr), sizeof(sc->sc_fr));
+	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
+
+	compat_reg = (compat_uint_t)(regs->sar);
+	err |= __put_user(compat_reg, &sc->sc_sar);
+	DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
+	/* Store upper half */
+	compat_reg = (compat_uint_t)(regs->sar >> 32);
+	err |= __put_user(compat_reg, &rf->rf_sar);	
+	DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
+	DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
+
+	return err;
+}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/signal32.h 001-linus.patch/arch/parisc/kernel/signal32.h
--- 000-virgin/arch/parisc/kernel/signal32.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/parisc/kernel/signal32.h	Tue Dec 30 16:38:56 2003
@@ -0,0 +1,25 @@
+#ifndef _PARISC64_KERNEL_SIGNAL32_H
+#define _PARISC64_KERNEL_SIGNAL32_H
+
+#include <linux/compat.h>
+#include <asm/compat_signal.h>
+#include <asm/compat_rt_sigframe.h>
+
+/* ELF32 signal handling */
+
+struct k_sigaction32 {
+	struct compat_sigaction sa;
+};
+
+void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
+void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
+int do_sigaltstack32 (const compat_stack_t *uss32, 
+		compat_stack_t *uoss32, unsigned long sp);
+long restore_sigcontext32(struct compat_sigcontext *sc, 
+		struct compat_regfile *rf,
+		struct pt_regs *regs);
+long setup_sigcontext32(struct compat_sigcontext *sc, 
+		struct compat_regfile *rf,
+		struct pt_regs *regs, int in_syscall);
+
+#endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/smp.c 001-linus.patch/arch/parisc/kernel/smp.c
--- 000-virgin/arch/parisc/kernel/smp.c	Wed Dec 17 18:59:54 2003
+++ 001-linus.patch/arch/parisc/kernel/smp.c	Tue Dec 30 16:38:56 2003
@@ -257,7 +257,7 @@ ipi_interrupt(int irq, void *dev_id, str
 				printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
 					this_cpu, which);
 				ops &= ~(1 << which);
-				return;
+				return IRQ_NONE;
 			} /* Switch */
 		} /* while (ops) */
 	}
@@ -326,7 +326,7 @@ int
 smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
 {
 	struct smp_call_struct data;
-	long timeout;
+	unsigned long timeout;
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	
 	data.func = func;
@@ -376,6 +376,8 @@ smp_call_function (void (*func) (void *i
 	return 0;
 }
 
+EXPORT_SYMBOL(smp_call_function);
+
 
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/sys_parisc.c 001-linus.patch/arch/parisc/kernel/sys_parisc.c
--- 000-virgin/arch/parisc/kernel/sys_parisc.c	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/parisc/kernel/sys_parisc.c	Tue Dec 30 16:38:56 2003
@@ -241,108 +241,6 @@ asmlinkage ssize_t parisc_readahead(int 
 }
 
 /*
- * FIXME, please remove this crap as soon as possible
- *
- * This is here to fix up broken glibc structures, 
- * which are already fixed in newer glibcs
- */
-#include <linux/msg.h>
-#include <linux/sem.h>
-#include <linux/shm.h>
-#include "sys32.h"
-
-struct broken_ipc_perm
-{
-    key_t key;			/* Key.  */
-    uid_t uid;			/* Owner's user ID.  */
-    gid_t gid;			/* Owner's group ID.  */
-    uid_t cuid;			/* Creator's user ID.  */
-    gid_t cgid;			/* Creator's group ID.  */
-    unsigned short int mode;		/* Read/write permission.  */
-    unsigned short int __pad1;
-    unsigned short int seq;		/* Sequence number.  */
-    unsigned short int __pad2;
-    unsigned long int __unused1;
-    unsigned long int __unused2;
-};
-		    
-struct broken_shmid64_ds {
-	struct broken_ipc_perm	shm_perm;	/* operation perms */
-	size_t			shm_segsz;	/* size of segment (bytes) */
-#ifndef __LP64__
-	unsigned int		__pad1;
-#endif
-	__kernel_time_t		shm_atime;	/* last attach time */
-#ifndef __LP64__
-	unsigned int		__pad2;
-#endif
-	__kernel_time_t		shm_dtime;	/* last detach time */
-#ifndef __LP64__
-	unsigned int		__pad3;
-#endif
-	__kernel_time_t		shm_ctime;	/* last change time */
-	__kernel_pid_t		shm_cpid;	/* pid of creator */
-	__kernel_pid_t		shm_lpid;	/* pid of last operator */
-	unsigned int		shm_nattch;	/* no. of current attaches */
-	unsigned int		__unused1;
-	unsigned int		__unused2;
-};
-
-static void convert_broken_perm (struct broken_ipc_perm *out, struct ipc64_perm *in)
-{
-	out->key  = in->key;
-	out->uid  = in->uid;
-	out->gid  = in->gid;
-	out->cuid = in->cuid;
-	out->cgid = in->cgid;
-	out->mode = in->mode;
-	out->seq  = in->seq;
-}
-
-static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_ds *sbuf)
-{
-	struct broken_shmid64_ds tbuf;
-	
-	memset(&tbuf, 0, sizeof tbuf);
-	convert_broken_perm (&tbuf.shm_perm, &sbuf->shm_perm);
-	tbuf.shm_segsz = sbuf->shm_segsz;
-	tbuf.shm_atime = sbuf->shm_atime;
-	tbuf.shm_dtime = sbuf->shm_dtime;
-	tbuf.shm_ctime = sbuf->shm_ctime;
-	tbuf.shm_cpid = sbuf->shm_cpid;
-	tbuf.shm_lpid = sbuf->shm_lpid;
-	tbuf.shm_nattch = sbuf->shm_nattch;
-	return copy_to_user(buf, &tbuf, sizeof tbuf) ? -EFAULT : 0;
-}
-
-int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf)
-{
-	return sys_msgctl (msqid, cmd & ~IPC_64, buf);
-}
-
-int sys_semctl_broken(int semid, int semnum, int cmd, union semun arg)
-{
-	return sys_semctl (semid, semnum, cmd & ~IPC_64, arg);
-}
-
-int sys_shmctl_broken(int shmid, int cmd, struct shmid64_ds *buf)
-{
-	struct shmid64_ds sbuf;
-	int err;
-
-	if (cmd & IPC_64) {
-		cmd &= ~IPC_64;
-		if (cmd == IPC_STAT || cmd == SHM_STAT) {
-			KERNEL_SYSCALL(err, sys_shmctl, shmid, cmd, (struct shmid_ds *)&sbuf);
-			if (err == 0)
-				err = copyout_broken_shmid64((struct broken_shmid64_ds *)buf, &sbuf);
-			return err;
-		}
-	}
-	return sys_shmctl (shmid, cmd, (struct shmid_ds *)buf);
-}
-
-/*
  * This changes the io permissions bitmap in the current task.
  */
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/sys_parisc32.c 001-linus.patch/arch/parisc/kernel/sys_parisc32.c
--- 000-virgin/arch/parisc/kernel/sys_parisc32.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/parisc/kernel/sys_parisc32.c	Tue Dec 30 16:38:56 2003
@@ -1352,12 +1352,10 @@ asmlinkage int sys32_lseek(unsigned int 
 	return sys_lseek(fd, offset, origin);
 }
 
-asmlinkage long sys32_semctl_broken(int semid, int semnum, int cmd, union semun arg)
+asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
 {
         union semun u;
 	
-	cmd &= ~IPC_64; /* should be removed together with the _broken suffix */
-
         if (cmd == SETVAL) {
                 /* Ugh.  arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
                  * The int should be in the first 4, but our argument
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/syscall_table.S 001-linus.patch/arch/parisc/kernel/syscall_table.S
--- 000-virgin/arch/parisc/kernel/syscall_table.S	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/arch/parisc/kernel/syscall_table.S	Tue Dec 30 16:38:56 2003
@@ -28,7 +28,7 @@
 #define ENTRY_COMP(_name_) .word sys_##_name_
 #endif
 
-	ENTRY_SAME(ni_syscall)	/* 0  -  old "setup()" system call*/
+	ENTRY_SAME(restart_syscall)	/* 0 */
 	ENTRY_SAME(exit)
 	ENTRY_SAME(fork_wrapper)
 	ENTRY_SAME(read)
@@ -260,15 +260,15 @@
 	ENTRY_COMP(recvmsg)
 	ENTRY_SAME(semop)		/* 185 */
 	ENTRY_SAME(semget)
-	ENTRY_DIFF(semctl_broken)
+	ENTRY_DIFF(semctl)
 	ENTRY_DIFF(msgsnd)
 	ENTRY_DIFF(msgrcv)
 	ENTRY_SAME(msgget)		/* 190 */
-	ENTRY_SAME(msgctl_broken)
+	ENTRY_SAME(msgctl)
 	ENTRY_SAME(shmat_wrapper)
 	ENTRY_SAME(shmdt)
 	ENTRY_SAME(shmget)
-	ENTRY_SAME(shmctl_broken)	/* 195 */
+	ENTRY_SAME(shmctl)		/* 195 */
 	ENTRY_SAME(ni_syscall)		/* streams1 */
 	ENTRY_SAME(ni_syscall)		/* streams2 */
 	ENTRY_SAME(lstat64)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/time.c 001-linus.patch/arch/parisc/kernel/time.c
--- 000-virgin/arch/parisc/kernel/time.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/arch/parisc/kernel/time.c	Tue Dec 30 16:38:56 2003
@@ -232,7 +232,6 @@ do_settimeofday (struct timespec *tv)
 	write_sequnlock_irq(&xtime_lock);
 	return 0;
 }
-
 EXPORT_SYMBOL(do_settimeofday);
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/traps.c 001-linus.patch/arch/parisc/kernel/traps.c
--- 000-virgin/arch/parisc/kernel/traps.c	Wed Dec 17 19:00:01 2003
+++ 001-linus.patch/arch/parisc/kernel/traps.c	Tue Dec 30 16:38:56 2003
@@ -430,9 +430,19 @@ void parisc_terminate(char *msg, struct 
 	if (!console_drivers)
 		pdc_console_restart();
 
-	if (code == 1)
-	    transfer_pim_to_trap_frame(regs);
+	/* Not all paths will gutter the processor... */
+	switch(code){
+
+	case 1:
+		transfer_pim_to_trap_frame(regs);
+		break;
+
+	default:
+		/* Fall through */
+		break;
 
+	}
+	    
 	show_stack(NULL, (unsigned long *)regs->gr[30]);
 
 	printk("\n");
@@ -447,6 +457,7 @@ void parisc_terminate(char *msg, struct 
 	 * system will shut down immediately right here. */
 	pdc_soft_power_button(0);
 	
+	/* Gutter the processor! */
 	for(;;)
 	    ;
 }
@@ -557,20 +568,45 @@ void handle_interruption(int code, struc
 		si.si_addr = (void *) regs->iaoq[0];
 		force_sig_info(SIGFPE, &si, current);
 		return;
-
+		
+	case 13:
+		/* Conditional Trap
+		   The condition succees in an instruction which traps 
+		   on condition  */
+		if(user_mode(regs)){
+			si.si_signo = SIGFPE;
+			/* Set to zero, and let the userspace app figure it out from
+		   	   the insn pointed to by si_addr */
+			si.si_code = 0;
+			si.si_addr = (void *) regs->iaoq[0];
+			force_sig_info(SIGFPE, &si, current);
+			return;
+		} else 
+			/* The kernel doesn't want to handle condition codes */
+			break;
+		
 	case 14:
 		/* Assist Exception Trap, i.e. floating point exception. */
 		die_if_kernel("Floating point exception", regs, 0); /* quiet */
 		handle_fpe(regs);
 		return;
-
+		
+	case 15:
+		/* Data TLB miss fault/Data page fault */
+		/* Fall through */
+	case 16:
+		/* Non-access instruction TLB miss fault */
+		/* The instruction TLB entry needed for the target address of the FIC
+		   is absent, and hardware can't find it, so we get to cleanup */
+		/* Fall through */
 	case 17:
 		/* Non-access data TLB miss fault/Non-access data page fault */
 		/* TODO: Still need to add slow path emulation code here */
-		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
-		
+		/* TODO: Understand what is meant by the TODO listed
+		         above this one. (Carlos) */
 		fault_address = regs->ior;
-		parisc_terminate("Non access data tlb fault!",regs,code,fault_address);
+		fault_space = regs->isr;
+		break;
 
 	case 18:
 		/* PCXS only -- later cpu's split this into types 26,27 & 28 */
@@ -580,9 +616,8 @@ void handle_interruption(int code, struc
 			return;
 		}
 		/* Fall Through */
-
-	case 15: /* Data TLB miss fault/Data page fault */
-	case 26: /* PCXL: Data memory access rights trap */
+	case 26: 
+		/* PCXL: Data memory access rights trap */
 		fault_address = regs->ior;
 		fault_space   = regs->isr;
 		break;
@@ -638,7 +673,6 @@ void handle_interruption(int code, struc
 			up_read(&current->mm->mmap_sem);
 		}
 		/* Fall Through */
-
 	case 27: 
 		/* Data memory protection ID trap */
 		die_if_kernel("Protection id trap", regs, code);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/kernel/unaligned.c 001-linus.patch/arch/parisc/kernel/unaligned.c
--- 000-virgin/arch/parisc/kernel/unaligned.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/parisc/kernel/unaligned.c	Tue Dec 30 16:38:57 2003
@@ -21,27 +21,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/module.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/atomic.h>
-
-#include <asm/smp.h>
-#include <asm/pdc.h>
 
 /* #define DEBUG_UNALIGNED 1 */
 
@@ -93,13 +74,17 @@
 #define OPCODE_STDA	OPCODE1(0x03,1,0xf)
 
 #define OPCODE_FLDWX	OPCODE1(0x09,0,0x0)
-#define OPCODE_FSTWX	OPCODE1(0x09,0,0x4)
+#define OPCODE_FLDWXR	OPCODE1(0x09,0,0x1)
+#define OPCODE_FSTWX	OPCODE1(0x09,0,0x8)
+#define OPCODE_FSTWXR	OPCODE1(0x09,0,0x9)
 #define OPCODE_FLDWS	OPCODE1(0x09,1,0x0)
-#define OPCODE_FSTWS	OPCODE1(0x09,1,0x4)
+#define OPCODE_FLDWSR	OPCODE1(0x09,1,0x1)
+#define OPCODE_FSTWS	OPCODE1(0x09,1,0x8)
+#define OPCODE_FSTWSR	OPCODE1(0x09,1,0x9)
 #define OPCODE_FLDDX	OPCODE1(0x0b,0,0x0)
-#define OPCODE_FSTDX	OPCODE1(0x0b,0,0x4)
+#define OPCODE_FSTDX	OPCODE1(0x0b,0,0x8)
 #define OPCODE_FLDDS	OPCODE1(0x0b,1,0x0)
-#define OPCODE_FSTDS	OPCODE1(0x0b,1,0x4)
+#define OPCODE_FSTDS	OPCODE1(0x0b,1,0x8)
 
 #define OPCODE_LDD_L	OPCODE2(0x14,0)
 #define OPCODE_FLDD_L	OPCODE2(0x14,1)
@@ -128,6 +113,9 @@
 #define IM5_3(i) IM((i),5)
 #define IM14(i) IM((i),14)
 
+#define ERR_NOTHANDLED	-1
+#define ERR_PAGEFAULT	-2
+
 int unaligned_enabled = 1;
 
 void die_if_kernel (char *str, struct pt_regs *regs, long err);
@@ -136,16 +124,28 @@ static int emulate_ldh(struct pt_regs *r
 {
 	unsigned long saddr = regs->ior;
 	unsigned long val = 0;
+	int ret;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n", 
 		regs->isr, regs->ior, toreg);
 
 	__asm__ __volatile__  (
-"	mtsp	%3, %%sr1\n"
-"	ldbs	0(%%sr1,%2), %%r20\n"
-"	ldbs	1(%%sr1,%2), %0\n"
-	"depw	%%r20, 23, 24, %0\n"
-	: "=r" (val)
+"	mtsp	%4, %%sr1\n"
+"1:	ldbs	0(%%sr1,%3), %%r20\n"
+"2:	ldbs	1(%%sr1,%3), %0\n"
+"	depw	%%r20, 23, 24, %0\n"
+"	cmpclr,= %%r0, %%r0, %1\n"
+"3:	ldo	-2(%%r0), %1\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(3b-1b)\n"
+"	.dword  2b,(3b-2b)\n"
+#else
+"	.word	1b,(3b-1b)\n"
+"	.word	2b,(3b-2b)\n"
+#endif
+"	.previous\n"
+	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r20" );
 
@@ -154,26 +154,39 @@ static int emulate_ldh(struct pt_regs *r
 	if (toreg)
 		regs->gr[toreg] = val;
 
-	return 0;
+	return ret;
 }
+
 static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
 	unsigned long val = 0;
+	int ret;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n", 
 		regs->isr, regs->ior, toreg);
 
 	__asm__ __volatile__  (
-"	zdep	%2,28,2,%%r19\n"		/* r19=(ofs&3)*8 */
-"	mtsp	%3, %%sr1\n"
-"	depw	%%r0,31,2,%2\n"
-"	ldw	0(%%sr1,%2),%0\n"
-"	ldw	4(%%sr1,%2),%%r20\n"
+"	zdep	%3,28,2,%%r19\n"		/* r19=(ofs&3)*8 */
+"	mtsp	%4, %%sr1\n"
+"	depw	%%r0,31,2,%3\n"
+"1:	ldw	0(%%sr1,%3),%0\n"
+"2:	ldw	4(%%sr1,%3),%%r20\n"
 "	subi	32,%%r19,%%r19\n"
 "	mtctl	%%r19,11\n"
 "	vshd	%0,%%r20,%0\n"
-	: "=r" (val)
+"	cmpclr,= %%r0, %%r0, %1\n"
+"3:	ldo	-2(%%r0), %1\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(3b-1b)\n"
+"	.dword  2b,(3b-2b)\n"
+#else
+"	.word	1b,(3b-1b)\n"
+"	.word	2b,(3b-2b)\n"
+#endif
+"	.previous\n"
+	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
 
@@ -184,12 +197,13 @@ static int emulate_ldw(struct pt_regs *r
 	else if (toreg)
 		regs->gr[toreg] = val;
 
-	return 0;
+	return ret;
 }
 static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
 	__u64 val = 0;
+	int ret;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", 
 		regs->isr, regs->ior, toreg);
@@ -200,51 +214,77 @@ static int emulate_ldd(struct pt_regs *r
 		return -1;
 #endif
 	__asm__ __volatile__  (
-"	depd,z	%2,60,3,%%r19\n"		/* r19=(ofs&7)*8 */
-"	mtsp	%3, %%sr1\n"
-"	depd	%%r0,63,3,%2\n"
-"	ldd	0(%%sr1,%2),%0\n"
-"	ldd	8(%%sr1,%2),%%r20\n"
+"	depd,z	%3,60,3,%%r19\n"		/* r19=(ofs&7)*8 */
+"	mtsp	%4, %%sr1\n"
+"	depd	%%r0,63,3,%3\n"
+"1:	ldd	0(%%sr1,%3),%0\n"
+"2:	ldd	8(%%sr1,%3),%%r20\n"
 "	subi	64,%%r19,%%r19\n"
 "	mtsar	%%r19\n"
 "	shrpd	%0,%%r20,%%sar,%0\n"
-	: "=r" (val)
+"	cmpclr,= %%r0, %%r0, %1\n"
+"3:	ldo	-2(%%r0), %1\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(3b-1b)\n"
+"	.dword  2b,(3b-2b)\n"
+#else
+"	.word	1b,(3b-1b)\n"
+"	.word	2b,(3b-2b)\n"
+#endif
+"	.previous\n"
+	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
 #else
     {
 	unsigned long valh=0,vall=0;
 	__asm__ __volatile__  (
-"	zdep	%4,29,2,%%r19\n"		/* r19=(ofs&3)*8 */
-"	mtsp	%5, %%sr1\n"
-"	dep	%%r0,31,2,%4\n"
-"	ldw	0(%%sr1,%5),%0\n"
-"	ldw	4(%%sr1,%5),%1\n"
-"	ldw	8(%%sr1,%5),%%r20\n"
+"	zdep	%5,29,2,%%r19\n"		/* r19=(ofs&3)*8 */
+"	mtsp	%6, %%sr1\n"
+"	dep	%%r0,31,2,%5\n"
+"1:	ldw	0(%%sr1,%5),%0\n"
+"2:	ldw	4(%%sr1,%5),%1\n"
+"3:	ldw	8(%%sr1,%5),%%r20\n"
 "	subi	32,%%r19,%%r19\n"
 "	mtsar	%%r19\n"
 "	vshd	%0,%1,%0\n"
 "	vshd	%1,%%r20,%1\n"
-	: "=r" (valh), "=r" (vall)
+"	cmpclr,= %%r0, %%r0, %2\n"
+"4:	ldo	-2(%%r0), %2\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(4b-1b)\n"
+"	.dword  2b,(4b-2b)\n"
+"	.dword	3b,(4b-3b)\n"
+#else
+"	.word	1b,(4b-1b)\n"
+"	.word	2b,(4b-2b)\n"
+"	.word	3b,(4b-3b)\n"
+#endif
+"	.previous\n"
+	: "=r" (valh), "=r" (vall), "=r" (ret)
 	: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
 	val=((__u64)valh<<32)|(__u64)vall;
     }
 #endif
 
-	DPRINTF("val = 0x" RFMT "\n", val);
+	DPRINTF("val = 0xllx\n", val);
 
 	if (flop)
 		regs->fr[toreg] = val;
 	else if (toreg)
 		regs->gr[toreg] = val;
 
-	return 0;
+	return ret;
 }
 
 static int emulate_sth(struct pt_regs *regs, int frreg)
 {
 	unsigned long val = regs->gr[frreg];
+	int ret;
+
 	if (!frreg)
 		val = 0;
 
@@ -252,19 +292,32 @@ static int emulate_sth(struct pt_regs *r
 		val, regs->isr, regs->ior);
 
 	__asm__ __volatile__ (
-"	mtsp %2, %%sr1\n"
-"	extrw,u %0, 23, 8, %%r19\n"
-"	stb %0, 1(%%sr1, %1)\n"
-"	stb %%r19, 0(%%sr1, %1)\n"
-	:
+"	mtsp %3, %%sr1\n"
+"	extrw,u %1, 23, 8, %%r19\n"
+"1:	stb %1, 1(%%sr1, %2)\n"
+"2:	stb %%r19, 0(%%sr1, %2)\n"
+"	cmpclr,= %%r0, %%r0, %0\n"
+"3:	ldo	-2(%%r0), %0\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(3b-1b)\n"
+"	.dword  2b,(3b-2b)\n"
+#else
+"	.word	1b,(3b-1b)\n"
+"	.word	2b,(3b-2b)\n"
+#endif
+"	.previous\n"
+	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19" );
 
-	return 0;
+	return ret;
 }
+
 static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 {
 	unsigned long val;
+	int ret;
 
 	if (flop)
 		val = ((__u32*)(regs->fr))[frreg];
@@ -278,22 +331,33 @@ static int emulate_stw(struct pt_regs *r
 
 
 	__asm__ __volatile__ (
-"	mtsp %2, %%sr1\n"
-"	zdep	%1, 28, 2, %%r19\n"
-"	dep	%%r0, 31, 2, %1\n"
+"	mtsp %3, %%sr1\n"
+"	zdep	%2, 28, 2, %%r19\n"
+"	dep	%%r0, 31, 2, %2\n"
 "	mtsar	%%r19\n"
 "	depwi,z	-2, %%sar, 32, %%r19\n"
-"	ldw	0(%%sr1,%1),%%r20\n"
-"	ldw	4(%%sr1,%1),%%r21\n"
-"	vshd	%%r0, %0, %%r22\n"
-"	vshd	%0, %%r0, %%r1\n"
+"1:	ldw	0(%%sr1,%2),%%r20\n"
+"2:	ldw	4(%%sr1,%2),%%r21\n"
+"	vshd	%%r0, %1, %%r22\n"
+"	vshd	%1, %%r0, %%r1\n"
 "	and	%%r20, %%r19, %%r20\n"
 "	andcm	%%r21, %%r19, %%r21\n"
 "	or	%%r22, %%r20, %%r20\n"
 "	or	%%r1, %%r21, %%r21\n"
-"	stw	%%r20,0(%%sr1,%1)\n"
-"	stw	%%r21,4(%%sr1,%1)\n"
-	:
+"	stw	%%r20,0(%%sr1,%2)\n"
+"	stw	%%r21,4(%%sr1,%2)\n"
+"	cmpclr,= %%r0, %%r0, %0\n"
+"3:	ldo	-2(%%r0), %0\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(3b-1b)\n"
+"	.dword  2b,(3b-2b)\n"
+#else
+"	.word	1b,(3b-1b)\n"
+"	.word	2b,(3b-2b)\n"
+#endif
+"	.previous\n"
+	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1" );
 
@@ -302,6 +366,7 @@ static int emulate_stw(struct pt_regs *r
 static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 {
 	__u64 val;
+	int ret;
 
 	if (flop)
 		val = regs->fr[frreg];
@@ -310,7 +375,7 @@ static int emulate_std(struct pt_regs *r
 	else
 		val = 0;
 
-	DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
+	DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
 		val,  regs->isr, regs->ior);
 
 #ifdef CONFIG_PA20
@@ -319,52 +384,84 @@ static int emulate_std(struct pt_regs *r
 		return -1;
 #endif
 	__asm__ __volatile__ (
-"	mtsp %2, %%sr1\n"
-"	depd,z	%1, 60, 3, %%r19\n"
-"	depd	%%r0, 63, 3, %1\n"
+"	mtsp %3, %%sr1\n"
+"	depd,z	%2, 60, 3, %%r19\n"
+"	depd	%%r0, 63, 3, %2\n"
 "	mtsar	%%r19\n"
 "	depdi,z	-2, %%sar, 64, %%r19\n"
-"	ldd	0(%%sr1,%1),%%r20\n"
-"	ldd	8(%%sr1,%1),%%r21\n"
-"	shrpd	%%r0, %0, %%sar, %%r22\n"
-"	shrpd	%0, %%r0, %%sar, %%r1\n"
+"1:	ldd	0(%%sr1,%2),%%r20\n"
+"2:	ldd	8(%%sr1,%2),%%r21\n"
+"	shrpd	%%r0, %1, %%sar, %%r22\n"
+"	shrpd	%1, %%r0, %%sar, %%r1\n"
 "	and	%%r20, %%r19, %%r20\n"
 "	andcm	%%r21, %%r19, %%r21\n"
 "	or	%%r22, %%r20, %%r20\n"
 "	or	%%r1, %%r21, %%r21\n"
-"	std	%%r20,0(%%sr1,%1)\n"
-"	std	%%r21,8(%%sr1,%1)\n"
-	:
+"3:	std	%%r20,0(%%sr1,%2)\n"
+"4:	std	%%r21,8(%%sr1,%2)\n"
+"	cmpclr,= %%r0, %%r0, %0\n"
+"5:	ldo	-2(%%r0), %0\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(5b-1b)\n"
+"	.dword  2b,(5b-2b)\n"
+"	.dword	3b,(5b-3b)\n"
+"	.dword  4b,(5b-4b)\n"
+#else
+"	.word	1b,(5b-1b)\n"
+"	.word	2b,(5b-2b)\n"
+"	.word	3b,(5b-3b)\n"
+"	.word	4b,(5b-4b)\n"
+#endif
+"	.previous\n"
+	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1" );
 #else
     {
 	unsigned long valh=(val>>32),vall=(val&0xffffffffl);
 	__asm__ __volatile__ (
-"	mtsp	%3, %%sr1\n"
-"	zdep	%1, 29, 2, %%r19\n"
-"	dep	%%r0, 31, 2, %1\n"
+"	mtsp	%4, %%sr1\n"
+"	zdep	%2, 29, 2, %%r19\n"
+"	dep	%%r0, 31, 2, %2\n"
 "	mtsar	%%r19\n"
 "	zvdepi	-2, 32, %%r19\n"
-"	ldw	0(%%sr1,%2),%%r20\n"
-"	ldw	8(%%sr1,%2),%%r21\n"
-"	vshd	%0, %1, %%r1\n"
-"	vshd	%%r0, %0, %0\n"
-"	vshd	%1, %%r0, %1\n"
+"1:	ldw	0(%%sr1,%3),%%r20\n"
+"2:	ldw	8(%%sr1,%3),%%r21\n"
+"	vshd	%1, %2, %%r1\n"
+"	vshd	%%r0, %1, %1\n"
+"	vshd	%2, %%r0, %2\n"
 "	and	%%r20, %%r19, %%r20\n"
 "	andcm	%%r21, %%r19, %%r21\n"
-"	or	%0, %%r20, %0\n"
-"	or	%1, %%r21, %1\n"
-"	stw	%0,0(%%sr1,%2)\n"
-"	stw	%%r1,4(%%sr1,%2)\n"
-"	stw	%1,8(%%sr1,%2)\n"
-	:
+"	or	%1, %%r20, %1\n"
+"	or	%2, %%r21, %2\n"
+"3:	stw	%1,0(%%sr1,%1)\n"
+"4:	stw	%%r1,4(%%sr1,%3)\n"
+"5:	stw	%2,8(%%sr1,%3)\n"
+"	cmpclr,= %%r0, %%r0, %0\n"
+"6:	ldo	-2(%%r0), %0\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+"	.dword	1b,(6b-1b)\n"
+"	.dword  2b,(6b-2b)\n"
+"	.dword	3b,(6b-3b)\n"
+"	.dword  4b,(6b-4b)\n"
+"	.dword  5b,(6b-5b)\n"
+#else
+"	.word	1b,(6b-1b)\n"
+"	.word	2b,(6b-2b)\n"
+"	.word	3b,(6b-3b)\n"
+"	.word	4b,(6b-4b)\n"
+"	.word  	5b,(6b-5b)\n"
+#endif
+"	.previous\n"
+	: "=r" (ret)
 	: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r1" );
     }
 #endif
 
-	return 0;
+	return ret;
 }
 
 void handle_unaligned(struct pt_regs *regs)
@@ -373,41 +470,10 @@ void handle_unaligned(struct pt_regs *re
 	static unsigned long last_time = 0;
 	unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
 	int modify = 0;
-	int ret = -1;
+	int ret = ERR_NOTHANDLED;
 	struct siginfo si;
 	register int flop=0;	/* true if this is a flop */
 
-	/* if the unaligned access is inside the kernel:
-	 *   if the access is caused by a syscall, then we fault the calling
-	 *     user process
-	 */
-	if (!user_mode(regs))
-	{
-		const struct exception_table_entry *fix;
-
-		/* see if the offending code have its own
-		 * exception handler 
-		 */ 
-
-		fix = search_exception_tables(regs->iaoq[0]);
-		if (fix)
-		{
-			/* lower bits of fix->skip are flags
-			 * upper bits are the handler addr
-			 */
-			if (fix->skip & 1)
-				regs->gr[8] = -EFAULT;
-			if (fix->skip & 2)
-				regs->gr[9] = 0;
-
-			regs->iaoq[0] += ((fix->skip) & ~3);
-			regs->iaoq[1] = regs->iaoq[0] + 4;
-			regs->gr[0] &= ~PSW_B;
-
-			return;
-		}
-	}
-
 	/* log a message with pacing */
 	if (user_mode(regs))
 	{
@@ -541,6 +607,8 @@ void handle_unaligned(struct pt_regs *re
 
 	case OPCODE_FLDWX:
 	case OPCODE_FLDWS:
+	case OPCODE_FLDWXR:
+	case OPCODE_FLDWSR:
 		flop=1;
 		ret = emulate_ldw(regs,FR3(regs->iir),1);
 		break;
@@ -553,6 +621,8 @@ void handle_unaligned(struct pt_regs *re
 
 	case OPCODE_FSTWX:
 	case OPCODE_FSTWS:
+	case OPCODE_FSTWXR:
+	case OPCODE_FSTWSR:
 		flop=1;
 		ret = emulate_stw(regs,FR3(regs->iir),1);
 		break;
@@ -567,7 +637,7 @@ void handle_unaligned(struct pt_regs *re
 	case OPCODE_LDCW_I:
 	case OPCODE_LDCD_S:
 	case OPCODE_LDCW_S:
-		ret = -1;	/* "undefined", but lets kill them. */
+		ret = ERR_NOTHANDLED;	/* "undefined", but lets kill them. */
 		break;
 	}
 #ifdef CONFIG_PA20
@@ -632,7 +702,7 @@ void handle_unaligned(struct pt_regs *re
 		regs->gr[R1(regs->iir)] = newbase;
 
 
-	if (ret < 0)
+	if (ret == ERR_NOTHANDLED)
 		printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir);
 
 	DPRINTF("ret = %d\n", ret);
@@ -641,13 +711,25 @@ void handle_unaligned(struct pt_regs *re
 	{
 		printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
 		die_if_kernel("Unaligned data reference", regs, 28);
+
+		if (ret == ERR_PAGEFAULT)
+		{
+			si.si_signo = SIGSEGV;
+			si.si_errno = 0;
+			si.si_code = SEGV_MAPERR;
+			si.si_addr = (void *)regs->ior;
+			force_sig_info(SIGSEGV, &si, current);
+		}
+		else
+		{
 force_sigbus:
-		/* couldn't handle it ... */
-		si.si_signo = SIGBUS;
-		si.si_errno = 0;
-		si.si_code = BUS_ADRALN;
-		si.si_addr = (void *)regs->ior;
-		force_sig_info(SIGBUS, &si, current);
+			/* couldn't handle it ... */
+			si.si_signo = SIGBUS;
+			si.si_errno = 0;
+			si.si_code = BUS_ADRALN;
+			si.si_addr = (void *)regs->ior;
+			force_sig_info(SIGBUS, &si, current);
+		}
 		
 		return;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/parisc/lib/lusercopy.S 001-linus.patch/arch/parisc/lib/lusercopy.S
--- 000-virgin/arch/parisc/lib/lusercopy.S	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/parisc/lib/lusercopy.S	Tue Dec 30 16:38:57 2003
@@ -133,6 +133,43 @@ $lcfu_zero_loop:
 	.procend
 
 	/*
+	 * unsigned long
+	 * lcopy_in_user(void *to, const void *from, unsigned long n)
+	 *
+	 * Returns 0 for success.
+	 * otherwise, returns number of bytes not transferred.
+	 */
+
+	.export lcopy_in_user,code
+lcopy_in_user:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+	comib,=,n   0,%r24,$lciu_done
+	get_sr
+$lciu_loop:
+	ldbs,ma     1(%sr1,%r25),%r1
+	addib,<>    -1,%r24,$lciu_loop
+1:      stbs,ma     %r1,1(%sr1,%r26)
+$lciu_done:
+	bv          %r0(%r2)
+	copy        %r24,%r28
+	.exit
+
+2:      b $lciu_done
+	ldo         1(%r24),%r24
+
+	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(2b-1b)
+#else
+	.word       1b,(2b-1b)
+#endif
+	.previous
+
+	.procend
+
+	/*
 	 * long lstrncpy_from_user(char *dst, const char *src, long n)
 	 *
 	 * Returns -EFAULT if exception before terminator,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ppc/kernel/irq.c 001-linus.patch/arch/ppc/kernel/irq.c
--- 000-virgin/arch/ppc/kernel/irq.c	Wed Dec 17 18:59:20 2003
+++ 001-linus.patch/arch/ppc/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -346,17 +346,19 @@ void enable_irq(unsigned int irq)
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_puts(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ", j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ", j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
@@ -381,22 +383,23 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
+	} else if (i == NR_IRQS) {
 #ifdef CONFIG_TAU_INT
-	if (tau_initialized){
-		seq_puts(p, "TAU: ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", tau_interrupts(j));
-		seq_puts(p, "  PowerPC             Thermal Assist (cpu temp)\n");
-	}
+		if (tau_initialized){
+			seq_puts(p, "TAU: ");
+			for (j = 0; j < NR_CPUS; j++)
+				if (cpu_online(j))
+					seq_printf(p, "%10u ", tau_interrupts(j));
+			seq_puts(p, "  PowerPC             Thermal Assist (cpu temp)\n");
+		}
 #endif
 #ifdef CONFIG_SMP
-	/* should this be per processor send/receive? */
-	seq_printf(p, "IPI (recv/sent): %10u/%u\n",
-		   atomic_read(&ipi_recv), atomic_read(&ipi_sent));
+		/* should this be per processor send/receive? */
+		seq_printf(p, "IPI (recv/sent): %10u/%u\n",
+				atomic_read(&ipi_recv), atomic_read(&ipi_sent));
 #endif
-	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+		seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+	}
 	return 0;
 }
 
@@ -569,67 +572,16 @@ static struct proc_dir_entry *smp_affini
 
 cpumask_t irq_affinity [NR_IRQS];
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	cpumask_t tmp = irq_affinity[(long)data];
-	int k, len = 0;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
-static unsigned int parse_hex_value (const char __user *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum [HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	int i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first 8 characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-	for (i = 0; i < count; i++) {
-		unsigned int c = hexnum[i];
-		int k;
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 4);
-		for (k = 0; k < 4; ++k)
-			if (c & (1 << k))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
 					unsigned long count, void *data)
 {
@@ -639,7 +591,7 @@ static int irq_affinity_write_proc (stru
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
@@ -664,19 +616,10 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	cpumask_t mask = *(cpumask_t *)data;
-	int k, len = 0;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(mask));
-		len += j;
-		page += j;
-		cpus_shift_right(mask, mask, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -686,7 +629,7 @@ static int prof_cpu_mask_write_proc (str
 	cpumask_t *mask = (cpumask_t *)data, full_count = count, err;
 	cpumask_t new_value;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ppc64/kernel/irq.c 001-linus.patch/arch/ppc64/kernel/irq.c
--- 000-virgin/arch/ppc64/kernel/irq.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/ppc64/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -323,18 +323,20 @@ EXPORT_SYMBOL(enable_irq);
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_printf(p, "           ");
-	for (j=0; j<NR_CPUS; j++) {
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ",j);
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++) {
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		}
+		seq_putc(p, '\n');
 	}
-	seq_putc(p, '\n');
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
@@ -359,8 +361,8 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+	} else if (i == NR_IRQS)
+		seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
 }
 
@@ -652,67 +654,16 @@ cpumask_t irq_affinity [NR_IRQS] = { [0 
 cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_NONE };
 #endif /* CONFIG_IRQ_ALL_CPUS */
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int k, len;
-	cpumask_t tmp = irq_affinity[(long)data];
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-
-	for (k = 0; k < sizeof(cpumask_t) / sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
-static unsigned int parse_hex_value (const char *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum[HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	int i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first HEX_DIGITS characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-
-	for (i = 0; i < count; i++) {
-		unsigned int c = hexnum[i];
-		int k;
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 4);
-		for (k = 0; k < 4; ++k)
-			if (test_bit(k, (unsigned long *)&c))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 static int irq_affinity_write_proc (struct file *file, const char *buffer,
 					unsigned long count, void *data)
 {
@@ -722,7 +673,7 @@ static int irq_affinity_write_proc (stru
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
@@ -744,10 +695,11 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	unsigned long *mask = (unsigned long *) data;
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%08lx\n", *mask);
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
@@ -757,7 +709,7 @@ static int prof_cpu_mask_write_proc (str
 	unsigned long full_count = count, err;
 	cpumask_t new_value;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/ppc64/mm/hugetlbpage.c 001-linus.patch/arch/ppc64/mm/hugetlbpage.c
--- 000-virgin/arch/ppc64/mm/hugetlbpage.c	Wed Dec 17 18:58:50 2003
+++ 001-linus.patch/arch/ppc64/mm/hugetlbpage.c	Tue Dec 30 16:38:57 2003
@@ -921,7 +921,7 @@ int is_hugepage_mem_enough(size_t size)
  * this far.
  */
 static struct page *hugetlb_nopage(struct vm_area_struct *vma,
-				unsigned long address, int unused)
+				unsigned long address, int *unused)
 {
 	BUG();
 	return NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/s390/kernel/compat_wrapper.S 001-linus.patch/arch/s390/kernel/compat_wrapper.S
--- 000-virgin/arch/s390/kernel/compat_wrapper.S	Wed Dec 17 19:00:00 2003
+++ 001-linus.patch/arch/s390/kernel/compat_wrapper.S	Tue Dec 30 16:38:57 2003
@@ -5,6 +5,7 @@
 *  S390 version
 *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
+*               Thomas Spatzier (tspat@de.ibm.com)
 */ 
 
 	.globl  sys32_exit_wrapper 
@@ -1230,3 +1231,37 @@ sys_epoll_wait_wrapper:
 	lgfr	%r4,%r4			# int
 	lgfr	%r5,%r5			# int
 	jg	sys_epoll_wait		# branch to system call
+
+	.globl	sys32_io_setup_wrapper
+sys32_io_setup_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# u32 *
+	jg	compat_sys_io_setup
+
+	.globl	sys32_io_destroy_wrapper
+sys32_io_destroy_wrapper:
+	llgfr	%r2,%r2			# (aio_context_t) u32
+	jg	sys_io_destroy
+
+	.globl	sys32_io_getevents_wrapper
+sys32_io_getevents_wrapper:
+	llgfr	%r2,%r2			# (aio_context_t) u32
+	lgfr	%r3,%r3			# long
+	lgfr	%r4,%r4			# long
+	llgtr	%r5,%r5			# struct io_event *
+	llgtr	%r6,%r6			# struct compat_timespec *
+	jg	compat_sys_io_getevents
+
+	.globl	sys32_io_submit_wrapper
+sys32_io_submit_wrapper:
+	llgfr	%r2,%r2			# (aio_context_t) u32
+	lgfr	%r3,%r3			# long
+	llgtr	%r4,%r4			# struct iocb **
+	jg	compat_sys_io_submit
+
+	.globl	sys32_io_cancel_wrapper
+sys32_io_cancel_wrapper:
+	llgfr	%r2,%r2			# (aio_context_t) u32
+	llgtr	%r3,%r3			# struct iocb *
+	llgtr	%r4,%r4			# struct io_event *
+	jg	sys_io_cancel
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/s390/kernel/setup.c 001-linus.patch/arch/s390/kernel/setup.c
--- 000-virgin/arch/s390/kernel/setup.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/s390/kernel/setup.c	Tue Dec 30 16:38:57 2003
@@ -617,17 +617,17 @@ static const char *intrclass_names[] = {
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-        int i, j;
+        int i = *(loff_t *) v, j;
 	
-        seq_puts(p, "           ");
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 	
-        for (j=0; j<NR_CPUS; j++)
-                if (cpu_online(j))
-                        seq_printf(p, "CPU%d       ",j);
-	
-        seq_putc(p, '\n');
-	
-        for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		seq_printf(p, "%s: ", intrclass_names[i]);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/s390/kernel/syscalls.S 001-linus.patch/arch/s390/kernel/syscalls.S
--- 000-virgin/arch/s390/kernel/syscalls.S	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/arch/s390/kernel/syscalls.S	Tue Dec 30 16:38:57 2003
@@ -251,11 +251,11 @@ SYSCALL(sys_sched_setaffinity,sys_sched_
 SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,sys32_sched_getaffinity_wrapper)	/* 240 */
 SYSCALL(sys_tgkill,sys_tgkill,sys_tgkill)
 NI_SYSCALL							/* reserved for TUX */
-SYSCALL(sys_io_setup,sys_io_setup,sys_ni_syscall)
-SYSCALL(sys_io_destroy,sys_io_destroy,sys_ni_syscall)
-SYSCALL(sys_io_getevents,sys_io_getevents,sys_ni_syscall)	/* 245 */
-SYSCALL(sys_io_submit,sys_io_submit,sys_ni_syscall)
-SYSCALL(sys_io_cancel,sys_io_cancel,sys_ni_syscall)
+SYSCALL(sys_io_setup,sys_io_setup,sys32_io_setup_wrapper)
+SYSCALL(sys_io_destroy,sys_io_destroy,sys32_io_destroy_wrapper)
+SYSCALL(sys_io_getevents,sys_io_getevents,sys32_io_getevents_wrapper)	/* 245 */
+SYSCALL(sys_io_submit,sys_io_submit,sys32_io_submit_wrapper)
+SYSCALL(sys_io_cancel,sys_io_cancel,sys32_io_cancel_wrapper)
 SYSCALL(sys_exit_group,sys_exit_group,sys32_exit_group_wrapper)
 SYSCALL(sys_epoll_create,sys_epoll_create,sys_epoll_create_wrapper)
 SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper)	/* 250 */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sh/kernel/irq.c 001-linus.patch/arch/sh/kernel/irq.c
--- 000-virgin/arch/sh/kernel/irq.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/arch/sh/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -93,17 +93,19 @@ struct hw_interrupt_type no_irq_type = {
 #if defined(CONFIG_PROC_FS)
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_puts(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-			seq_printf(p, "CPU%d       ",j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
+	if (i < ACTUAL_NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/Makefile 001-linus.patch/arch/sparc/Makefile
--- 000-virgin/arch/sparc/Makefile	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/arch/sparc/Makefile	Tue Dec 30 16:38:57 2003
@@ -49,7 +49,12 @@ NET_Y		:= $(patsubst %/, %/built-in.o, $
 LIBS_Y1		:= $(patsubst %/, %/lib.a, $(libs-y))
 LIBS_Y2		:= $(patsubst %/, %/built-in.o, $(libs-y))
 LIBS_Y		:= $(LIBS_Y1) $(LIBS_Y2)
-export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y
+
+ifdef CONFIG_KALLSYMS
+kallsyms.o := .tmp_kallsyms2.o
+endif
+
+export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y kallsyms.o
 
 # Default target
 all: image
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/boot/Makefile 001-linus.patch/arch/sparc/boot/Makefile
--- 000-virgin/arch/sparc/boot/Makefile	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/arch/sparc/boot/Makefile	Tue Dec 30 16:38:57 2003
@@ -19,7 +19,7 @@ quiet_cmd_btfix		= BTFIX $@
 
 BTOBJS := $(HEAD_Y) $(INIT_Y)
 BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y)
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group
+LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group $(kallsyms.o)
 
 # Actual linking
 $(obj)/image: $(obj)/btfix.o FORCE
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/asm-offsets.c 001-linus.patch/arch/sparc/kernel/asm-offsets.c
--- 000-virgin/arch/sparc/kernel/asm-offsets.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/sparc/kernel/asm-offsets.c	Tue Dec 30 16:38:57 2003
@@ -38,12 +38,6 @@ int foo(void)
 	DEFINE(AOFF_thread_fork_kpsr,
 			offsetof(struct thread_struct, fork_kpsr));
 	BLANK();
-	DEFINE(AOFF_thread_w_saved, offsetof(struct thread_struct, w_saved));
-	DEFINE(AOFF_thread_rwbuf_stkptrs,
-			offsetof(struct thread_struct, rwbuf_stkptrs));
-	DEFINE(AOFF_thread_reg_window,
-			offsetof(struct thread_struct, reg_window));
-	BLANK();
 	DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context));
 
 	/* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/entry.S 001-linus.patch/arch/sparc/kernel/entry.S
--- 000-virgin/arch/sparc/kernel/entry.S	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/sparc/kernel/entry.S	Tue Dec 30 16:38:57 2003
@@ -1907,9 +1907,8 @@ kuw_patch1:
 	wr	%o5, 0x0, %psr			! re-enable interrupts
 	WRITE_PAUSE				! burn baby burn
 3:
-	ld	[%g6 + TI_TASK], %o4
 	retl					! return
-	 st	%g0, [%o4 + AOFF_task_thread + AOFF_thread_w_saved]	! no windows saved
+	 st	%g0, [%g6 + TI_W_SAVED]		! no windows saved
 
 	.align	4
 	.globl	C_LABEL(restore_current)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/etrap.S 001-linus.patch/arch/sparc/kernel/etrap.S
--- 000-virgin/arch/sparc/kernel/etrap.S	Wed Dec 17 18:59:59 2003
+++ 001-linus.patch/arch/sparc/kernel/etrap.S	Tue Dec 30 16:38:57 2003
@@ -12,7 +12,6 @@
 #include <asm/page.h>
 #include <asm/psr.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
 #include <asm/winmacro.h>
 #include <asm/asmmacro.h>
 #include <asm/thread_info.h>
@@ -57,7 +56,7 @@ tsetup_7win_patch6:	and	%g2, 0x7f, %g2
 	 *
 	 * sethi	%hi(trap_setup), %l4
 	 * jmpl		%l4 + %lo(trap_setup), %l6
-	 * mov		1, %l4
+	 * nop
 	 */
 
 	/* 2 3 4  window number
@@ -156,9 +155,8 @@ trap_setup_from_user:
 	and	%t_kstack, %curptr, %curptr
 #endif
 
-	/* Clear current->thread.w_saved */
-	ld	[%curptr + TI_TASK], %g2
-	st	%g0, [%g2 + AOFF_task_thread + AOFF_thread_w_saved]
+	/* Clear current_thread_info->w_saved */
+	st	%g0, [%curptr + TI_W_SAVED]
 
 	/* See if we are in the trap window. */
 	andcc	%t_twinmask, %t_wim, %g0
@@ -292,8 +290,7 @@ trap_setup_user_stack_is_bolixed:
 	/* From user/kernel into invalid window w/bad user
 	 * stack. Save bad user stack, and return to caller.
 	 */
-	ld	[%curptr + TI_TASK], %glob_tmp
-	SAVE_BOLIXED_USER_STACK(glob_tmp, g3)
+	SAVE_BOLIXED_USER_STACK(curptr, g3)
 	restore	%g0, %g0, %g0
 
 	jmpl	%t_retpc + 0x8, %g0
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/irq.c 001-linus.patch/arch/sparc/kernel/irq.c
--- 000-virgin/arch/sparc/kernel/irq.c	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/arch/sparc/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -102,7 +102,7 @@ struct irqaction *irq_action[NR_IRQS] = 
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 #ifdef CONFIG_SMP
@@ -114,7 +114,7 @@ int show_interrupts(struct seq_file *p, 
 		
 		return show_sun4d_interrupts(p, v);
 	}
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		local_irq_save(flags);
 	        action = *(i + irq_action);
 		if (!action) 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/process.c 001-linus.patch/arch/sparc/kernel/process.c
--- 000-virgin/arch/sparc/kernel/process.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/arch/sparc/kernel/process.c	Tue Dec 30 16:38:57 2003
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/kallsyms.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
@@ -207,11 +208,12 @@ void __show_backtrace(unsigned long fp)
         while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
             !(((unsigned long) rw) & 0x7)) {
 		printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
-		       "FP[%08lx] CALLER[%08lx]\n", cpu,
+		       "FP[%08lx] CALLER[%08lx]: ", cpu,
 		       rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
 		       rw->ins[4], rw->ins[5],
 		       rw->ins[6],
 		       rw->ins[7]);
+		print_symbol("%s\n", rw->ins[7]);
 		rw = (struct reg_window *) rw->ins[6];
 	}
 	spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
@@ -279,12 +281,14 @@ void show_regs(struct pt_regs *r)
 
         printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx    %s\n",
 	       r->psr, r->pc, r->npc, r->y, print_tainted());
+	print_symbol("PC: <%s>\n", r->pc);
 	printk("%%G: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3],
 	       r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]);
 	printk("%%O: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11],
 	       r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]);
+	print_symbol("RPC: <%s>\n", r->u_regs[15]);
 
 	printk("%%L: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
@@ -318,7 +322,8 @@ void show_stack(struct task_struct *tsk,
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		printk("[%08lx] ", pc);
+		printk("[%08lx : ", pc);
+		print_symbol("%s ] ", pc);
 		fp = rw->ins[6];
 	} while (++count < 16);
 	printk("\n");
@@ -356,7 +361,7 @@ void exit_thread(void)
 
 void flush_thread(void)
 {
-	current->thread.w_saved = 0;
+	current_thread_info()->w_saved = 0;
 
 	/* No new signal delivery by default */
 	current->thread.new_signal = 0;
@@ -490,9 +495,6 @@ int copy_thread(int nr, unsigned long cl
 	ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
 	ti->kwim = current->thread.fork_kwim;
 
-	/* This is used for sun4c only */
-	atomic_set(&p->thread.refcount, 1);
-
 	if(regs->psr & PSR_PS) {
 		extern struct pt_regs fake_swapper_regs;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/ptrace.c 001-linus.patch/arch/sparc/kernel/ptrace.c
--- 000-virgin/arch/sparc/kernel/ptrace.c	Wed Dec 17 18:59:56 2003
+++ 001-linus.patch/arch/sparc/kernel/ptrace.c	Tue Dec 30 16:38:57 2003
@@ -72,7 +72,7 @@ static inline void read_sunos_user(struc
 				   struct task_struct *tsk, long *addr)
 {
 	struct pt_regs *cregs = tsk->thread.kregs;
-	struct thread_struct *t = &tsk->thread;
+	struct thread_info *t = tsk->thread_info;
 	int v;
 	
 	if(offset >= 1024)
@@ -93,16 +93,16 @@ static inline void read_sunos_user(struc
 	}
 	switch(offset) {
 	case 0:
-		v = tsk->thread_info->ksp;
+		v = t->ksp;
 		break;
 	case 4:
-		v = tsk->thread_info->kpc;
+		v = t->kpc;
 		break;
 	case 8:
-		v = tsk->thread_info->kpsr;
+		v = t->kpsr;
 		break;
 	case 12:
-		v = tsk->thread_info->uwinmask;
+		v = t->uwinmask;
 		break;
 	case 832:
 		v = t->w_saved;
@@ -167,7 +167,7 @@ static inline void write_sunos_user(stru
 				    struct task_struct *tsk)
 {
 	struct pt_regs *cregs = tsk->thread.kregs;
-	struct thread_struct *t = &tsk->thread;
+	struct thread_info *t = tsk->thread_info;
 	unsigned long value = regs->u_regs[UREG_I3];
 
 	if(offset >= 1024)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/rtrap.S 001-linus.patch/arch/sparc/kernel/rtrap.S
--- 000-virgin/arch/sparc/kernel/rtrap.S	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/sparc/kernel/rtrap.S	Tue Dec 30 16:38:57 2003
@@ -7,7 +7,6 @@
 #include <asm/cprefix.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/asi.h>
 #include <asm/smp.h>
@@ -87,8 +86,7 @@ ret_trap_continue:
 	wr	%t_psr, 0x0, %psr
 	WRITE_PAUSE
 
-	ld	[%curptr + TI_TASK], %o5
-	ld	[%o5 + AOFF_task_thread + AOFF_thread_w_saved], %twin_tmp1
+	ld	[%curptr + TI_W_SAVED], %twin_tmp1
 	orcc	%g0, %twin_tmp1, %g0
 	be	ret_trap_nobufwins
 	 nop
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/setup.c 001-linus.patch/arch/sparc/kernel/setup.c
--- 000-virgin/arch/sparc/kernel/setup.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/arch/sparc/kernel/setup.c	Tue Dec 30 16:38:57 2003
@@ -105,8 +105,6 @@ unsigned int boot_flags __initdata = 0;
 #define BOOTME_DEBUG  0x1
 #define BOOTME_SINGLE 0x2
 
-static int console_fb __initdata = 0;
-
 /* Exported for mm/init.c:paging_init. */
 unsigned long cmdline_memory_size __initdata = 0;
 
@@ -160,6 +158,31 @@ static void __init process_switch(char c
 	}
 }
 
+static void __init process_console(char *commands)
+{
+	serial_console = 0;
+	commands += 8;
+	/* Linux-style serial */
+	if (!strncmp(commands, "ttyS", 4))
+		serial_console = simple_strtoul(commands + 4, NULL, 10) + 1;
+	else if (!strncmp(commands, "tty", 3)) {
+		char c = *(commands + 3);
+		/* Solaris-style serial */
+		if (c == 'a' || c == 'b')
+			serial_console = c - 'a' + 1;
+		/* else Linux-style fbcon, not serial */
+	}
+#if defined(CONFIG_PROM_CONSOLE)
+	if (!strncmp(commands, "prom", 4)) {
+		char *p;
+
+		for (p = commands - 8; *p && *p != ' '; p++)
+			*p = ' ';
+		conswitchp = &prom_con;
+	}
+#endif
+}
+
 static void __init boot_flags_init(char *commands)
 {
 	while (*commands) {
@@ -174,37 +197,27 @@ static void __init boot_flags_init(char 
 			commands++;
 			while (*commands && *commands != ' ')
 				process_switch(*commands++);
-		} else {
-			if (!strncmp(commands, "console=", 8)) {
-				commands += 8;
-#if defined(CONFIG_PROM_CONSOLE)
-				if (!strncmp (commands, "prom", 4)) {
-					char *p;
-					
-					for (p = commands - 8; *p && *p != ' '; p++)
-						*p = ' ';
-					conswitchp = &prom_con;
-					console_fb = 1;
-				}
-#endif
-			} else if (!strncmp(commands, "mem=", 4)) {
-				/*
-				 * "mem=XXX[kKmM] overrides the PROM-reported
-				 * memory size.
-				 */
-				cmdline_memory_size = simple_strtoul(commands + 4,
-							     &commands, 0);
-				if (*commands == 'K' || *commands == 'k') {
-					cmdline_memory_size <<= 10;
-					commands++;
-				} else if (*commands=='M' || *commands=='m') {
-					cmdline_memory_size <<= 20;
-					commands++;
-				}
-			}
-			while (*commands && *commands != ' ')
+			continue;
+		}
+		if (!strncmp(commands, "console=", 8)) {
+			process_console(commands);
+		} else if (!strncmp(commands, "mem=", 4)) {
+			/*
+			 * "mem=XXX[kKmM] overrides the PROM-reported
+			 * memory size.
+			 */
+			cmdline_memory_size = simple_strtoul(commands + 4,
+						     &commands, 0);
+			if (*commands == 'K' || *commands == 'k') {
+				cmdline_memory_size <<= 10;
+				commands++;
+			} else if (*commands=='M' || *commands=='m') {
+				cmdline_memory_size <<= 20;
 				commands++;
+			}
 		}
+		while (*commands && *commands != ' ')
+			commands++;
 	}
 }
 
@@ -330,34 +343,6 @@ void __init setup_arch(char **cmdline_p)
 
 	prom_setsync(prom_sync_me);
 
-#ifndef CONFIG_SERIAL_CONSOLE	/* Not CONFIG_SERIAL_SUNCORE: to be gone. */
-	serial_console = 0;
-#else
-	if (console_fb != 0) {
-		serial_console = 0;
-	} else {
-		int idev = prom_query_input_device();
-		int odev = prom_query_output_device();
-		if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
-			serial_console = 0;
-		} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
-			serial_console = 1;
-		} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
-			serial_console = 2;
-		} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
-			prom_printf("MrCoffee ttya\n");
-			serial_console = 1;
-		} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
-			serial_console = 0;
-			prom_printf("MrCoffee keyboard\n");
-		} else {
-			prom_printf("Confusing console (idev %d, odev %d)\n",
-			    idev, odev);
-			serial_console = 1;
-		}
-	}
-#endif
-
 	if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
 	   ((*(short *)linux_dbvec) != -1)) {
 		printk("Booted under KADB. Syncing trap table.\n");
@@ -370,6 +355,41 @@ void __init setup_arch(char **cmdline_p)
 	paging_init();
 }
 
+static int __init set_preferred_console(void)
+{
+	int idev, odev;
+
+	/* The user has requested a console so this is already set up. */
+	if (serial_console >= 0)
+		return -EBUSY;
+
+	idev = prom_query_input_device();
+	odev = prom_query_output_device();
+	if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
+		serial_console = 0;
+	} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
+		serial_console = 1;
+	} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
+		serial_console = 2;
+	} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
+		prom_printf("MrCoffee ttya\n");
+		serial_console = 1;
+	} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
+		serial_console = 0;
+		prom_printf("MrCoffee keyboard\n");
+	} else {
+		prom_printf("Confusing console (idev %d, odev %d)\n",
+		    idev, odev);
+		serial_console = 1;
+	}
+
+	if (serial_console)
+		return add_preferred_console("ttyS", serial_console - 1, NULL);
+
+	return -ENODEV;
+}
+console_initcall(set_preferred_console);
+
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
 {
 	return -EIO;
@@ -458,5 +478,5 @@ void sun_do_break(void)
 	prom_cmdline();
 }
 
-int serial_console;
+int serial_console = -1;
 int stop_a_enabled = 1;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/signal.c 001-linus.patch/arch/sparc/kernel/signal.c
--- 000-virgin/arch/sparc/kernel/signal.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/arch/sparc/kernel/signal.c	Tue Dec 30 16:38:57 2003
@@ -432,6 +432,7 @@ setup_frame(struct sigaction *sa, struct
 	int window = 0, err;
 	unsigned long pc = regs->pc;
 	unsigned long npc = regs->npc;
+	struct thread_info *tp = current_thread_info();
 	void *sig_address;
 	int sig_code;
 
@@ -459,20 +460,20 @@ setup_frame(struct sigaction *sa, struct
 	err |= __put_user(regs->psr, &sc->sigc_psr);
 	err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
 	err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
-	err |= __put_user(current->thread.w_saved, &sc->sigc_oswins);
-	if (current->thread.w_saved)
-		for (window = 0; window < current->thread.w_saved; window++) {
-			put_user((char *)current->thread.rwbuf_stkptrs[window],
+	err |= __put_user(tp->w_saved, &sc->sigc_oswins);
+	if (tp->w_saved)
+		for (window = 0; window < tp->w_saved; window++) {
+			put_user((char *)tp->rwbuf_stkptrs[window],
 				 &sc->sigc_spbuf[window]);
 			err |= __copy_to_user(&sc->sigc_wbuf[window],
-					      &current->thread.reg_window[window],
+					      &tp->reg_window[window],
 					      sizeof(struct reg_window));
 		}
 	else
 		err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP],
 				      sizeof(struct reg_window));
 
-	current->thread.w_saved = 0; /* So process is allowed to execute. */
+	tp->w_saved = 0; /* So process is allowed to execute. */
 
 	err |= __put_user(signr, &sframep->sig_num);
 	sig_address = NULL;
@@ -601,7 +602,7 @@ new_setup_frame(struct k_sigaction *ka, 
 	if (invalid_frame_pointer(sf, sigframe_size))
 		goto sigill_and_return;
 
-	if (current->thread.w_saved != 0)
+	if (current_thread_info()->w_saved != 0)
 		goto sigill_and_return;
 
 	/* 2. Save the current process state */
@@ -675,7 +676,7 @@ new_setup_rt_frame(struct k_sigaction *k
 		get_sigframe(&ka->sa, regs, sigframe_size);
 	if (invalid_frame_pointer(sf, sigframe_size))
 		goto sigill;
-	if (current->thread.w_saved != 0)
+	if (current_thread_info()->w_saved != 0)
 		goto sigill;
 
 	err  = __put_user(regs->pc, &sf->regs.pc);
@@ -752,6 +753,7 @@ setup_svr4_frame(struct sigaction *sa, u
 	svr4_gwindows_t __user *gw;
 	svr4_ucontext_t __user *uc;
 	svr4_sigset_t	setv;
+	struct thread_info *tp = current_thread_info();
 	int window = 0, err;
 
 	synchronize_user_stack();
@@ -808,7 +810,7 @@ setup_svr4_frame(struct sigaction *sa, u
 	err |= __put_user(gw, &mc->gwin);
 	    
 	/* 2. Number of windows to restore at setcontext(): */
-	err |= __put_user(current->thread.w_saved, &gw->count);
+	err |= __put_user(tp->w_saved, &gw->count);
 
 	/* 3. Save each valid window
 	 *    Currently, it makes a copy of the windows from the kernel copy.
@@ -821,16 +823,16 @@ setup_svr4_frame(struct sigaction *sa, u
 	 *    These windows are just used in case synchronize_user_stack failed
 	 *    to flush the user windows.
 	 */
-	for (window = 0; window < current->thread.w_saved; window++) {
+	for (window = 0; window < tp->w_saved; window++) {
 		err |= __put_user((int *) &(gw->win[window]), &gw->winptr[window]);
 		err |= __copy_to_user(&gw->win[window],
-				      &current->thread.reg_window[window],
+				      &tp->reg_window[window],
 				      sizeof(svr4_rwindow_t));
 		err |= __put_user(0, gw->winptr[window]);
 	}
 
 	/* 4. We just pay attention to the gw->count field on setcontext */
-	current->thread.w_saved = 0; /* So process is allowed to execute. */
+	tp->w_saved = 0; /* So process is allowed to execute. */
 
 	/* Setup the signal information.  Solaris expects a bunch of
 	 * information to be passed to the signal handler, we don't provide
@@ -878,7 +880,7 @@ asmlinkage int svr4_getcontext(svr4_ucon
 
 	synchronize_user_stack();
 
-	if (current->thread.w_saved)
+	if (current_thread_info()->w_saved)
 		goto sigsegv_and_return;
 
 	err = clear_user(uc, sizeof(*uc));
@@ -928,7 +930,6 @@ sigsegv_and_return:
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
 asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
 {
-	struct thread_struct *tp = &current->thread;
 	svr4_gregset_t  __user *gr;
 	unsigned long pc, npc, psr;
 	sigset_t set;
@@ -940,8 +941,8 @@ asmlinkage int svr4_setcontext(svr4_ucon
 	 * svr4_setup_frame when sync_user_windows is done?
 	 */
 	flush_user_windows();
-	
-	if (tp->w_saved)
+
+	if (current_thread_info()->w_saved)
 		goto sigsegv_and_return;
 
 	if (((uint) c) & 3)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/sun4d_irq.c 001-linus.patch/arch/sparc/kernel/sun4d_irq.c
--- 000-virgin/arch/sparc/kernel/sun4d_irq.c	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/arch/sparc/kernel/sun4d_irq.c	Tue Dec 30 16:38:57 2003
@@ -75,25 +75,25 @@ spinlock_t sun4d_imsk_lock = SPIN_LOCK_U
 
 int show_sun4d_interrupts(struct seq_file *p, void *v)
 {
-	int i, j = 0, k = 0, sbusl;
+	int i = *(loff_t *) v, j = 0, k = 0, sbusl;
 	struct irqaction * action;
 #ifdef CONFIG_SMP
 	int x;
 #endif
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		sbusl = pil_to_sbus[i];
 		if (!sbusl) {
 	 		action = *(i + irq_action);
 			if (!action) 
-		        	continue;
+		        	goto out;
 		} else {
 			for (j = 0; j < nsbi; j++) {
 				for (k = 0; k < 4; k++)
 					if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action))
 						goto found_it;
 			}
-			continue;
+			goto out;
 		}
 found_it:	seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
@@ -128,6 +128,7 @@ found_it:	seq_printf(p, "%3d: ", i);
 		}
 		seq_putc(p, '\n');
 	}
+out:
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/traps.c 001-linus.patch/arch/sparc/kernel/traps.c
--- 000-virgin/arch/sparc/kernel/traps.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/arch/sparc/kernel/traps.c	Tue Dec 30 16:38:57 2003
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>  /* for jiffies */
 #include <linux/kernel.h>
+#include <linux/kallsyms.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -118,7 +119,9 @@ void die_if_kernel(char *str, struct pt_
 		      count++ < 30				&&
                       (((unsigned long) rw) >= PAGE_OFFSET)	&&
 		      !(((unsigned long) rw) & 0x7)) {
-			printk("Caller[%08lx]\n", rw->ins[7]);
+			printk("Caller[%08lx]", rw->ins[7]);
+			print_symbol(": %s\n", rw->ins[7]);
+			printk("\n");
 			rw = (struct reg_window *)rw->ins[6];
 		}
 	}
@@ -497,7 +500,10 @@ void trap_init(void)
 	    TI_KSP         != offsetof(struct thread_info, ksp) ||
 	    TI_KPC         != offsetof(struct thread_info, kpc) ||
 	    TI_KPSR        != offsetof(struct thread_info, kpsr) ||
-	    TI_KWIM        != offsetof(struct thread_info, kwim))
+	    TI_KWIM        != offsetof(struct thread_info, kwim) ||
+	    TI_REG_WINDOW  != offsetof(struct thread_info, reg_window) ||
+	    TI_RWIN_SPTRS  != offsetof(struct thread_info, rwbuf_stkptrs) ||
+	    TI_W_SAVED     != offsetof(struct thread_info, w_saved))
 		thread_info_offsets_are_bolixed_pete();
 
 	/* Attach to the address space of init_task. */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/windows.c 001-linus.patch/arch/sparc/kernel/windows.c
--- 000-virgin/arch/sparc/kernel/windows.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/arch/sparc/kernel/windows.c	Tue Dec 30 16:38:57 2003
@@ -36,7 +36,7 @@ void flush_user_windows(void)
 	: "g4", "cc");
 }
 
-static inline void shift_window_buffer(int first_win, int last_win, struct thread_struct *tp)
+static inline void shift_window_buffer(int first_win, int last_win, struct thread_info *tp)
 {
 	int i;
 
@@ -57,11 +57,10 @@ static inline void shift_window_buffer(i
  */
 void synchronize_user_stack(void)
 {
-	struct thread_struct *tp;
+	struct thread_info *tp = current_thread_info();
 	int window;
 
 	flush_user_windows();
-	tp = &current->thread;
 	if(!tp->w_saved)
 		return;
 
@@ -110,12 +109,11 @@ static inline void copy_aligned_window(v
 
 void try_to_clear_window_buffer(struct pt_regs *regs, int who)
 {
-	struct thread_struct *tp;
+	struct thread_info *tp = current_thread_info();
 	int window;
 
 	lock_kernel();
 	flush_user_windows();
-	tp = &current->thread;
 	for(window = 0; window < tp->w_saved; window++) {
 		unsigned long sp = tp->rwbuf_stkptrs[window];
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/wof.S 001-linus.patch/arch/sparc/kernel/wof.S
--- 000-virgin/arch/sparc/kernel/wof.S	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/arch/sparc/kernel/wof.S	Tue Dec 30 16:38:57 2003
@@ -8,7 +8,6 @@
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/smp.h>
 #include <asm/asi.h>
@@ -211,20 +210,18 @@ spwin_user_stack_is_bolixed:
 	bne	spwin_bad_ustack_from_kernel
 	 nop
 
-	ld	[%curptr + TI_TASK], %glob_tmp
-
 	/* Oh well, throw this one window into the per-task window
 	 * buffer, the first one.
 	 */
-	st	%sp, [%glob_tmp + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
-	STORE_WINDOW(glob_tmp + AOFF_task_thread + AOFF_thread_reg_window)
+	st	%sp, [%curptr + TI_RWIN_SPTRS]
+	STORE_WINDOW(curptr + TI_REG_WINDOW)
 	restore	%g0, %g0, %g0
 
 	/* LOCATION: Trap Window */
 
 	/* Back in the trap window, update winbuffer save count. */
 	mov	1, %twin_tmp
-	st	%twin_tmp, [%glob_tmp + AOFF_task_thread + AOFF_thread_w_saved]
+	st	%twin_tmp, [%curptr + TI_W_SAVED]
 
 		/* Compute new user window mask.  What we are basically
 		 * doing is taking two windows, the invalid one at trap
@@ -275,8 +272,7 @@ spwin_bad_ustack_from_kernel:
 	 * a per-process window buffer until we can properly handle
 	 * this later on.
 	 */
-	ld	[%curptr + TI_TASK], %glob_tmp	/* Using curptr one last time */
-	SAVE_BOLIXED_USER_STACK(glob_tmp, g6)	/* ...now using g6 as scratch */
+	SAVE_BOLIXED_USER_STACK(curptr, glob_tmp)
 	restore	%g0, %g0, %g0
 
 	/* LOCATION: Trap window */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/kernel/wuf.S 001-linus.patch/arch/sparc/kernel/wuf.S
--- 000-virgin/arch/sparc/kernel/wuf.S	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/arch/sparc/kernel/wuf.S	Tue Dec 30 16:38:57 2003
@@ -8,7 +8,6 @@
 #include <asm/contregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
 #include <asm/psr.h>
 #include <asm/smp.h>
 #include <asm/asi.h>
@@ -187,8 +186,7 @@ fwin_user_stack_is_bolixed:
 	mov	0x1, %g5
 	sll	%g5, %g3, %g5
 	st	%g5, [%curptr + TI_UWINMASK]		! one live user window still
-	ld	[%curptr + TI_TASK], %g5
-	st	%g0, [%g5 + AOFF_task_thread + AOFF_thread_w_saved]		! no windows in the buffer
+	st	%g0, [%curptr + TI_W_SAVED]		! no windows in the buffer
 
 	wr	%t_psr, PSR_ET, %psr			! enable traps
 	nop
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/mm/fault.c 001-linus.patch/arch/sparc/mm/fault.c
--- 000-virgin/arch/sparc/mm/fault.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/arch/sparc/mm/fault.c	Tue Dec 30 16:38:57 2003
@@ -422,6 +422,12 @@ asmlinkage void do_sun4c_fault(struct pt
 		}
 	}
 
+	if (!mm) {
+		/* We are oopsing. */
+		do_sparc_fault(regs, text_fault, write, address);
+		BUG();	/* P3 Oops already, you bitch */
+	}
+
 	pgdp = pgd_offset(mm, address);
 	ptep = sun4c_pte_offset_kernel((pmd_t *) pgdp, address);
 
@@ -544,7 +550,7 @@ void window_overflow_fault(void)
 {
 	unsigned long sp;
 
-	sp = current->thread.rwbuf_stkptrs[0];
+	sp = current_thread_info()->rwbuf_stkptrs[0];
 	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
 		force_user_fault(sp + 0x38, 1);
 	force_user_fault(sp, 1);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/mm/init.c 001-linus.patch/arch/sparc/mm/init.c
--- 000-virgin/arch/sparc/mm/init.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/sparc/mm/init.c	Tue Dec 30 16:38:57 2003
@@ -209,7 +209,8 @@ unsigned long __init bootmem_init(unsign
 	if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) {
 		highstart_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT);
 		max_low_pfn = calc_max_low_pfn();
-		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", calc_highpages());
+		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+		    calc_highpages() >> (20 - PAGE_SHIFT));
 	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc/mm/sun4c.c 001-linus.patch/arch/sparc/mm/sun4c.c
--- 000-virgin/arch/sparc/mm/sun4c.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/arch/sparc/mm/sun4c.c	Tue Dec 30 16:38:57 2003
@@ -1067,23 +1067,21 @@ static void sun4c_free_thread_info(struc
 	unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tiaddr));
 	int entry = BUCKET_NUM(tiaddr);
 
-	if (atomic_dec_and_test(&ti->task->thread.refcount)) {
-		/* We are deleting a mapping, so the flush here is mandatory. */
-		sun4c_flush_page(tiaddr);
+	/* We are deleting a mapping, so the flush here is mandatory. */
+	sun4c_flush_page(tiaddr);
 #ifndef CONFIG_SUN4	
-		sun4c_flush_page(tiaddr + PAGE_SIZE);
+	sun4c_flush_page(tiaddr + PAGE_SIZE);
 #endif
-		sun4c_put_pte(tiaddr, 0);
+	sun4c_put_pte(tiaddr, 0);
 #ifndef CONFIG_SUN4	
-		sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
+	sun4c_put_pte(tiaddr + PAGE_SIZE, 0);
 #endif
-		sun4c_bucket[entry] = BUCKET_EMPTY;
-		if (entry < sun4c_lowbucket_avail)
-			sun4c_lowbucket_avail = entry;
+	sun4c_bucket[entry] = BUCKET_EMPTY;
+	if (entry < sun4c_lowbucket_avail)
+		sun4c_lowbucket_avail = entry;
 
-		free_pages(pages, THREAD_INFO_ORDER);
-		garbage_collect(entry);
-	}
+	free_pages(pages, THREAD_INFO_ORDER);
+	garbage_collect(entry);
 }
 
 static void __init sun4c_init_buckets(void)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/Kconfig 001-linus.patch/arch/sparc64/Kconfig
--- 000-virgin/arch/sparc64/Kconfig	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/arch/sparc64/Kconfig	Tue Dec 30 16:38:57 2003
@@ -808,16 +808,9 @@ config DEBUG_SPINLOCK
 	  best used in conjunction with the NMI watchdog so that spinlock
 	  deadlocks are also debuggable.
 
-# We have a custom atomic_dec_and_lock() implementation but it's not
-# compatible with spinlock debugging so we need to fall back on
-# the generic version in that case.
-config HAVE_DEC_LOCK
-	bool
-	depends on SMP && !DEBUG_SPINLOCK
-	default y
-
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
+	depends DEBUG_KERNEL
 	help
 	  If you say Y here, various routines which may sleep will become very
 	  noisy if they are called with a spinlock held.	
@@ -844,8 +837,17 @@ config DEBUG_INFO
 	  If you don't debug the kernel, you can say N.
 	  
 config STACK_DEBUG
+	depends on DEBUG_KERNEL
 	bool "Stack Overflow Detection Support"
 
+# We have a custom atomic_dec_and_lock() implementation but it's not
+# compatible with spinlock debugging so we need to fall back on
+# the generic version in that case.
+config HAVE_DEC_LOCK
+	bool
+	depends on SMP && !DEBUG_SPINLOCK
+	default y
+
 config MCOUNT
 	bool
 	depends on STACK_DEBUG
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/defconfig 001-linus.patch/arch/sparc64/defconfig
--- 000-virgin/arch/sparc64/defconfig	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/sparc64/defconfig	Tue Dec 30 16:38:57 2003
@@ -138,7 +138,6 @@ CONFIG_FB_FFB=y
 #
 # Console display driver support
 #
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_MDA_CONSOLE is not set
 # CONFIG_PROM_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
@@ -243,7 +242,6 @@ CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_BLK_DEV_GENERIC is not set
 CONFIG_BLK_DEV_OPTI621=m
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDE_TCQ is not set
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_IDEDMA_ONLYDISK=y
@@ -1508,7 +1506,6 @@ CONFIG_USB_USS720=m
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -1571,12 +1568,12 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_HAVE_DEC_LOCK=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_STACK_DEBUG is not set
+CONFIG_HAVE_DEC_LOCK=y
 
 #
 # Security options
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/kernel/ebus.c 001-linus.patch/arch/sparc64/kernel/ebus.c
--- 000-virgin/arch/sparc64/kernel/ebus.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/sparc64/kernel/ebus.c	Tue Dec 30 16:38:57 2003
@@ -424,7 +424,8 @@ void __init fill_ebus_child(int node, st
 
 static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
 {
-	if (!strcmp(dev->prom_name, "i2c"))
+	if (!strcmp(dev->prom_name, "i2c") ||
+	    !strcmp(dev->prom_name, "SUNW,lombus"))
 		return 1;
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/kernel/irq.c 001-linus.patch/arch/sparc64/kernel/irq.c
--- 000-virgin/arch/sparc64/kernel/irq.c	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/arch/sparc64/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -128,16 +128,16 @@ static void register_irq_proc (unsigned 
 int show_interrupts(struct seq_file *p, void *v)
 {
 	unsigned long flags;
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction *action;
 #ifdef CONFIG_SMP
 	int j;
 #endif
 
 	spin_lock_irqsave(&irq_action_lock, flags);
-	for (i = 0; i < (NR_IRQS + 1); i++) {
+	if (i <= NR_IRQS) {
 		if (!(action = *(i + irq_action)))
-			continue;
+			goto out_unlock;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -157,6 +157,7 @@ int show_interrupts(struct seq_file *p, 
 		}
 		seq_putc(p, '\n');
 	}
+out_unlock:
 	spin_unlock_irqrestore(&irq_action_lock, flags);
 
 	return 0;
@@ -1204,11 +1205,17 @@ static int irq_affinity_read_proc (char 
 {
 	struct ino_bucket *bp = ivector_table + (long)data;
 	struct irqaction *ap = bp->irq_info;
-	unsigned long mask = get_smpaff_in_irqaction(ap);
+	cpumask_t mask = get_smpaff_in_irqaction(ap);
+	int len;
+
+	if (cpus_empty(mask))
+		mask = cpu_online_map;
 
-	if (count < HEX_DIGITS+1)
+	len = cpumask_snprintf(page, count, mask);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%016lx\n", mask == 0 ? ~0UL : mask);
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static inline void set_intr_affinity(int irq, unsigned long hw_aff)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/kernel/pci_sabre.c 001-linus.patch/arch/sparc64/kernel/pci_sabre.c
--- 000-virgin/arch/sparc64/kernel/pci_sabre.c	Wed Dec 17 18:59:46 2003
+++ 001-linus.patch/arch/sparc64/kernel/pci_sabre.c	Tue Dec 30 16:38:57 2003
@@ -321,10 +321,7 @@ static int __sabre_read_pci_cfg(struct p
 static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
 			      int where, int size, u32 *value)
 {
-	if (bus->number)
-		return __sabre_read_pci_cfg(bus, devfn, where, size, value);
-
-	if (sabre_out_of_range(devfn)) {
+	if (!bus->number && sabre_out_of_range(devfn)) {
 		switch (size) {
 		case 1:
 			*value = 0xff;
@@ -339,6 +336,15 @@ static int sabre_read_pci_cfg(struct pci
 		return PCIBIOS_SUCCESSFUL;
 	}
 
+	if (bus->number || PCI_SLOT(devfn))
+		return __sabre_read_pci_cfg(bus, devfn, where, size, value);
+
+	/* When accessing PCI config space of the PCI controller itself (bus
+	 * 0, device slot 0, function 0) there are restrictions.  Each
+	 * register must be accessed as it's natural size.  Thus, for example
+	 * the Vendor ID must be accessed as a 16-bit quantity.
+	 */
+
 	switch (size) {
 	case 1:
 		if (where < 8) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/kernel/setup.c 001-linus.patch/arch/sparc64/kernel/setup.c
--- 000-virgin/arch/sparc64/kernel/setup.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/arch/sparc64/kernel/setup.c	Tue Dec 30 16:38:57 2003
@@ -320,8 +320,6 @@ unsigned int boot_flags = 0;
 #define BOOTME_DEBUG  0x1
 #define BOOTME_SINGLE 0x2
 
-static int console_fb __initdata = 0;
-
 /* Exported for mm/init.c:paging_init. */
 unsigned long cmdline_memory_size = 0;
 
@@ -374,6 +372,33 @@ static void __init process_switch(char c
 	}
 }
 
+static void __init process_console(char *commands)
+{
+	serial_console = 0;
+	commands += 8;
+	/* Linux-style serial */
+	if (!strncmp(commands, "ttyS", 4))
+		serial_console = simple_strtoul(commands + 4, NULL, 10) + 1;
+	else if (!strncmp(commands, "tty", 3)) {
+		char c = *(commands + 3);
+		/* Solaris-style serial */
+		if (c == 'a' || c == 'b') {
+			serial_console = c - 'a' + 1;
+			prom_printf ("Using /dev/tty%c as console.\n", c);
+		}
+		/* else Linux-style fbcon, not serial */
+	}
+#if defined(CONFIG_PROM_CONSOLE)
+	if (!strncmp(commands, "prom", 4)) {
+		char *p;
+
+		for (p = commands - 8; *p && *p != ' '; p++)
+			*p = ' ';
+		conswitchp = &prom_con;
+	}
+#endif
+}
+
 static void __init boot_flags_init(char *commands)
 {
 	while (*commands) {
@@ -384,49 +409,31 @@ static void __init boot_flags_init(char 
 		/* Process any command switches, otherwise skip it. */
 		if (*commands == '\0')
 			break;
-		else if (*commands == '-') {
+		if (*commands == '-') {
 			commands++;
 			while (*commands && *commands != ' ')
 				process_switch(*commands++);
-		} else {
-			if (!strncmp(commands, "console=", 8)) {
-				commands += 8;
-				if (!strncmp (commands, "ttya", 4)) {
-					console_fb = 2;
-					prom_printf ("Using /dev/ttya as console.\n");
-				} else if (!strncmp (commands, "ttyb", 4)) {
-					console_fb = 3;
-					prom_printf ("Using /dev/ttyb as console.\n");
-#if defined(CONFIG_PROM_CONSOLE)
-				} else if (!strncmp (commands, "prom", 4)) {
-					char *p;
-					
-					for (p = commands - 8; *p && *p != ' '; p++)
-						*p = ' ';
-					conswitchp = &prom_con;
-					console_fb = 1;
-#endif
-				} else {
-					console_fb = 1;
-				}
-			} else if (!strncmp(commands, "mem=", 4)) {
-				/*
-				 * "mem=XXX[kKmM]" overrides the PROM-reported
-				 * memory size.
-				 */
-				cmdline_memory_size = simple_strtoul(commands + 4,
-								     &commands, 0);
-				if (*commands == 'K' || *commands == 'k') {
-					cmdline_memory_size <<= 10;
-					commands++;
-				} else if (*commands=='M' || *commands=='m') {
-					cmdline_memory_size <<= 20;
-					commands++;
-				}
-			}
-			while (*commands && *commands != ' ')
+			continue;
+		}
+		if (!strncmp(commands, "console=", 8)) {
+			process_console(commands);
+		} else if (!strncmp(commands, "mem=", 4)) {
+			/*
+			 * "mem=XXX[kKmM]" overrides the PROM-reported
+			 * memory size.
+			 */
+			cmdline_memory_size = simple_strtoul(commands + 4,
+							     &commands, 0);
+			if (*commands == 'K' || *commands == 'k') {
+				cmdline_memory_size <<= 10;
+				commands++;
+			} else if (*commands=='M' || *commands=='m') {
+				cmdline_memory_size <<= 20;
 				commands++;
+			}
 		}
+		while (*commands && *commands != ' ')
+			commands++;
 	}
 }
 
@@ -546,38 +553,38 @@ void __init setup_arch(char **cmdline_p)
 	}
 #endif
 
-	switch (console_fb) {
-	case 0: /* Let's get our io devices from prom */
-		{
-			int idev = prom_query_input_device();
-			int odev = prom_query_output_device();
-			if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
-				serial_console = 0;
-			} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
-				serial_console = 1;
-			} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
-				serial_console = 2;
-			} else {
-				prom_printf("Inconsistent console: "
-					    "input %d, output %d\n",
-					    idev, odev);
-				prom_halt();
-			}
-		}
-		break;
-	case 1: /* Force one of the framebuffers as console */
+	paging_init();
+}
+
+static int __init set_preferred_console(void)
+{
+	int idev, odev;
+
+	/* The user has requested a console so this is already set up. */
+	if (serial_console >= 0)
+		return -EBUSY;
+
+	idev = prom_query_input_device();
+	odev = prom_query_output_device();
+	if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
 		serial_console = 0;
-		break;
-	case 2: /* Force ttya as console */
+	} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
 		serial_console = 1;
-		break;
-	case 3: /* Force ttyb as console */
+	} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
 		serial_console = 2;
-		break;
-	};
+	} else {
+		prom_printf("Inconsistent console: "
+			    "input %d, output %d\n",
+			    idev, odev);
+		prom_halt();
+	}
 
-	paging_init();
+	if (serial_console)
+		return add_preferred_console("ttyS", serial_console - 1, NULL);
+
+	return -ENODEV;
 }
+console_initcall(set_preferred_console);
 
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
 {
@@ -671,7 +678,7 @@ void sun_do_break(void)
 	prom_cmdline();
 }
 
-int serial_console;
+int serial_console = -1;
 int stop_a_enabled = 1;
 
 static int __init topology_init(void)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/kernel/systbls.S 001-linus.patch/arch/sparc64/kernel/systbls.S
--- 000-virgin/arch/sparc64/kernel/systbls.S	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/sparc64/kernel/systbls.S	Tue Dec 30 16:38:57 2003
@@ -72,8 +72,8 @@ sys_call_table32:
 /*250*/	.word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
 	.word sys_ni_syscall, compat_clock_settime, compat_clock_gettime, compat_clock_getres, compat_clock_nanosleep
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, compat_timer_settime, compat_timer_gettime, sys_timer_getoverrun
-	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
-/*270*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
+	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
+/*270*/	.word compat_sys_io_submit, sys_io_cancel, compat_sys_io_getevents, sys_ni_syscall
 
 	/* Now the 64-bit native Linux syscall table. */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/sparc64/mm/hugetlbpage.c 001-linus.patch/arch/sparc64/mm/hugetlbpage.c
--- 000-virgin/arch/sparc64/mm/hugetlbpage.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/sparc64/mm/hugetlbpage.c	Tue Dec 30 16:38:57 2003
@@ -504,7 +504,7 @@ int is_hugepage_mem_enough(size_t size)
  * this far.
  */
 static struct page *hugetlb_nopage(struct vm_area_struct *vma,
-				   unsigned long address, int unused)
+				   unsigned long address, int *unused)
 {
 	BUG();
 	return NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/um/kernel/irq.c 001-linus.patch/arch/um/kernel/irq.c
--- 000-virgin/arch/um/kernel/irq.c	Wed Dec 17 18:59:20 2003
+++ 001-linus.patch/arch/um/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -572,53 +572,14 @@ static struct proc_dir_entry * smp_affin
  */
 static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-	return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
-}
-
-static unsigned int parse_hex_value (const char *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum [HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	int i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first 8 characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-
-	for (i = 0; i < count; i++) {
-		unsigned int k, c = hexnum[i];
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 16);
-		for (k = 0; k < 4; ++k)
-			if (c & (1 << k))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
+	len += sprintf(page + len, "\n");
+	return len;
 }
 
 static int irq_affinity_write_proc (struct file *file, const char *buffer,
@@ -630,7 +591,7 @@ static int irq_affinity_write_proc (stru
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 
 #ifdef CONFIG_SMP
 	/*
@@ -652,19 +613,10 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	cpumask_t tmp, *mask = (cpumask_t *) data;
-	int k, len = 0;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-	tmp = *mask;
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -674,7 +626,7 @@ static int prof_cpu_mask_write_proc (str
 	cpumask_t *mask = (cpumask_t *)data, new_value;
 	unsigned long full_count = count, err;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/v850/kernel/irq.c 001-linus.patch/arch/v850/kernel/irq.c
--- 000-virgin/arch/v850/kernel/irq.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/arch/v850/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -81,16 +81,18 @@ volatile unsigned long irq_err_count, sp
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i;
+	int i = *(loff_t *) v;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_puts(p, "           ");
-	for (i=0; i < 1 /*smp_num_cpus*/; i++)
-		seq_printf(p, "CPU%d       ", i);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (i=0; i < 1 /*smp_num_cpus*/; i++)
+			seq_printf(p, "CPU%d       ", i);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		int j, count, num;
 		const char *type_name = irq_desc[i].handler->typename;
 		spin_lock_irqsave(&irq_desc[j].lock, flags);
@@ -121,8 +123,8 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[j].lock, flags);
-	}
-	seq_printf(p, "ERR: %10lu\n", irq_err_count);
+	} else if (i == NR_IRQS)
+		seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/Kconfig 001-linus.patch/arch/x86_64/Kconfig
--- 000-virgin/arch/x86_64/Kconfig	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/arch/x86_64/Kconfig	Tue Dec 30 16:38:57 2003
@@ -371,6 +371,12 @@ config IA32_EMULATION
 	  turn this on, unless you're 100% sure that you don't have any 32-bit programs
 	  left.
 
+config IA32_AOUT
+       bool "IA32 a.out support"
+       depends on IA32_EMULATION
+       help
+         Support old a.out binaries in the 32bit emulation.
+
 config COMPAT
 	bool
 	depends on IA32_EMULATION
@@ -505,6 +511,7 @@ config FRAME_POINTER
 	 Normally you should say N.
 
 config IOMMU_DEBUG
+       depends on GART_IOMMU && DEBUG_KERNEL
        bool "Force IOMMU to on" 
        help
          Force the IOMMU to on even when you have less than 4GB of memory and add 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/defconfig 001-linus.patch/arch/x86_64/defconfig
--- 000-virgin/arch/x86_64/defconfig	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/arch/x86_64/defconfig	Tue Dec 30 16:38:57 2003
@@ -743,7 +743,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_INIT_DEBUG is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_FRAME_POINTER is not set
-CONFIG_IOMMU_DEBUG=y
+# CONFIG_IOMMU_DEBUG is not set
 CONFIG_IOMMU_LEAK=y
 CONFIG_MCE_DEBUG=y
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/ia32/Makefile 001-linus.patch/arch/x86_64/ia32/Makefile
--- 000-virgin/arch/x86_64/ia32/Makefile	Wed Dec 17 18:58:38 2003
+++ 001-linus.patch/arch/x86_64/ia32/Makefile	Tue Dec 30 16:38:57 2003
@@ -6,6 +6,8 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entr
 	ia32_signal.o tls32.o \
 	ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o
 
+obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
+
 $(obj)/syscall32.o: $(src)/syscall32.c $(obj)/vsyscall.so
 
 # Teach kbuild about targets
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/ia32/ia32_aout.c 001-linus.patch/arch/x86_64/ia32/ia32_aout.c
--- 000-virgin/arch/x86_64/ia32/ia32_aout.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/arch/x86_64/ia32/ia32_aout.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,506 @@
+/*
+ *  a.out loader for x86-64
+ *
+ *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
+ *  Hacked together by Andi Kleen
+ */
+
+#include <linux/module.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/slab.h>
+#include <linux/binfmts.h>
+#include <linux/personality.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/user32.h>
+
+#undef WARN_OLD
+
+extern int ia32_setup_arg_pages(struct linux_binprm *bprm);
+
+static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
+static int load_aout_library(struct file*);
+static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
+
+/*
+ * fill in the user structure for a core dump..
+ */
+static void dump_thread32(struct pt_regs * regs, struct user32 * dump)
+{
+	u32 fs,gs;
+
+/* changed the size calculations - should hopefully work better. lbt */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = regs->rsp & ~(PAGE_SIZE - 1);
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+	dump->u_debugreg[0] = current->thread.debugreg0;  
+	dump->u_debugreg[1] = current->thread.debugreg1;  
+	dump->u_debugreg[2] = current->thread.debugreg2;  
+	dump->u_debugreg[3] = current->thread.debugreg3;  
+	dump->u_debugreg[4] = 0;  
+	dump->u_debugreg[5] = 0;  
+	dump->u_debugreg[6] = current->thread.debugreg6;  
+	dump->u_debugreg[7] = current->thread.debugreg7;  
+
+	if (dump->start_stack < 0xc0000000)
+		dump->u_ssize = ((unsigned long) (0xc0000000 - dump->start_stack)) >> PAGE_SHIFT;
+
+	dump->regs.ebx = regs->rbx;
+	dump->regs.ecx = regs->rcx;
+	dump->regs.edx = regs->rdx;
+	dump->regs.esi = regs->rsi;
+	dump->regs.edi = regs->rdi;
+	dump->regs.ebp = regs->rbp;
+	dump->regs.eax = regs->rax;
+	dump->regs.ds = current->thread.ds;
+	dump->regs.es = current->thread.es;
+	asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs;
+	asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; 
+	dump->regs.orig_eax = regs->orig_rax;
+	dump->regs.eip = regs->rip;
+	dump->regs.cs = regs->cs;
+	dump->regs.eflags = regs->eflags;
+	dump->regs.esp = regs->rsp;
+	dump->regs.ss = regs->ss;
+
+#if 1 /* FIXME */
+	dump->u_fpvalid = 0;
+#else
+	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
+#endif
+}
+
+static struct linux_binfmt aout_format = {
+	.module		= THIS_MODULE,
+	.load_binary	= load_aout_binary,
+	.load_shlib	= load_aout_library,
+	.core_dump	= aout_core_dump,
+	.min_coredump	= PAGE_SIZE
+};
+
+static void set_brk(unsigned long start, unsigned long end)
+{
+	start = PAGE_ALIGN(start);
+	end = PAGE_ALIGN(end);
+	if (end <= start)
+		return;
+	do_brk(start, end - start);
+}
+
+/*
+ * These are the only things you should do on a core-file: use only these
+ * macros to write out all the necessary info.
+ */
+
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+
+#define DUMP_WRITE(addr, nr)	\
+	if (!dump_write(file, (void *)(addr), (nr))) \
+		goto end_coredump;
+
+#define DUMP_SEEK(offset) \
+if (file->f_op->llseek) { \
+	if (file->f_op->llseek(file,(offset),0) != (offset)) \
+ 		goto end_coredump; \
+} else file->f_pos = (offset)
+
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently only a stub-function.
+ *
+ * Note that setuid/setgid files won't make a core-dump if the uid/gid
+ * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable"
+ * field, which also makes sure the core-dumps won't be recursive if the
+ * dumping of the process results in another error..
+ */
+
+static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
+{
+	mm_segment_t fs;
+	int has_dumped = 0;
+	unsigned long dump_start, dump_size;
+	struct user32 dump;
+#       define START_DATA(u)	(u.u_tsize << PAGE_SHIFT)
+#       define START_STACK(u)   (u.start_stack)
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	has_dumped = 1;
+	current->flags |= PF_DUMPCORE;
+       	strncpy(dump.u_comm, current->comm, sizeof(current->comm));
+	dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
+	dump.signal = signr;
+	dump_thread32(regs, &dump);
+
+/* If the size of the dump file exceeds the rlimit, then see what would happen
+   if we wrote the stack, but not the data area.  */
+	if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
+	    current->rlim[RLIMIT_CORE].rlim_cur)
+		dump.u_dsize = 0;
+
+/* Make sure we have enough room to write the stack and data areas. */
+	if ((dump.u_ssize+1) * PAGE_SIZE >
+	    current->rlim[RLIMIT_CORE].rlim_cur)
+		dump.u_ssize = 0;
+
+/* make sure we actually have a data and stack area to dump */
+	set_fs(USER_DS);
+	if (verify_area(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+		dump.u_dsize = 0;
+	if (verify_area(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+		dump.u_ssize = 0;
+
+	set_fs(KERNEL_DS);
+/* struct user */
+	DUMP_WRITE(&dump,sizeof(dump));
+/* Now dump all of the user data.  Include malloced stuff as well */
+	DUMP_SEEK(PAGE_SIZE);
+/* now we start writing out the user space info */
+	set_fs(USER_DS);
+/* Dump the data area */
+	if (dump.u_dsize != 0) {
+		dump_start = START_DATA(dump);
+		dump_size = dump.u_dsize << PAGE_SHIFT;
+		DUMP_WRITE(dump_start,dump_size);
+	}
+/* Now prepare to dump the stack area */
+	if (dump.u_ssize != 0) {
+		dump_start = START_STACK(dump);
+		dump_size = dump.u_ssize << PAGE_SHIFT;
+		DUMP_WRITE(dump_start,dump_size);
+	}
+/* Finally dump the task struct.  Not be used by gdb, but could be useful */
+	set_fs(KERNEL_DS);
+	DUMP_WRITE(current,sizeof(*current));
+end_coredump:
+	set_fs(fs);
+	return has_dumped;
+}
+
+/*
+ * create_aout_tables() parses the env- and arg-strings in new user
+ * memory and creates the pointer tables from them, and puts their
+ * addresses on the "stack", returning the new stack pointer value.
+ */
+static u32 * create_aout_tables(char * p, struct linux_binprm * bprm)
+{
+	u32 *argv, *envp;
+	u32 * sp;
+	int argc = bprm->argc;
+	int envc = bprm->envc;
+
+	sp = (u32 *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p);
+	sp -= envc+1;
+	envp = (u32 *) sp;
+	sp -= argc+1;
+	argv = (u32 *) sp;
+	put_user((unsigned long) envp,--sp);
+	put_user((unsigned long) argv,--sp);
+	put_user(argc,--sp);
+	current->mm->arg_start = (unsigned long) p;
+	while (argc-->0) {
+		char c;
+		put_user((u32)(unsigned long)p,argv++);
+		do {
+			get_user(c,p++);
+		} while (c);
+	}
+	put_user(NULL,argv);
+	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+	while (envc-->0) {
+		char c;
+		put_user((u32)(unsigned long)p,envp++);
+		do {
+			get_user(c,p++);
+		} while (c);
+	}
+	put_user(NULL,envp);
+	current->mm->env_end = (unsigned long) p;
+	return sp;
+}
+
+/*
+ * These are the functions used to load a.out style executables and shared
+ * libraries.  There is no binary dependent code anywhere else.
+ */
+
+static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+	struct exec ex;
+	unsigned long error;
+	unsigned long fd_offset;
+	unsigned long rlim;
+	int retval;
+
+	ex = *((struct exec *) bprm->buf);		/* exec-header */
+	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+	    i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+		return -ENOEXEC;
+	}
+
+	fd_offset = N_TXTOFF(ex);
+
+	/* Check initial limits. This avoids letting people circumvent
+	 * size limits imposed on them by creating programs with large
+	 * arrays in the data or bss.
+	 */
+	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim >= RLIM_INFINITY)
+		rlim = ~0;
+	if (ex.a_data + ex.a_bss > rlim)
+		return -ENOMEM;
+
+	/* Flush all traces of the currently running executable */
+	retval = flush_old_exec(bprm);
+	if (retval)
+		return retval;
+
+	regs->cs = __USER32_CS; 
+	regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
+		regs->r13 = regs->r14 = regs->r15 = 0;
+	set_thread_flag(TIF_IA32); 
+
+	/* OK, This is the point of no return */
+	set_personality(PER_LINUX);
+
+	current->mm->end_code = ex.a_text +
+		(current->mm->start_code = N_TXTADDR(ex));
+	current->mm->end_data = ex.a_data +
+		(current->mm->start_data = N_DATADDR(ex));
+	current->mm->brk = ex.a_bss +
+		(current->mm->start_brk = N_BSSADDR(ex));
+	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+
+	current->mm->rss = 0;
+	current->mm->mmap = NULL;
+	compute_creds(bprm);
+ 	current->flags &= ~PF_FORKNOEXEC;
+
+	if (N_MAGIC(ex) == OMAGIC) {
+		unsigned long text_addr, map_size;
+		loff_t pos;
+
+		text_addr = N_TXTADDR(ex);
+
+		pos = 32;
+		map_size = ex.a_text+ex.a_data;
+
+		error = do_brk(text_addr & PAGE_MASK, map_size);
+		if (error != (text_addr & PAGE_MASK)) {
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+
+		error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
+			  ex.a_text+ex.a_data, &pos);
+		if ((signed long)error < 0) {
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+			 
+		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
+	} else {
+#ifdef WARN_OLD
+		static unsigned long error_time, error_time2;
+		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
+		    (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ)
+		{
+			printk(KERN_NOTICE "executable not page aligned\n");
+			error_time2 = jiffies;
+		}
+
+		if ((fd_offset & ~PAGE_MASK) != 0 &&
+		    (jiffies-error_time) > 5*HZ)
+		{
+			printk(KERN_WARNING 
+			       "fd_offset is not page aligned. Please convert program: %s\n",
+			       bprm->file->f_dentry->d_name.name);
+			error_time = jiffies;
+		}
+#endif
+
+		if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+			loff_t pos = fd_offset;
+			do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+					ex.a_text+ex.a_data, &pos);
+			flush_icache_range((unsigned long) N_TXTADDR(ex),
+					   (unsigned long) N_TXTADDR(ex) +
+					   ex.a_text+ex.a_data);
+			goto beyond_if;
+		}
+
+		down_write(&current->mm->mmap_sem);
+		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+			PROT_READ | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT,
+			fd_offset);
+		up_write(&current->mm->mmap_sem);
+
+		if (error != N_TXTADDR(ex)) {
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+
+		down_write(&current->mm->mmap_sem);
+ 		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+				PROT_READ | PROT_WRITE | PROT_EXEC,
+				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT,
+				fd_offset + ex.a_text);
+		up_write(&current->mm->mmap_sem);
+		if (error != N_DATADDR(ex)) {
+			send_sig(SIGKILL, current, 0);
+			return error;
+		}
+	}
+beyond_if:
+	set_binfmt(&aout_format);
+
+	set_brk(current->mm->start_brk, current->mm->brk);
+
+	retval = ia32_setup_arg_pages(bprm); 
+	if (retval < 0) { 
+		/* Someone check-me: is this error path enough? */ 
+		send_sig(SIGKILL, current, 0); 
+		return retval;
+	}
+
+	current->mm->start_stack =
+		(unsigned long) create_aout_tables((char *) bprm->p, bprm);
+	/* start thread */
+	asm volatile("movl %0,%%fs" :: "r" (0)); \
+	asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS));
+	load_gs_index(0); 
+	(regs)->rip = ex.a_entry;
+	(regs)->rsp = current->mm->start_stack;
+	(regs)->eflags = 0x200;
+	(regs)->cs = __USER32_CS;
+	(regs)->ss = __USER32_DS;
+	set_fs(USER_DS);
+	if (unlikely(current->ptrace & PT_PTRACED)) {
+		if (current->ptrace & PT_TRACE_EXEC)
+			ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
+		else
+			send_sig(SIGTRAP, current, 0);
+	}
+	return 0;
+}
+
+static int load_aout_library(struct file *file)
+{
+	struct inode * inode;
+	unsigned long bss, start_addr, len;
+	unsigned long error;
+	int retval;
+	struct exec ex;
+
+	inode = file->f_dentry->d_inode;
+
+	retval = -ENOEXEC;
+	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+	if (error != sizeof(ex))
+		goto out;
+
+	/* We come in here for the regular a.out style of shared libraries */
+	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
+	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
+	    i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+		goto out;
+	}
+
+	if (N_FLAGS(ex))
+		goto out;
+
+	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
+	   this off to get the starting address for the page */
+
+	start_addr =  ex.a_entry & 0xfffff000;
+
+	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
+		loff_t pos = N_TXTOFF(ex);
+
+#ifdef WARN_OLD
+		static unsigned long error_time;
+		if ((jiffies-error_time) > 5*HZ)
+		{
+			printk(KERN_WARNING 
+			       "N_TXTOFF is not page aligned. Please convert library: %s\n",
+			       file->f_dentry->d_name.name);
+			error_time = jiffies;
+		}
+#endif
+
+		do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		
+		file->f_op->read(file, (char *)start_addr,
+			ex.a_text + ex.a_data, &pos);
+		flush_icache_range((unsigned long) start_addr,
+				   (unsigned long) start_addr + ex.a_text + ex.a_data);
+
+		retval = 0;
+		goto out;
+	}
+	/* Now use mmap to map the library into memory. */
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+			PROT_READ | PROT_WRITE | PROT_EXEC,
+			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
+			N_TXTOFF(ex));
+	up_write(&current->mm->mmap_sem);
+	retval = error;
+	if (error != start_addr)
+		goto out;
+
+	len = PAGE_ALIGN(ex.a_text + ex.a_data);
+	bss = ex.a_text + ex.a_data + ex.a_bss;
+	if (bss > len) {
+		error = do_brk(start_addr + len, bss - len);
+		retval = error;
+		if (error != start_addr + len)
+			goto out;
+	}
+	retval = 0;
+out:
+	return retval;
+}
+
+static int __init init_aout_binfmt(void)
+{
+	return register_binfmt(&aout_format);
+}
+
+static void __exit exit_aout_binfmt(void)
+{
+	unregister_binfmt(&aout_format);
+}
+
+module_init(init_aout_binfmt);
+module_exit(exit_aout_binfmt);
+MODULE_LICENSE("GPL");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/ia32/ia32_signal.c 001-linus.patch/arch/x86_64/ia32/ia32_signal.c
--- 000-virgin/arch/x86_64/ia32/ia32_signal.c	Wed Dec 17 18:59:45 2003
+++ 001-linus.patch/arch/x86_64/ia32/ia32_signal.c	Tue Dec 30 16:38:57 2003
@@ -46,25 +46,25 @@ void signal_fault(struct pt_regs *regs, 
 
 static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
 {
+	int err;
 	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
 		return -EFAULT;
-	if (from->si_code < 0) { 
-		/* the only field that's different is the alignment
-		   of the pointer in sigval_t. Move that 4 bytes down including
-		   padding. */
-		memmove(&((siginfo_t32 *)&from)->si_int,
-			&from->si_int, 
-			sizeof(siginfo_t) - offsetof(siginfo_t, si_int));
-		/* last 4 bytes stay the same */
-		return __copy_to_user(to, from, sizeof(siginfo_t32));
-	} else {
-		int err;
 
-		/* If you change siginfo_t structure, please be sure
+	/* If you change siginfo_t structure, please make sure that
 		   this code is fixed accordingly.
 		   It should never copy any pad contained in the structure
 		   to avoid security leaks, but must copy the generic
 		   3 ints plus the relevant union member.  */
+
+	if (from->si_code < 0) {
+		err = __put_user(from->si_signo, &to->si_signo);
+		err |= __put_user(from->si_errno, &to->si_errno);
+		err |= __put_user(from->si_code, &to->si_code);
+		err |= __put_user(from->_sifields._rt._pid, &to->_sifields._rt._pid);
+		err |= __put_user(from->_sifields._rt._uid, &to->_sifields._rt._uid);
+		err |= __put_user((u32)(u64)from->_sifields._rt._sigval.sival_ptr,
+				  &to->_sifields._rt._sigval.sival_ptr);
+	} else {
 		err = __put_user(from->si_signo, &to->si_signo);
 		err |= __put_user(from->si_errno, &to->si_errno);
 		err |= __put_user(from->si_code, &to->si_code);
@@ -86,8 +86,8 @@ static int ia32_copy_siginfo_to_user(sig
 			break;
 		/* case __SI_RT: This is not generated by the kernel as of now.  */
 		}
-		return err;
 	}
+	return err;
 }
 
 asmlinkage long
@@ -173,6 +173,9 @@ ia32_restore_sigcontext(struct pt_regs *
 {
 	unsigned int err = 0;
 	
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
 #if DEBUG_SIG
 	printk("SIG restore_sigcontext: sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
 		sc, sc->err, sc->eip, sc->cs, sc->eflags);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/ia32/ia32entry.S 001-linus.patch/arch/x86_64/ia32/ia32entry.S
--- 000-virgin/arch/x86_64/ia32/ia32entry.S	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/x86_64/ia32/ia32entry.S	Tue Dec 30 16:38:57 2003
@@ -221,7 +221,7 @@ ia32_sys_call_table:
 	.quad sys_chmod		/* 15 */
 	.quad sys_lchown16
 	.quad ni_syscall			/* old break syscall holder */
-	.quad ni_syscall	/* (old)stat */ 
+	.quad sys_stat
 	.quad sys32_lseek
 	.quad sys_getpid		/* 20 */
 	.quad sys_mount	/* mount  */
@@ -231,7 +231,7 @@ ia32_sys_call_table:
 	.quad sys_stime		/* stime */		/* 25 */
 	.quad sys32_ptrace	/* ptrace */
 	.quad sys_alarm		/* XXX sign extension??? */ 
-	.quad ni_syscall	/* (old)fstat */
+	.quad sys_fstat	/* (old)fstat */
 	.quad sys_pause
 	.quad compat_sys_utime	/* 30 */
 	.quad ni_syscall	/* old stty syscall holder */
@@ -287,7 +287,7 @@ ia32_sys_call_table:
 	.quad sys_setgroups16
 	.quad sys32_old_select
 	.quad sys_symlink
-	.quad ni_syscall	/* (old)lstat */
+	.quad sys_lstat
 	.quad sys_readlink		/* 85 */
 	.quad sys_uselib
 	.quad sys_swapon
@@ -396,8 +396,8 @@ ia32_sys_call_table:
 	.quad stub32_vfork            /* 190 */
 	.quad compat_sys_getrlimit
 	.quad sys32_mmap2
-	.quad sys_truncate
-	.quad sys_ftruncate
+	.quad sys32_truncate64
+	.quad sys32_ftruncate64
 	.quad sys32_stat64		/* 195 */
 	.quad sys32_lstat64
 	.quad sys32_fstat64
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/ia32/sys_ia32.c 001-linus.patch/arch/x86_64/ia32/sys_ia32.c
--- 000-virgin/arch/x86_64/ia32/sys_ia32.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/x86_64/ia32/sys_ia32.c	Tue Dec 30 16:38:57 2003
@@ -110,6 +110,21 @@ int cp_compat_stat(struct kstat *kbuf, s
 	return 0;
 }
 
+extern long sys_truncate(char *, loff_t);
+extern long sys_ftruncate(int, loff_t);
+
+asmlinkage long
+sys32_truncate64(char * filename, unsigned long offset_low, unsigned long offset_high)
+{
+       return sys_truncate(filename, ((loff_t) offset_high << 32) | offset_low);
+}
+
+asmlinkage long
+sys32_ftruncate64(unsigned int fd, unsigned long offset_low, unsigned long offset_high)
+{
+       return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
+}
+
 /* Another set for IA32/LFS -- x86_64 struct stat is different due to 
    support for 64bit inode numbers. */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/Makefile 001-linus.patch/arch/x86_64/kernel/Makefile
--- 000-virgin/arch/x86_64/kernel/Makefile	Wed Dec 17 18:59:16 2003
+++ 001-linus.patch/arch/x86_64/kernel/Makefile	Tue Dec 30 16:38:57 2003
@@ -25,6 +25,6 @@ obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o
 obj-$(CONFIG_MODULES)		+= module.o
 
 bootflag-y			+= ../../i386/kernel/bootflag.o
-cpuid-$(CONFIG_X86_CPUID)	+= ../../i386/kernel/cpuid.o
+cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
 
 obj-$(CONFIG_CPU_FREQ)	+=	cpufreq/
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/irq.c 001-linus.patch/arch/x86_64/kernel/irq.c
--- 000-virgin/arch/x86_64/kernel/irq.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/x86_64/kernel/irq.c	Tue Dec 30 16:38:57 2003
@@ -138,17 +138,19 @@ atomic_t irq_mis_count;
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
 	unsigned long flags;
 
-	seq_printf(p, "           ");
-	for (j=0; j<NR_CPUS; j++)
-		if (cpu_online(j))
-		seq_printf(p, "CPU%d       ",j);
-	seq_putc(p, '\n');
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
@@ -170,25 +172,26 @@ int show_interrupts(struct seq_file *p, 
 		seq_putc(p, '\n');
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	seq_printf(p, "NMI: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-		seq_printf(p, "%10u ", cpu_pda[j].__nmi_count);
-	seq_putc(p, '\n');
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", cpu_pda[j].__nmi_count);
+		seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
-	seq_printf(p, "LOC: ");
-	for (j = 0; j < NR_CPUS; j++)
-		if (cpu_online(j))
-		seq_printf(p, "%10u ", cpu_pda[j].apic_timer_irqs);
-	seq_putc(p, '\n');
+		seq_printf(p, "LOC: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", cpu_pda[j].apic_timer_irqs);
+		seq_putc(p, '\n');
 #endif
-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 #ifdef CONFIG_X86_IO_APIC
 #ifdef APIC_MISMATCH_DEBUG
-	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
 #endif
+	}
 	return 0;
 }
 
@@ -801,47 +804,6 @@ int setup_irq(unsigned int irq, struct i
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 
-#define HEX_DIGITS (2*sizeof(cpumask_t))
-
-static unsigned int parse_hex_value (const char *buffer,
-		unsigned long count, cpumask_t *ret)
-{
-	unsigned char hexnum [HEX_DIGITS];
-	cpumask_t value = CPU_MASK_NONE;
-	unsigned i;
-
-	if (!count)
-		return -EINVAL;
-	if (count > HEX_DIGITS)
-		count = HEX_DIGITS;
-	if (copy_from_user(hexnum, buffer, count))
-		return -EFAULT;
-
-	/*
-	 * Parse the first 8 characters as a hex string, any non-hex char
-	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-	 */
-
-	for (i = 0; i < count; i++) {
-		unsigned int k, c = hexnum[i];
-
-		switch (c) {
-			case '0' ... '9': c -= '0'; break;
-			case 'a' ... 'f': c -= 'a'-10; break;
-			case 'A' ... 'F': c -= 'A'-10; break;
-		default:
-			goto out;
-		}
-		cpus_shift_left(value, value, 4);
-		for (k = 0; k < 4; ++k)
-			if (c & (1 << k))
-				cpu_set(k, value);
-	}
-out:
-	*ret = value;
-	return 0;
-}
-
 #ifdef CONFIG_SMP
 
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
@@ -850,19 +812,10 @@ static cpumask_t irq_affinity [NR_IRQS] 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	int k, len;
-	cpumask_t tmp = irq_affinity[(long)data];
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
 		return -EINVAL;
-
-	for (k = len = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -875,7 +828,7 @@ static int irq_affinity_write_proc (stru
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
@@ -897,20 +850,10 @@ static int irq_affinity_write_proc (stru
 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
-	cpumask_t tmp, *mask = (cpumask_t *) data;
-	int k, len;
-
-	if (count < HEX_DIGITS+1)
+	int len = cpumask_snprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
 		return -EINVAL;
-
-	tmp = *mask;
-	for (k = len = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(page, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		page += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-	len += sprintf(page, "\n");
+	len += sprintf(page + len, "\n");
 	return len;
 }
 
@@ -920,7 +863,7 @@ static int prof_cpu_mask_write_proc (str
 	unsigned long full_count = count, err;
 	cpumask_t new_value, *mask = (cpumask_t *)data;
 
-	err = parse_hex_value(buffer, count, &new_value);
+	err = cpumask_parse(buffer, count, new_value);
 	if (err)
 		return err;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/mpparse.c 001-linus.patch/arch/x86_64/kernel/mpparse.c
--- 000-virgin/arch/x86_64/kernel/mpparse.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/arch/x86_64/kernel/mpparse.c	Tue Dec 30 16:38:57 2003
@@ -226,7 +226,7 @@ static int __init smp_read_mpc(struct mp
 	unsigned char *mpt=((unsigned char *)mpc)+count;
 
 	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
-		panic("SMP mptable: bad signature [%c%c%c%c]!\n",
+		printk("SMP mptable: bad signature [%c%c%c%c]!\n",
 			mpc->mpc_signature[0],
 			mpc->mpc_signature[1],
 			mpc->mpc_signature[2],
@@ -234,7 +234,7 @@ static int __init smp_read_mpc(struct mp
 		return 0;
 	}
 	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
-		panic("SMP mptable: checksum error!\n");
+		printk("SMP mptable: checksum error!\n");
 		return 0;
 	}
 	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/pci-gart.c 001-linus.patch/arch/x86_64/kernel/pci-gart.c
--- 000-virgin/arch/x86_64/kernel/pci-gart.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/arch/x86_64/kernel/pci-gart.c	Tue Dec 30 16:38:57 2003
@@ -44,12 +44,13 @@ static int no_agp; 
 #ifdef CONFIG_IOMMU_DEBUG
 int panic_on_overflow = 1; 
 int force_iommu = 1;
-int sac_force_size = 0; 
 #else
-int panic_on_overflow = 1; /* for testing */
+int panic_on_overflow = 0;
 int force_iommu = 0;
-int sac_force_size = 256*1024*1024;
 #endif
+int iommu_merge = 0; 
+int iommu_sac_force = 0; 
+int iommu_fullflush = 1;
 
 /* Allocation bitmap for the remapping area */ 
 static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED;
@@ -125,7 +126,7 @@ static void free_iommu(unsigned long off
 /* 
  * Use global flush state to avoid races with multiple flushers.
  */
-static void __flush_gart(struct pci_dev *dev)
+static void flush_gart(struct pci_dev *dev)
 { 
 	unsigned long flags;
 	int bus = dev ? dev->bus->number : -1;
@@ -134,13 +135,17 @@ static void __flush_gart(struct pci_dev 
 	int i;
 
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
-	/* recheck flush count inside lock */
-	if (need_flush) { 
+	if (need_flush || iommu_fullflush) { 
 		for (i = 0; northbridges[i]; i++) {
+			u32 w;
 			if (bus >= 0 && !(cpu_isset_const(i, bus_cpumask)))
 				continue;
 			pci_write_config_dword(northbridges[i], 0x9c, 
 					       northbridge_flush_word[i] | 1); 
+			/* Make sure the hardware actually executed the flush. */
+			do { 
+				pci_read_config_dword(northbridges[i], 0x9c, &w);
+			} while (w & 1);
 			flushed++;
 		} 
 		if (!flushed) 
@@ -150,12 +155,6 @@ static void __flush_gart(struct pci_dev 
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
 } 
 
-static inline void flush_gart(struct pci_dev *dev)
-{ 
-	if (need_flush)
-		__flush_gart(dev);
-} 
-
 /* 
  * Allocate memory for a consistent mapping.
  * All mappings are consistent here, so this is just a wrapper around
@@ -174,11 +173,16 @@ void *pci_alloc_consistent(struct pci_de
 	} else {
 		dma_mask = hwdev->consistent_dma_mask; 
 	}
+
 	if (dma_mask == 0) 
 		dma_mask = 0xffffffff; 
 	if (dma_mask < 0xffffffff || no_iommu)
 		gfp |= GFP_DMA;
 
+	/* Kludge to make it bug-to-bug compatible with i386. i386
+	   uses the normal dma_mask for alloc_consistent. */
+	dma_mask &= hwdev->dma_mask;
+
 	memory = (void *)__get_free_pages(gfp, get_order(size));
 	if (memory == NULL) {
 		return NULL; 
@@ -394,7 +398,9 @@ static int __pci_map_cont(struct scatter
 	
 	for (i = start; i < stopat; i++) {
 		struct scatterlist *s = &sg[i];
-		unsigned long start_addr = s->dma_address;
+		unsigned long pages, addr;
+		unsigned long phys_addr = s->dma_address;
+		
 		BUG_ON(i > start && s->offset);
 		if (i == start) {
 			*sout = *s; 
@@ -403,8 +409,10 @@ static int __pci_map_cont(struct scatter
 		} else { 
 			sout->length += s->length; 
 		}
-		unsigned long addr = start_addr;
-		while (addr < start_addr + s->length) { 
+
+		addr = phys_addr;
+		pages = to_pages(s->offset, s->length); 
+		while (pages--) { 
 			iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); 
 			SET_LEAK(iommu_page);
 			addr += PAGE_SIZE;
@@ -437,7 +445,7 @@ int pci_map_sg(struct pci_dev *dev, stru
 	int out;
 	int start;
 	unsigned long pages = 0;
-	int need = 0;
+	int need = 0, nextneed;
 
 	unsigned long size = 0; 
 
@@ -453,13 +461,14 @@ int pci_map_sg(struct pci_dev *dev, stru
 		BUG_ON(s->length == 0); 
 
 		size += s->length; 
+		nextneed = need_iommu(dev, addr, s->length); 
 
 		/* Handle the previous not yet processed entries */
 		if (i > start) {
 			struct scatterlist *ps = &sg[i-1];
 			/* Can only merge when the last chunk ends on a page 
-			   boundary. */
-			if (!force_iommu || !need || (i-1 > start && ps->offset) ||
+			   boundary and the new one doesn't have an offset. */
+			if (!iommu_merge || !nextneed || !need || s->offset ||
 			    (ps->offset + ps->length) % PAGE_SIZE) { 
 				if (pci_map_cont(sg, start, i, sg+out, pages, 
 						 need) < 0)
@@ -470,7 +479,7 @@ int pci_map_sg(struct pci_dev *dev, stru
 			}
 	}
 
-		need = need_iommu(dev, addr, s->length); 
+		need = nextneed;
 		pages += to_pages(s->offset, s->length);
 	}
 	if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0)
@@ -544,14 +553,12 @@ int pci_dma_supported(struct pci_dev *de
 
 	   Problem with this is that if we overflow the IOMMU area
 	   and return DAC as fallback address the device may not handle it correctly.
-	   As a compromise we only do this if the IOMMU area is >= 256MB 
-	   which should make overflow unlikely enough.
 	   
 	   As a special case some controllers have a 39bit address mode 
 	   that is as efficient as 32bit (aic79xx). Don't force SAC for these.
 	   Assume all masks <= 40 bits are of this type. Normally this doesn't
 	   make any difference, but gives more gentle handling of IOMMU overflow. */
-	if (force_iommu && (mask > 0xffffffffffULL) && (iommu_size >= sac_force_size)){ 
+	if (iommu_sac_force && (mask >= 0xffffffffffULL)) { 
 		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask);
 		return 0; 
 	}
@@ -680,7 +687,7 @@ static int __init pci_iommu_init(void)
 	unsigned long iommu_start;
 	struct pci_dev *dev;
 		
-#ifndef CONFIG_AGP_AMD_8151
+#ifndef CONFIG_AGP_AMD64
 	no_agp = 1; 
 #else
 	/* Makefile puts PCI initialization via subsys_initcall first. */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/pci-nommu.c 001-linus.patch/arch/x86_64/kernel/pci-nommu.c
--- 000-virgin/arch/x86_64/kernel/pci-nommu.c	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/arch/x86_64/kernel/pci-nommu.c	Tue Dec 30 16:38:57 2003
@@ -4,6 +4,8 @@
 #include <linux/string.h>
 #include <asm/proto.h>
 
+int iommu_merge = 0;
+
 /* 
  * Dummy IO MMU functions
  */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/signal.c 001-linus.patch/arch/x86_64/kernel/signal.c
--- 000-virgin/arch/x86_64/kernel/signal.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/arch/x86_64/kernel/signal.c	Tue Dec 30 16:38:57 2003
@@ -93,6 +93,8 @@ restore_sigcontext(struct pt_regs *regs,
 {
 	unsigned int err = 0;
 
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->x)
 
@@ -355,8 +357,6 @@ handle_signal(unsigned long sig, siginfo
 		/* If so, check system call restarting.. */
 		switch (regs->rax) {
 		        case -ERESTART_RESTARTBLOCK:
-				current_thread_info()->restart_block.fn = do_no_restart_syscall;
-				/* FALL THROUGH */
 			case -ERESTARTNOHAND:
 				regs->rax = -EINTR;
 				break;
@@ -371,10 +371,6 @@ handle_signal(unsigned long sig, siginfo
 				regs->rax = regs->orig_rax;
 				regs->rip -= 2;
 		}
-		if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK){
-			regs->rax = __NR_restart_syscall;
- 			regs->rip -= 2;
- 		}		
 	}
 
 #ifdef CONFIG_IA32_EMULATION
@@ -453,6 +449,10 @@ int do_signal(struct pt_regs *regs, sigs
 			regs->rax = regs->orig_rax;
 			regs->rip -= 2;
 		}
+		if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
+			regs->rax = __NR_restart_syscall;
+			regs->rip -= 2;
+		}
 	}
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/kernel/traps.c 001-linus.patch/arch/x86_64/kernel/traps.c
--- 000-virgin/arch/x86_64/kernel/traps.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/arch/x86_64/kernel/traps.c	Tue Dec 30 16:38:57 2003
@@ -218,8 +218,12 @@ void show_stack(struct task_struct *tsk,
 	// debugging aid: "show_stack(NULL, NULL);" prints the
 	// back trace for this cpu.
 
-	if(rsp==NULL)
-		rsp=(unsigned long*)&rsp;
+	if (rsp == NULL) {
+		if (tsk)
+			rsp = (unsigned long *)tsk->thread.rsp;
+		else
+			rsp = (unsigned long *)&rsp;
+	}
 
 	stack = rsp;
 	for(i=0; i < kstack_depth_to_print; i++) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/arch/x86_64/mm/fault.c 001-linus.patch/arch/x86_64/mm/fault.c
--- 000-virgin/arch/x86_64/mm/fault.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/arch/x86_64/mm/fault.c	Tue Dec 30 16:38:57 2003
@@ -73,6 +73,9 @@ static int is_prefetch(struct pt_regs *r
 	if (regs->cs & (1<<2))
 		return 0;
 
+	if ((regs->cs & 3) != 0 && regs->rip >= TASK_SIZE)
+		return 0;
+
 	while (scan_more && instr < max_instr) { 
 		unsigned char opcode;
 		unsigned char instr_hi;
@@ -337,7 +340,8 @@ bad_area_nosemaphore:
 		}
        
 		tsk->thread.cr2 = address;
-		tsk->thread.error_code = error_code;
+		/* Kernel addresses are always protection faults */
+		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
 		tsk->thread.trap_no = 14;
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/crypto/tcrypt.c 001-linus.patch/crypto/tcrypt.c
--- 000-virgin/crypto/tcrypt.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/crypto/tcrypt.c	Tue Dec 30 16:38:57 2003
@@ -6,2384 +6,409 @@
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) 
- * any later version.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <asm/scatterlist.h>
-#include <linux/string.h>
-#include <linux/crypto.h>
-#include <linux/highmem.h>
-#include "tcrypt.h"
-
-/*
- * Need to kmalloc() memory for testing kmap().
- */
-#define TVMEMSIZE	4096
-#define XBUFSIZE	32768
-
-/*
- * Indexes into the xbuf to simulate cross-page access.
- */
-#define IDX1		37
-#define IDX2		32400
-#define IDX3		1
-#define IDX4		8193
-#define IDX5		22222
-#define IDX6		17101
-#define IDX7		27333
-#define IDX8		3000
-
-static int mode;
-static char *xbuf;
-static char *tvmem;
-
-static char *check[] = {
-	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
-	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"deflate", NULL
-};
-
-static void
-hexdump(unsigned char *buf, unsigned int len)
-{
-	while (len--)
-		printk("%02x", *buf++);
-
-	printk("\n");
-}
-
-static void
-test_md5(void)
-{
-	char *p;
-	unsigned int i;
-	struct scatterlist sg[2];
-	char result[128];
-	struct crypto_tfm *tfm;
-	struct md5_testvec *md5_tv;
-	unsigned int tsize;
-
-	printk("\ntesting md5\n");
-
-	tsize = sizeof (md5_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, md5_tv_template, tsize);
-	md5_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("md5", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for md5\n");
-		return;
-	}
-
-	for (i = 0; i < MD5_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = md5_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(md5_tv[i].plaintext);
-
-		crypto_digest_init(tfm);
-		crypto_digest_update(tfm, sg, 1);
-		crypto_digest_final(tfm, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, md5_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	printk("\ntesting md5 across pages\n");
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-	memcpy(&xbuf[IDX1], "abcdefghijklm", 13);
-	memcpy(&xbuf[IDX2], "nopqrstuvwxyz", 13);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 13;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 13;
-
-	memset(result, 0, sizeof (result));
-	crypto_digest_digest(tfm, sg, 2, result);
-	hexdump(result, crypto_tfm_alg_digestsize(tfm));
-
-	printk("%s\n",
-	       memcmp(result, md5_tv[4].digest,
-		      crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-	crypto_free_tfm(tfm);
-}
-
-#ifdef CONFIG_CRYPTO_HMAC
-static void
-test_hmac_md5(void)
-{
-	char *p;
-	unsigned int i, klen;
-	struct scatterlist sg[2];
-	char result[128];
-	struct crypto_tfm *tfm;
-	struct hmac_md5_testvec *hmac_md5_tv;
-	unsigned int tsize;
-
-	tfm = crypto_alloc_tfm("md5", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for md5\n");
-		return;
-	}
-
-	printk("\ntesting hmac_md5\n");
-	
-	tsize = sizeof (hmac_md5_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-
-	memcpy(tvmem, hmac_md5_tv_template, tsize);
-	hmac_md5_tv = (void *) tvmem;
-
-	for (i = 0; i < HMAC_MD5_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = hmac_md5_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(hmac_md5_tv[i].plaintext);
-
-		klen = strlen(hmac_md5_tv[i].key);
-		crypto_hmac(tfm, hmac_md5_tv[i].key, &klen, sg, 1, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, hmac_md5_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	printk("\ntesting hmac_md5 across pages\n");
-
-	memset(xbuf, 0, XBUFSIZE);
-
-	memcpy(&xbuf[IDX1], "what do ya want ", 16);
-	memcpy(&xbuf[IDX2], "for nothing?", 12);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 16;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 12;
-
-	memset(result, 0, sizeof (result));
-	klen = strlen(hmac_md5_tv[7].key);
-	crypto_hmac(tfm, hmac_md5_tv[7].key, &klen, sg, 2, result);
-	hexdump(result, crypto_tfm_alg_digestsize(tfm));
-
-	printk("%s\n",
-	       memcmp(result, hmac_md5_tv[7].digest,
-		      crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-out:
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_hmac_sha1(void)
-{
-	char *p;
-	unsigned int i, klen;
-	struct crypto_tfm *tfm;
-	struct hmac_sha1_testvec *hmac_sha1_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA1_DIGEST_SIZE];
-
-	tfm = crypto_alloc_tfm("sha1", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha1\n");
-		return;
-	}
-
-	printk("\ntesting hmac_sha1\n");
-
-	tsize = sizeof (hmac_sha1_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-
-	memcpy(tvmem, hmac_sha1_tv_template, tsize);
-	hmac_sha1_tv = (void *) tvmem;
-
-	for (i = 0; i < HMAC_SHA1_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = hmac_sha1_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(hmac_sha1_tv[i].plaintext);
-
-		klen = strlen(hmac_sha1_tv[i].key);
-		
-		crypto_hmac(tfm, hmac_sha1_tv[i].key, &klen, sg, 1, result);
-
-		hexdump(result, sizeof (result));
-		printk("%s\n",
-		       memcmp(result, hmac_sha1_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	printk("\ntesting hmac_sha1 across pages\n");
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-
-	memcpy(&xbuf[IDX1], "what do ya want ", 16);
-	memcpy(&xbuf[IDX2], "for nothing?", 12);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 16;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 12;
-
-	memset(result, 0, sizeof (result));
-	klen = strlen(hmac_sha1_tv[7].key);
-	crypto_hmac(tfm, hmac_sha1_tv[7].key, &klen, sg, 2, result);
-	hexdump(result, crypto_tfm_alg_digestsize(tfm));
-
-	printk("%s\n",
-	       memcmp(result, hmac_sha1_tv[7].digest,
-		      crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-out:
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_hmac_sha256(void)
-{
-	char *p;
-	unsigned int i, klen;
-	struct crypto_tfm *tfm;
-	struct hmac_sha256_testvec *hmac_sha256_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA256_DIGEST_SIZE];
-
-	tfm = crypto_alloc_tfm("sha256", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha256\n");
-		return;
-	}
-
-	printk("\ntesting hmac_sha256\n");
-
-	tsize = sizeof (hmac_sha256_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-
-	memcpy(tvmem, hmac_sha256_tv_template, tsize);
-	hmac_sha256_tv = (void *) tvmem;
-
-	for (i = 0; i < HMAC_SHA256_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = hmac_sha256_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(hmac_sha256_tv[i].plaintext);
-
-		klen = strlen(hmac_sha256_tv[i].key);
-	
-		hexdump(hmac_sha256_tv[i].key, strlen(hmac_sha256_tv[i].key));
-		crypto_hmac(tfm, hmac_sha256_tv[i].key, &klen, sg, 1, result);
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, hmac_sha256_tv[i].digest,
-		       crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-	}
-
-out:
-	crypto_free_tfm(tfm);
-}
-
-#endif	/* CONFIG_CRYPTO_HMAC */
-
-static void
-test_md4(void)
-{
-	char *p;
-	unsigned int i;
-	struct scatterlist sg[1];
-	char result[128];
-	struct crypto_tfm *tfm;
-	struct md4_testvec *md4_tv;
-	unsigned int tsize;
-
-	printk("\ntesting md4\n");
-
-	tsize = sizeof (md4_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, md4_tv_template, tsize);
-	md4_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("md4", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for md4\n");
-		return;
-	}
-
-	for (i = 0; i < MD4_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = md4_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(md4_tv[i].plaintext);
-
-		crypto_digest_digest(tfm, sg, 1, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, md4_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_sha1(void)
-{
-	char *p;
-	unsigned int i;
-	struct crypto_tfm *tfm;
-	struct sha1_testvec *sha1_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA1_DIGEST_SIZE];
-
-	printk("\ntesting sha1\n");
-
-	tsize = sizeof (sha1_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, sha1_tv_template, tsize);
-	sha1_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("sha1", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha1\n");
-		return;
-	}
-
-	for (i = 0; i < SHA1_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = sha1_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(sha1_tv[i].plaintext);
-
-		crypto_digest_init(tfm);
-		crypto_digest_update(tfm, sg, 1);
-		crypto_digest_final(tfm, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, sha1_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	printk("\ntesting sha1 across pages\n");
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-	memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28);
-	memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 28;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 28;
-
-	memset(result, 0, sizeof (result));
-	crypto_digest_digest(tfm, sg, 2, result);
-	hexdump(result, crypto_tfm_alg_digestsize(tfm));
-	printk("%s\n",
-	       memcmp(result, sha1_tv[1].digest,
-		      crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_sha256(void)
-{
-	char *p;
-	unsigned int i;
-	struct crypto_tfm *tfm;
-	struct sha256_testvec *sha256_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA256_DIGEST_SIZE];
-
-	printk("\ntesting sha256\n");
-
-	tsize = sizeof (sha256_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, sha256_tv_template, tsize);
-	sha256_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("sha256", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha256\n");
-		return;
-	}
-
-	for (i = 0; i < SHA256_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = sha256_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(sha256_tv[i].plaintext);
-
-		crypto_digest_init(tfm);
-		crypto_digest_update(tfm, sg, 1);
-		crypto_digest_final(tfm, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, sha256_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	printk("\ntesting sha256 across pages\n");
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-	memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28);
-	memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 28;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 28;
-
-	memset(result, 0, sizeof (result));
-	crypto_digest_digest(tfm, sg, 2, result);
-	hexdump(result, crypto_tfm_alg_digestsize(tfm));
-	printk("%s\n",
-	       memcmp(result, sha256_tv[1].digest,
-		      crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
-		     
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_sha384(void)
-{
-	char *p;
-	unsigned int i;
-	struct crypto_tfm *tfm;
-	struct sha384_testvec *sha384_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA384_DIGEST_SIZE];
-
-	printk("\ntesting sha384\n");
-
-	tsize = sizeof (sha384_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, sha384_tv_template, tsize);
-	sha384_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("sha384", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha384\n");
-		return;
-	}
-
-	for (i = 0; i < SHA384_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = sha384_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(sha384_tv[i].plaintext);
-
-		crypto_digest_init(tfm);
-		crypto_digest_update(tfm, sg, 1);
-		crypto_digest_final(tfm, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, sha384_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	crypto_free_tfm(tfm);
-}
-
-static void
-test_sha512(void)
-{
-	char *p;
-	unsigned int i;
-	struct crypto_tfm *tfm;
-	struct sha512_testvec *sha512_tv;
-	struct scatterlist sg[2];
-	unsigned int tsize;
-	char result[SHA512_DIGEST_SIZE];
-
-	printk("\ntesting sha512\n");
-
-	tsize = sizeof (sha512_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, sha512_tv_template, tsize);
-	sha512_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("sha512", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for sha512\n");
-		return;
-	}
-
-	for (i = 0; i < SHA512_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-		memset(result, 0, sizeof (result));
-
-		p = sha512_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = strlen(sha512_tv[i].plaintext);
-
-		crypto_digest_init(tfm);
-		crypto_digest_update(tfm, sg, 1);
-		crypto_digest_final(tfm, result);
-
-		hexdump(result, crypto_tfm_alg_digestsize(tfm));
-		printk("%s\n",
-		       memcmp(result, sha512_tv[i].digest,
-			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-		       "pass");
-	}
-
-	crypto_free_tfm(tfm);
-}
-
-void
-test_des(void)
-{
-	unsigned int ret, i, len;
-	unsigned int tsize;
-	char *p, *q;
-	struct crypto_tfm *tfm;
-	char *key;
-	char res[8];
-	struct des_tv *des_tv;
-	struct scatterlist sg[8];
-
-	printk("\ntesting des encryption\n");
-
-	tsize = sizeof (des_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, des_enc_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("des", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for des (default ecb)\n");
-		return;
-	}
-
-	for (i = 0; i < DES_ENC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		key = des_tv[i].key;
-		tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
-
-		ret = crypto_cipher_setkey(tfm, key, 8);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!des_tv[i].fail)
-				goto out;
-		}
-
-		len = des_tv[i].len;
-
-		p = des_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-		ret = crypto_cipher_encrypt(tfm, sg, sg, len);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-
-	}
-
-	printk("\ntesting des ecb encryption across pages\n");
-
-	i = 5;
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	hexdump(key, 8);
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-	memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8);
-	memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 8;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 8;
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 16);
-	if (ret) {
-		printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
-
-	printk("\ntesting des ecb encryption chunking scenario A\n");
-
-	/*
-	 * Scenario A:
-	 * 
-	 *  F1       F2      F3
-	 *  [8 + 6]  [2 + 8] [8]
-	 *       ^^^^^^   ^
-	 *       a    b   c
-	 *
-	 * Chunking should begin at a, then end with b, and
-	 * continue encrypting at an offset of 2 until c.
-	 *
-	 */
-	i = 7;
-
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-
-	/* Frag 1: 8 + 6 */
-	memcpy(&xbuf[IDX3], des_tv[i].plaintext, 14);
-
-	/* Frag 2: 2 + 8 */
-	memcpy(&xbuf[IDX4], des_tv[i].plaintext + 14, 10);
-
-	/* Frag 3: 8 */
-	memcpy(&xbuf[IDX5], des_tv[i].plaintext + 24, 8);
-
-	p = &xbuf[IDX3];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 14;
-
-	p = &xbuf[IDX4];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 10;
-
-	p = &xbuf[IDX5];
-	sg[2].page = virt_to_page(p);
-	sg[2].offset = offset_in_page(p);
-	sg[2].length = 8;
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 32);
-
-	if (ret) {
-		printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 14);
-	printk("%s\n", memcmp(q, des_tv[i].result, 14) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 10);
-	printk("%s\n", memcmp(q, des_tv[i].result + 14, 10) ? "fail" : "pass");
-
-	printk("page 3\n");
-	q = kmap(sg[2].page) + sg[2].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result + 24, 8) ? "fail" : "pass");
-
-	printk("\ntesting des ecb encryption chunking scenario B\n");
-
-	/*
-	 * Scenario B:
-	 * 
-	 *  F1  F2  F3  F4
-	 *  [2] [1] [3] [2 + 8 + 8]
-	 */
-	i = 7;
-
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-
-	/* Frag 1: 2 */
-	memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2);
-
-	/* Frag 2: 1 */
-	memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 1);
-
-	/* Frag 3: 3 */
-	memcpy(&xbuf[IDX5], des_tv[i].plaintext + 3, 3);
-
-	/* Frag 4: 2 + 8 + 8 */
-	memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 18);
-
-	p = &xbuf[IDX3];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 2;
-
-	p = &xbuf[IDX4];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 1;
-
-	p = &xbuf[IDX5];
-	sg[2].page = virt_to_page(p);
-	sg[2].offset = offset_in_page(p);
-	sg[2].length = 3;
-
-	p = &xbuf[IDX6];
-	sg[3].page = virt_to_page(p);
-	sg[3].offset = offset_in_page(p);
-	sg[3].length = 18;
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 24);
-
-	if (ret) {
-		printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 2);
-	printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 1);
-	printk("%s\n", memcmp(q, des_tv[i].result + 2, 1) ? "fail" : "pass");
-
-	printk("page 3\n");
-	q = kmap(sg[2].page) + sg[2].offset;
-	hexdump(q, 3);
-	printk("%s\n", memcmp(q, des_tv[i].result + 3, 3) ? "fail" : "pass");
-
-	printk("page 4\n");
-	q = kmap(sg[3].page) + sg[3].offset;
-	hexdump(q, 18);
-	printk("%s\n", memcmp(q, des_tv[i].result + 6, 18) ? "fail" : "pass");
-
-	printk("\ntesting des ecb encryption chunking scenario C\n");
-
-	/*
-	 * Scenario B:
-	 * 
-	 *  F1  F2  F3  F4  F5
-	 *  [2] [2] [2] [2] [8]
-	 */
-	i = 7;
-
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-
-	/* Frag 1: 2 */
-	memcpy(&xbuf[IDX3], des_tv[i].plaintext, 2);
-
-	/* Frag 2: 2 */
-	memcpy(&xbuf[IDX4], des_tv[i].plaintext + 2, 2);
-
-	/* Frag 3: 2 */
-	memcpy(&xbuf[IDX5], des_tv[i].plaintext + 4, 2);
-
-	/* Frag 4: 2 */
-	memcpy(&xbuf[IDX6], des_tv[i].plaintext + 6, 2);
-
-	/* Frag 5: 8 */
-	memcpy(&xbuf[IDX7], des_tv[i].plaintext + 8, 8);
-
-	p = &xbuf[IDX3];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 2;
-
-	p = &xbuf[IDX4];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 2;
-
-	p = &xbuf[IDX5];
-	sg[2].page = virt_to_page(p);
-	sg[2].offset = offset_in_page(p);
-	sg[2].length = 2;
-
-	p = &xbuf[IDX6];
-	sg[3].page = virt_to_page(p);
-	sg[3].offset = offset_in_page(p);
-	sg[3].length = 2;
-
-	p = &xbuf[IDX7];
-	sg[4].page = virt_to_page(p);
-	sg[4].offset = offset_in_page(p);
-	sg[4].length = 8;
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 16);
-
-	if (ret) {
-		printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 2);
-	printk("%s\n", memcmp(q, des_tv[i].result, 2) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 2);
-	printk("%s\n", memcmp(q, des_tv[i].result + 2, 2) ? "fail" : "pass");
-
-	printk("page 3\n");
-	q = kmap(sg[2].page) + sg[2].offset;
-	hexdump(q, 2);
-	printk("%s\n", memcmp(q, des_tv[i].result + 4, 2) ? "fail" : "pass");
-
-	printk("page 4\n");
-	q = kmap(sg[3].page) + sg[3].offset;
-	hexdump(q, 2);
-	printk("%s\n", memcmp(q, des_tv[i].result + 6, 2) ? "fail" : "pass");
-
-	printk("page 5\n");
-	q = kmap(sg[4].page) + sg[4].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
-
-	printk("\ntesting des ecb encryption chunking scenario D\n");
-
-	/*
-	 * Scenario D, torture test, one byte per frag.
-	 */
-	i = 7;
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, XBUFSIZE);
-
-	xbuf[IDX1] = des_tv[i].plaintext[0];
-	xbuf[IDX2] = des_tv[i].plaintext[1];
-	xbuf[IDX3] = des_tv[i].plaintext[2];
-	xbuf[IDX4] = des_tv[i].plaintext[3];
-	xbuf[IDX5] = des_tv[i].plaintext[4];
-	xbuf[IDX6] = des_tv[i].plaintext[5];
-	xbuf[IDX7] = des_tv[i].plaintext[6];
-	xbuf[IDX8] = des_tv[i].plaintext[7];
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 1;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 1;
-
-	p = &xbuf[IDX3];
-	sg[2].page = virt_to_page(p);
-	sg[2].offset = offset_in_page(p);
-	sg[2].length = 1;
-
-	p = &xbuf[IDX4];
-	sg[3].page = virt_to_page(p);
-	sg[3].offset = offset_in_page(p);
-	sg[3].length = 1;
-
-	p = &xbuf[IDX5];
-	sg[4].page = virt_to_page(p);
-	sg[4].offset = offset_in_page(p);
-	sg[4].length = 1;
-
-	p = &xbuf[IDX6];
-	sg[5].page = virt_to_page(p);
-	sg[5].offset = offset_in_page(p);
-	sg[5].length = 1;
-
-	p = &xbuf[IDX7];
-	sg[6].page = virt_to_page(p);
-	sg[6].offset = offset_in_page(p);
-	sg[6].length = 1;
-
-	p = &xbuf[IDX8];
-	sg[7].page = virt_to_page(p);
-	sg[7].offset = offset_in_page(p);
-	sg[7].length = 1;
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 8);
-	if (ret) {
-		printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	for (i = 0; i < 8; i++)
-		res[i] = *(char *) (kmap(sg[i].page) + sg[i].offset);
-
-	hexdump(res, 8);
-	printk("%s\n", memcmp(res, des_tv[7].result, 8) ? "fail" : "pass");
-
-	printk("\ntesting des decryption\n");
-
-	tsize = sizeof (des_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-	memcpy(tvmem, des_dec_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	for (i = 0; i < DES_DEC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		key = des_tv[i].key;
-
-		tfm->crt_flags = 0;
-		ret = crypto_cipher_setkey(tfm, key, 8);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		len = des_tv[i].len;
-
-		p = des_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("des_decrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-
-	}
-
-	printk("\ntesting des ecb decryption across pages\n");
-
-	i = 6;
-
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-	memcpy(&xbuf[IDX1], des_tv[i].plaintext, 8);
-	memcpy(&xbuf[IDX2], des_tv[i].plaintext + 8, 8);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 8;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 8;
-
-	ret = crypto_cipher_decrypt(tfm, sg, sg, 16);
-	if (ret) {
-		printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result, 8) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 8);
-	printk("%s\n", memcmp(q, des_tv[i].result + 8, 8) ? "fail" : "pass");
-
-	/*
-	 * Scenario E:
-	 * 
-	 *  F1   F2      F3
-	 *  [3]  [5 + 7] [1]
-	 *
-	 */
-	printk("\ntesting des ecb decryption chunking scenario E\n");
-	i = 2;
-
-	key = des_tv[i].key;
-	tfm->crt_flags = 0;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-
-	memcpy(&xbuf[IDX1], des_tv[i].plaintext, 3);
-	memcpy(&xbuf[IDX2], des_tv[i].plaintext + 3, 12);
-	memcpy(&xbuf[IDX3], des_tv[i].plaintext + 15, 1);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 3;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 12;
-
-	p = &xbuf[IDX3];
-	sg[2].page = virt_to_page(p);
-	sg[2].offset = offset_in_page(p);
-	sg[2].length = 1;
-
-	ret = crypto_cipher_decrypt(tfm, sg, sg, 16);
-
-	if (ret) {
-		printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 3);
-	printk("%s\n", memcmp(q, des_tv[i].result, 3) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 12);
-	printk("%s\n", memcmp(q, des_tv[i].result + 3, 12) ? "fail" : "pass");
-
-	printk("page 3\n");
-	q = kmap(sg[2].page) + sg[2].offset;
-	hexdump(q, 1);
-	printk("%s\n", memcmp(q, des_tv[i].result + 15, 1) ? "fail" : "pass");
-
-	crypto_free_tfm(tfm);
-
-	tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC);
-	if (tfm == NULL) {
-		printk("failed to load transform for des cbc\n");
-		return;
-	}
-
-	printk("\ntesting des cbc encryption\n");
-
-	tsize = sizeof (des_cbc_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-	memcpy(tvmem, des_cbc_enc_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
-	crypto_cipher_get_iv(tfm, res, crypto_tfm_alg_ivsize(tfm));
-	
-	if (memcmp(res, des_tv[i].iv, sizeof(res))) {
-		printk("crypto_cipher_[set|get]_iv() failed\n");
-		goto out;
-	}
-	
-	for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		key = des_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, 8);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		len = des_tv[i].len;
-		p = des_tv[i].plaintext;
-
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-
-		crypto_cipher_set_iv(tfm, des_tv[i].iv,
-				     crypto_tfm_alg_ivsize(tfm));
-
-		ret = crypto_cipher_encrypt(tfm, sg, sg, len);
-		if (ret) {
-			printk("des_cbc_encrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-	}
-
-	crypto_free_tfm(tfm);
-
-	/*
-	 * Scenario F:
-	 * 
-	 *  F1       F2      
-	 *  [8 + 5]  [3 + 8]
-	 *
-	 */
-	printk("\ntesting des cbc encryption chunking scenario F\n");
-	i = 4;
-
-	tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC);
-	if (tfm == NULL) {
-		printk("failed to load transform for CRYPTO_ALG_DES_CCB\n");
-		return;
-	}
-
-	tfm->crt_flags = 0;
-	key = des_tv[i].key;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-
-	memcpy(&xbuf[IDX1], des_tv[i].plaintext, 13);
-	memcpy(&xbuf[IDX2], des_tv[i].plaintext + 13, 11);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 13;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 11;
-
-	crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
-
-	ret = crypto_cipher_encrypt(tfm, sg, sg, 24);
-	if (ret) {
-		printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 13);
-	printk("%s\n", memcmp(q, des_tv[i].result, 13) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 11);
-	printk("%s\n", memcmp(q, des_tv[i].result + 13, 11) ? "fail" : "pass");
-
-	tsize = sizeof (des_cbc_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-	memcpy(tvmem, des_cbc_dec_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	printk("\ntesting des cbc decryption\n");
-
-	for (i = 0; i < DES_CBC_DEC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		tfm->crt_flags = 0;
-		key = des_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, 8);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		len = des_tv[i].len;
-		p = des_tv[i].plaintext;
-
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-
-		crypto_cipher_set_iv(tfm, des_tv[i].iv,
-				      crypto_tfm_alg_blocksize(tfm));
-
-		ret = crypto_cipher_decrypt(tfm, sg, sg, len);
-		if (ret) {
-			printk("des_cbc_decrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		hexdump(tfm->crt_cipher.cit_iv, 8);
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-	}
-
-	/*
-	 * Scenario G:
-	 * 
-	 *  F1   F2      
-	 *  [4]  [4]
-	 *
-	 */
-	printk("\ntesting des cbc decryption chunking scenario G\n");
-	i = 3;
-
-	tfm->crt_flags = 0;
-	key = des_tv[i].key;
-
-	ret = crypto_cipher_setkey(tfm, key, 8);
-	if (ret) {
-		printk("setkey() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	/* setup the dummy buffer first */
-	memset(xbuf, 0, sizeof (xbuf));
-	memcpy(&xbuf[IDX1], des_tv[i].plaintext, 4);
-	memcpy(&xbuf[IDX2], des_tv[i].plaintext + 4, 4);
-
-	p = &xbuf[IDX1];
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = 4;
-
-	p = &xbuf[IDX2];
-	sg[1].page = virt_to_page(p);
-	sg[1].offset = offset_in_page(p);
-	sg[1].length = 4;
-
-	crypto_cipher_set_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
-
-	ret = crypto_cipher_decrypt(tfm, sg, sg, 8);
-	if (ret) {
-		printk("des_cbc_decrypt() failed flags=%x\n", tfm->crt_flags);
-		goto out;
-	}
-
-	printk("page 1\n");
-	q = kmap(sg[0].page) + sg[0].offset;
-	hexdump(q, 4);
-	printk("%s\n", memcmp(q, des_tv[i].result, 4) ? "fail" : "pass");
-
-	printk("page 2\n");
-	q = kmap(sg[1].page) + sg[1].offset;
-	hexdump(q, 4);
-	printk("%s\n", memcmp(q, des_tv[i].result + 4, 4) ? "fail" : "pass");
-
-      out:
-	crypto_free_tfm(tfm);
-}
-
-void
-test_des3_ede(void)
-{
-	unsigned int ret, i, len;
-	unsigned int tsize;
-	char *p, *q;
-	struct crypto_tfm *tfm;
-	char *key;
-	/*char res[8]; */
-	struct des_tv *des_tv;
-	struct scatterlist sg[8];
-
-	printk("\ntesting des3 ede encryption\n");
-
-	tsize = sizeof (des3_ede_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, des3_ede_enc_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("des3_ede", CRYPTO_TFM_MODE_ECB);
-	if (tfm == NULL) {
-		printk("failed to load transform for 3des ecb\n");
-		return;
-	}
-
-	for (i = 0; i < DES3_EDE_ENC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		key = des_tv[i].key;
-		ret = crypto_cipher_setkey(tfm, key, 24);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!des_tv[i].fail)
-				goto out;
-		}
-
-		len = des_tv[i].len;
-
-		p = des_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-		ret = crypto_cipher_encrypt(tfm, sg, sg, len);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-	}
-
-	printk("\ntesting des3 ede decryption\n");
-
-	tsize = sizeof (des3_ede_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, des3_ede_dec_tv_template, tsize);
-	des_tv = (void *) tvmem;
-
-	for (i = 0; i < DES3_EDE_DEC_TEST_VECTORS; i++) {
-		printk("test %u:\n", i + 1);
-
-		key = des_tv[i].key;
-		ret = crypto_cipher_setkey(tfm, key, 24);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!des_tv[i].fail)
-				goto out;
-		}
-
-		len = des_tv[i].len;
-
-		p = des_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = len;
-		ret = crypto_cipher_decrypt(tfm, sg, sg, len);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, len);
-
-		printk("%s\n",
-		       memcmp(q, des_tv[i].result, len) ? "fail" : "pass");
-	}
-
-      out:
-	crypto_free_tfm(tfm);
-}
-
-void
-test_blowfish(void)
-{
-	unsigned int ret, i;
-	unsigned int tsize;
-	char *p, *q;
-	struct crypto_tfm *tfm;
-	char *key;
-	struct bf_tv *bf_tv;
-	struct scatterlist sg[1];
-
-	printk("\ntesting blowfish encryption\n");
-
-	tsize = sizeof (bf_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, bf_enc_tv_template, tsize);
-	bf_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("blowfish", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for blowfish (default ecb)\n");
-		return;
-	}
-
-	for (i = 0; i < BF_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, bf_tv[i].keylen * 8);
-		key = bf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!bf_tv[i].fail)
-				goto out;
-		}
-
-		p = bf_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = bf_tv[i].plen;
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, bf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ?
-			"fail" : "pass");
-	}
-
-	printk("\ntesting blowfish decryption\n");
-
-	tsize = sizeof (bf_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, bf_dec_tv_template, tsize);
-	bf_tv = (void *) tvmem;
-
-	for (i = 0; i < BF_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, bf_tv[i].keylen * 8);
-		key = bf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!bf_tv[i].fail)
-				goto out;
-		}
-
-		p = bf_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = bf_tv[i].plen;
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, bf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen) ?
-			"fail" : "pass");
-	}
-	
-	crypto_free_tfm(tfm);
-	
-	tfm = crypto_alloc_tfm("blowfish", CRYPTO_TFM_MODE_CBC);
-	if (tfm == NULL) {
-		printk("failed to load transform for blowfish cbc\n");
-		return;
-	}
-
-	printk("\ntesting blowfish cbc encryption\n");
-
-	tsize = sizeof (bf_cbc_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-	memcpy(tvmem, bf_cbc_enc_tv_template, tsize);
-	bf_tv = (void *) tvmem;
-
-	for (i = 0; i < BF_CBC_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, bf_tv[i].keylen * 8);
-
-		key = bf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		p = bf_tv[i].plaintext;
-
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length =  bf_tv[i].plen;
-
-		crypto_cipher_set_iv(tfm, bf_tv[i].iv,
-				     crypto_tfm_alg_ivsize(tfm));
-
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("blowfish_cbc_encrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, bf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen)
-			? "fail" : "pass");
-	}
-
-	printk("\ntesting blowfish cbc decryption\n");
-
-	tsize = sizeof (bf_cbc_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-	memcpy(tvmem, bf_cbc_dec_tv_template, tsize);
-	bf_tv = (void *) tvmem;
-
-	for (i = 0; i < BF_CBC_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, bf_tv[i].keylen * 8);
-		key = bf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, bf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		p = bf_tv[i].plaintext;
-
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length =  bf_tv[i].plen;
-
-		crypto_cipher_set_iv(tfm, bf_tv[i].iv,
-				     crypto_tfm_alg_ivsize(tfm));
-
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("blowfish_cbc_decrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, bf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, bf_tv[i].result, bf_tv[i].rlen)
-			? "fail" : "pass");
-	}
-
-out:
-	crypto_free_tfm(tfm);
-}
-
-
-void
-test_twofish(void)
-{
-	unsigned int ret, i;
-	unsigned int tsize;
-	char *p, *q;
-	struct crypto_tfm *tfm;
-	char *key;
-	struct tf_tv *tf_tv;
-	struct scatterlist sg[1];
-
-	printk("\ntesting twofish encryption\n");
-
-	tsize = sizeof (tf_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, tf_enc_tv_template, tsize);
-	tf_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("twofish", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for blowfish (default ecb)\n");
-		return;
-	}
-
-	for (i = 0; i < TF_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, tf_tv[i].keylen * 8);
-		key = tf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!tf_tv[i].fail)
-				goto out;
-		}
-
-		p = tf_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = tf_tv[i].plen;
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, tf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
-			"fail" : "pass");
-	}
-
-	printk("\ntesting twofish decryption\n");
-
-	tsize = sizeof (tf_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, tf_dec_tv_template, tsize);
-	tf_tv = (void *) tvmem;
-
-	for (i = 0; i < TF_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, tf_tv[i].keylen * 8);
-		key = tf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!tf_tv[i].fail)
-				goto out;
-		}
-
-		p = tf_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = tf_tv[i].plen;
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, tf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
-			"fail" : "pass");
-	}
-
-	crypto_free_tfm(tfm);
-	
-	tfm = crypto_alloc_tfm("twofish", CRYPTO_TFM_MODE_CBC);
-	if (tfm == NULL) {
-		printk("failed to load transform for twofish cbc\n");
-		return;
-	}
-
-	printk("\ntesting twofish cbc encryption\n");
-
-	tsize = sizeof (tf_cbc_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-	memcpy(tvmem, tf_cbc_enc_tv_template, tsize);
-	tf_tv = (void *) tvmem;
-
-	for (i = 0; i < TF_CBC_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, tf_tv[i].keylen * 8);
-
-		key = tf_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		p = tf_tv[i].plaintext;
-
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length =  tf_tv[i].plen;
-
-		crypto_cipher_set_iv(tfm, tf_tv[i].iv,
-				     crypto_tfm_alg_ivsize(tfm));
-
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("blowfish_cbc_encrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, tf_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
-			? "fail" : "pass");
-	}
-
-	printk("\ntesting twofish cbc decryption\n");
-
-	tsize = sizeof (tf_cbc_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		goto out;
-	}
-	memcpy(tvmem, tf_cbc_dec_tv_template, tsize);
-	tf_tv = (void *) tvmem;
-
-	for (i = 0; i < TF_CBC_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, tf_tv[i].keylen * 8);
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ * 14 - 09 - 2003 
+ *	Rewritten by Kartikey Mahendra Bhatt
+ */
 
-		key = tf_tv[i].key;
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/highmem.h>
+#include "tcrypt.h"
 
-		ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
+/*
+ * Need to kmalloc() memory for testing kmap().
+ */
+#define TVMEMSIZE	4096
+#define XBUFSIZE	32768
 
-		p = tf_tv[i].plaintext;
+/*
+ * Indexes into the xbuf to simulate cross-page access.
+ */
+#define IDX1		37
+#define IDX2		32400
+#define IDX3		1
+#define IDX4		8193
+#define IDX5		22222
+#define IDX6		17101
+#define IDX7		27333
+#define IDX8		3000
 
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length =  tf_tv[i].plen;
+/*
+* Used by test_cipher()
+*/
+#define ENCRYPT 1
+#define DECRYPT 0
+#define MODE_ECB 1
+#define MODE_CBC 0
 
-		crypto_cipher_set_iv(tfm, tf_tv[i].iv,
-				     crypto_tfm_alg_ivsize(tfm));
+static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("blowfish_cbc_decrypt() failed flags=%x\n",
-			       tfm->crt_flags);
-			goto out;
-		}
+static int mode;
+static char *xbuf;
+static char *tvmem;
 
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, tf_tv[i].rlen);
+static char *check[] = {
+	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
+	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
+	"deflate", NULL
+};
 
-		printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
-			? "fail" : "pass");
-	}
+static void
+hexdump(unsigned char *buf, unsigned int len)
+{
+	while (len--)
+		printk("%02x", *buf++);
 
-out:	
-	crypto_free_tfm(tfm);
+	printk("\n");
 }
 
-void
-test_serpent(void)
+static void 
+test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
 {
-	unsigned int ret, i, tsize;
-	u8 *p, *q, *key;
-	struct crypto_tfm *tfm;
-	struct serpent_tv *serp_tv;
-	struct scatterlist sg[1];
-
-	printk("\ntesting serpent encryption\n");
+	char *p; 
+        unsigned int i, j, k, temp;
+        struct scatterlist sg[8];
+        char result[64];
+        struct crypto_tfm *tfm;
+        struct hash_testvec *hash_tv;
+        unsigned int tsize;
+	 
+        printk("\ntesting %s\n", algo);
 
-	tfm = crypto_alloc_tfm("serpent", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for serpent (default ecb)\n");
+	tsize = sizeof (struct hash_testvec);
+	tsize *= tcount;
+	
+	if (tsize > TVMEMSIZE) {
+		printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
 		return;
 	}
 
-	tsize = sizeof (serpent_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
+	memcpy(tvmem, template, tsize);
+	hash_tv = (void *) tvmem;
+	tfm = crypto_alloc_tfm(algo, 0);
+	if (tfm == NULL) {
+		printk("failed to load transform for %s\n", algo);
 		return;
 	}
 
-	memcpy(tvmem, serpent_enc_tv_template, tsize);
-	serp_tv = (void *) tvmem;
-	for (i = 0; i < SERPENT_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, serp_tv[i].keylen * 8);
-		key = serp_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, serp_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!serp_tv[i].fail)
-				goto out;
-		}
+	for (i = 0; i < tcount; i++) {
+		printk ("test %u:\n", i + 1);
+		memset (result, 0, 64);
 
-		p = serp_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = sizeof(serp_tv[i].plaintext);
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
+		p = hash_tv[i].plaintext;
+		sg[0].page = virt_to_page (p);
+		sg[0].offset = offset_in_page (p);
+		sg[0].length = hash_tv[i].psize;
 
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(serp_tv[i].result));
+		crypto_digest_init (tfm);
+		crypto_digest_update (tfm, sg, 1);
+		crypto_digest_final (tfm, result);
 
-		printk("%s\n", memcmp(q, serp_tv[i].result,
-			sizeof(serp_tv[i].result)) ? "fail" : "pass");
+		hexdump (result, crypto_tfm_alg_digestsize (tfm));
+		printk("%s\n",
+			memcmp(result, hash_tv[i].digest,
+				crypto_tfm_alg_digestsize(tfm)) ? "fail" :
+			"pass");
 	}
 
-	printk("\ntesting serpent decryption\n");
-
-	tsize = sizeof (serpent_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
+	printk ("testing %s across pages\n", algo);
 
-	memcpy(tvmem, serpent_dec_tv_template, tsize);
-	serp_tv = (void *) tvmem;
-	for (i = 0; i < SERPENT_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, serp_tv[i].keylen * 8);
-		key = serp_tv[i].key;
+	/* setup the dummy buffer first */
+        memset(xbuf, 0, XBUFSIZE);
 
-		ret = crypto_cipher_setkey(tfm, key, serp_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		if (hash_tv[i].np) {
+			j++;
+			printk ("test %u:\n", j);
+			memset (result, 0, 64);
 
-			if (!serp_tv[i].fail)
-				goto out;
-		}
+			temp = 0;
+			for (k = 0; k < hash_tv[i].np; k++) {
+				memcpy (&xbuf[IDX[k]], hash_tv[i].plaintext + temp, 
+						hash_tv[i].tap[k]);	
+				temp += hash_tv[i].tap[k];
+				p = &xbuf[IDX[k]];
+				sg[k].page = virt_to_page (p);
+				sg[k].offset = offset_in_page (p);
+				sg[k].length = hash_tv[i].tap[k];
+			}
 
-		p = serp_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = sizeof(serp_tv[i].plaintext);
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
+			crypto_digest_digest (tfm, sg, hash_tv[i].np, result);
+			
+			hexdump (result, crypto_tfm_alg_digestsize (tfm));
+			printk("%s\n",
+				memcmp(result, hash_tv[i].digest,
+					crypto_tfm_alg_digestsize(tfm)) ? "fail" :
+				"pass");
 		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(serp_tv[i].result));
-
-		printk("%s\n", memcmp(q, serp_tv[i].result,
-			sizeof(serp_tv[i].result)) ? "fail" : "pass");
 	}
-
-out:
-	crypto_free_tfm(tfm);
+	
+	crypto_free_tfm (tfm);
 }
 
+
+#ifdef CONFIG_CRYPTO_HMAC
+
 static void
-test_cast6(void)
+test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
 {
-	unsigned int ret, i, tsize;
-	u8 *p, *q, *key;
+	char *p;
+	unsigned int i, j, k, temp;
+	struct scatterlist sg[8];
+	char result[64];
 	struct crypto_tfm *tfm;
-	struct cast6_tv *cast_tv;
-	struct scatterlist sg[1];
+	struct hmac_testvec *hmac_tv;
+	unsigned int tsize, klen;
 
-	printk("\ntesting cast6 encryption\n");
-
-	tfm = crypto_alloc_tfm("cast6", 0);
+	tfm = crypto_alloc_tfm(algo, 0);
 	if (tfm == NULL) {
-		printk("failed to load transform for cast6 (default ecb)\n");
+		printk("failed to load transform for %s\n", algo);
 		return;
 	}
 
-	tsize = sizeof (cast6_enc_tv_template);
+	printk("\ntesting hmac_%s\n", algo);
+	
+	tsize = sizeof (struct hmac_testvec);
+	tsize *= tcount;
 	if (tsize > TVMEMSIZE) {
 		printk("template (%u) too big for tvmem (%u)\n", tsize,
 		       TVMEMSIZE);
-		return;
+		goto out;
 	}
 
-	memcpy(tvmem, cast6_enc_tv_template, tsize);
-	cast_tv = (void *) tvmem;
-	for (i = 0; i < CAST6_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, cast_tv[i].keylen * 8);
-		key = cast_tv[i].key;
+	memcpy(tvmem, template, tsize);
+	hmac_tv = (void *) tvmem;
 
-		ret = crypto_cipher_setkey(tfm, key, cast_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!cast_tv[i].fail)
-				goto out;
-		}
+	for (i = 0; i < tcount; i++) {
+		printk("test %u:\n", i + 1);
+		memset(result, 0, sizeof (result));
 
-		p = cast_tv[i].plaintext;
+		p = hmac_tv[i].plaintext;
+		klen = hmac_tv[i].ksize;
 		sg[0].page = virt_to_page(p);
-		sg[0].offset = ((long) p & ~PAGE_MASK);
-		sg[0].length = sizeof(cast_tv[i].plaintext);
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(cast_tv[i].result));
-
-		printk("%s\n", memcmp(q, cast_tv[i].result,
-			sizeof(cast_tv[i].result)) ? "fail" : "pass");
-	}
+		sg[0].offset = offset_in_page(p);
+		sg[0].length = hmac_tv[i].psize;
 
-	printk("\ntesting cast6 decryption\n");
+		crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result);
 
-	tsize = sizeof (cast6_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
+		hexdump(result, crypto_tfm_alg_digestsize(tfm));
+		printk("%s\n",
+		       memcmp(result, hmac_tv[i].digest,
+			      crypto_tfm_alg_digestsize(tfm)) ? "fail" :
+		       "pass");
 	}
 
-	memcpy(tvmem, cast6_dec_tv_template, tsize);
-	cast_tv = (void *) tvmem;
-	for (i = 0; i < CAST6_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, cast_tv[i].keylen * 8);
-		key = cast_tv[i].key;
+	printk("\ntesting hmac_%s across pages\n", algo);
 
-		ret = crypto_cipher_setkey(tfm, key, cast_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!cast_tv[i].fail)
-				goto out;
-		}
-
-		p = cast_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = ((long) p & ~PAGE_MASK);
-		sg[0].length = sizeof(cast_tv[i].plaintext);
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
+	memset(xbuf, 0, XBUFSIZE);
+	
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		if (hmac_tv[i].np) {
+			j++;
+			printk ("test %u:\n",j);
+			memset (result, 0, 64);
+
+			temp = 0;
+			klen = hmac_tv[i].ksize;
+			for (k = 0; k < hmac_tv[i].np; k++) {
+				memcpy (&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, 
+						hmac_tv[i].tap[k]);	
+				temp += hmac_tv[i].tap[k];
+				p = &xbuf[IDX[k]];
+				sg[k].page = virt_to_page (p);
+				sg[k].offset = offset_in_page (p);
+				sg[k].length = hmac_tv[i].tap[k];
+			}
+
+			crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, 
+					result);
+			hexdump(result, crypto_tfm_alg_digestsize(tfm));
+			
+			printk("%s\n",
+				memcmp(result, hmac_tv[i].digest,
+					crypto_tfm_alg_digestsize(tfm)) ? "fail" : 
+				"pass");
 		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(cast_tv[i].result));
-
-		printk("%s\n", memcmp(q, cast_tv[i].result,
-			sizeof(cast_tv[i].result)) ? "fail" : "pass");
 	}
-
 out:
 	crypto_free_tfm(tfm);
 }
 
+#endif	/* CONFIG_CRYPTO_HMAC */
+
 void
-test_aes(void)
+test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, unsigned int tcount)
 {
-	unsigned int ret, i;
+	unsigned int ret, i, j, k, temp;
 	unsigned int tsize;
 	char *p, *q;
 	struct crypto_tfm *tfm;
 	char *key;
-	struct aes_tv *aes_tv;
-	struct scatterlist sg[1];
-
-	printk("\ntesting aes encryption\n");
-
-	tsize = sizeof (aes_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, aes_enc_tv_template, tsize);
-	aes_tv = (void *) tvmem;
-
-	tfm = crypto_alloc_tfm("aes", 0);
-	if (tfm == NULL) {
-		printk("failed to load transform for aes (default ecb)\n");
-		return;
-	}
-
-	for (i = 0; i < AES_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, aes_tv[i].keylen * 8);
-		key = aes_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!aes_tv[i].fail)
-				goto out;
-		}
+	struct cipher_testvec *cipher_tv;
+	struct scatterlist sg[8];
+	char e[11], m[4];
 
-		p = aes_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = aes_tv[i].plen;
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
+	if (enc == ENCRYPT)
+	        strncpy(e, "encryption", 11);
+	else
+        	strncpy(e, "decryption", 11);
+	if (mode == MODE_ECB)
+        	strncpy(m, "ECB", 4);
+	else
+        	strncpy(m, "CBC", 4);
 
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, aes_tv[i].rlen);
+	printk("\ntesting %s %s %s \n", algo, m, e);
 
-		printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
-			"fail" : "pass");
-	}
+	tsize = sizeof (struct cipher_testvec);	
+	tsize *= tcount;
 	
-	printk("\ntesting aes decryption\n");
-
-	tsize = sizeof (aes_dec_tv_template);
 	if (tsize > TVMEMSIZE) {
 		printk("template (%u) too big for tvmem (%u)\n", tsize,
 		       TVMEMSIZE);
 		return;
 	}
 
-	memcpy(tvmem, aes_dec_tv_template, tsize);
-	aes_tv = (void *) tvmem;
-
-	for (i = 0; i < AES_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n",
-			i + 1, aes_tv[i].keylen * 8);
-		key = aes_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, aes_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!aes_tv[i].fail)
-				goto out;
-		}
-
-		p = aes_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = aes_tv[i].plen;
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, aes_tv[i].rlen);
-
-		printk("%s\n", memcmp(q, aes_tv[i].result, aes_tv[i].rlen) ?
-			"fail" : "pass");
-	}
-
-out:
-	crypto_free_tfm(tfm);
-}
-
-void
-test_cast5(void)
-{
-	unsigned int ret, i, tsize;
-	u8 *p, *q, *key;
-	struct crypto_tfm *tfm;
-	struct cast5_tv *c5_tv;
-	struct scatterlist sg[1];
-
-	printk("\ntesting cast5 encryption\n");
+	memcpy(tvmem, template, tsize);
+	cipher_tv = (void *) tvmem;
 
-	tfm = crypto_alloc_tfm("cast5", 0);
+	if (mode) 
+		tfm = crypto_alloc_tfm (algo, 0);
+	else 
+		tfm = crypto_alloc_tfm (algo, CRYPTO_TFM_MODE_CBC);
+	
 	if (tfm == NULL) {
-		printk("failed to load transform for cast5 (default ecb)\n");
-		return;
-	}
-
-	tsize = sizeof (cast5_enc_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
+		printk("failed to load transform for %s %s\n", algo, m);
 		return;
 	}
+	
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		if (!(cipher_tv[i].np)) {
+			j++;	
+			printk("test %u (%d bit key):\n",
+			j, cipher_tv[i].klen * 8);
 
-	memcpy(tvmem, cast5_enc_tv_template, tsize);
-	c5_tv = (void *) tvmem;
-	for (i = 0; i < CAST5_ENC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, c5_tv[i].keylen * 8);
-		key = c5_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, c5_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
+			tfm->crt_flags = 0;
+			if (cipher_tv[i].wk) 
+				tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
+			key = cipher_tv[i].key;
+	
+			ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
+			if (ret) {
+				printk("setkey() failed flags=%x\n", tfm->crt_flags);
+	
+				if (!cipher_tv[i].fail)
+					goto out;
+			}	
 
-			if (!c5_tv[i].fail)
+			p = cipher_tv[i].input;
+			sg[0].page = virt_to_page(p);
+			sg[0].offset = offset_in_page(p);
+			sg[0].length = cipher_tv[i].ilen;
+	
+			if (!mode) {
+				crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
+					crypto_tfm_alg_ivsize (tfm));
+			}
+		
+			if (enc)
+				ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
+			else
+				ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
+			
+				
+			if (ret) {
+				printk("%s () failed flags=%x\n", e, tfm->crt_flags);
 				goto out;
+			}	
+	
+			q = kmap(sg[0].page) + sg[0].offset;
+			hexdump(q, cipher_tv[i].rlen);
+	
+			printk("%s\n", 
+				memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" : 
+			"pass");
 		}
-
-		p = c5_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = ((long) p & ~PAGE_MASK);
-		sg[0].length = sizeof(c5_tv[i].plaintext);
-		ret = crypto_cipher_encrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("encrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
-		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(c5_tv[i].ciphertext));
-
-		printk("%s\n", memcmp(q, c5_tv[i].ciphertext,
-			sizeof(c5_tv[i].ciphertext)) ? "fail" : "pass");
 	}
 	
-	tsize = sizeof (cast5_dec_tv_template);
-	if (tsize > TVMEMSIZE) {
-		printk("template (%u) too big for tvmem (%u)\n", tsize,
-		       TVMEMSIZE);
-		return;
-	}
-
-	memcpy(tvmem, cast5_dec_tv_template, tsize);
-	c5_tv = (void *) tvmem;
-	for (i = 0; i < CAST5_DEC_TEST_VECTORS; i++) {
-		printk("test %u (%d bit key):\n", i + 1, c5_tv[i].keylen * 8);
-		key = c5_tv[i].key;
-
-		ret = crypto_cipher_setkey(tfm, key, c5_tv[i].keylen);
-		if (ret) {
-			printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
-			if (!c5_tv[i].fail)
-				goto out;
-		}
-
-		p = c5_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = ((long) p & ~PAGE_MASK);
-		sg[0].length = sizeof(c5_tv[i].plaintext);
-		ret = crypto_cipher_decrypt(tfm, sg, sg, sg[0].length);
-		if (ret) {
-			printk("decrypt() failed flags=%x\n", tfm->crt_flags);
-			goto out;
+	printk("\ntesting %s %s %s across pages (chunking) \n", algo, m, e);
+	memset(xbuf, 0, XBUFSIZE);
+	
+	j = 0;
+	for (i = 0; i < tcount; i++) {
+		if (cipher_tv[i].np) {
+			j++;				
+			printk("test %u (%d bit key):\n",
+			j, cipher_tv[i].klen * 8);
+
+			tfm->crt_flags = 0;			
+			if (cipher_tv[i].wk) 
+				tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
+			key = cipher_tv[i].key;
+			
+			ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);		
+			if (ret) {
+				printk("setkey() failed flags=%x\n", tfm->crt_flags);
+				
+				if (!cipher_tv[i].fail)
+					goto out;
+			}
+
+			temp = 0;
+			for (k = 0; k < cipher_tv[i].np; k++) {
+				memcpy (&xbuf[IDX[k]], cipher_tv[i].input + temp, 
+						cipher_tv[i].tap[k]);	
+				temp += cipher_tv[i].tap[k];
+				p = &xbuf[IDX[k]];
+				sg[k].page = virt_to_page (p);
+				sg[k].offset = offset_in_page (p);
+				sg[k].length = cipher_tv[i].tap[k];
+			}
+			
+			if (!mode) {
+				crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
+						crypto_tfm_alg_ivsize (tfm));
+			}
+			
+			if (enc)
+				ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
+			else
+				ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
+			
+			if (ret) {
+				printk("%s () failed flags=%x\n", e, tfm->crt_flags);
+				goto out;
+			}
+
+			temp = 0;
+			for (k = 0; k < cipher_tv[i].np; k++) {
+				printk("page %u\n", k);
+				q = kmap(sg[k].page) + sg[k].offset;
+				hexdump(q, cipher_tv[i].tap[k]);
+				printk("%s\n", 
+					memcmp(q, cipher_tv[i].result + temp, 
+						cipher_tv[i].tap[k]) ? "fail" : 
+					"pass");
+				temp += cipher_tv[i].tap[k];
+			}
 		}
-
-		q = kmap(sg[0].page) + sg[0].offset;
-		hexdump(q, sizeof(c5_tv[i].ciphertext));
-
-		printk("%s\n", memcmp(q, c5_tv[i].ciphertext,
-			sizeof(c5_tv[i].ciphertext)) ? "fail" : "pass");
 	}
+
 out:
-	crypto_free_tfm (tfm);
+	crypto_free_tfm(tfm);
 }
 
 static void
@@ -2485,75 +510,118 @@ do_test(void)
 	switch (mode) {
 
 	case 0:
-		test_md5();
-		test_sha1();
-		test_des();
-		test_des3_ede();
-		test_md4();
-		test_sha256();
-		test_blowfish();
-		test_twofish();
-		test_serpent();
-		test_cast6();
-		test_aes();
-		test_sha384();
-		test_sha512();
-		test_deflate();
-		test_cast5();
-		test_cast6();
+		test_hash("md5", md5_tv_template, MD5_TEST_VECTORS);
+		
+		test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS);
+		
+		//DES
+		test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS);
+                test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
+                test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
+                test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
+	
+		//DES3_EDE
+		test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
+                test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
+		
+		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
+		
+		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
+		
+		//BLOWFISH
+		test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS);
+		
+		//TWOFISH
+		test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
+		
+		//SERPENT
+		test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS);
+		test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS);
+		
+		//AES
+		test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
+		test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
+
+		//CAST5
+		test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS);
+		test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS);
+		
+		//CAST6
+		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
+		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
+
+		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
+		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+		test_deflate();		
 #ifdef CONFIG_CRYPTO_HMAC
-		test_hmac_md5();
-		test_hmac_sha1();
-		test_hmac_sha256();
+		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
+		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);		
+		test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
 #endif		
 		break;
 
 	case 1:
-		test_md5();
+		test_hash("md5", md5_tv_template, MD5_TEST_VECTORS);
 		break;
 
 	case 2:
-		test_sha1();
+		test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS);
 		break;
 
 	case 3:
-		test_des();
+		test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS);
+		test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
+		test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
+		test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
 		break;
 
 	case 4:
-		test_des3_ede();
+		test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
+                test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
 		break;
 
 	case 5:
-		test_md4();
+		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
 		break;
 		
 	case 6:
-		test_sha256();
+		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
 		break;
 	
 	case 7:
-		test_blowfish();
+		test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS);
+		test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS);
 		break;
 
 	case 8:
-		test_twofish();
+		test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
+		test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
 		break;
-
+		
 	case 9:
-		test_serpent();
 		break;
 
 	case 10:
-		test_aes();
+		test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
+		test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);	
 		break;
 
 	case 11:
-		test_sha384();
+		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		break;
 		
 	case 12:
-		test_sha512();
+		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		break;
 
 	case 13:
@@ -2561,24 +629,26 @@ do_test(void)
 		break;
 
 	case 14:
-		test_cast5();
+		test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS);
+		test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS);
 		break;
 
 	case 15:
-		test_cast6();
+		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
+		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 		break;
 
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
-		test_hmac_md5();
+		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
 		break;
 		
 	case 101:
-		test_hmac_sha1();
+		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);		
 		break;
 	
 	case 102:
-		test_hmac_sha256();
+		test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
 		break;
 
 #endif
@@ -2614,7 +684,14 @@ init(void)
 	return 0;
 }
 
+/*
+ * If an init function is provided, an exit function must also be provided
+ * to allow module unload.
+ */
+static void __exit fini(void) { }
+
 module_init(init);
+module_exit(fini);
 
 MODULE_PARM(mode, "i");
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/crypto/tcrypt.h 001-linus.patch/crypto/tcrypt.h
--- 000-virgin/crypto/tcrypt.h	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/crypto/tcrypt.h	Tue Dec 30 16:38:57 2003
@@ -1,4 +1,4 @@
-/* 
+/*
  * Quick & dirty crypto testing module.
  *
  * This will only exist until we have a better testing mechanism
@@ -6,565 +6,165 @@
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
  * Software Foundation; either version 2 of the License, or (at your option) 
  * any later version.
  *
+ * 14 - 09 - 2003 Changes by Kartikey Mahendra Bhatt
+ *
  */
 #ifndef _CRYPTO_TCRYPT_H
 #define _CRYPTO_TCRYPT_H
 
-#define MD5_DIGEST_SIZE		16
-#define MD4_DIGEST_SIZE		16
-#define SHA1_DIGEST_SIZE	20
-#define SHA256_DIGEST_SIZE	32
-#define SHA384_DIGEST_SIZE	48
-#define SHA512_DIGEST_SIZE	64
-
-/*
- * MD4 test vectors from RFC1320
- */
-#define MD4_TEST_VECTORS	7
-
-struct md4_testvec {
-	char plaintext[128];
-	char digest[MD4_DIGEST_SIZE];
-} md4_tv_template[] = {
-	{ "",
-		{ 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
-		  0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }
-	},
-	
-	{ "a",
-		{ 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
-		  0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }
-	},
-
-	{ "abc",
-		{ 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
-		  0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }
-	},
-	
-	{ "message digest",
-		{ 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
-		  0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }
-	},
-	
-	{ "abcdefghijklmnopqrstuvwxyz",
-		{ 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
-		  0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }
-	},
-		
-	{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-		{ 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
-		  0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }
-	},
-	
-	{ "123456789012345678901234567890123456789012345678901234567890123"
-	  "45678901234567890",
-		{ 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
-		  0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }
-	},
-};
+#define MAX_DIGEST_SIZE		64
+#define MAX_TAP			8
 
-/*
- * MD5 test vectors from RFC1321
- */
-#define MD5_TEST_VECTORS	7
+#define MAX_KEYLEN		56
+#define MAX_IVLEN		32
 
-struct md5_testvec {
+struct hash_testvec {
 	char plaintext[128];
-	char digest[MD5_DIGEST_SIZE];
-} md5_tv_template[] = {
-	{ "",
-		{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
-		  0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
-	        	
-	{ "a",
-		{ 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
-		  0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
-		  
-	{ "abc",
-		{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
-		  0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, 
-		  
-	{ "message digest",
-		{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
-		  0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
-		  
-	{ "abcdefghijklmnopqrstuvwxyz",
-		{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
-		  0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
-		  
-	{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-		{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
-		  0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
-		  
-	{ "12345678901234567890123456789012345678901234567890123456789012"
-	  "345678901234567890",
-		{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
-		  0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }
+	unsigned char psize;
+	char digest[MAX_DIGEST_SIZE];
+	unsigned char np;
+	unsigned char tap[MAX_TAP];		
 };
 
-#ifdef CONFIG_CRYPTO_HMAC
-/*
- * HMAC-MD5 test vectors from RFC2202
- * (These need to be fixed to not use strlen).
- */
-#define HMAC_MD5_TEST_VECTORS	7
-
-struct hmac_md5_testvec {
+struct hmac_testvec {	
 	char key[128];
+	unsigned char ksize;
 	char plaintext[128];
-	char digest[MD5_DIGEST_SIZE];
+	unsigned char psize;
+	char digest[MAX_DIGEST_SIZE];
+	unsigned char np;
+	unsigned char tap[MAX_TAP];		
 };
 
-struct hmac_md5_testvec hmac_md5_tv_template[] =
-{
-	
-	{
-		{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00},
-		  
-		"Hi There",
-		
-		{ 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
-		  0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }
-	},
-	    
-	{
-		{ 'J', 'e', 'f', 'e', 0 },
-		
-		"what do ya want for nothing?",
-		
-		{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
-		  0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 },
-		  
-		{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0x00 },
-		  
-		{ 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
-		  0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }
-	},
-	
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00 },
-		  
-		{ 
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0x00 },
-		  
-		{ 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
-		  0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 }
-	},
-	
-	{
-		{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 },
-		  
-		"Test With Truncation",
-		
-		{ 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
-		  0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c }
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0x00 },
-		  
-		"Test Using Larger Than Block-Size Key - Hash Key First",
-		
-		{ 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
-		  0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd }
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0x00 },
-		
-		"Test Using Larger Than Block-Size Key and Larger Than One "
-		"Block-Size Data",
-		
-		{ 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
-		  0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }
-	},
-	
-	/* cross page test, need to retain key */
-	
-	{
-		{ 'J', 'e', 'f', 'e', 0 },
-		
-		"what do ya want for nothing?",
-		
-		{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
-		  0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }
-	},
-	
+struct cipher_testvec {
+	unsigned char fail;
+	unsigned char wk; /* weak key flag */
+	char key[MAX_KEYLEN];
+	unsigned char klen;
+	char iv[MAX_IVLEN];
+	char input[48];
+	unsigned char ilen;
+	char result[48];
+	unsigned char rlen;
+	int np;
+	unsigned char tap[MAX_TAP];	
 };
 
-	
 /*
- * HMAC-SHA1 test vectors from RFC2202
+ * MD4 test vectors from RFC1320
  */
+#define MD4_TEST_VECTORS	7
 
-#define HMAC_SHA1_TEST_VECTORS	7
-
-struct hmac_sha1_testvec {
-	char key[128];
-	char plaintext[128];
-	char digest[SHA1_DIGEST_SIZE];
-} hmac_sha1_tv_template[] = {
-	
-	{
-		{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x00},
-		  
-		"Hi There",
-
-		{ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
-                  0xe2, 0x8b, 0xc0, 0xb6, 0xfb ,0x37, 0x8c, 0x8e, 0xf1,
-                  0x46, 0xbe, 0x00 }
-	},
-	    
-	{
-		{ 'J', 'e', 'f', 'e', 0 },
-		
-		"what do ya want for nothing?",
-
-		{ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 
-		  0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }
-
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0x00},
-
-		  
-		{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0x00 },
-		  
-		{ 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 
-		  0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 }
-
-	},
-	
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00 },
-		  
-		{ 
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0x00 },
-		  
-		{ 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 
-		  0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda }
-
-	},
-	
-	{
-		{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x00 },
-		  
-		"Test With Truncation",
-		
-		{ 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 
-  		  0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 }
-
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0x00 },
-		  
-		"Test Using Larger Than Block-Size Key - Hash Key First",
-		
-		{ 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 
-  		  0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 }
-
-	},
-	
+struct hash_testvec md4_tv_template [] = {
 	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0x00 },
-		
-		"Test Using Larger Than Block-Size Key and Larger Than One "
-		"Block-Size Data",
-		
-		{ 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 
-		  0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 }
+		.plaintext = "",
+		.digest	= { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+			    0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 },
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+			    0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
+			    0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
+			    0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
+			    0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 },
+		.np	= 2,
+		.tap	= { 13, 13 },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
+			    0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 },
+	}, {
+		.plaintext = "123456789012345678901234567890123456789012345678901234567890123"
+			     "45678901234567890",
+		.psize	= 80,
+		.digest	= { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
+			    0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 },
 	},
-	
-	/* cross page test */
-	{
-		{ 'J', 'e', 'f', 'e', 0 },
-		
-		"what do ya want for nothing?",
-
-		{ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 
-		  0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }
-
-	},
-
 };
 
 /*
- * HMAC-SHA256 test vectors from
- * draft-ietf-ipsec-ciph-sha-256-01.txt
+ * MD5 test vectors from RFC1321
  */
-#define HMAC_SHA256_TEST_VECTORS	10
-
-struct hmac_sha256_testvec {
-	char key[128];
-	char plaintext[128];
-	char digest[SHA256_DIGEST_SIZE];
-} hmac_sha256_tv_template[] = {
-
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
-		  0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x00 },
-		  
-	
-		{ "abc" },
-		
-		{ 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a,
-		  0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a,
-		  0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66,
-		  0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 },
-
-	},
-	
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
-		   0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x00 },
-		
-		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
-		
-		{ 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08,
-		  0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae,
-		  0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49,
-		  0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 }
-	},
-
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
-		  0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x00 },
-		
-		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-		  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
-		
-		{ 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34,
-		  0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab,
-		  0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5,
-		  0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 }
-	},
-
-	{
-		{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00 },
-		
-		{ "Hi There" },
-		
-		{ 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
-		  0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5,
-		  0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c,
-		  0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 }
-	},
-
-	{
-		{ "Jefe" },
-		
-		{ "what do ya want for nothing?" },
-		
-		{ 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
-		  0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
-		  0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
-		  0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 }
-	},
-
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 },
-		
-		{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-		  0xdd, 0xdd, 0x00 },
-		
-		{ 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
-		  0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62,
-		  0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc,
-		  0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 }
-	},
-
-	{
-		{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-		  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-		  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
-		  0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
-		  0x21, 0x22, 0x23, 0x24, 0x25, 0x00 },
-		
-		{ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
-		  0xcd, 0xcd, 0x00 },
-		
-		{ 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74,
-		  0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55,
-		  0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85,
-		  0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 }
-	},
-
-	{
-		{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00 },
-		
-		{ "Test With Truncation" },
-		
-		{ 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b,
-		  0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17,
-		  0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27,
-		  0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 }
-	},
-	
-	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 },
-		
-		{ "Test Using Larger Than Block-Size Key - Hash Key First" },
-		
-		{ 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09,
-		  0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb,
-		  0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e,
-		  0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f }
-	},
+#define MD5_TEST_VECTORS	7
 
+struct hash_testvec md5_tv_template[] = {
 	{
-		{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00 },
-		
-		{ "Test Using Larger Than Block-Size Key and Larger Than "
-		  "One Block-Size Data" },
-		
-		{ 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3,
-		  0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8,
-		  0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc,
-		  0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 }
-	},
+		.digest	= { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+			    0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e },
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+			    0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+			    0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+			    0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+			    0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b },
+		.np	= 2,
+		.tap	= {13, 13}
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+			    0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f },
+	}, {
+		.plaintext = "12345678901234567890123456789012345678901234567890123456789012"
+			     "345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+			    0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a },
+	}
 };
 
-
-#endif	/* CONFIG_CRYPTO_HMAC */
-
 /*
  * SHA1 test vectors  from from FIPS PUB 180-1
  */
 #define SHA1_TEST_VECTORS	2
 
-struct sha1_testvec {
-	char plaintext[128];
-	char digest[SHA1_DIGEST_SIZE];
-} sha1_tv_template[] = {
-	{ "abc",
-	  { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 
-	    0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C ,0x9C, 0xD0, 0xD8, 0x9D }
-	},
-	        	
-	{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-
-	  { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E ,0xBA, 0xAE,
-	    0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }
+struct hash_testvec sha1_tv_template[] = {
+	{ 
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+			    0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 56,
+		.digest	= { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
+			    0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 },
+		.np	= 2,
+		.tap	= { 28, 28 }
 	}
 };
 
@@ -573,22 +173,23 @@ struct sha1_testvec {
  */
 #define SHA256_TEST_VECTORS	2
 
-struct sha256_testvec {
-	char plaintext[128];
-	char digest[SHA256_DIGEST_SIZE];
-} sha256_tv_template[] = {
-	{ "abc",
-	  { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
-	    0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
-	    0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
-	    0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
-	},
-	        	
-	{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-	  { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
-	    0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
-	    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
-	    0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
+struct hash_testvec sha256_tv_template[] = {	
+	{ 
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+			    0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+			    0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+			    0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 56,
+		.digest	= { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+			    0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+			    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+			    0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },
+		.np	= 2,
+		.tap	= { 28, 28 }
 	},
 };
 
@@ -597,47 +198,47 @@ struct sha256_testvec {
  */
 #define SHA384_TEST_VECTORS	4
 
-struct sha384_testvec {
-	char plaintext[128];
-	char digest[SHA384_DIGEST_SIZE];
-} sha384_tv_template[] = {
-
-	{ "abc",
-	  { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
-	    0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
-	    0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
-	    0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
-	    0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
-	    0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }
-	},
-	
-	{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-	  { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
-	    0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
-	    0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
-	    0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
-	    0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
-	    0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b  }
-	},
-	
-	{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-	  "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
-	  { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
-	    0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
-	    0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
-	    0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
-	    0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
-	    0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39  }
-	},
-	
-	{ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
-	  "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
-	  { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb,
-	    0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a,
-	    0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc,
-	    0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a,
-	    0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a,
-	    0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 }
+struct hash_testvec sha384_tv_template[] = {
+	{ 
+		.plaintext= "abc",
+		.psize	= 3,
+		.digest	= { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+			    0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+			    0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+			    0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+			    0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+			    0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 56,
+		.digest	= { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
+			    0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
+			    0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
+			    0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
+			    0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
+			    0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b},
+	}, {
+		.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ 			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+		.psize	= 112,
+		.digest	= { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+			    0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+			    0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+			    0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+			    0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+			    0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39  },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+			     "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+		.psize	= 104,
+		.digest	= { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb,
+			    0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a,
+			    0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc,
+			    0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a,
+			    0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a,
+			    0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 },
+		.np	= 4,
+		.tap	= { 26, 26, 26, 26 }
 	},
 };
 
@@ -646,439 +247,616 @@ struct sha384_testvec {
  */
 #define SHA512_TEST_VECTORS	4
 
-struct sha512_testvec {
-	char plaintext[128];
-	char digest[SHA512_DIGEST_SIZE];
-} sha512_tv_template[] = {
-
-	{ "abc",
-	  { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
-	    0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
-	    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
-	    0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
-	    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
-	    0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
-	    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
-	    0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
-	},
-	
-	{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-	  { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
-	    0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
-	    0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
-	    0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
-	    0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
-	    0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
-	    0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
-	    0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 }
-	},
-	
-	{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-	  "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
-	  { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
-	    0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
-	    0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
-	    0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
-	    0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
-	    0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
-	    0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
-	    0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
-	},
-	
-	{ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
-	  "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
-	  { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11,
-	    0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d,
-	    0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c,
-	    0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d,
-	    0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67,
-	    0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe,
-	    0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8,
-	    0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9
-	  }
+struct hash_testvec sha512_tv_template[] = {
+	{ 
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+			    0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+			    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+			    0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+			    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+			    0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+			    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+			    0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 56,
+		.digest	= { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
+			    0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
+			    0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
+			    0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
+			    0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
+			    0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
+			    0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
+			    0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 },
+	}, {
+		.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+		.psize	= 112,
+		.digest	= { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+			    0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+			    0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+			    0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+			    0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+			    0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+			    0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+			    0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+			     "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+		.psize	= 104,
+		.digest	= { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11,
+			    0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d,
+			    0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c,
+			    0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d,
+			    0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67,
+			    0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe,
+			    0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8,
+			    0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 },
+		.np	= 4,
+		.tap	= { 26, 26, 26, 26 }
 	},
 };
 
+#ifdef CONFIG_CRYPTO_HMAC
 /*
- * DES test vectors.
+ * HMAC-MD5 test vectors from RFC2202
+ * (These need to be fixed to not use strlen).
  */
-#define DES_ENC_TEST_VECTORS		5
-#define DES_DEC_TEST_VECTORS		2
-#define DES_CBC_ENC_TEST_VECTORS	4
-#define DES_CBC_DEC_TEST_VECTORS	3
-#define DES3_EDE_ENC_TEST_VECTORS	3
-#define DES3_EDE_DEC_TEST_VECTORS	3
-
-struct des_tv {
-	unsigned int len;
-	int fail;
-	char key[24];
-	char iv[8];
-	char plaintext[128];
-	char result[128];
-};
-
-struct des_tv des_enc_tv_template[] = {
-
-	/* From Applied Cryptography */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }
-	},
-	
-	/* Same key, different plaintext block */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0 },
-		{ 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
-		{ 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }
-	},
-	
-	/* Sbox test from NBS */
-	{
-		8, 0,
-		
-		{ 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
-		{ 0 },
-		{ 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 },
-		{ 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B }
-	},
-	
-	/* Three blocks */
-	{
-		24, 0,
-		
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		
-		{ 0 },
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
-		  0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
-		  0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
-
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
-		  0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
-		  0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },		  
-	},
-	
-	/* Weak key */
-	{
-		8, 1,
-		
-		{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
-		{ 0 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d }
-	},
-	
-	/* Two blocks -- for testing encryption across pages */
-	{
-		16, 0,
-		
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		
-		{ 0 },
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
-		  0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
-
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
-		  0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b }
-	},
+#define HMAC_MD5_TEST_VECTORS	7
 
-	/* Two blocks -- for testing decryption across pages */
-	{
-		16, 0,
-		
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		
-		{ 0 },
-		
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
-		  0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
-		  
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
-		  0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
-	},
-	
-	/* Four blocks -- for testing encryption with chunking */
+struct hmac_testvec hmac_md5_tv_template[] =
+{	
 	{
-		24, 0,
-		
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		
-		{ 0 },
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
-		  0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
-		  0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef,
-		  0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
-
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
-		  0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
-		  0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90,
-		  0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+		.key	= { [0 ... 15] =  0x0b },
+		.ksize	= 16,
+		.plaintext = "Hi There",
+		.psize	= 8,
+		.digest	= { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+			    0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
+	}, {
+		.key	= { 'J', 'e', 'f', 'e' },
+		.ksize	= 4,
+		.plaintext = "what do ya want for nothing?",
+		.psize	= 28,
+		.digest	= { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+			    0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
+		.np	= 2,
+		.tap	= {14, 14}
+	}, {
+		.key	= { [0 ... 15] = 0xaa },
+		.ksize	= 16,
+		.plaintext = { [0 ... 49] =  0xdd },
+		.psize	= 50,
+		.digest	= { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+			    0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 },
+	}, {
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, },
+		.ksize	= 25,
+		.plaintext = { [0 ... 49] =  0xcd },
+		.psize	= 50,
+		.digest	= { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
+			    0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 },
+	}, {
+		.key	= { [0 ... 15] = 0x0c },
+		.ksize	= 16,
+		.plaintext = "Test With Truncation",
+		.psize	= 20,
+		.digest	= { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
+			    0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c },
+	}, {
+		.key	= { [0 ... 79] =  0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+		.psize	= 54,
+		.digest	= { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
+			    0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd },
+	}, {
+		.key	= { [0 ... 79] =  0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+			     "Block-Size Data",
+		.psize	= 73,
+		.digest	= { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+			    0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e },
 	},
-	
 };
 
-struct des_tv des_dec_tv_template[] = {
-
-	/* From Applied Cryptography */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0 },
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
-	},
-	
-	/* Sbox test from NBS */
-	{
-		8, 0,
+/*
+ * HMAC-SHA1 test vectors from RFC2202
+ */
+#define HMAC_SHA1_TEST_VECTORS	7
 
-		{ 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
-		{ 0 },
-		{ 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B },
-		{ 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 }
-	},
-	
-	/* Two blocks, for chunking test */
+struct hmac_testvec hmac_sha1_tv_template[] = {	
 	{
-		16, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0 },
-		
-		{ 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
-		  0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B },
-		  
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
-		  0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 }
+		.key	= { [0 ... 19] = 0x0b },
+		.ksize	= 20,
+		.plaintext = "Hi There",
+		.psize	= 8,
+		.digest	= { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+			    0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1,
+			    0x46, 0xbe },
+	}, {
+		.key	= { 'J', 'e', 'f', 'e' },		
+		.ksize	= 4,
+		.plaintext = "what do ya want for nothing?",
+		.psize	= 28,
+		.digest	= { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 
+			    0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 },
+		.np	= 2,
+		.tap	= { 14, 14 }
+	}, {
+		.key	= { [0 ... 19] = 0xaa },
+		.ksize	= 20,
+		.plaintext = { [0 ... 49] = 0xdd },
+		.psize	= 50,
+		.digest	= { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 
+			    0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 },
+	}, {
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 },
+		.ksize	= 25,
+		.plaintext = { [0 ... 49] = 0xcd },
+		.psize	= 50,
+		.digest	= { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 
+			    0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda },
+	}, {
+		.key	= { [0 ... 19] = 0x0c },
+		.ksize	= 20,
+		.plaintext = "Test With Truncation",
+		.psize	= 20,
+		.digest	= { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 
+			    0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 },
+	}, {
+		.key	= { [0 ... 79] = 0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+		.psize	= 54,
+		.digest	= { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 
+			    0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 },
+	}, {
+		.key	= { [0 ... 79] = 0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+			     "Block-Size Data",
+		.psize	= 73,
+		.digest	= { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 
+			    0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 },
 	},
-
 };
 
-struct des_tv des_cbc_enc_tv_template[] = {
-	/* From OpenSSL */
-	{
-		24, 0,
-		
-		{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
-		{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
-		
-		{ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
-		  0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
-		  0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 
-		  0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 },
-		  
-		{ 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
-		  0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
-		  0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68, 
-		  0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 }
-	},
+/*
+ * HMAC-SHA256 test vectors from
+ * draft-ietf-ipsec-ciph-sha-256-01.txt
+ */
+#define HMAC_SHA256_TEST_VECTORS	10
 
-	/* FIPS Pub 81 */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
-		{ 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
-		{ 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
-		
-	},
-	
+struct hmac_testvec hmac_sha256_tv_template[] = {
 	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
-		{ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
-		{ 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-	},
-	
-	{	
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		{ 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
-		{ 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
-	},
-	
-	/* Copy of openssl vector for chunk testing */
-	
-	/* From OpenSSL */
-	{
-		24, 0,
-		
-		{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
-		{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
-		
-		{ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
-		  0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
-		  0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 
-		  0x66, 0x6F, 0x72, 0x20, 0x00, 0x31, 0x00, 0x00 },
-		  
-		{ 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
-		  0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
-		  0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68, 
-		  0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4 }
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20},
+		.ksize	= 32,
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a,
+			    0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a,
+			    0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66,
+			    0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 },
+	}, {
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
+		.ksize	= 32,
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 56,
+		.digest	= { 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08,
+			    0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae,
+			    0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49,
+			    0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 },
+	}, {
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
+		.ksize	= 32,
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+			     "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+		.psize	= 112,
+		.digest	= { 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34,
+			    0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab,
+			    0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5,
+			    0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 },
+	}, {
+		.key	= { [0 ... 31] = 0x0b },
+		.ksize	= 32,
+		.plaintext = "Hi There",
+		.psize	= 8,
+		.digest	= { 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
+			    0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5,
+			    0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c,
+			    0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 },
+	}, {
+		.key	= "Jefe",
+		.ksize	= 4,
+		.plaintext = "what do ya want for nothing?",
+		.psize	= 28,
+		.digest	= { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+			    0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+			    0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+			    0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 },
+		.np	= 2,
+		.tap	= { 14, 14 }
+	}, {
+		.key	= { [0 ... 31] = 0xaa },
+		.ksize	= 32,
+		.plaintext = { [0 ... 49] = 0xdd },
+		.psize	= 50,
+		.digest	= { 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
+			    0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62,
+			    0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc,
+			    0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 },
+	}, {
+		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+			    0x21, 0x22, 0x23, 0x24, 0x25 },
+		.ksize	= 37,
+		.plaintext = { [0 ... 49] = 0xcd },
+		.psize	= 50,
+		.digest	= { 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74,
+			    0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55,
+			    0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85,
+			    0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 },
+	}, {
+		.key	= { [0 ... 31] = 0x0c },
+		.ksize	= 32,
+		.plaintext = "Test With Truncation",
+		.psize	= 20,
+		.digest	= { 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b,
+			    0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17,
+			    0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27,
+			    0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 },
+	}, {
+		.key	= { [0 ... 79] = 0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+		.psize	= 54,
+		.digest	= { 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09,
+			    0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb,
+			    0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e,
+			    0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f },
+	}, {
+		.key	= { [0 ... 79] = 0xaa },
+		.ksize	= 80,
+		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than "
+			     "One Block-Size Data",
+		.psize	= 73,
+		.digest	= { 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3,
+			    0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8,
+			    0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc,
+			    0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 },
 	},
-
-	
 };
 
-struct des_tv des_cbc_dec_tv_template[] = {
+#endif	/* CONFIG_CRYPTO_HMAC */
 
-	/* FIPS Pub 81 */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
-		{ 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
-		{ 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
-	},
-	
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
-		{ 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		{ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
-	},
-	
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		{ 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
-		{ 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
-	},
-	
-	/* Copy of above, for chunk testing */
-	
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		{ 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
-		{ 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+/*
+ * DES test vectors.
+ */
+#define DES_ENC_TEST_VECTORS		10
+#define DES_DEC_TEST_VECTORS		4
+#define DES_CBC_ENC_TEST_VECTORS	5
+#define DES_CBC_DEC_TEST_VECTORS	4
+#define DES3_EDE_ENC_TEST_VECTORS	3
+#define DES3_EDE_DEC_TEST_VECTORS	3
+
+struct cipher_testvec des_enc_tv_template[] = {
+	{ /* From Applied Cryptography */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+		.ilen	= 8,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
+		.rlen	= 8,
+	}, { /* Same key, different plaintext block */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+		.ilen	= 8,
+		.result	= { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+		.rlen	= 8,
+	}, { /* Sbox test from NBS */
+		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
+		.klen	= 8,
+		.input	= { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
+		.ilen	= 8,
+		.result	= { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
+		.rlen	= 8,
+	}, { /* Three blocks */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
+		.ilen	= 24,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
+		.rlen	= 24,
+	}, { /* Weak key */
+		.fail	= 1,
+		.wk	= 1,
+		.key	= { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+		.ilen	= 8,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
+		.rlen	= 8,
+	}, { /* Two blocks -- for testing encryption across pages */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+		.ilen	= 16,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+		.rlen	= 16,
+		.np	= 2,
+		.tap	= { 8, 8 }
+	}, { /* Four blocks -- for testing encryption with chunking */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+		.ilen	= 32,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+		.rlen	= 32,
+		.np	= 3,
+		.tap	= { 14, 10, 8 } 
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
+		.ilen	= 24,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
+		.rlen	= 24,
+		.np	= 4,
+		.tap	= { 2, 1, 3, 18 } 
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
+		.ilen	= 16,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
+		.rlen	= 16,
+		.np	= 5,
+		.tap	= { 2, 2, 2, 2, 8 } 
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+		.ilen	= 8,
+		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
+		.rlen	= 8,
+		.np	= 8,
+		.tap	= { 1, 1, 1, 1, 1, 1, 1, 1 } 
+	},
+};
+
+struct cipher_testvec des_dec_tv_template[] = {
+	{ /* From Applied Cryptography */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
+		.rlen	= 8,
+	}, { /* Sbox test from NBS */
+		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },		
+		.klen	= 8,
+		.input	= { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
+		.ilen	= 8,
+		.result	= { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
+		.rlen	= 8,
+	}, { /* Two blocks, for chunking test */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
+		.rlen	= 16,
+		.np	= 2,
+		.tap	= { 8, 8 }
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+			    0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+			    0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
+		.rlen	= 16,
+		.np	= 3,
+		.tap	= { 3, 12, 1 }
+	},
+};
+
+struct cipher_testvec des_cbc_enc_tv_template[] = {
+	{ /* From OpenSSL */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},		
+		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.ilen	= 24,
+		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
+			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
+			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, 
+		.rlen	= 24,
+	}, { /* FIPS Pub 81 */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },		
+		.input	= { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
+		.ilen	= 8,
+		.result	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+		.input	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+		.ilen	= 8,
+		.result	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+		.rlen	= 8,
+	}, {	
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+		.input	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+		.ilen	= 8,
+		.result	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+		.rlen	= 8,
+	}, { /* Copy of openssl vector for chunk testing */	
+	     /* From OpenSSL */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},		
+		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.ilen	= 24,
+		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
+			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
+			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, 
+		.rlen	= 24,
+		.np	= 2,
+		.tap	= { 13, 11 }
+	},
+};
+
+struct cipher_testvec des_cbc_dec_tv_template[] = {
+	{ /* FIPS Pub 81 */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+		.input	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+		.ilen	= 8,
+		.result	= { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },		
+		.input	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+		.ilen	= 8,
+		.result	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
+		.ilen	= 8,
+		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+		.rlen	= 8,
+	}, { /* Copy of above, for chunk testing */	
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
+		.ilen	= 8,
+		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
+		.rlen	= 8,
+		.np	= 2,
+		.tap	= { 4, 4 }
 	},
 };
 
 /*
  * We really need some more test vectors, especially for DES3 CBC.
  */
-struct des_tv des3_ede_enc_tv_template[] = {
-
-	/* These are from openssl */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-		  
-		{ 0 },
-		
-		{ 0x73, 0x6F, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x61  },
-		
-		{ 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
-	},
-	
-	{
-		8, 0,
-		
-		{ 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17,
-		  0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98,
-		  0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57  },
-		 
-		{ 0 },
-		
-		{ 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65  },
-		
-		{ 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30  }
-	},
-	
-
-	{
-		8, 0,
-		
-		{ 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20,
-		  0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01,
-		  0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01  },
-		  
-		{ 0 },
-			  
-		{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00  },
-		
-		{ 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b  }	
+struct cipher_testvec des3_ede_enc_tv_template[] = {
+	{ /* These are from openssl */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		.klen	= 24,
+		.input	= { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
+		.ilen	= 8,
+		.result	= { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+			    0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+			    0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
+		.klen	= 24,
+		.input	= { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
+		.ilen	= 8,
+		.result	= { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			    0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+			    0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
+		.klen	= 24,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
+		.rlen	= 8,
 	},
 };
 
-struct des_tv des3_ede_dec_tv_template[] = {
-
-	/* These are from openssl */
-	{
-		8, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-		  
-		{ 0 },
-		
-		
-		{ 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
-		
-		{ 0x73, 0x6F, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x61  },
-	},
-	
-	{
-		8, 0,
-		
-		{ 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17,
-		  0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98,
-		  0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57  },
-		 
-		{ 0 },
-		
-		{ 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30  },
-		
-		{ 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65  },
-		
-	},
-	
-
-	{
-		8, 0,
-		
-		{ 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20,
-		  0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01,
-		  0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01  },
-		  
-		{ 0 },
-			  
-		{ 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b  },
-		
-		{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00  },
+struct cipher_testvec des3_ede_dec_tv_template[] = {
+	{ /* These are from openssl */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		.klen	= 24,
+		.input	= { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
+		.ilen	= 8,
+		.result	= { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+			    0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+			    0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
+		.klen	= 24,
+		.input	= { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
+		.ilen	= 8,
+		.result	= { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+			    0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+			    0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
+		.klen	= 24,
+		.input	= { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
 	},
 };
 
@@ -1090,189 +868,151 @@ struct des_tv des3_ede_dec_tv_template[]
 #define BF_CBC_ENC_TEST_VECTORS	1
 #define BF_CBC_DEC_TEST_VECTORS	1
 
-struct bf_tv {
-	unsigned int keylen;
-	unsigned int plen;
-	unsigned int rlen;
-	int fail;
-	char key[56];
-	char iv[8];
-	char plaintext[32];
-	char result[32];
-};
-
-struct bf_tv bf_enc_tv_template[] = {
-
-	/* DES test vectors from OpenSSL */
-	{
-		8, 8, 8, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
-		{ 0 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78 },
-	},
-	
-	{
-		8, 8, 8, 0,
-		{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E,  },
-		{ 0 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-		{ 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE },
-	},
-	
-	{
-		8, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, },
-		{ 0 },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		{ 0xE8, 0x7A, 0x24, 0x4E, 0x2C, 0xC8, 0x5E, 0x82 }
-	},
-	
-	/* Vary the keylength... */
-	
-	{
-		16, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F },
-		{ 0 },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		{ 0x93, 0x14, 0x28, 0x87, 0xEE, 0x3B, 0xE1, 0x5C }
-	},
-	
-	{
-		21, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
-		  0x00, 0x11, 0x22, 0x33, 0x44 },
-		{ 0 },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		{ 0xE6, 0xF5, 0x1E, 0xD7, 0x9B, 0x9D, 0xB2, 0x1F }
-	},
-	
-	/* Generated with bf488 */
-	{
-		56, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F, 
-		  0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76, 
-		  0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, 
-		  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
-		  { 0 },
-		  { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		  { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 }
-	}
-	
-};
-
-struct bf_tv bf_dec_tv_template[] = {
-
-	/* DES test vectors from OpenSSL */
-	{
-		8, 8, 8, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
-		{ 0 },
-		{ 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-	},
-	
-	{
-		8, 8, 8, 0,
-		{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E,  },
-		{ 0 },
-		{ 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }
-	},
-	
-	{
-		8, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, },
-		{ 0 },
-		{ 0xE8, 0x7A, 0x24, 0x4E, 0x2C, 0xC8, 0x5E, 0x82 },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
-	},
-	
-	/* Vary the keylength... */
-	
-	{
-		16, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F },
-		{ 0 },
-		{ 0x93, 0x14, 0x28, 0x87, 0xEE, 0x3B, 0xE1, 0x5C },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
-	},
-	
-	{
-		21, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
-		  0x00, 0x11, 0x22, 0x33, 0x44 },
-		{ 0 },
-		{ 0xE6, 0xF5, 0x1E, 0xD7, 0x9B, 0x9D, 0xB2, 0x1F },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
-	},
-	
-	/* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */
-	{
-		56, 8, 8, 0,
-		{ 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
-		  0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F, 
-		  0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76, 
-		  0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, 
-		  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
-		{ 0 },
-		{ 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
-	}
-};
-
-struct bf_tv bf_cbc_enc_tv_template[] = {
-
-	/* From OpenSSL */
-	{
-		16, 32, 32, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 },
-		  
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		
-		{ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
-		  0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
-		  0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20,
-		  0x66, 0x6F, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
-		  
-		{ 0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6,
-		  0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93,
-		  0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9,
-		  0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC }
-	},
-};
-
-struct bf_tv bf_cbc_dec_tv_template[] = {
-
-	/* From OpenSSL */
-	{
-		16, 32, 32, 0,
-		
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 },
-		  
-		{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-		
-		{ 0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6,
-		  0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93,
-		  0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9,
-		  0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC },
-		  
-		{ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
-		  0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
-		  0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20,
-		  0x66, 0x6F, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 }
+struct cipher_testvec bf_enc_tv_template[] = {
+	{ /* DES test vectors from OpenSSL */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 8,
+		.result	= { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
+		.rlen	= 8,
+	}, { /* Vary the keylength... */	
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
+		.klen	= 16,
+		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 8,
+		.result	= { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+			    0x00, 0x11, 0x22, 0x33, 0x44 },
+		.klen	= 21,
+		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 8,
+		.result	= { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
+		.rlen	= 8,
+	}, { /* Generated with bf488 */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, 
+			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, 
+			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 
+			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+		.klen	= 56,
+		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 8,
+		.result	= { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
+		.rlen	= 8,
+	},
+};
+
+struct cipher_testvec bf_dec_tv_template[] = {
+	{ /* DES test vectors from OpenSSL */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
+		.klen	= 8,
+		.input	= { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.input	= { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
+		.ilen	= 8,
+		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 8,
+	}, { /* Vary the keylength... */	
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
+		.klen	= 16,
+		.input	= { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
+		.ilen	= 8,
+		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+			    0x00, 0x11, 0x22, 0x33, 0x44 },
+		.klen	= 21,
+		.input	= { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
+		.ilen	= 8,
+		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 8,
+	}, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, 
+			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, 
+			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 
+			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+		.klen	= 56,
+		.input	= { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
+		.ilen	= 8,
+		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 8,
+	},
+};
+
+struct cipher_testvec bf_cbc_enc_tv_template[] = {
+	{ /* From OpenSSL */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 16,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },		
+		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+			    0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 32,
+		.result	= { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+			    0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+			    0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+			    0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
+		.rlen	= 32,
+	},
+};
+
+struct cipher_testvec bf_cbc_dec_tv_template[] = {
+	{ /* From OpenSSL */
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 16,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },		
+		.input	= { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+			    0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+			    0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+			    0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
+		.ilen	= 32,
+		.result	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+			    0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 32,
 	},
 };
 
@@ -1284,212 +1024,161 @@ struct bf_tv bf_cbc_dec_tv_template[] = 
 #define TF_CBC_ENC_TEST_VECTORS		4
 #define TF_CBC_DEC_TEST_VECTORS		4
 
-struct tf_tv {
-	unsigned int keylen;
-	unsigned int plen;
-	unsigned int rlen;
-	int fail;
-	char key[32];
-	char iv[16];
-	char plaintext[48];
-	char result[48];
-};
-
-struct tf_tv tf_enc_tv_template[] = {
-	{
-		16, 16, 16, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
-		  0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }
-	},
-	{
-		24, 16, 16, 0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
-		{ 0 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF,
-		  0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 }
-	},
-	{	
-		32, 16, 16, 0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },
-		{ 0 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
-		  0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 }
-	},
-};
-
-struct tf_tv tf_dec_tv_template[] = {
-	{
-		16, 16, 16, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0 },
-		{ 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
-		  0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  
-	},
-	{
-		24, 16, 16, 0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
-		{ 0 },
-		{ 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF,
-		  0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	},
-	{	
-		32, 16, 16, 0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
-		  0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-		  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },
-		{ 0 },
-		{ 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
-		  0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	},
-};
-
-struct tf_tv tf_cbc_enc_tv_template[] = {
-	/* Generated with Nettle */
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
-	},
-	
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
-	},
-	
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
-		  0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
-	},
-	
-	{
-		16, 48, 48, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
-		  0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
-		  0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
-		  0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
-	},
-};
-
-struct tf_tv tf_cbc_dec_tv_template[] = {
-	/* Reverse of the first four above */
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },		  
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	},
-	
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
-		{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  
-	},
-	
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
-		{ 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
-		  0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  
-	},
-	
+struct cipher_testvec tf_enc_tv_template[] = {
 	{
-		16, 48, 48, 0,
-		
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-		  0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
-		  0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
-		  0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
-		  0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
-		  0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+			    0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+			    0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
+		.rlen	= 16,
+	},
+};
+
+struct cipher_testvec tf_dec_tv_template[] = {
+	{
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+			    0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+			    0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	},
+};
+
+struct cipher_testvec tf_cbc_enc_tv_template[] = {
+	{ /* Generated with Nettle */
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { [0 ... 15] = 0x00 },
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },		
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { [0 ... 15] = 0x00 },
+		.input	= { [0 ... 47] = 0x00 },
+		.ilen	= 48,
+		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+			    0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+			    0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
+		.rlen	= 48,
+	},
+};
+
+struct cipher_testvec tf_cbc_dec_tv_template[] = {
+	{ /* Reverse of the first four above */
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { [0 ... 15] = 0x00 },
+		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },		  
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+		.input	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+		.input	= { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.iv	= { [0 ... 15] = 0x00 },
+		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+			    0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+			    0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
+		.ilen	= 48,
+		.result	= { [0 ... 47] = 0x00 },
+		.rlen	= 48,
 	},
 };
 
@@ -1500,179 +1189,162 @@ struct tf_tv tf_cbc_dec_tv_template[] = 
 #define SERPENT_ENC_TEST_VECTORS	4
 #define SERPENT_DEC_TEST_VECTORS	4
 
-struct serpent_tv {
-	unsigned int keylen, fail;
-	u8 key[32], plaintext[16], result[16];
-};
-
-struct serpent_tv serpent_enc_tv_template[] = 
+struct cipher_testvec serpent_enc_tv_template[] = 
 {
 	{
-		0, 0,
-		{ 0 },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
-		  0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 }
+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.ilen	= 16,
+		.result	= { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+			    0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.klen	= 16,
+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.ilen	= 16,
+		.result	= { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+			    0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.klen	= 32,
+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.ilen	= 16,
+		.result	= { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+			    0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
+		.rlen	= 16,
+	}, {
+		.key	= { [15] = 0x80 },
+		.klen	= 16,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+			    0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
+		.rlen	= 16,
 	},
-	{
-		16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
-		  0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d }
-	},
-	{
-		32, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
-		  0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c }
-	},
-	{
-		16, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
-		  0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49}
-	}
 };
 
-struct serpent_tv serpent_dec_tv_template[] = 
+struct cipher_testvec serpent_dec_tv_template[] = 
 {
 	{
-		0, 0,
-		{ 0 },
-		{ 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
-		  0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-
-	},
-	{
-		16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
-		  0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-	},
-	{
-		32, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-
-		{ 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
-		  0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.input	= { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+			    0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
+		.ilen	= 16,
+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.klen	= 16,
+		.input	= { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+			    0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
+		.ilen	= 16,
+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.klen	= 32,
+		.input	= { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+			    0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
+		.ilen	= 16,
+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.rlen	= 16,
+	}, {
+		.key	= { [15] = 0x80 },
+		.klen	= 16,
+		.input	= { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+			    0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
 	},
-	{
-		16, 0,
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
-		{ 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
-		  0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  
-	}
 };
 
 /* Cast6 test vectors from RFC 2612 */
 #define CAST6_ENC_TEST_VECTORS	3
 #define CAST6_DEC_TEST_VECTORS  3
 
-struct cast6_tv {
-	unsigned keylen;
-	unsigned fail;
-	u8 key[32];
-	u8 plaintext[16];
-	u8 result[16];
-};
-
-struct cast6_tv cast6_enc_tv_template[] = 
+struct cipher_testvec cast6_enc_tv_template[] = 
 {
 	{
-		16, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-		  0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
-		  0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
+		.klen	= 16,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
+			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
+			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
+		.klen	= 24,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
+			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
+		.klen	= 32,
+		.input	= { [0 ... 15] = 0x00 },
+		.ilen	= 16,
+		.result	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
+			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
+		.rlen	= 16,
 	},
-	{
-		24, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-		  0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
-		  0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
-		  0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
-	},
-	{
-		32, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
-                  0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
-		  0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
-		  0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-		{ 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
-		  0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
-	}
 };
 
-struct cast6_tv cast6_dec_tv_template[] = 
+struct cipher_testvec cast6_dec_tv_template[] = 
 {
 	{
-		16, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-		  0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
-		{ 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
-		  0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	},
-	{
-		24, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-		  0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
-		  0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
-		{ 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
-		  0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
+		.klen	= 16,
+		.input	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
+			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
+			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
+		.klen	= 24,
+		.input	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
+			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
+		.klen	= 32,
+		.input	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
+			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
+		.ilen	= 16,
+		.result	= { [0 ... 15] = 0x00 },
+		.rlen	= 16,
 	},
-	{
-		32, 
-		0,
-		{ 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
-                  0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
-		  0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
-		  0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
-		{ 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
-		  0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
-		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	}
 };
 
 
@@ -1682,90 +1354,77 @@ struct cast6_tv cast6_dec_tv_template[] 
 #define AES_ENC_TEST_VECTORS 3
 #define AES_DEC_TEST_VECTORS 3
 
-struct aes_tv {
-	unsigned int keylen;
-	unsigned int plen;
-	unsigned int rlen;
-	int fail;
-	char key[32];
-	char iv[8];
-	char plaintext[16];
-	char result[16];
-};
-
-struct aes_tv aes_enc_tv_template[] = { 
-	/* From FIPS-197 */
-	{
-		16, 16, 16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0 },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
-		{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
-		  0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
-	},
-	{
-		24, 16, 16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
-		{ 0 },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
-		{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
-		  0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
-	},
-	{
-		32, 16, 16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-		{ 0 },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
-		{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
-		  0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
-	},
-};
-
-struct aes_tv aes_dec_tv_template[] = { 
-	/* From FIPS-197 */
-	{
-		16, 16, 16, 0,
-		
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-		{ 0 },
-		{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
-		  0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
-	},
-	
-	{
-		24, 16, 16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
-		{ 0 },
-		{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
-		  0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },  
-	},
-	{
-		32, 16, 16, 0,
-		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-		{ 0 },
-		{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
-		  0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
-		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
-		  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+struct cipher_testvec aes_enc_tv_template[] = { 
+	{ /* From FIPS-197 */
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.klen	= 16,
+		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.ilen	= 16,
+		.result	= { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+			    0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+		.klen	= 24,
+		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.ilen	= 16,
+		.result	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+			    0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.klen	= 32,
+		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.ilen	= 16,
+		.result	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+			    0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
+		.rlen	= 16,
+	},
+};
+
+struct cipher_testvec aes_dec_tv_template[] = { 
+	{ /* From FIPS-197 */
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+		.klen	= 16,
+		.input	= { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+			    0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
+		.ilen	= 16,
+		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+		.klen	= 24,
+		.input	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+			    0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
+		.ilen	= 16,
+		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },  
+		.rlen	= 16,
+	}, {
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.klen	= 32,
+		.input	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+			    0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
+		.ilen	= 16,
+		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.rlen	= 16,
 	},
 };
 
@@ -1773,68 +1432,60 @@ struct aes_tv aes_dec_tv_template[] = { 
 #define CAST5_ENC_TEST_VECTORS	3
 #define CAST5_DEC_TEST_VECTORS	3
 
-struct cast5_tv {
-	unsigned keylen;
-	unsigned fail;
-	u8 key[16];
-	u8 plaintext[8];
-	u8 ciphertext[8];
-};
-
-struct cast5_tv cast5_enc_tv_template[] =
+struct cipher_testvec cast5_enc_tv_template[] =
 {
 	{
-		16,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
-		  0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
-
-	},
-	{
-		10,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
-		  0x23, 0x45 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+			    0x23, 0x45 },
+		.klen	= 10,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12 },
+		.klen	= 5,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
+		.rlen	= 8,
 	},
-	{
-		5,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-		{ 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
-	}
 };
 
-struct cast5_tv cast5_dec_tv_template[] =
+struct cipher_testvec cast5_dec_tv_template[] =
 {
 	{
-		16,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
-		  0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A },
-		{ 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-
-	},
-	{
-		10,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
-		  0x23, 0x45 },
-		{ 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
+		.klen	= 16,
+		.input	= { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+			    0x23, 0x45 },
+		.klen	= 10,
+		.input	= { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12 },
+		.klen	= 5,
+		.input	= { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
 	},
-	{
-		5,
-		0,
-		{ 0x01, 0x23, 0x45, 0x67, 0x12 },
-		{ 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
-		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
-	}
 };
 
 /*
@@ -1857,83 +1508,73 @@ struct comp_testvec {
 
 struct comp_testvec deflate_comp_tv_template[] = {
 	{
-	  70, 38,
-	  
-	  "Join us now and share the software "
-	  "Join us now and share the software ",
-
-          { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
-            0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
-            0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
-            0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
-            0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 
-          },
-	},
-	  
-	{
-	  191, 122,
-	  
-	  "This document describes a compression method based on the DEFLATE"
-	  "compression algorithm.  This document defines the application of "
-	  "the DEFLATE algorithm to the IP Payload Compression Protocol.",
-	  
-	  { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
-	    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
-	    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
-	    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
-	    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
-	    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
-	    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
-	    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
-	    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
-	    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
-	    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
-	    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
-	    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
-	    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
-	    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
-	    0xfa, 0x02 },
+		.inlen	= 70,
+		.outlen	= 38,
+	  	.input	= "Join us now and share the software "
+			  "Join us now and share the software ",
+		.output	= { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+			    0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+			    0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+			    0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+			    0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
+	}, {
+		.inlen	= 191,
+		.outlen	= 122,
+		.input	= "This document describes a compression method based on the DEFLATE"
+			  "compression algorithm.  This document defines the application of "
+			  "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+		.output	= { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+			    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+			    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+			    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+			    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+			    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+			    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+			    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+			    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+			    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+			    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+			    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+			    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+			    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+			    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+			    0xfa, 0x02 },
 	},
 };
 
 struct comp_testvec deflate_decomp_tv_template[] = {
 	{
-	  122, 191,
-	  
-	  { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
-	    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
-	    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
-	    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
-	    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
-	    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
-	    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
-	    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
-	    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
-	    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
-	    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
-	    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
-	    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
-	    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
-	    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
-	    0xfa, 0x02 },
-	    
-	    "This document describes a compression method based on the DEFLATE"
-	    "compression algorithm.  This document defines the application of "
-	    "the DEFLATE algorithm to the IP Payload Compression Protocol.",
-	},
-	
-	{
-	  38, 70,
-	  
-          { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
-            0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
-            0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
-            0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
-            0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00
-          },
-          
-          "Join us now and share the software "
-	  "Join us now and share the software ",
+		.inlen	= 122,
+		.outlen	= 191,
+		.input	= { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+			    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+			    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+			    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+			    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+			    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+			    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+			    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+			    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+			    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+			    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+			    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+			    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+			    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+			    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+			    0xfa, 0x02 },
+		.output	= "This document describes a compression method based on the DEFLATE"
+			  "compression algorithm.  This document defines the application of "
+			  "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+	}, {
+		.inlen	= 38,
+		.outlen	= 70,
+		.input	= { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+			    0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+			    0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+			    0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+			    0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
+		.output	= "Join us now and share the software "
+			  "Join us now and share the software ",
 	},
 };
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/acorn/char/i2c.c 001-linus.patch/drivers/acorn/char/i2c.c
--- 000-virgin/drivers/acorn/char/i2c.c	Wed Dec 17 18:59:59 2003
+++ 001-linus.patch/drivers/acorn/char/i2c.c	Tue Dec 30 16:38:57 2003
@@ -280,13 +280,15 @@ static int ioc_client_reg(struct i2c_cli
 	    client->addr == 0x50) {
 		struct rtc_tm rtctm;
 		unsigned int year;
+		struct timespec tv;
 
 		rtc_client = client;
 		get_rtc_time(&rtctm, &year);
 
-		xtime.tv_nsec = rtctm.cs * 10000000;
-		xtime.tv_sec  = mktime(year, rtctm.mon, rtctm.mday,
-				       rtctm.hours, rtctm.mins, rtctm.secs);
+		tv.tv_nsec = rtctm.cs * 10000000;
+		tv.tv_sec  = mktime(year, rtctm.mon, rtctm.mday,
+				    rtctm.hours, rtctm.mins, rtctm.secs);
+		do_settimeofday(&tv);
 		set_rtc = k_set_rtc_time;
 	}
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/acpi/Kconfig 001-linus.patch/drivers/acpi/Kconfig
--- 000-virgin/drivers/acpi/Kconfig	Wed Dec 17 18:59:57 2003
+++ 001-linus.patch/drivers/acpi/Kconfig	Tue Dec 30 16:38:57 2003
@@ -251,12 +251,6 @@ config ACPI_SYSTEM
 	  This driver will enable your system to shut down using ACPI, and
 	  dump your ACPI DSDT table using /proc/acpi/dsdt.
 
-config ACPI_EFI
-	bool
-	depends on ACPI_INTERPRETER
-	depends on IA64
-	default y
-
 config ACPI_RELAXED_AML
 	bool "Relaxed AML"
 	depends on ACPI_INTERPRETER
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/acpi/osl.c 001-linus.patch/drivers/acpi/osl.c
--- 000-virgin/drivers/acpi/osl.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/drivers/acpi/osl.c	Tue Dec 30 16:38:57 2003
@@ -41,10 +41,7 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_ACPI_EFI
 #include <linux/efi.h>
-u64 efi_mem_attributes (u64 phys_addr);
-#endif
 
 
 #define _COMPONENT		ACPI_OS_SERVICES
@@ -140,22 +137,24 @@ acpi_os_free(void *ptr)
 acpi_status
 acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
 {
-#ifdef CONFIG_ACPI_EFI
-	addr->pointer_type = ACPI_PHYSICAL_POINTER;
-	if (efi.acpi20)
-		addr->pointer.physical = (acpi_physical_address) virt_to_phys(efi.acpi20);
-	else if (efi.acpi)
-		addr->pointer.physical = (acpi_physical_address) virt_to_phys(efi.acpi);
-	else {
-		printk(KERN_ERR PREFIX "System description tables not found\n");
-		return AE_NOT_FOUND;
-	}
-#else
-	if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
-		printk(KERN_ERR PREFIX "System description tables not found\n");
-		return AE_NOT_FOUND;
+	if (efi_enabled) {
+		addr->pointer_type = ACPI_PHYSICAL_POINTER;
+		if (efi.acpi20)
+			addr->pointer.physical =
+				(acpi_physical_address) virt_to_phys(efi.acpi20);
+		else if (efi.acpi)
+			addr->pointer.physical =
+				(acpi_physical_address) virt_to_phys(efi.acpi);
+		else {
+			printk(KERN_ERR PREFIX "System description tables not found\n");
+			return AE_NOT_FOUND;
+		}
+	} else {
+		if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
+			printk(KERN_ERR PREFIX "System description tables not found\n");
+			return AE_NOT_FOUND;
+		}
 	}
-#endif /*CONFIG_ACPI_EFI*/
 
 	return AE_OK;
 }
@@ -163,22 +162,22 @@ acpi_os_get_root_pointer(u32 flags, stru
 acpi_status
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt)
 {
-#ifdef CONFIG_ACPI_EFI
-	if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
-		*virt = phys_to_virt(phys);
+	if (efi_enabled) {
+		if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
+			*virt = phys_to_virt(phys);
+		} else {
+			*virt = ioremap(phys, size);
+		}
 	} else {
-		*virt = ioremap(phys, size);
-	}
-#else
-	if (phys > ULONG_MAX) {
-		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
-		return AE_BAD_PARAMETER;
+		if (phys > ULONG_MAX) {
+			printk(KERN_ERR PREFIX "Cannot map memory that high\n");
+			return AE_BAD_PARAMETER;
+		}
+		/*
+	 	 * ioremap checks to ensure this is in reserved space
+	 	 */
+		*virt = ioremap((unsigned long) phys, size);
 	}
-	/*
-	 * ioremap checks to ensure this is in reserved space
-	 */
-	*virt = ioremap((unsigned long) phys, size);
-#endif
 
 	if (!*virt)
 		return AE_NO_MEMORY;
@@ -369,19 +368,17 @@ acpi_os_read_memory(
 {
 	u32			dummy;
 	void			*virt_addr;
-
-#ifdef CONFIG_ACPI_EFI
 	int			iomem = 0;
 
-	if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
+	if (efi_enabled) {
+		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
+			virt_addr = phys_to_virt(phys_addr);
+		} else {
+			iomem = 1;
+			virt_addr = ioremap(phys_addr, width);
+		}
+	} else
 		virt_addr = phys_to_virt(phys_addr);
-	} else {
-		iomem = 1;
-		virt_addr = ioremap(phys_addr, width);
-	}
-#else
-	virt_addr = phys_to_virt(phys_addr);
-#endif
 	if (!value)
 		value = &dummy;
 
@@ -399,10 +396,10 @@ acpi_os_read_memory(
 		BUG();
 	}
 
-#ifdef CONFIG_ACPI_EFI
-	if (iomem)
-		iounmap(virt_addr);
-#endif
+	if (efi_enabled) {
+		if (iomem)
+			iounmap(virt_addr);
+	}
 
 	return AE_OK;
 }
@@ -414,19 +411,17 @@ acpi_os_write_memory(
 	u32			width)
 {
 	void			*virt_addr;
-
-#ifdef CONFIG_ACPI_EFI
 	int			iomem = 0;
 
-	if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
+	if (efi_enabled) {
+		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
+			virt_addr = phys_to_virt(phys_addr);
+		} else {
+			iomem = 1;
+			virt_addr = ioremap(phys_addr, width);
+		}
+	} else
 		virt_addr = phys_to_virt(phys_addr);
-	} else {
-		iomem = 1;
-		virt_addr = ioremap(phys_addr, width);
-	}
-#else
-	virt_addr = phys_to_virt(phys_addr);
-#endif
 
 	switch (width) {
 	case 8:
@@ -442,10 +437,8 @@ acpi_os_write_memory(
 		BUG();
 	}
 
-#ifdef CONFIG_ACPI_EFI
 	if (iomem)
 		iounmap(virt_addr);
-#endif
 
 	return AE_OK;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/acpi/pci_irq.c 001-linus.patch/drivers/acpi/pci_irq.c
--- 000-virgin/drivers/acpi/pci_irq.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/acpi/pci_irq.c	Tue Dec 30 16:38:57 2003
@@ -237,7 +237,7 @@ acpi_pci_irq_add_prt (
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
 
-static int
+int
 acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
 {
 	struct acpi_prt_entry	*entry = NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/base/node.c 001-linus.patch/drivers/base/node.c
--- 000-virgin/drivers/base/node.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/drivers/base/node.c	Tue Dec 30 16:38:57 2003
@@ -18,18 +18,16 @@ static struct sysdev_class node_class = 
 static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
 {
 	struct node *node_dev = to_node(dev);
-	cpumask_t tmp = node_dev->cpumap;
-	int k, len = 0;
+	cpumask_t mask = node_dev->cpumap;
+	int len;
 
-	for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
-		int j = sprintf(buf, "%04hx", (u16)cpus_coerce(tmp));
-		len += j;
-		buf += j;
-		cpus_shift_right(tmp, tmp, 16);
-	}
-        len += sprintf(buf, "\n");
+	/* FIXME - someone should pass us a buffer size (count) or
+	 * use seq_file or something to avoid buffer overrun risk. */
+	len = cpumask_snprintf(buf, 99 /* XXX FIXME */, mask);
+	len += sprintf(buf + len, "\n");
 	return len;
 }
+
 static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL);
 
 #define K(x) ((x) << (PAGE_SHIFT - 10))
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/base/platform.c 001-linus.patch/drivers/base/platform.c
--- 000-virgin/drivers/base/platform.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/drivers/base/platform.c	Tue Dec 30 16:38:57 2003
@@ -14,8 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-struct device legacy_bus = {
-	.bus_id		= "legacy",
+struct device platform_bus = {
+	.bus_id		= "platform",
 };
 
 /**
@@ -29,7 +29,7 @@ int platform_device_register(struct plat
 		return -EINVAL;
 
 	if (!pdev->dev.parent)
-		pdev->dev.parent = &legacy_bus;
+		pdev->dev.parent = &platform_bus;
 
 	pdev->dev.bus = &platform_bus_type;
 	
@@ -105,11 +105,11 @@ struct bus_type platform_bus_type = {
 
 int __init platform_bus_init(void)
 {
-	device_register(&legacy_bus);
+	device_register(&platform_bus);
 	return bus_register(&platform_bus_type);
 }
 
-EXPORT_SYMBOL(legacy_bus);
+EXPORT_SYMBOL(platform_bus);
 EXPORT_SYMBOL(platform_bus_type);
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/block/DAC960.c 001-linus.patch/drivers/block/DAC960.c
--- 000-virgin/drivers/block/DAC960.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/drivers/block/DAC960.c	Tue Dec 30 16:38:57 2003
@@ -2474,7 +2474,6 @@ static boolean DAC960_V2_ReportDeviceCon
 static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
-  struct request_queue *RequestQueue;
   int n;
 
   /*
@@ -2483,26 +2482,22 @@ static boolean DAC960_RegisterBlockDevic
   if (register_blkdev(MajorNumber, "dac960") < 0)
       return false;
 
-  /*
-    Initialize the I/O Request Queue.
-  */
-  RequestQueue = blk_init_queue(DAC960_RequestFunction,&Controller->queue_lock);
-  if (!RequestQueue) {
-      unregister_blkdev(MajorNumber, "dac960");
-      return false;
-  }
-  Controller->RequestQueue = RequestQueue;
-  blk_queue_bounce_limit(RequestQueue, Controller->BounceBufferLimit);
-  RequestQueue->queuedata = Controller;
-  blk_queue_max_hw_segments(RequestQueue,
-			    Controller->DriverScatterGatherLimit);
-  blk_queue_max_phys_segments(RequestQueue,
-		 	    Controller->DriverScatterGatherLimit);
-  blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
-
   for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
 	struct gendisk *disk = Controller->disks[n];
+  	struct request_queue *RequestQueue;
 
+	/* for now, let all request queues share controller's lock */
+  	RequestQueue = blk_init_queue(DAC960_RequestFunction,&Controller->queue_lock);
+  	if (!RequestQueue) {
+		printk("DAC960: failure to allocate request queue\n");
+		continue;
+  	}
+  	Controller->RequestQueue[n] = RequestQueue;
+  	blk_queue_bounce_limit(RequestQueue, Controller->BounceBufferLimit);
+  	RequestQueue->queuedata = Controller;
+  	blk_queue_max_hw_segments(RequestQueue, Controller->DriverScatterGatherLimit);
+	blk_queue_max_phys_segments(RequestQueue, Controller->DriverScatterGatherLimit);
+	blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
 	disk->queue = RequestQueue;
 	sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
 	sprintf(disk->devfs_name, "rd/host%d/target%d", Controller->ControllerNumber, n);
@@ -2527,17 +2522,17 @@ static void DAC960_UnregisterBlockDevice
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
   int disk;
 
-  for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++)
-	  del_gendisk(Controller->disks[disk]);
+  /* does order matter when deleting gendisk and cleanup in request queue? */
+  for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
+	del_gendisk(Controller->disks[disk]);
+	blk_cleanup_queue(Controller->RequestQueue[disk]);
+	Controller->RequestQueue[disk] = NULL;
+  }
 
   /*
     Unregister the Block Device Major Number for this DAC960 Controller.
   */
   unregister_blkdev(MajorNumber, "dac960");
-  /*
-    Remove the I/O Request Queue.
-  */
-  blk_cleanup_queue(Controller->RequestQueue);
 }
 
 /*
@@ -3253,58 +3248,83 @@ static void DAC960_V2_QueueReadWriteComm
 }
 
 
+static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_queue *req_q)
+{
+	struct request *Request;
+	DAC960_Command_T *Command;
+
+   while(1) {
+	Request = elv_next_request(req_q);
+	if (!Request)
+		return 1;
+
+	Command = DAC960_AllocateCommand(Controller);
+	if (Command == NULL)
+		return 0;
+
+	if (rq_data_dir(Request) == READ) {
+		Command->DmaDirection = PCI_DMA_FROMDEVICE;
+		Command->CommandType = DAC960_ReadCommand;
+	} else {
+		Command->DmaDirection = PCI_DMA_TODEVICE;
+		Command->CommandType = DAC960_WriteCommand;
+	}
+	Command->Completion = Request->waiting;
+	Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
+	Command->BlockNumber = Request->sector;
+	Command->BlockCount = Request->nr_sectors;
+	Command->Request = Request;
+	blkdev_dequeue_request(Request);
+	Command->SegmentCount = blk_rq_map_sg(req_q,
+		  Command->Request, Command->cmd_sglist);
+	/* pci_map_sg MAY change the value of SegCount */
+	Command->SegmentCount = pci_map_sg(Controller->PCIDevice, Command->cmd_sglist,
+		 Command->SegmentCount, Command->DmaDirection);
+
+	DAC960_QueueReadWriteCommand(Command);
+  }
+}
+
 /*
   DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
   I/O Request Queue and queues it to the Controller.  WaitForCommand is true if
   this function should wait for a Command to become available if necessary.
   This function returns true if an I/O Request was queued and false otherwise.
 */
-
-static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
-				     boolean WaitForCommand)
+static void DAC960_ProcessRequest(DAC960_Controller_T *controller)
 {
-  struct request_queue *RequestQueue = Controller->RequestQueue;
-  struct request *Request;
-  DAC960_Command_T *Command;
+	int i;
 
-  if (!Controller->ControllerInitialized)
-     return false;
+	if (!controller->ControllerInitialized)
+		return;
 
-  while (true) {
-      Request = elv_next_request(RequestQueue);
-      if (!Request)
-	      return false;
+	/* Do this better later! */
+	for (i = controller->req_q_index; i < DAC960_MaxLogicalDrives; i++) {
+		struct request_queue *req_q = controller->RequestQueue[i];
 
-      Command = DAC960_AllocateCommand(Controller);
-      if (Command != NULL)
-          break;
+		if (req_q == NULL)
+			continue;
 
-      if (!WaitForCommand)
-          return false;
+		if (!DAC960_process_queue(controller, req_q)) {
+			controller->req_q_index = i;
+			return;
+		}
+	}
 
-      DAC960_WaitForCommand(Controller);
-  }
-  if (rq_data_dir(Request) == READ) {
-    Command->DmaDirection = PCI_DMA_FROMDEVICE;
-    Command->CommandType = DAC960_ReadCommand;
-  } else {
-    Command->DmaDirection = PCI_DMA_TODEVICE;
-    Command->CommandType = DAC960_WriteCommand;
-  }
-  Command->Completion = Request->waiting;
-  Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
-  Command->BlockNumber = Request->sector;
-  Command->BlockCount = Request->nr_sectors;
-  Command->Request = Request;
-  blkdev_dequeue_request(Request);
-  Command->SegmentCount = blk_rq_map_sg(Controller->RequestQueue,
-		  Command->Request, Command->cmd_sglist);
-  /* pci_map_sg MAY change the value of SegCount */
-  Command->SegmentCount = pci_map_sg(Controller->PCIDevice, Command->cmd_sglist,
-		 Command->SegmentCount, Command->DmaDirection);
+	if (controller->req_q_index == 0)
+		return;
 
-  DAC960_QueueReadWriteCommand(Command);
-  return true;
+	for (i = 0; i < controller->req_q_index; i++) {
+		struct request_queue *req_q = controller->RequestQueue[i];
+
+		if (req_q == NULL)
+			continue;
+
+		if (!DAC960_process_queue(controller, req_q)) {
+			controller->req_q_index = i;
+			return;
+		}
+	}
 }
 
 
@@ -3321,6 +3341,7 @@ static void DAC960_queue_partial_rw(DAC9
 {
   DAC960_Controller_T *Controller = Command->Controller;
   struct request *Request = Command->Request;
+  struct request_queue *req_q = Controller->RequestQueue[Command->LogicalDriveNumber];
 
   if (Command->DmaDirection == PCI_DMA_FROMDEVICE)
     Command->CommandType = DAC960_ReadRetryCommand;
@@ -3333,11 +3354,9 @@ static void DAC960_queue_partial_rw(DAC9
    * code should almost never be called, just go with a
    * simple coding.
    */
-  (void)blk_rq_map_sg(Controller->RequestQueue, Command->Request,
-                                        Command->cmd_sglist);
+  (void)blk_rq_map_sg(req_q, Command->Request, Command->cmd_sglist);
 
-  (void)pci_map_sg(Controller->PCIDevice, Command->cmd_sglist, 1,
-		                        Command->DmaDirection);
+  (void)pci_map_sg(Controller->PCIDevice, Command->cmd_sglist, 1, Command->DmaDirection);
   /*
    * Resubmitting the request sector at a time is really tedious.
    * But, this should almost never happen.  So, we're willing to pay
@@ -3357,9 +3376,7 @@ static void DAC960_queue_partial_rw(DAC9
 
 static void DAC960_RequestFunction(struct request_queue *RequestQueue)
 {
-	int i = 0;
-	while (DAC960_ProcessRequest(RequestQueue->queuedata, (i++ == 0)))
-		;
+	DAC960_ProcessRequest(RequestQueue->queuedata);
 }
 
 /*
@@ -5205,8 +5222,7 @@ static irqreturn_t DAC960_BA_InterruptHa
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5249,8 +5265,7 @@ static irqreturn_t DAC960_LP_InterruptHa
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5289,8 +5304,7 @@ static irqreturn_t DAC960_LA_InterruptHa
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5329,8 +5343,7 @@ static irqreturn_t DAC960_PG_InterruptHa
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5365,8 +5378,7 @@ static irqreturn_t DAC960_PD_InterruptHa
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5440,8 +5452,7 @@ static irqreturn_t DAC960_P_InterruptHan
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-	  ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/block/DAC960.h 001-linus.patch/drivers/block/DAC960.h
--- 000-virgin/drivers/block/DAC960.h	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/drivers/block/DAC960.h	Tue Dec 30 16:38:57 2003
@@ -2333,7 +2333,8 @@ typedef struct DAC960_Controller
   DAC960_Command_T *FreeCommands;
   unsigned char *CombinedStatusBuffer;
   unsigned char *CurrentStatusBuffer;
-  struct request_queue *RequestQueue;
+  struct request_queue *RequestQueue[DAC960_MaxLogicalDrives];
+  int req_q_index;
   spinlock_t queue_lock;
   wait_queue_head_t CommandWaitQueue;
   wait_queue_head_t HealthStatusWaitQueue;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/block/ll_rw_blk.c 001-linus.patch/drivers/block/ll_rw_blk.c
--- 000-virgin/drivers/block/ll_rw_blk.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/drivers/block/ll_rw_blk.c	Tue Dec 30 16:38:57 2003
@@ -2460,7 +2460,7 @@ static int __end_that_request_first(stru
 
 	if (!uptodate) {
 		error = -EIO;
-		if (!(req->flags & REQ_QUIET))
+		if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
 			printk("end_request: I/O error, dev %s, sector %llu\n",
 				req->rq_disk ? req->rq_disk->disk_name : "?",
 				(unsigned long long)req->sector);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/agp/alpha-agp.c 001-linus.patch/drivers/char/agp/alpha-agp.c
--- 000-virgin/drivers/char/agp/alpha-agp.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/char/agp/alpha-agp.c	Tue Dec 30 16:38:57 2003
@@ -13,7 +13,7 @@
 
 static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma,
 					     unsigned long address,
-					     int write_access)
+					     int *type)
 {
 	alpha_agp_info *agp = agp_bridge->dev_private_data;
 	dma_addr_t dma_addr;
@@ -30,6 +30,8 @@ static struct page *alpha_core_agp_vm_no
 	 */
 	page = virt_to_page(__va(pa));
 	get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/drm/drmP.h 001-linus.patch/drivers/char/drm/drmP.h
--- 000-virgin/drivers/char/drm/drmP.h	Wed Dec 17 18:59:16 2003
+++ 001-linus.patch/drivers/char/drm/drmP.h	Tue Dec 30 16:38:57 2003
@@ -760,16 +760,16 @@ extern int	     DRM(fasync)(int fd, stru
 				/* Mapping support (drm_vm.h) */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 				   unsigned long address,
-				   int write_access);
+				   int *type);
 extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
-				       int write_access);
+				       int *type);
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
-				       int write_access);
+				       int *type);
 extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
 				      unsigned long address,
-				      int write_access);
+				      int *type);
 extern void	     DRM(vm_open)(struct vm_area_struct *vma);
 extern void	     DRM(vm_close)(struct vm_area_struct *vma);
 extern void	     DRM(vm_shm_close)(struct vm_area_struct *vma);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/drm/drm_vm.h 001-linus.patch/drivers/char/drm/drm_vm.h
--- 000-virgin/drivers/char/drm/drm_vm.h	Wed Dec 17 18:59:59 2003
+++ 001-linus.patch/drivers/char/drm/drm_vm.h	Tue Dec 30 16:38:57 2003
@@ -76,7 +76,7 @@ struct vm_operations_struct   DRM(vm_sg_
  */
 struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 			    unsigned long address,
-			    int write_access)
+			    int *type)
 {
 #if __REALLY_HAVE_AGP
 	drm_file_t *priv  = vma->vm_file->private_data;
@@ -133,6 +133,8 @@ struct page *DRM(vm_nopage)(struct vm_ar
 			  baddr, __va(agpmem->memory->memory[offset]), offset,
 			  atomic_read(&page->count));
 
+		if (type)
+			*type = VM_FAULT_MINOR;
 		return page;
         }
 vm_nopage_error:
@@ -154,7 +156,7 @@ vm_nopage_error:
  */
 struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 				unsigned long address,
-				int write_access)
+				int *type)
 {
 	drm_map_t	 *map	 = (drm_map_t *)vma->vm_private_data;
 	unsigned long	 offset;
@@ -170,6 +172,8 @@ struct page *DRM(vm_shm_nopage)(struct v
 	if (!page)
 		return NOPAGE_OOM;
 	get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 
 	DRM_DEBUG("shm_nopage 0x%lx\n", address);
 	return page;
@@ -268,7 +272,7 @@ void DRM(vm_shm_close)(struct vm_area_st
  */
 struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 				unsigned long address,
-				int write_access)
+				int *type)
 {
 	drm_file_t	 *priv	 = vma->vm_file->private_data;
 	drm_device_t	 *dev	 = priv->dev;
@@ -287,6 +291,8 @@ struct page *DRM(vm_dma_nopage)(struct v
 			     (offset & (~PAGE_MASK))));
 
 	get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 
 	DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
 	return page;
@@ -304,7 +310,7 @@ struct page *DRM(vm_dma_nopage)(struct v
  */
 struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
 			       unsigned long address,
-			       int write_access)
+			       int *type)
 {
 	drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
 	drm_file_t *priv = vma->vm_file->private_data;
@@ -325,6 +331,8 @@ struct page *DRM(vm_sg_nopage)(struct vm
 	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
 	page = entry->pagelist[page_offset];
 	get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 
 	return page;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/keyboard.c 001-linus.patch/drivers/char/keyboard.c
--- 000-virgin/drivers/char/keyboard.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/drivers/char/keyboard.c	Tue Dec 30 16:38:57 2003
@@ -941,16 +941,16 @@ static unsigned short x86_keycodes[256] 
 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-	 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
-	284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
-	367,288,302,304,350, 92,334,512,116,377,109,111,373,347,348,349,
-	360, 93, 94, 95, 98,376,100,101,321,316,354,286,289,102,351,355,
+	 80, 81, 82, 83, 84, 93, 86, 87, 88, 94, 95, 85,259,375,260, 90,
+	284,285,309,311,312, 91,327,328,329,331,333,335,336,337,338,339,
+	367,288,302,304,350, 89,334,326,116,377,109,111,126,347,348,349,
+	360,261,262,263,298,376,100,101,321,316,373,286,289,102,351,355,
 	103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
-	291,108,381,281,290,272,292,305,280, 99,112,257,258,359,270,114,
-	118,117,125,374,379,115,112,125,121,123,264,265,266,267,268,269,
-	271,273,276,277,278,282,283,295,296,297,299,300,301,293,303,307,
-	308,310,313,314,315,317,318,319,320,357,322,323,324,325,326,330,
-	332,340,365,342,343,344,345,346,356,113,341,368,369,370,371,372 };
+	291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+	264,117,271,374,379,115,125,273,121,123, 92,265,266,267,268,269,
+	120,119,118,277,278,282,283,295,296,297,299,300,301,293,303,307,
+	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
+	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
 
 #ifdef CONFIG_MAC_EMUMOUSEBTN
 extern int mac_hid_mouse_emulate_buttons(int, int, int);
@@ -972,11 +972,18 @@ static int emulate_raw(struct vc_data *v
 	if (keycode > 255 || !x86_keycodes[keycode])
 		return -1; 
 
-	if (keycode == KEY_PAUSE) {
-		put_queue(vc, 0xe1);
-		put_queue(vc, 0x1d | up_flag);
-		put_queue(vc, 0x45 | up_flag);
-		return 0;
+	switch (keycode) {
+		case KEY_PAUSE:
+			put_queue(vc, 0xe1);
+			put_queue(vc, 0x1d | up_flag);
+			put_queue(vc, 0x45 | up_flag);
+			return 0;
+		case KEY_LANG1:
+			if (!up_flag) put_queue(vc, 0xf1);
+			return 0;
+		case KEY_LANG2:
+			if (!up_flag) put_queue(vc, 0xf2);
+			return 0;
 	} 
 
 	if (keycode == KEY_SYSRQ && sysrq_alt) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/vt_ioctl.c 001-linus.patch/drivers/char/vt_ioctl.c
--- 000-virgin/drivers/char/vt_ioctl.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/drivers/char/vt_ioctl.c	Tue Dec 30 16:38:57 2003
@@ -332,7 +332,7 @@ do_fontx_ioctl(int cmd, struct consolefo
 }
 
 static inline int 
-do_unimap_ioctl(int cmd, struct unimapdesc *user_ud,int perm)
+do_unimap_ioctl(int cmd, struct unimapdesc *user_ud, int perm, unsigned int console)
 {
 	struct unimapdesc tmp;
 	int i = 0; 
@@ -348,9 +348,11 @@ do_unimap_ioctl(int cmd, struct unimapde
 	case PIO_UNIMAP:
 		if (!perm)
 			return -EPERM;
-		return con_set_unimap(fg_console, tmp.entry_ct, tmp.entries);
+		return con_set_unimap(console, tmp.entry_ct, tmp.entries);
 	case GIO_UNIMAP:
-		return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
+		if (!perm && fg_console != console)
+			return -EPERM;
+		return con_get_unimap(console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
 	}
 	return 0;
 }
@@ -966,13 +968,13 @@ int vt_ioctl(struct tty_struct *tty, str
 			return -EPERM;
 		i = copy_from_user(&ui, (void *)arg, sizeof(struct unimapinit));
 		if (i) return -EFAULT;
-		con_clear_unimap(fg_console, &ui);
+		con_clear_unimap(console, &ui);
 		return 0;
 	      }
 
 	case PIO_UNIMAP:
 	case GIO_UNIMAP:
-		return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm);
+		return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm, console);
 
 	case VT_LOCKSWITCH:
 		if (!capable(CAP_SYS_TTY_CONFIG))
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/Kconfig 001-linus.patch/drivers/char/watchdog/Kconfig
--- 000-virgin/drivers/char/watchdog/Kconfig	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/char/watchdog/Kconfig	Tue Dec 30 16:38:57 2003
@@ -17,7 +17,7 @@ config WATCHDOG
 	  implementation entirely in software (which can sometimes fail to
 	  reboot the machine) and a driver for hardware watchdog boards, which
 	  are more robust and can also keep track of the temperature inside
-	  your computer. For details, read <file:Documentation/watchdog.txt>
+	  your computer. For details, read <file:Documentation/watchdog/watchdog.txt>
 	  in the kernel source.
 
 	  The watchdog is usually used together with the watchdog daemon
@@ -114,7 +114,7 @@ config PCWATCHDOG
 	  This card simply watches your kernel to make sure it doesn't freeze,
 	  and if it does, it reboots your computer after a certain amount of
 	  time. This driver is like the WDT501 driver but for different
-	  hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
+	  hardware. Please read <file:Documentation/watchdog/pcwd-watchdog.txt>. The PC
 	  watchdog cards can be ordered from <http://www.berkprod.com/>.
 
 	  To compile this driver as a module, choose M here: the
@@ -276,6 +276,21 @@ config W83877F_WDT
 
 	  Most people will say N.
 
+config W83627HF_WDT
+	tristate "W83627HF Watchdog Timer"
+	depends on WATCHDOG
+	---help---
+	  This is the driver for the hardware watchdog on the W83627HF chipset
+	  as used in Advantech PC-9578 and Tyan S2721-533 motherboards
+	  (and likely others).  This watchdog simply watches your kernel to
+	  make sure it doesn't freeze, and if it does, it reboots your computer
+	  after a certain amount of time.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called w83627hf_wdt.
+
+	  Most people will say N.
+
 config MACHZ_WDT
 	tristate "ZF MachZ Watchdog"
 	depends on WATCHDOG
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/Makefile 001-linus.patch/drivers/char/watchdog/Makefile
--- 000-virgin/drivers/char/watchdog/Makefile	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/drivers/char/watchdog/Makefile	Tue Dec 30 16:38:57 2003
@@ -25,6 +25,7 @@ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_
 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
 obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
 obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
 obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/i810-tco.c 001-linus.patch/drivers/char/watchdog/i810-tco.c
--- 000-virgin/drivers/char/watchdog/i810-tco.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/drivers/char/watchdog/i810-tco.c	Tue Dec 30 16:38:57 2003
@@ -232,9 +232,8 @@ static ssize_t i810tco_write (struct fil
 
 		/* someone wrote to us, we should reload the timer */
 		tco_timer_reload ();
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static int i810tco_ioctl (struct inode *inode, struct file *file,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/ib700wdt.c 001-linus.patch/drivers/char/watchdog/ib700wdt.c
--- 000-virgin/drivers/char/watchdog/ib700wdt.c	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/drivers/char/watchdog/ib700wdt.c	Tue Dec 30 16:38:57 2003
@@ -161,9 +161,8 @@ ibwdt_write(struct file *file, const cha
 			}
 		}
 		ibwdt_ping();
-		return 1;
 	}
-	return 0;
+	return count;
 }
 
 static int
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/indydog.c 001-linus.patch/drivers/char/watchdog/indydog.c
--- 000-virgin/drivers/char/watchdog/indydog.c	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/drivers/char/watchdog/indydog.c	Tue Dec 30 16:38:57 2003
@@ -113,9 +113,8 @@ static ssize_t indydog_write(struct file
 			}
 		}
 		indydog_ping();
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static int indydog_ioctl(struct inode *inode, struct file *file,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/machzwd.c 001-linus.patch/drivers/char/watchdog/machzwd.c
--- 000-virgin/drivers/char/watchdog/machzwd.c	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/drivers/char/watchdog/machzwd.c	Tue Dec 30 16:38:57 2003
@@ -343,10 +343,9 @@ static ssize_t zf_write(struct file *fil
 		next_heartbeat = jiffies + ZF_USER_TIMEO;
 		dprintk("user ping at %ld\n", jiffies);
 		
-		return 1;
 	}
 
-	return 0;
+	return count;
 }
 
 static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/mixcomwd.c 001-linus.patch/drivers/char/watchdog/mixcomwd.c
--- 000-virgin/drivers/char/watchdog/mixcomwd.c	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/drivers/char/watchdog/mixcomwd.c	Tue Dec 30 16:38:57 2003
@@ -156,9 +156,8 @@ static ssize_t mixcomwd_write(struct fil
 			}
 		}
 		mixcomwd_ping();
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static int mixcomwd_ioctl(struct inode *inode, struct file *file,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/pcwd.c 001-linus.patch/drivers/char/watchdog/pcwd.c
--- 000-virgin/drivers/char/watchdog/pcwd.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/drivers/char/watchdog/pcwd.c	Tue Dec 30 16:38:57 2003
@@ -419,9 +419,8 @@ static ssize_t pcwd_write(struct file *f
 			}
 		}
 		pcwd_send_heartbeat();
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static int pcwd_open(struct inode *ino, struct file *filep)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/sa1100_wdt.c 001-linus.patch/drivers/char/watchdog/sa1100_wdt.c
--- 000-virgin/drivers/char/watchdog/sa1100_wdt.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/char/watchdog/sa1100_wdt.c	Tue Dec 30 16:38:57 2003
@@ -106,7 +106,7 @@ static ssize_t sa1100dog_write(struct fi
 		OSMR3 = OSCR + pre_margin;
 	}
 
-	return len ? 1 : 0;
+	return len;
 }
 
 static struct watchdog_info ident = {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/softdog.c 001-linus.patch/drivers/char/watchdog/softdog.c
--- 000-virgin/drivers/char/watchdog/softdog.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/char/watchdog/softdog.c	Tue Dec 30 16:38:57 2003
@@ -155,9 +155,8 @@ static ssize_t softdog_write(struct file
 			}
 		}
 		mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static int softdog_ioctl(struct inode *inode, struct file *file,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/w83627hf_wdt.c 001-linus.patch/drivers/char/watchdog/w83627hf_wdt.c
--- 000-virgin/drivers/char/watchdog/w83627hf_wdt.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/char/watchdog/w83627hf_wdt.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,324 @@
+/*
+ *	w83627hf WDT driver
+ *
+ *	(c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
+ *
+ *	Based on advantechwdt.c which is based on wdt.c.
+ *	Original copyright messages:
+ *
+ *	(c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *				http://www.redhat.com
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
+ *
+ *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define WATCHDOG_NAME "w83627hf WDT"
+#define PFX WATCHDOG_NAME ": "
+#define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
+
+static unsigned long wdt_is_open;
+static char expect_close;
+
+/* You must set this - there is no sane way to probe for this board. */
+static int wdt_io = 0x2E;
+module_param(wdt_io, int, 0);
+MODULE_PARM_DESC(wdt_io, "w83627hf WDT io port (default 0x2E)");
+
+static int timeout = WATCHDOG_TIMEOUT;	/* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ *	Kernel methods.
+ */
+
+#define WDT_EFER (wdt_io+0)   /* Extended Function Enable Registers */
+#define WDT_EFIR (wdt_io+0)   /* Extended Function Index Register (same as EFER) */
+#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
+
+static void
+wdt_ctrl(int timeout)
+{
+	outb_p(0x87, WDT_EFER); /* Enter extended function mode */
+	outb_p(0x87, WDT_EFER); /* Again according to manual */
+
+	outb_p(0x07, WDT_EFER); /* point to logical device number reg */
+	outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
+	outb_p(0x30, WDT_EFER); /* select CR30 */
+	outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */
+
+	outb_p(0xF6, WDT_EFER);    /* Select CRF6 */
+	outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */
+
+	outb_p(0xAA, WDT_EFER); /* Leave extended function mode */
+}
+
+static void
+wdt_ping(void)
+{
+	wdt_ctrl(timeout);
+}
+
+static void
+wdt_disable(void)
+{
+	wdt_ctrl(0);
+}
+
+static ssize_t
+wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf+i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = 42;
+			}
+		}
+		wdt_ping();
+	}
+	return count;
+}
+
+static int
+wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	  unsigned long arg)
+{
+	int new_timeout;
+	static struct watchdog_info ident = {
+		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+		.firmware_version = 1,
+		.identity = "Advantech WDT",
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+	  if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+	    return -EFAULT;
+	  break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+	  return put_user(0, (int *)arg);
+
+	case WDIOC_KEEPALIVE:
+	  wdt_ping();
+	  break;
+
+	case WDIOC_SETTIMEOUT:
+	  if (get_user(new_timeout, (int *)arg))
+		  return -EFAULT;
+	  if ((new_timeout < 1) || (new_timeout > 63))
+		  return -EINVAL;
+	  timeout = new_timeout;
+	  wdt_ping();
+	  /* Fall */
+
+	case WDIOC_GETTIMEOUT:
+	  return put_user(timeout, (int *)arg);
+
+	case WDIOC_SETOPTIONS:
+	{
+	  int options, retval = -EINVAL;
+
+	  if (get_user(options, (int *)arg))
+	    return -EFAULT;
+
+	  if (options & WDIOS_DISABLECARD) {
+	    wdt_disable();
+	    retval = 0;
+	  }
+
+	  if (options & WDIOS_ENABLECARD) {
+	    wdt_ping();
+	    retval = 0;
+	  }
+
+	  return retval;
+	}
+
+	default:
+	  return -ENOTTY;
+	}
+	return 0;
+}
+
+static int
+wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &wdt_is_open))
+		return -EBUSY;
+	/*
+	 *	Activate
+	 */
+
+	wdt_ping();
+	return 0;
+}
+
+static int
+wdt_close(struct inode *inode, struct file *file)
+{
+	if (expect_close == 42) {
+		wdt_disable();
+	} else {
+		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+		wdt_ping();
+	}
+	clear_bit(0, &wdt_is_open);
+	expect_close = 0;
+	return 0;
+}
+
+/*
+ *	Notifier for system down
+ */
+
+static int
+wdt_notify_sys(struct notifier_block *this, unsigned long code,
+	void *unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT) {
+		/* Turn the WDT off */
+		wdt_disable();
+	}
+	return NOTIFY_DONE;
+}
+
+/*
+ *	Kernel Interfaces
+ */
+
+static struct file_operations wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= wdt_write,
+	.ioctl		= wdt_ioctl,
+	.open		= wdt_open,
+	.release	= wdt_close,
+};
+
+static struct miscdevice wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &wdt_fops,
+};
+
+/*
+ *	The WDT needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off.
+ */
+
+static struct notifier_block wdt_notifier = {
+	.notifier_call = wdt_notify_sys,
+	.next = NULL,
+	.priority = 0,
+};
+
+static int __init
+wdt_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");
+
+	if (timeout < 1 || timeout > 63) {
+		timeout = WATCHDOG_TIMEOUT;
+		printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
+			timeout);
+	}
+
+	if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
+		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
+			wdt_io);
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = register_reboot_notifier(&wdt_notifier);
+	if (ret != 0) {
+		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+			ret);
+		goto unreg_regions;
+	}
+
+	ret = misc_register(&wdt_miscdev);
+	if (ret != 0) {
+		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+			WATCHDOG_MINOR, ret);
+		goto unreg_reboot;
+	}
+
+	printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+		timeout, nowayout);
+
+out:
+	return ret;
+unreg_reboot:
+	unregister_reboot_notifier(&wdt_notifier);
+unreg_regions:
+	release_region(wdt_io, 1);
+	goto out;
+}
+
+static void __exit
+wdt_exit(void)
+{
+	misc_deregister(&wdt_miscdev);
+	unregister_reboot_notifier(&wdt_notifier);
+	release_region(wdt_io,1);
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
+MODULE_DESCRIPTION("w38627hf WDT driver");
+
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/char/watchdog/wdt.c 001-linus.patch/drivers/char/watchdog/wdt.c
--- 000-virgin/drivers/char/watchdog/wdt.c	Wed Dec 17 18:58:50 2003
+++ 001-linus.patch/drivers/char/watchdog/wdt.c	Tue Dec 30 16:38:57 2003
@@ -265,9 +265,8 @@ static ssize_t wdt_write(struct file *fi
 			}
 		}
 		wdt_ping();
-		return 1;
 	}
-	return 0;
+	return count;
 }
 
 /**
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/i2c/i2c-core.c 001-linus.patch/drivers/i2c/i2c-core.c
--- 000-virgin/drivers/i2c/i2c-core.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/drivers/i2c/i2c-core.c	Tue Dec 30 16:38:57 2003
@@ -136,10 +136,10 @@ int i2c_add_adapter(struct i2c_adapter *
 
 	/* Add the adapter to the driver core.
 	 * If the parent pointer is not set up,
-	 * we add this adapter to the legacy bus.
+	 * we add this adapter to the host bus.
 	 */
 	if (adap->dev.parent == NULL)
-		adap->dev.parent = &legacy_bus;
+		adap->dev.parent = &platform_bus;
 	sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
 	adap->dev.driver = &i2c_adapter_driver;
 	adap->dev.release = &i2c_adapter_dev_release;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/i2c/i2c-dev.c 001-linus.patch/drivers/i2c/i2c-dev.c
--- 000-virgin/drivers/i2c/i2c-dev.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/drivers/i2c/i2c-dev.c	Tue Dec 30 16:38:57 2003
@@ -223,7 +223,7 @@ int i2cdev_ioctl (struct inode *inode, s
 
 		/* Put an arbritrary limit on the number of messages that can
 		 * be sent at once */
-		if (rdwr_arg.nmsgs > 42)
+		if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
 			return -EINVAL;
 		
 		rdwr_pa = (struct i2c_msg *)
@@ -447,7 +447,7 @@ static int i2cdev_attach_adapter(struct 
 
 	/* register this i2c device with the driver core */
 	i2c_dev->adap = adap;
-	if (adap->dev.parent == &legacy_bus)
+	if (adap->dev.parent == &platform_bus)
 		i2c_dev->class_dev.dev = &adap->dev;
 	else
 		i2c_dev->class_dev.dev = adap->dev.parent;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/Kconfig 001-linus.patch/drivers/ide/Kconfig
--- 000-virgin/drivers/ide/Kconfig	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/ide/Kconfig	Tue Dec 30 16:38:57 2003
@@ -745,6 +745,14 @@ config BLK_DEV_SVWKS
 	  This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5
 	  chipsets.
 
+config BLK_DEV_SGIIOC4
+	tristate "Silicon Graphics IOC4 chipset support"
+	depends on IA64_SGI_SN2
+	help
+	  This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
+	  chipset, which has one channel and can support two devices.
+	  Please say Y here if you have an Altix System from SGI.
+
 config BLK_DEV_SIIMAGE
 	tristate "Silicon Image chipset support"
 	help
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/arm/icside.c 001-linus.patch/drivers/ide/arm/icside.c
--- 000-virgin/drivers/ide/arm/icside.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/ide/arm/icside.c	Tue Dec 30 16:38:57 2003
@@ -214,7 +214,7 @@ static void icside_maskproc(ide_drive_t 
 #define NR_ENTRIES 256
 #define TABLE_SIZE (NR_ENTRIES * 8)
 
-static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
+static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct icside_state *state = hwif->hwif_data;
@@ -543,7 +543,7 @@ icside_dma_common(ide_drive_t *drive, st
 	BUG_ON(hwif->sg_dma_active);
 	BUG_ON(dma_channel_active(hwif->hw.dma));
 
-	ide_build_sglist(drive, rq);
+	icside_build_sglist(drive, rq);
 
 	/*
 	 * Ensure that we have the right interrupt routed.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/ide-cd.c 001-linus.patch/drivers/ide/ide-cd.c
--- 000-virgin/drivers/ide/ide-cd.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/ide/ide-cd.c	Tue Dec 30 16:38:57 2003
@@ -3343,7 +3343,8 @@ static int idecd_open(struct inode * ino
 	drive->usage++;
 
 	if (!info->buffer)
-		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
+		info->buffer = kmalloc(SECTOR_BUFFER_SIZE,
+					GFP_KERNEL|__GFP_REPEAT);
         if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
 		drive->usage--;
 	return rc;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/ide-dma.c 001-linus.patch/drivers/ide/ide-dma.c
--- 000-virgin/drivers/ide/ide-dma.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/ide/ide-dma.c	Tue Dec 30 16:38:57 2003
@@ -200,8 +200,8 @@ EXPORT_SYMBOL_GPL(ide_dma_intr);
  *	kernel provide the necessary cache management so that we can
  *	operate in a portable fashion
  */
- 
-static int ide_build_sglist (ide_drive_t *drive, struct request *rq)
+
+int ide_build_sglist(ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scatterlist *sg = hwif->sg_table;
@@ -220,6 +220,8 @@ static int ide_build_sglist (ide_drive_t
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
 
+EXPORT_SYMBOL_GPL(ide_build_sglist);
+
 /**
  *	ide_raw_build_sglist	-	map IDE scatter gather for DMA
  *	@drive: the drive to build the DMA table for
@@ -230,8 +232,8 @@ static int ide_build_sglist (ide_drive_t
  *	of the  kernel provide the necessary cache management so that we can
  *	operate in a portable fashion
  */
- 
-static int ide_raw_build_sglist (ide_drive_t *drive, struct request *rq)
+
+int ide_raw_build_sglist(ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scatterlist *sg = hwif->sg_table;
@@ -270,6 +272,8 @@ static int ide_raw_build_sglist (ide_dri
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
 
+EXPORT_SYMBOL_GPL(ide_raw_build_sglist);
+
 /**
  *	ide_build_dmatable	-	build IDE DMA table
  *
@@ -925,11 +929,13 @@ int ide_release_iomio_dma (ide_hwif_t *h
  */
 int ide_release_dma (ide_hwif_t *hwif)
 {
+	if (hwif->mmio == 2)
+		return 1;
 	if (hwif->chipset == ide_etrax100)
 		return 1;
 
 	ide_release_dma_engine(hwif);
-	if (hwif->mmio)
+	if (hwif->mmio == 1)
 		return ide_release_mmio_dma(hwif);
 	return ide_release_iomio_dma(hwif);
 }
@@ -986,6 +992,21 @@ fail:
 	return 1;
 }
 
+int ide_mapped_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
+{
+	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
+
+	hwif->dma_base = base;
+	if (hwif->cds->extra && hwif->channel == 0)
+		hwif->dma_extra = hwif->cds->extra;
+
+	if(hwif->mate)
+		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
+	else
+		hwif->dma_master = base;
+	return 0;
+}
+
 int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
 	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
@@ -1020,7 +1041,9 @@ int ide_iomio_dma (ide_hwif_t *hwif, uns
  */
 int ide_dma_iobase (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
-	if (hwif->mmio)
+	if (hwif->mmio == 2)
+		return ide_mapped_mmio_dma(hwif, base,ports);
+	if (hwif->mmio == 1)
 		return ide_mmio_dma(hwif, base, ports);
 	return ide_iomio_dma(hwif, base, ports);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/ide-tape.c 001-linus.patch/drivers/ide/ide-tape.c
--- 000-virgin/drivers/ide/ide-tape.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/drivers/ide/ide-tape.c	Tue Dec 30 16:38:57 2003
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/ide-tape.c		Version 1.17b	Oct, 2002
+ * linux/drivers/ide/ide-tape.c		Version 1.18	Nov, 2003
  *
  * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
  *
@@ -422,7 +422,7 @@
  *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
  */
 
-#define IDETAPE_VERSION "1.17b-ac1"
+#define IDETAPE_VERSION "1.18"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -450,9 +450,6 @@
 #include <asm/unaligned.h>
 #include <asm/bitops.h>
 
-
-#define NO_LONGER_REQUIRED	(1)
-
 /*
  *	OnStream support
  */
@@ -652,9 +649,11 @@ typedef struct {
 #define IDETAPE_PC_STACK		(10 + IDETAPE_MAX_PC_RETRIES)
 
 /*
- *	Some tape drives require a long irq timeout
+ * Some drives (for example, Seagate STT3401A Travan) require a very long
+ * timeout, because they don't return an interrupt or clear their busy bit
+ * until after the command completes (even retension commands).
  */
-#define IDETAPE_WAIT_CMD		(60*HZ)
+#define IDETAPE_WAIT_CMD		(900*HZ)
 
 /*
  *	The following parameter is used to select the point in the internal
@@ -1032,6 +1031,10 @@ typedef struct {
 
 	/* the door is currently locked */
 	int door_locked;
+	/* the tape hardware is write protected */
+	char drv_write_prot;
+	/* the tape is write protected (hardware or opened as read-only) */
+	char write_prot;
 
 	/*
 	 * OnStream flags
@@ -1164,6 +1167,8 @@ typedef struct {
 #define IDETAPE_DRQ_INTERRUPT		6	/* DRQ interrupt device */
 #define IDETAPE_READ_ERROR		7
 #define IDETAPE_PIPELINE_ACTIVE		8	/* pipeline active */
+/* 0 = no tape is loaded, so we don't rewind after ejecting */
+#define IDETAPE_MEDIUM_PRESENT		9
 
 /*
  *	Supported ATAPI tape drives packet commands
@@ -1665,6 +1670,20 @@ static void idetape_analyze_error (ide_d
 		idetape_update_buffers(pc);
 	}
 
+	/*
+	 * If error was the result of a zero-length read or write command,
+	 * with sense key=5, asc=0x22, ascq=0, let it slide.  Some drives
+	 * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
+	 */
+	if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD)
+	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */
+		if (result->sense_key == 5) {
+			/* don't report an error, everything's ok */
+			pc->error = 0;
+			/* don't retry read/write */
+			set_bit(PC_ABORT, &pc->flags);
+		}
+	}
 	if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
 		pc->error = IDETAPE_ERROR_FILEMARK;
 		set_bit(PC_ABORT, &pc->flags);
@@ -1805,10 +1824,15 @@ static void idetape_remove_stage_head (i
 	}
 }
 
-static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage)
+/*
+ * This will free all the pipeline stages starting from new_last_stage->next
+ * to the end of the list, and point tape->last_stage to new_last_stage.
+ */
+static void idetape_abort_pipeline(ide_drive_t *drive,
+				   idetape_stage_t *new_last_stage)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	idetape_stage_t *stage = tape->next_stage;
+	idetape_stage_t *stage = new_last_stage->next;
 	idetape_stage_t *nstage;
 
 #if IDETAPE_DEBUG_LOG
@@ -1822,9 +1846,9 @@ static void idetape_abort_pipeline (ide_
 		--tape->nr_pending_stages;
 		stage = nstage;
 	}
-	tape->last_stage = last_stage;
-	if (last_stage)
-		last_stage->next = NULL;
+	if (new_last_stage)
+		new_last_stage->next = NULL;
+	tape->last_stage = new_last_stage;
 	tape->next_stage = NULL;
 }
 
@@ -2430,7 +2454,14 @@ static void idetape_create_mode_sense_cm
 	if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
 		pc->c[1] = 8;	/* DBD = 1 - Don't return block descriptors */
 	pc->c[2] = page_code;
-	pc->c[3] = 255;		/* Don't limit the returned information */
+	/*
+	 * Changed pc->c[3] to 0 (255 will at best return unused info).
+	 *
+	 * For SCSI this byte is defined as subpage instead of high byte
+	 * of length and some IDE drives seem to interpret it this way
+	 * and return an error when 255 is used.
+	 */
+	pc->c[3] = 0;
 	pc->c[4] = 255;		/* (We will just discard data in that case) */
 	if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
 		pc->request_transfer = 12;
@@ -2544,8 +2575,9 @@ static ide_startstop_t idetape_media_acc
 	if (status.b.dsc) {
 		if (status.b.check) {
 			/* Error detected */
-			printk(KERN_ERR "ide-tape: %s: I/O error, ",tape->name);
-
+			if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
+				printk(KERN_ERR "ide-tape: %s: I/O error, ",
+						tape->name);
 			/* Retry operation */
 			return idetape_retry_pc(drive);
 		}
@@ -3295,25 +3327,28 @@ static int idetape_wait_ready(ide_drive_
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_pc_t pc;
+	int load_attempted = 0;
 
 	/*
 	 * Wait for the tape to become ready
 	 */
+	set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
 	timeout += jiffies;
 	while (time_before(jiffies, timeout)) {
 		idetape_create_test_unit_ready_cmd(&pc);
 		if (!__idetape_queue_pc_tail(drive, &pc))
 			return 0;
-		if (tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) {
+		if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
+		    || (tape->asc == 0x3A)) {	/* no media */
+			if (load_attempted)
+				return -ENOMEDIUM;
 			idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK);
 			__idetape_queue_pc_tail(drive, &pc);
-			idetape_create_test_unit_ready_cmd(&pc);
-			if (!__idetape_queue_pc_tail(drive, &pc))
-				return 0;
-		}
-		if (!(tape->sense_key == 2 && tape->asc == 4 &&
-		      (tape->ascq == 1 || tape->ascq == 8)))
-			break;
+			load_attempted = 1;
+		/* not about to be ready */
+		} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
+			     (tape->ascq == 1 || tape->ascq == 8)))
+			return -EIO;
 		current->state = TASK_INTERRUPTIBLE;
   		schedule_timeout(HZ / 10);
 	}
@@ -3369,25 +3404,10 @@ static int idetape_read_position (ide_dr
 		printk(KERN_INFO "ide-tape: Reached idetape_read_position\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
-#ifdef NO_LONGER_REQUIRED
-	idetape_flush_tape_buffers(drive);
-#endif
 	idetape_create_read_position_cmd(&pc);
 	if (idetape_queue_pc_tail(drive, &pc))
 		return -1;
 	position = tape->first_frame_position;
-#ifdef NO_LONGER_REQUIRED
-	if (tape->onstream) {
-		if ((position != tape->last_frame_position - tape->blocks_in_buffer) &&
-		    (position != tape->last_frame_position + tape->blocks_in_buffer)) {
-			if (tape->blocks_in_buffer == 0) {
-				printk("ide-tape: %s: correcting read position %d, %d, %d\n", tape->name, position, tape->last_frame_position, tape->blocks_in_buffer);
-				position = tape->last_frame_position;
-				tape->first_frame_position = position;
-			}
-		}
-	}
-#endif
 	return position;
 }
 
@@ -3436,6 +3456,8 @@ static int __idetape_discard_read_pipeli
 
 	if (tape->chrdev_direction != idetape_direction_read)
 		return 0;
+
+	/* Remove merge stage. */
 	cnt = tape->merge_stage_size / tape->tape_block_size;
 	if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
 		++cnt;		/* Filemarks count as 1 sector */
@@ -3444,9 +3466,12 @@ static int __idetape_discard_read_pipeli
 		__idetape_kfree_stage(tape->merge_stage);
 		tape->merge_stage = NULL;
 	}
+
+	/* Clear pipeline flags. */
 	clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
 	tape->chrdev_direction = idetape_direction_none;
-	
+
+	/* Remove pipeline stages. */
 	if (tape->first_stage == NULL)
 		return 0;
 
@@ -4059,13 +4084,17 @@ static int idetape_initiate_read (ide_dr
 		 *	Issue a read 0 command to ensure that DSC handshake
 		 *	is switched from completion mode to buffer available
 		 *	mode.
+		 *	No point in issuing this if DSC overlap isn't supported,
+		 *	some drives (Seagate STT3401A) will return an error.
 		 */
-		bytes_read = idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 0, tape->merge_stage->bh);
-		if (bytes_read < 0) {
-			__idetape_kfree_stage(tape->merge_stage);
-			tape->merge_stage = NULL;
-			tape->chrdev_direction = idetape_direction_none;
-			return bytes_read;
+		if (drive->dsc_overlap) {
+			bytes_read = idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 0, tape->merge_stage->bh);
+			if (bytes_read < 0) {
+				__idetape_kfree_stage(tape->merge_stage);
+				tape->merge_stage = NULL;
+				tape->chrdev_direction = idetape_direction_none;
+				return bytes_read;
+			}
 		}
 	}
 	if (tape->restart_speed_control_req)
@@ -4898,6 +4927,10 @@ static ssize_t idetape_chrdev_write (str
 		return -ENXIO;
 	}
 
+	/* The drive is write protected. */
+	if (tape->write_prot)
+		return -EACCES;
+
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
 		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_write, "
@@ -4979,13 +5012,17 @@ static ssize_t idetape_chrdev_write (str
 		 *	Issue a write 0 command to ensure that DSC handshake
 		 *	is switched from completion mode to buffer available
 		 *	mode.
+		 *	No point in issuing this if DSC overlap isn't supported,
+		 *	some drives (Seagate STT3401A) will return an error.
 		 */
-		retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
-		if (retval < 0) {
-			__idetape_kfree_stage(tape->merge_stage);
-			tape->merge_stage = NULL;
-			tape->chrdev_direction = idetape_direction_none;
-			return retval;
+		if (drive->dsc_overlap) {
+			retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
+			if (retval < 0) {
+				__idetape_kfree_stage(tape->merge_stage);
+				tape->merge_stage = NULL;
+				tape->chrdev_direction = idetape_direction_none;
+				return retval;
+			}
 		}
 #if ONSTREAM_DEBUG
 		if (tape->debug_level >= 2)
@@ -5141,7 +5178,7 @@ ok:
  *	Note:
  *
  *		MTBSF and MTBSFM are not supported when the tape doesn't
- *		supports spacing over filemarks in the reverse direction.
+ *		support spacing over filemarks in the reverse direction.
  *		In this case, MTFSFM is also usually not supported (it is
  *		supported in the rare case in which we crossed the filemark
  *		during our read-ahead pipelined operation mode).
@@ -5211,6 +5248,8 @@ static int idetape_mtioctop (ide_drive_t
 	}
 	switch (mt_op) {
 		case MTWEOF:
+			if (tape->write_prot)
+				return -EACCES;
 			idetape_discard_read_pipeline(drive, 1);
 			for (i = 0; i < mt_count; i++) {
 				retval = idetape_write_filemark(drive);
@@ -5231,9 +5270,21 @@ static int idetape_mtioctop (ide_drive_t
 			return (idetape_queue_pc_tail(drive, &pc));
 		case MTUNLOAD:
 		case MTOFFL:
+			/*
+			 * If door is locked, attempt to unlock before
+			 * attempting to eject.
+			 */
+			if (tape->door_locked) {
+				if (idetape_create_prevent_cmd(drive, &pc, 0))
+					if (!idetape_queue_pc_tail(drive, &pc))
+						tape->door_locked = DOOR_UNLOCKED;
+			}
 			idetape_discard_read_pipeline(drive, 0);
 			idetape_create_load_unload_cmd(drive, &pc,!IDETAPE_LU_LOAD_MASK);
-			return (idetape_queue_pc_tail(drive, &pc));
+			retval = idetape_queue_pc_tail(drive, &pc);
+			if (!retval)
+				clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
+			return retval;
 		case MTNOP:
 			idetape_discard_read_pipeline(drive, 0);
 			return (idetape_flush_tape_buffers(drive));
@@ -5409,6 +5460,8 @@ static int idetape_chrdev_ioctl (struct 
 					mtget.mt_gstat |= GMT_EOD(0xffffffff);
 				if (position <= OS_DATA_STARTFRAME1)
 					mtget.mt_gstat |= GMT_BOT(0xffffffff);
+			} else if (tape->drv_write_prot) {
+				mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
 			}
 			if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget)))
 				return -EFAULT;
@@ -5530,6 +5583,8 @@ ok:
 	return 1;
 }
 
+static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive);
+
 /*
  *	Our character device open function.
  */
@@ -5539,7 +5594,8 @@ static int idetape_chrdev_open (struct i
 	ide_drive_t *drive;
 	idetape_tape_t *tape;
 	idetape_pc_t pc;
-			
+	int retval;
+
 #if IDETAPE_DEBUG_LOG
 	printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
 #endif /* IDETAPE_DEBUG_LOG */
@@ -5552,11 +5608,7 @@ static int idetape_chrdev_open (struct i
 
 	if (test_and_set_bit(IDETAPE_BUSY, &tape->flags))
 		return -EBUSY;
-	if (!tape->onstream) {	
-		idetape_read_position(drive);
-		if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
-			(void) idetape_rewind_tape(drive);
-	} else {
+	if (tape->onstream) {
 		if (minor & 64) {
 			tape->tape_block_size = tape->stage_size = 32768 + 512;
 			tape->raw = 1;
@@ -5566,16 +5618,42 @@ static int idetape_chrdev_open (struct i
 		}
                 idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level);
 	}
-	if (idetape_wait_ready(drive, 60 * HZ)) {
+	retval = idetape_wait_ready(drive, 60 * HZ);
+	if (retval) {
 		clear_bit(IDETAPE_BUSY, &tape->flags);
 		printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
-		return -EBUSY;
+		return retval;
 	}
-	if (tape->onstream)
-		idetape_read_position(drive);
+
+	idetape_read_position(drive);
+	if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
+		(void)idetape_rewind_tape(drive);
+
 	if (tape->chrdev_direction != idetape_direction_read)
 		clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
 
+	/* Read block size and write protect status from drive. */
+	idetape_get_blocksize_from_block_descriptor(drive);
+
+	/* Set write protect flag if device is opened as read-only. */
+	if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
+		tape->write_prot = 1;
+	else
+		tape->write_prot = tape->drv_write_prot;
+
+	/* Make sure drive isn't write protected if user wants to write. */
+	if (tape->write_prot) {
+		if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
+		    (filp->f_flags & O_ACCMODE) == O_RDWR) {
+			clear_bit(IDETAPE_BUSY, &tape->flags);
+			return -EROFS;
+		}
+	}
+
+	/*
+	 * Lock the tape drive door so user can't eject.
+	 * Analyze headers for OnStream drives.
+	 */
 	if (tape->chrdev_direction == idetape_direction_none) {
 		if (idetape_create_prevent_cmd(drive, &pc, 1)) {
 			if (!idetape_queue_pc_tail(drive, &pc)) {
@@ -5638,7 +5716,7 @@ static int idetape_chrdev_release (struc
 		__idetape_kfree_stage(tape->cache_stage);
 		tape->cache_stage = NULL;
 	}
-	if (minor < 128)
+	if (minor < 128 && test_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags))
 		(void) idetape_rewind_tape(drive);
 	if (tape->chrdev_direction == idetape_direction_none) {
 		if (tape->door_locked == DOOR_LOCKED) {
@@ -6059,6 +6137,8 @@ static void idetape_get_blocksize_from_b
 	header = (idetape_mode_parameter_header_t *) pc.buffer;
 	block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t));
 	tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2];
+	tape->drv_write_prot = (header->dsp & 0x80) >> 7;
+
 #if IDETAPE_DEBUG_INFO
 	printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size);
 #endif /* IDETAPE_DEBUG_INFO */
@@ -6139,6 +6219,9 @@ static void idetape_setup (ide_drive_t *
 		}
 	}
 #endif /* CONFIG_BLK_DEV_IDEPCI */
+	/* Seagate Travan drives do not support DSC overlap. */
+	if (strstr(drive->id->model, "Seagate STT3401"))
+		drive->dsc_overlap = 0;
 	tape->drive = drive;
 	tape->minor = minor;
 	tape->name[0] = 'h';
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/ide.c 001-linus.patch/drivers/ide/ide.c
--- 000-virgin/drivers/ide/ide.c	Wed Dec 17 18:58:38 2003
+++ 001-linus.patch/drivers/ide/ide.c	Tue Dec 30 16:38:57 2003
@@ -1632,12 +1632,12 @@ int generic_ide_ioctl(struct block_devic
 #endif /* CONFIG_IDE_TASK_IOCTL */
 
 		case HDIO_DRIVE_CMD:
-			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			if (!capable(CAP_SYS_RAWIO))
 				return -EACCES;
 			return ide_cmd_ioctl(drive, cmd, arg);
 
 		case HDIO_DRIVE_TASK:
-			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			if (!capable(CAP_SYS_RAWIO))
 				return -EACCES;
 			return ide_task_ioctl(drive, cmd, arg);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/pci/Makefile 001-linus.patch/drivers/ide/pci/Makefile
--- 000-virgin/drivers/ide/pci/Makefile	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/ide/pci/Makefile	Tue Dec 30 16:38:57 2003
@@ -21,6 +21,7 @@ obj-$(CONFIG_BLK_DEV_PDC202XX_NEW)	+= pd
 obj-$(CONFIG_BLK_DEV_PIIX)		+= piix.o
 obj-$(CONFIG_BLK_DEV_RZ1000)		+= rz1000.o
 obj-$(CONFIG_BLK_DEV_SVWKS)		+= serverworks.o
+obj-$(CONFIG_BLK_DEV_SGIIOC4)		+= sgiioc4.o
 obj-$(CONFIG_BLK_DEV_SIIMAGE)		+= siimage.o
 obj-$(CONFIG_BLK_DEV_SIS5513)		+= sis5513.o
 obj-$(CONFIG_BLK_DEV_SL82C105)		+= sl82c105.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/pci/piix.c 001-linus.patch/drivers/ide/pci/piix.c
--- 000-virgin/drivers/ide/pci/piix.c	Wed Dec 17 18:58:07 2003
+++ 001-linus.patch/drivers/ide/pci/piix.c	Tue Dec 30 16:38:57 2003
@@ -768,8 +768,8 @@ static void __init piix_check_450nx(void
 		/* Only on the original revision: IDE DMA can hang */
 		if(rev == 0x00)
 			no_piix_dma = 1;
-		/* On all revisions PXB bus lock must be disabled for IDE */
-		else if(cfg & (1<<14))
+		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
+		else if(cfg & (1<<14) && rev < 5)
 			no_piix_dma = 2;
 	}
 	if(no_piix_dma)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/pci/sgiioc4.c 001-linus.patch/drivers/ide/pci/sgiioc4.c
--- 000-virgin/drivers/ide/pci/sgiioc4.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/ide/pci/sgiioc4.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,833 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <asm/io.h>
+
+#include <linux/ide.h>
+
+/* IOC4 Specific Definitions */
+#define IOC4_CMD_OFFSET		0x100
+#define IOC4_CTRL_OFFSET	0x120
+#define IOC4_DMA_OFFSET		0x140
+#define IOC4_INTR_OFFSET	0x0
+
+#define IOC4_TIMING		0x00
+#define IOC4_DMA_PTR_L		0x01
+#define IOC4_DMA_PTR_H		0x02
+#define IOC4_DMA_ADDR_L		0x03
+#define IOC4_DMA_ADDR_H		0x04
+#define IOC4_BC_DEV		0x05
+#define IOC4_BC_MEM		0x06
+#define	IOC4_DMA_CTRL		0x07
+#define	IOC4_DMA_END_ADDR	0x08
+
+/* Bits in the IOC4 Control/Status Register */
+#define	IOC4_S_DMA_START	0x01
+#define	IOC4_S_DMA_STOP		0x02
+#define	IOC4_S_DMA_DIR		0x04
+#define	IOC4_S_DMA_ACTIVE	0x08
+#define	IOC4_S_DMA_ERROR	0x10
+#define	IOC4_ATA_MEMERR		0x02
+
+/* Read/Write Directions */
+#define	IOC4_DMA_WRITE		0x04
+#define	IOC4_DMA_READ		0x00
+
+/* Interrupt Register Offsets */
+#define IOC4_INTR_REG		0x03
+#define	IOC4_INTR_SET		0x05
+#define	IOC4_INTR_CLEAR		0x07
+
+#define IOC4_IDE_CACHELINE_SIZE	128
+#define IOC4_CMD_CTL_BLK_SIZE	0x20
+#define IOC4_SUPPORTED_FIRMWARE_REV 46
+
+typedef struct {
+	u32 timing_reg0;
+	u32 timing_reg1;
+	u32 low_mem_ptr;
+	u32 high_mem_ptr;
+	u32 low_mem_addr;
+	u32 high_mem_addr;
+	u32 dev_byte_count;
+	u32 mem_byte_count;
+	u32 status;
+} ioc4_dma_regs_t;
+
+/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
+/* IOC4 has only 1 IDE channel */
+#define IOC4_PRD_BYTES       16
+#define IOC4_PRD_ENTRIES     (PAGE_SIZE /(4*IOC4_PRD_BYTES))
+
+
+static void
+sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+			unsigned long ctrl_port, unsigned long irq_port)
+{
+	unsigned long reg = data_port;
+	int i;
+
+	/* Registers are word (32 bit) aligned */
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+		hw->io_ports[i] = reg + i * 4;
+
+	if (ctrl_port)
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+
+	if (irq_port)
+		hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
+}
+
+static void
+sgiioc4_maskproc(ide_drive_t * drive, int mask)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+		   IDE_CONTROL_REG);
+}
+
+
+static int
+sgiioc4_checkirq(ide_hwif_t * hwif)
+{
+	u8 intr_reg =
+	    hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4);
+
+	if (intr_reg & 0x03)
+		return 1;
+
+	return 0;
+}
+
+
+static int
+sgiioc4_clearirq(ide_drive_t * drive)
+{
+	u32 intr_reg;
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long other_ir =
+	    hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
+
+	/* Code to check for PCI error conditions */
+	intr_reg = hwif->INL(other_ir);
+	if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
+		/*
+		 * Using hwif->INB to read the IDE_STATUS_REG has a side effect
+		 * of clearing the interrupt.  The first read should clear it
+		 * if it is set.  The second read should return a "clear" status
+		 * if it got cleared.  If not, then spin for a bit trying to
+		 * clear it.
+		 */
+		u8 stat = hwif->INB(IDE_STATUS_REG);
+		int count = 0;
+		stat = hwif->INB(IDE_STATUS_REG);
+		while ((stat & 0x80) && (count++ < 100)) {
+			udelay(1);
+			stat = hwif->INB(IDE_STATUS_REG);
+		}
+
+		if (intr_reg & 0x02) {
+			/* Error when transferring DMA data on PCI bus */
+			u32 pci_err_addr_low, pci_err_addr_high,
+			    pci_stat_cmd_reg;
+
+			pci_err_addr_low =
+				hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]);
+			pci_err_addr_high =
+				hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4);
+			pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
+					      &pci_stat_cmd_reg);
+			printk(KERN_ERR
+			       "%s(%s) : PCI Bus Error when doing DMA:"
+				   " status-cmd reg is 0x%x\n",
+			       __FUNCTION__, drive->name, pci_stat_cmd_reg);
+			printk(KERN_ERR
+			       "%s(%s) : PCI Error Address is 0x%x%x\n",
+			       __FUNCTION__, drive->name,
+			       pci_err_addr_high, pci_err_addr_low);
+			/* Clear the PCI Error indicator */
+			pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
+					       0x00000146);
+		}
+
+		/* Clear the Interrupt, Error bits on the IOC4 */
+		hwif->OUTL(0x03, other_ir);
+
+		intr_reg = hwif->INL(other_ir);
+	}
+
+	return intr_reg & 3;
+}
+
+static int
+sgiioc4_ide_dma_begin(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
+	unsigned int temp_reg = reg | IOC4_S_DMA_START;
+
+	hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
+
+	return 0;
+}
+
+static u32
+sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
+{
+	u32	ioc4_dma;
+	int	count;
+
+	count = 0;
+	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
+		udelay(1);
+		ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	}
+	return ioc4_dma;
+}
+
+/* Stops the IOC4 DMA Engine */
+static int
+sgiioc4_ide_dma_end(ide_drive_t * drive)
+{
+	u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
+	ide_hwif_t *hwif = HWIF(drive);
+	u64 dma_base = hwif->dma_base;
+	int dma_stat = 0;
+	unsigned long *ending_dma = (unsigned long *) hwif->dma_base2;
+
+	hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+
+	ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+	if (ioc4_dma & IOC4_S_DMA_STOP) {
+		printk(KERN_ERR
+		       "%s(%s): IOC4 DMA STOP bit is still 1 :"
+		       "ioc4_dma_reg 0x%x\n",
+		       __FUNCTION__, drive->name, ioc4_dma);
+		dma_stat = 1;
+	}
+
+	/*
+	 * The IOC4 will DMA 1's to the ending dma area to indicate that
+	 * previous data DMA is complete.  This is necessary because of relaxed
+	 * ordering between register reads and DMA writes on the Altix.
+	 */
+	while ((cnt++ < 200) && (!valid)) {
+		for (num = 0; num < 16; num++) {
+			if (ending_dma[num]) {
+				valid = 1;
+				break;
+			}
+		}
+		udelay(1);
+	}
+	if (!valid) {
+		printk(KERN_ERR "%s(%s) : DMA incomplete\n", __FUNCTION__,
+		       drive->name);
+		dma_stat = 1;
+	}
+
+	bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4);
+	bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4);
+
+	if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
+		if (bc_dev > bc_mem + 8) {
+			printk(KERN_ERR
+			       "%s(%s): WARNING!! byte_count_dev %d "
+			       "!= byte_count_mem %d\n",
+			       __FUNCTION__, drive->name, bc_dev, bc_mem);
+		}
+	}
+
+	drive->waiting_for_dma = 0;
+	ide_destroy_dmatable(drive);
+
+	return dma_stat;
+}
+
+static int
+sgiioc4_ide_dma_check(ide_drive_t * drive)
+{
+	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
+		printk(KERN_INFO
+		       "Couldnot set %s in Multimode-2 DMA mode | "
+			   "Drive %s using PIO instead\n",
+		       drive->name, drive->name);
+		drive->using_dma = 0;
+	} else
+		drive->using_dma = 1;
+
+	return 0;
+}
+
+static int
+sgiioc4_ide_dma_on(ide_drive_t * drive)
+{
+	drive->using_dma = 1;
+
+	return HWIF(drive)->ide_dma_host_on(drive);
+}
+
+static int
+sgiioc4_ide_dma_off(ide_drive_t * drive)
+{
+	printk(KERN_INFO "%s: DMA disabled\n", drive->name);
+
+	return HWIF(drive)->ide_dma_off_quietly(drive);
+}
+
+static int
+sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
+{
+	drive->using_dma = 0;
+
+	return HWIF(drive)->ide_dma_host_off(drive);
+}
+
+/* returns 1 if dma irq issued, 0 otherwise */
+static int
+sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
+{
+	return sgiioc4_checkirq(HWIF(drive));
+}
+
+static int
+sgiioc4_ide_dma_host_on(ide_drive_t * drive)
+{
+	if (drive->using_dma)
+		return 0;
+
+	return 1;
+}
+
+static int
+sgiioc4_ide_dma_host_off(ide_drive_t * drive)
+{
+	sgiioc4_clearirq(drive);
+
+	return 0;
+}
+
+static int
+sgiioc4_ide_dma_verbose(ide_drive_t * drive)
+{
+	if (drive->using_dma == 1)
+		printk(", UDMA(16)");
+	else
+		printk(", PIO");
+
+	return 1;
+}
+
+static int
+sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
+{
+	HWIF(drive)->resetproc(drive);
+
+	return __ide_dma_lostirq(drive);
+}
+
+static void
+sgiioc4_resetproc(ide_drive_t * drive)
+{
+	sgiioc4_ide_dma_end(drive);
+	sgiioc4_clearirq(drive);
+}
+
+static u8
+sgiioc4_INB(unsigned long port)
+{
+	u8 reg = (u8) inb(port);
+
+	if ((port & 0xFFF) == 0x11C) {	/* Status register of IOC4 */
+		if (reg & 0x51) {	/* Not busy...check for interrupt */
+			unsigned long other_ir = port - 0x110;
+			unsigned int intr_reg = (u32) inl(other_ir);
+
+			/* Clear the Interrupt, Error bits on the IOC4 */
+			if (intr_reg & 0x03) {
+				outl(0x03, other_ir);
+				intr_reg = (u32) inl(other_ir);
+			}
+		}
+	}
+
+	return reg;
+}
+
+/* Creates a dma map for the scatter-gather list entries */
+static void __init
+ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+{
+	int num_ports = sizeof (ioc4_dma_regs_t);
+
+	printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
+	       dma_base, dma_base + num_ports - 1);
+
+	if (!request_region(dma_base, num_ports, hwif->name)) {
+		printk(KERN_ERR
+		       "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
+		       "ALREADY in use\n",
+		       __FUNCTION__, hwif->name, (void *) dma_base,
+		       (void *) dma_base + num_ports - 1);
+		goto dma_alloc_failure;
+	}
+
+	hwif->dma_base = dma_base;
+	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
+					  IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+					  &hwif->dmatable_dma);
+
+	if (!hwif->dmatable_cpu)
+		goto dma_alloc_failure;
+
+	hwif->sg_table =
+	    kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL);
+
+	if (!hwif->sg_table)
+		goto dma_sgalloc_failure;
+
+	hwif->dma_base2 = (unsigned long)
+		pci_alloc_consistent(hwif->pci_dev,
+				     IOC4_IDE_CACHELINE_SIZE,
+				     (dma_addr_t *) &(hwif->dma_status));
+
+	if (!hwif->dma_base2)
+		goto dma_base2alloc_failure;
+
+	return;
+
+dma_base2alloc_failure:
+	kfree(hwif->sg_table);
+
+dma_sgalloc_failure:
+	pci_free_consistent(hwif->pci_dev,
+			    IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+			    hwif->dmatable_cpu, hwif->dmatable_dma);
+	printk(KERN_INFO
+	       "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
+	       __FUNCTION__, hwif->name);
+	printk(KERN_INFO
+	       "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+
+dma_alloc_failure:
+	/* Disable DMA because we couldnot allocate any DMA maps */
+	hwif->autodma = 0;
+	hwif->atapi_dma = 0;
+}
+
+/* Initializes the IOC4 DMA Engine */
+static void
+sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
+{
+	u32 ioc4_dma;
+	ide_hwif_t *hwif = HWIF(drive);
+	u64 dma_base = hwif->dma_base;
+	u32 dma_addr, ending_dma_addr;
+
+	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+
+	if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
+		printk(KERN_WARNING
+			"%s(%s):Warning!! DMA from previous transfer was still active\n",
+		       __FUNCTION__, drive->name);
+		hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+		if (ioc4_dma & IOC4_S_DMA_STOP)
+			printk(KERN_ERR
+			       "%s(%s) : IOC4 Dma STOP bit is still 1\n",
+			       __FUNCTION__, drive->name);
+	}
+
+	ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+	if (ioc4_dma & IOC4_S_DMA_ERROR) {
+		printk(KERN_WARNING
+		       "%s(%s) : Warning!! - DMA Error during Previous"
+		       " transfer | status 0x%x\n",
+		       __FUNCTION__, drive->name, ioc4_dma);
+		hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
+
+		if (ioc4_dma & IOC4_S_DMA_STOP)
+			printk(KERN_ERR
+			       "%s(%s) : IOC4 DMA STOP bit is still 1\n",
+			       __FUNCTION__, drive->name);
+	}
+
+	/* Address of the Scatter Gather List */
+	dma_addr = cpu_to_le32(hwif->dmatable_dma);
+	hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4);
+
+	/* Address of the Ending DMA */
+	memset((unsigned int *) hwif->dma_base2, 0, IOC4_IDE_CACHELINE_SIZE);
+	ending_dma_addr = cpu_to_le32(hwif->dma_status);
+	hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4);
+
+	hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4);
+	drive->waiting_for_dma = 1;
+}
+
+/* IOC4 Scatter Gather list Format 					 */
+/* 128 Bit entries to support 64 bit addresses in the future		 */
+/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format	 */
+/* --------------------------------------------------------------------- */
+/* | Upper 32 bits - Zero           |	 	Lower 32 bits- address | */
+/* --------------------------------------------------------------------- */
+/* | Upper 32 bits - Zero	    |EOL| 15 unused     | 16 Bit Length| */
+/* --------------------------------------------------------------------- */
+/* Creates the scatter gather list, DMA Table */
+static unsigned int
+sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned int *table = hwif->dmatable_cpu;
+	unsigned int count = 0, i = 1;
+	struct scatterlist *sg;
+
+	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
+		hwif->sg_nents = i = ide_raw_build_sglist(drive, rq);
+	else
+		hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
+	if (!i)
+		return 0;	/* sglist of length Zero */
+
+	sg = hwif->sg_table;
+	while (i && sg_dma_len(sg)) {
+		dma_addr_t cur_addr;
+		int cur_len;
+		cur_addr = sg_dma_address(sg);
+		cur_len = sg_dma_len(sg);
+
+		while (cur_len) {
+			if (count++ >= IOC4_PRD_ENTRIES) {
+				printk(KERN_WARNING
+				       "%s: DMA table too small\n",
+				       drive->name);
+				goto use_pio_instead;
+			} else {
+				u32 xcount, bcount =
+				    0x10000 - (cur_addr & 0xffff);
+
+				if (bcount > cur_len)
+					bcount = cur_len;
+
+				/* put the addr, length in
+				 * the IOC4 dma-table format */
+				*table = 0x0;
+				table++;
+				*table = cpu_to_be32(cur_addr);
+				table++;
+				*table = 0x0;
+				table++;
+
+				xcount = bcount & 0xffff;
+				*table = cpu_to_be32(xcount);
+				table++;
+
+				cur_addr += bcount;
+				cur_len -= bcount;
+			}
+		}
+
+		sg++;
+		i--;
+	}
+
+	if (count) {
+		table--;
+		*table |= cpu_to_be32(0x80000000);
+		return count;
+	}
+
+use_pio_instead:
+	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
+		     hwif->sg_dma_direction);
+	hwif->sg_dma_active = 0;
+
+	return 0;		/* revert to PIO for this request */
+}
+
+static int
+sgiioc4_ide_dma_read(ide_drive_t * drive)
+{
+	struct request *rq = HWGROUP(drive)->rq;
+	unsigned int count = 0;
+
+	if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) {
+		/* try PIO instead of DMA */
+		return 1;
+	}
+	/* Writes FROM the IOC4 TO Main Memory */
+	sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive);
+
+	return 0;
+}
+
+static int
+sgiioc4_ide_dma_write(ide_drive_t * drive)
+{
+	struct request *rq = HWGROUP(drive)->rq;
+	unsigned int count = 0;
+
+	if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) {
+		/* try PIO instead of DMA */
+		return 1;
+	}
+
+	sgiioc4_configure_for_dma(IOC4_DMA_READ, drive);
+	/* Writes TO the IOC4 FROM Main Memory */
+
+	return 0;
+}
+
+static void __init
+ide_init_sgiioc4(ide_hwif_t * hwif)
+{
+	hwif->mmio = 2;
+	hwif->autodma = 1;
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x0;	/* Disable Ultra DMA */
+	hwif->mwdma_mask = 0x2;	/* Multimode-2 DMA  */
+	hwif->swdma_mask = 0x2;
+	hwif->identify = NULL;
+	hwif->tuneproc = NULL;	/* Sets timing for PIO mode */
+	hwif->speedproc = NULL;	/* Sets timing for DMA &/or PIO modes */
+	hwif->selectproc = NULL;/* Use the default routine to select drive */
+	hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */
+	hwif->pre_reset = NULL;	/* No HBA specific pre_set needed */
+	hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
+						clear interrupts */
+	hwif->intrproc = NULL;	/* Enable or Disable interrupt from drive */
+	hwif->maskproc = &sgiioc4_maskproc;	/* Mask on/off NIEN register */
+	hwif->quirkproc = NULL;
+	hwif->busproc = NULL;
+
+	hwif->ide_dma_read = &sgiioc4_ide_dma_read;
+	hwif->ide_dma_write = &sgiioc4_ide_dma_write;
+	hwif->ide_dma_begin = &sgiioc4_ide_dma_begin;
+	hwif->ide_dma_end = &sgiioc4_ide_dma_end;
+	hwif->ide_dma_check = &sgiioc4_ide_dma_check;
+	hwif->ide_dma_on = &sgiioc4_ide_dma_on;
+	hwif->ide_dma_off = &sgiioc4_ide_dma_off;
+	hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
+	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
+	hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
+	hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
+	hwif->ide_dma_bad_drive = &__ide_dma_bad_drive;
+	hwif->ide_dma_good_drive = &__ide_dma_good_drive;
+	hwif->ide_dma_count = &__ide_dma_count;
+	hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose;
+	hwif->ide_dma_retune = &__ide_dma_retune;
+	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
+	hwif->ide_dma_timeout = &__ide_dma_timeout;
+	hwif->INB = &sgiioc4_INB;
+}
+
+static int __init
+sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
+{
+	unsigned long base, ctl, dma_base, irqport;
+	ide_hwif_t *hwif;
+	int h;
+
+	for (h = 0; h < MAX_HWIFS; ++h) {
+		hwif = &ide_hwifs[h];
+		/* Find an empty HWIF */
+		if (hwif->chipset == ide_unknown)
+			break;
+	}
+
+	/*  Get the CmdBlk and CtrlBlk Base Registers */
+	base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
+	ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
+	irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
+	dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
+
+	if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
+		printk(KERN_ERR
+			"%s : %s -- ERROR, Port Addresses "
+			"0x%p to 0x%p ALREADY in use\n",
+		       __FUNCTION__, hwif->name, (void *) base,
+		       (void *) base + IOC4_CMD_CTL_BLK_SIZE);
+		return 1;
+	}
+
+	if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
+		/* Initialize the IO registers */
+		sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
+		memcpy(hwif->io_ports, hwif->hw.io_ports,
+		       sizeof (hwif->io_ports));
+		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+	}
+
+	hwif->irq = dev->irq;
+	hwif->chipset = ide_pci;
+	hwif->pci_dev = dev;
+	hwif->channel = 0;	/* Single Channel chip */
+	hwif->cds = (struct ide_pci_device_s *) d;
+	hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
+
+	/* Initializing chipset IRQ Registers */
+	hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
+
+	ide_init_sgiioc4(hwif);
+
+	if (dma_base)
+		ide_dma_sgiioc4(hwif, dma_base);
+	else
+		printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
+		       hwif->name, d->name);
+
+	probe_hwif_init(hwif);
+	return 0;
+}
+
+/* This ensures that we can build this for generic kernels without
+ * having all the SN2 code sync'd and merged.
+ */
+typedef enum pciio_endian_e {
+	PCIDMA_ENDIAN_BIG,
+	PCIDMA_ENDIAN_LITTLE
+} pciio_endian_t;
+pciio_endian_t __attribute__ ((weak)) snia_pciio_endian_set(struct pci_dev
+					    *pci_dev, pciio_endian_t device_end,
+					    pciio_endian_t desired_end);
+
+static unsigned int __init
+pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
+{
+	unsigned int class_rev;
+
+	if (pci_enable_device(dev)) {
+		printk(KERN_ERR
+		       "Failed to enable device %s at slot %s\n",
+		       d->name, dev->slot_name);
+		return 1;
+	}
+	pci_set_master(dev);
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+	printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
+			d->name, dev->slot_name, class_rev);
+	if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
+		printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
+			"firmware is obsolete - please upgrade to revision"
+			"46 or higher\n", d->name, dev->slot_name);
+		return 1;
+	}
+
+	/* Enable Byte Swapping in the PIC... */
+	if (snia_pciio_endian_set) {
+		snia_pciio_endian_set(dev, PCIDMA_ENDIAN_LITTLE,
+				      PCIDMA_ENDIAN_BIG);
+	} else {
+		printk(KERN_ERR
+		       "Failed to set endianness for device %s at slot %s\n",
+		       d->name, dev->slot_name);
+		return 1;
+	}
+
+	return sgiioc4_ide_setup_pci_device(dev, d);
+}
+
+static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
+	{
+	 /* Channel 0 */
+	 .vendor = PCI_VENDOR_ID_SGI,
+	 .device = PCI_DEVICE_ID_SGI_IOC4,
+	 .name = "SGIIOC4",
+	 .init_hwif = ide_init_sgiioc4,
+	 .init_dma = ide_dma_sgiioc4,
+	 .channels = 1,
+	 .autodma = AUTODMA,
+	 /* SGI IOC4 doesn't have enablebits. */
+	 .bootable = ON_BOARD,
+	}
+};
+
+static int __devinit
+sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &sgiioc4_chipsets[id->driver_data];
+	if (dev->device != d->device) {
+		printk(KERN_ERR "Error in %s(dev 0x%p | id 0x%p )\n",
+		       __FUNCTION__, (void *) dev, (void *) id);
+		BUG();
+	}
+
+	if (pci_init_sgiioc4(dev, d))
+		return 0;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static struct pci_device_id sgiioc4_pci_tbl[] = {
+	{PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
+	 PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0},
+	{0}
+};
+
+static struct pci_driver driver = {
+	.name = "SGI-IOC4 IDE",
+	.id_table = sgiioc4_pci_tbl,
+	.probe = sgiioc4_init_one,
+};
+
+static int
+sgiioc4_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+static void
+sgiioc4_ide_exit(void)
+{
+	ide_pci_unregister_driver(&driver);
+}
+
+module_init(sgiioc4_ide_init);
+module_exit(sgiioc4_ide_exit);
+
+MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
+MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ide/setup-pci.c 001-linus.patch/drivers/ide/setup-pci.c
--- 000-virgin/drivers/ide/setup-pci.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/drivers/ide/setup-pci.c	Tue Dec 30 16:38:57 2003
@@ -474,6 +474,11 @@ fixup_address:
  *	state
  */
  
+#ifndef CONFIG_BLK_DEV_IDEDMA_PCI
+static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
+{
+}
+#else
 static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
 {
 	u16 pcicmd;
@@ -516,6 +521,7 @@ static void ide_hwif_setup_dma(struct pc
 		}
 	}
 }
+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
 
 /**
  *	ide_setup_pci_controller	-	set up IDE PCI
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/ieee1394/dma.c 001-linus.patch/drivers/ieee1394/dma.c
--- 000-virgin/drivers/ieee1394/dma.c	Wed Dec 17 18:58:50 2003
+++ 001-linus.patch/drivers/ieee1394/dma.c	Tue Dec 30 16:38:57 2003
@@ -187,7 +187,7 @@ void dma_region_sync(struct dma_region *
 /* nopage() handler for mmap access */
 
 static struct page*
-dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int write_access)
+dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	unsigned long offset;
 	unsigned long kernel_virt_addr;
@@ -202,6 +202,8 @@ dma_region_pagefault(struct vm_area_stru
 	    (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) )
 		goto out;
 
+	if (type)
+		*type = VM_FAULT_MINOR;
 	offset = address - area->vm_start;
 	kernel_virt_addr = (unsigned long) dma->kvirt + offset;
 	ret = vmalloc_to_page((void*) kernel_virt_addr);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/input.c 001-linus.patch/drivers/input/input.c
--- 000-virgin/drivers/input/input.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/input/input.c	Tue Dec 30 16:38:57 2003
@@ -447,9 +447,10 @@ void input_register_device(struct input_
 	list_add_tail(&dev->node, &input_dev_list);
 
 	list_for_each_entry(handler, &input_handler_list, node)
-		if ((id = input_match_device(handler->id_table, dev)))
-			if ((handle = handler->connect(handler, dev, id)))
-				input_link_handle(handle);
+		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
+			if ((id = input_match_device(handler->id_table, dev)))
+				if ((handle = handler->connect(handler, dev, id)))
+					input_link_handle(handle);
 
 #ifdef CONFIG_HOTPLUG
 	input_call_hotplug("add", dev);
@@ -507,9 +508,10 @@ void input_register_handler(struct input
 	list_add_tail(&handler->node, &input_handler_list);
 	
 	list_for_each_entry(dev, &input_dev_list, node)
-		if ((id = input_match_device(handler->id_table, dev)))
-			if ((handle = handler->connect(handler, dev, id)))
-				input_link_handle(handle);
+		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
+			if ((id = input_match_device(handler->id_table, dev)))
+				if ((handle = handler->connect(handler, dev, id)))
+					input_link_handle(handle);
 
 #ifdef CONFIG_PROC_FS
 	input_devices_state++;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/joydev.c 001-linus.patch/drivers/input/joydev.c
--- 000-virgin/drivers/input/joydev.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/input/joydev.c	Tue Dec 30 16:38:57 2003
@@ -380,10 +380,6 @@ static struct input_handle *joydev_conne
 	struct joydev *joydev;
 	int i, j, t, minor;
 
-	/* Avoid tablets */
-        if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
-		return NULL;
-
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
 	if (minor == JOYDEV_MINORS) {
 		printk(KERN_ERR "joydev: no more free joydev devices\n");
@@ -464,6 +460,15 @@ static void joydev_disconnect(struct inp
 		joydev_free(joydev);
 }
 
+static struct input_device_id joydev_blacklist[] = {
+	{
+		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
+		.evbit = { BIT(EV_KEY) },
+		.keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+	}, 	/* Avoid itouchpads, touchscreens and tablets */
+	{ }, 	/* Terminating entry */
+};
+
 static struct input_device_id joydev_ids[] = {
 	{
 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
@@ -493,6 +498,7 @@ static struct input_handler joydev_handl
 	.minor =	JOYDEV_MINOR_BASE,
 	.name =		"joydev",
 	.id_table =	joydev_ids,
+	.blacklist = 	joydev_blacklist,
 };
 
 static int __init joydev_init(void)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/keyboard/atkbd.c 001-linus.patch/drivers/input/keyboard/atkbd.c
--- 000-virgin/drivers/input/keyboard/atkbd.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/drivers/input/keyboard/atkbd.c	Tue Dec 30 16:38:57 2003
@@ -48,33 +48,30 @@ static int atkbd_softrepeat;
  */
 
 static unsigned char atkbd_set2_keycode[512] = {
-	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41, 85,
-	  0, 56, 42,182, 29, 16,  2, 89,  0,  0, 44, 31, 30, 17,  3, 90,
-	  0, 46, 45, 32, 18,  5,  4, 91, 90, 57, 47, 33, 20, 19,  6,  0,
-	 91, 49, 48, 35, 34, 21,  7,  0,  0,  0, 50, 36, 22,  8,  9,  0,
+
+	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
+	  0, 56, 42,182, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
+	  0, 46, 45, 32, 18,  5,  4,186,  0, 57, 47, 33, 20, 19,  6, 85,
+	  0, 49, 48, 35, 34, 21,  7, 89,  0,  0, 50, 36, 22,  8,  9, 90,
 	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
-	122, 89, 40,120, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0,  0,
-	 85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121,  0,123,
+	  0,181, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0,194,
+	  0, 86,193,192,184,  0, 14,185,  0, 79,182, 75, 71,124,  0,  0,
 	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
-	  0,  0,  0, 65, 99,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255,
-	  0,  0, 92, 90, 85,  0,137,  0,  0,  0,  0, 91, 89,144,115,  0,
-	217,100,255,  0, 97,165,164,  0,156,  0,  0,140,115,  0,  0,125,
-	173,114,  0,113,152,163,151,126,128,166,  0,140,  0,147,  0,127,
-	159,167,115,160,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
-	157,  0,114,166,168,  0,  0,213,155,  0, 98,113,  0,163,  0,138,
-	226,  0,  0,  0,  0,  0,153,140,  0,255, 96,  0,  0,  0,143,  0,
-	133,  0,116,  0,143,  0,174,133,  0,107,  0,105,102,  0,  0,112,
-	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119
+	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
+	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
+	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
+	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
+	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
+	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
+
+	  0,  0,  0, 65, 99,
 };
 
 static unsigned char atkbd_set3_keycode[512] = {
+
 	  0,  0,  0,  0,  0,  0,  0, 59,  1,138,128,129,130, 15, 41, 60,
 	131, 29, 42, 86, 58, 16,  2, 61,133, 56, 44, 31, 30, 17,  3, 62,
 	134, 46, 45, 32, 18,  5,  4, 63,135, 57, 47, 33, 20, 19,  6, 64,
@@ -83,25 +80,21 @@ static unsigned char atkbd_set3_keycode[
 	113,114, 40, 84, 26, 13, 87, 99, 97, 54, 28, 27, 43, 84, 88, 70,
 	108,105,119,103,111,107, 14,110,  0, 79,106, 75, 71,109,102,104,
 	 82, 83, 80, 76, 77, 72, 69, 98,  0, 96, 81,  0, 78, 73, 55, 85,
+
 	 89, 90, 91, 92, 74,185,184,182,  0,  0,  0,125,126,127,112,  0,
 	  0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
-	148,149,147,140,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255
+	148,149,147,140
 };
 
 static unsigned char atkbd_unxlate_table[128] = {
-	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
-	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
-	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
-	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
-	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
-	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
-	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
-	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
+          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
+         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
+         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
+         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
+         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
+        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
+         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
+         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
 };
 
 #define ATKBD_CMD_SETLEDS	0x10ed
@@ -125,6 +118,9 @@ static unsigned char atkbd_unxlate_table
 #define ATKBD_RET_EMULX		0x80
 #define ATKBD_RET_EMUL1		0xe1
 #define ATKBD_RET_RELEASE	0xf0
+#define ATKBD_RET_HANGUEL	0xf1
+#define ATKBD_RET_HANJA		0xf2
+#define ATKBD_RET_ERR		0xff
 
 #define ATKBD_KEY_UNKNOWN	  0
 #define ATKBD_KEY_NULL		255
@@ -156,6 +152,17 @@ struct atkbd {
 	unsigned long time;
 };
 
+static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
+{
+	input_regs(dev, regs);
+	if (value == 3) {
+		input_report_key(dev, code, 1);
+		input_report_key(dev, code, 0);
+	} else
+		input_event(dev, EV_KEY, code, value);
+	input_sync(dev);
+}
+
 /*
  * atkbd_interrupt(). Here takes place processing of data received from
  * the keyboard into events.
@@ -184,47 +191,37 @@ static irqreturn_t atkbd_interrupt(struc
 		atkbd->resend = 0;
 #endif
 
-	switch (code) {
-		case ATKBD_RET_ACK:
-			atkbd->ack = 1;
-			goto out;
-		case ATKBD_RET_NAK:
-			atkbd->ack = -1;
-			goto out;
-	}
-
-	if (atkbd->translated) do {
-
-		if (atkbd->emul != 1) {
-			if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
-				break;
-			if (code == ATKBD_RET_BAT) {
-				if (!atkbd->bat_xl)
-					break;
-				atkbd->bat_xl = 0;
-			}
-			if (code == (ATKBD_RET_BAT & 0x7f))
-				atkbd->bat_xl = 1;
+	if (!atkbd->ack)
+		switch (code) {
+			case ATKBD_RET_ACK:
+				atkbd->ack = 1;
+				goto out;
+			case ATKBD_RET_NAK:
+				atkbd->ack = -1;
+				goto out;
 		}
 
-		if (code < 0x80) {
-			code = atkbd_unxlate_table[code];
-			break;
-		}
-
-		if (atkbd->cmdcnt)
-			break;
-
-		code = atkbd_unxlate_table[code & 0x7f];
-		atkbd->release = 1;
-
-	} while (0);
-
 	if (atkbd->cmdcnt) {
 		atkbd->cmdbuf[--atkbd->cmdcnt] = code;
 		goto out;
 	}
 
+	if (atkbd->translated) {
+
+		if (atkbd->emul ||
+		    !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
+		      code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
+		      code == ATKBD_RET_ERR ||
+	             (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
+			atkbd->release = code >> 7;
+			code &= 0x7f;
+		}
+
+		if (!atkbd->emul &&
+		     (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
+			atkbd->bat_xl = !atkbd->release;
+	}
+
 	switch (code) {
 		case ATKBD_RET_BAT:
 			serio_rescan(atkbd->serio);
@@ -238,22 +235,33 @@ static irqreturn_t atkbd_interrupt(struc
 		case ATKBD_RET_RELEASE:
 			atkbd->release = 1;
 			goto out;
+		case ATKBD_RET_HANGUEL:
+			atkbd_report_key(&atkbd->dev, regs, KEY_LANG1, 3);
+			goto out;
+		case ATKBD_RET_HANJA:
+			atkbd_report_key(&atkbd->dev, regs, KEY_LANG2, 3);
+			goto out;
+		case ATKBD_RET_ERR:
+			printk(KERN_WARNING "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
+			goto out;
 	}
 
+	if (atkbd->set != 3)
+		code = (code & 0x7f) | ((code & 0x80) << 1);
 	if (atkbd->emul) {
 		if (--atkbd->emul)
 			goto out;
-		code |= 0x100;
+		code |= (atkbd->set != 3) ? 0x80 : 0x100;
 	}
 
 	switch (atkbd->keycode[code]) {
 		case ATKBD_KEY_NULL:
 			break;
 		case ATKBD_KEY_UNKNOWN:
-			printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x, data %#x, on %s).\n",
+			printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
 				atkbd->release ? "released" : "pressed",
 				atkbd->translated ? "translated" : "raw", 
-				atkbd->set, code, data, serio->phys);
+				atkbd->set, code, serio->phys);
 			break;
 		default:
 			value = atkbd->release ? 0 :
@@ -273,9 +281,7 @@ static irqreturn_t atkbd_interrupt(struc
 					break;
 			}
 
-			input_regs(&atkbd->dev, regs);
-			input_event(&atkbd->dev, EV_KEY, atkbd->keycode[code], value);
-			input_sync(&atkbd->dev);
+			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
 	atkbd->release = 0;
@@ -369,10 +375,11 @@ static int atkbd_command(struct atkbd *a
 static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct atkbd *atkbd = dev->private;
-	struct { int p; u8 v; } period[] =	
-		{ {30, 0x00}, {25, 0x02}, {20, 0x04}, {15, 0x08}, {10, 0x0c}, {7, 0x10}, {5, 0x14}, {0, 0x14} };
-	struct { int d; u8 v; } delay[] =
-        	{ {1000, 0x60}, {750, 0x40}, {500, 0x20}, {250, 0x00}, {0, 0x00} };
+	const short period[32] =
+		{ 33,  37,  42,  46,  50,  54,  58,  63,  67,  75,  83,  92, 100, 109, 116, 125,
+		 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
+	const short delay[4] =
+		{ 250, 500, 750, 1000 };
 	char param[2];
 	int i, j;
 
@@ -406,11 +413,11 @@ static int atkbd_event(struct input_dev 
 			if (atkbd_softrepeat) return 0;
 
 			i = j = 0;
-			while (period[i].p > dev->rep[REP_PERIOD]) i++;
-			while (delay[j].d > dev->rep[REP_DELAY]) j++;
-			dev->rep[REP_PERIOD] = period[i].p;
-			dev->rep[REP_DELAY] = delay[j].d;
-			param[0] = period[i].v | delay[j].v;
+			while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
+			while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
+			dev->rep[REP_PERIOD] = period[i];
+			dev->rep[REP_DELAY] = delay[j];
+			param[0] = i | (j << 5);
 			atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
 
 			return 0;
@@ -623,6 +630,7 @@ static void atkbd_connect(struct serio *
 		atkbd->dev.rep[REP_PERIOD] = 33;
 	}
 
+	atkbd->ack = 1;
 	atkbd->serio = serio;
 
 	init_input_dev(&atkbd->dev);
@@ -665,16 +673,22 @@ static void atkbd_connect(struct serio *
 
 	sprintf(atkbd->phys, "%s/input0", serio->phys);
 
-	if (atkbd->set == 3)
-		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
-	else
+	if (atkbd->translated) {
+		for (i = 0; i < 128; i++) {
+			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
+		}
+	} else if (atkbd->set == 2) {
 		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
+	} else {
+		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+	}
 
 	atkbd->dev.name = atkbd->name;
 	atkbd->dev.phys = atkbd->phys;
 	atkbd->dev.id.bustype = BUS_I8042;
 	atkbd->dev.id.vendor = 0x0001;
-	atkbd->dev.id.product = atkbd->set;
+	atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
 	atkbd->dev.id.version = atkbd->id;
 
 	for (i = 0; i < 512; i++)
@@ -686,10 +700,62 @@ static void atkbd_connect(struct serio *
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
+/*
+ * atkbd_reconnect() tries to restore keyboard into a sane state and is
+ * most likely called on resume.
+ */
+
+static int atkbd_reconnect(struct serio *serio)
+{
+	struct atkbd *atkbd = serio->private;
+	struct serio_dev *dev = serio->dev;
+	int i;
+
+        if (!dev) {
+                printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
+                return -1;
+        }
+
+	if (atkbd->write) {
+		if (atkbd_probe(atkbd))
+			return -1;
+
+		atkbd->set = atkbd_set_3(atkbd);
+		atkbd_enable(atkbd);
+	} else {
+		atkbd->set = 2;
+		atkbd->id = 0xab00;
+	}
+
+	/*
+	 * Here we probably should check if the keyboard has the same set that
+         * it had before and bail out if it's different. But this will most likely
+         * cause new keyboard device be created... and for the user it will look
+         * like keyboard is lost
+	 */
+
+	if (atkbd->translated) {
+		for (i = 0; i < 128; i++) {
+			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
+		}
+	} else if (atkbd->set == 2) {
+		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
+	} else {
+		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+	}
+
+	for (i = 0; i < 512; i++)
+		if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
+			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
+
+	return 0;
+}
 
 static struct serio_dev atkbd_dev = {
 	.interrupt =	atkbd_interrupt,
 	.connect =	atkbd_connect,
+	.reconnect = 	atkbd_reconnect,
 	.disconnect =	atkbd_disconnect,
 	.cleanup =	atkbd_cleanup,
 };
@@ -709,9 +775,17 @@ static int __init atkbd_setup_reset(char
         if (ints[0] > 0) atkbd_reset = ints[1];
         return 1;
 }
+static int __init atkbd_setup_softrepeat(char *str)
+{
+        int ints[4];
+        str = get_options(str, ARRAY_SIZE(ints), ints);
+        if (ints[0] > 0) atkbd_softrepeat = ints[1];
+        return 1;
+}
 
 __setup("atkbd_set=", atkbd_setup_set);
 __setup("atkbd_reset", atkbd_setup_reset);
+__setup("atkbd_softrepeat=", atkbd_setup_softrepeat);
 #endif
 
 int __init atkbd_init(void)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/Kconfig 001-linus.patch/drivers/input/mouse/Kconfig
--- 000-virgin/drivers/input/mouse/Kconfig	Wed Dec 17 18:59:25 2003
+++ 001-linus.patch/drivers/input/mouse/Kconfig	Tue Dec 30 16:38:57 2003
@@ -23,27 +23,18 @@ config MOUSE_PS2
 	  mice with wheels and extra buttons, Microsoft, Logitech or Genius
 	  compatible.
 
+	  Synaptics TouchPad users might be interested in a specialized
+	  XFree86 driver at:
+		http://w1.894.telia.com/~u89404340/touchpad/index.html
+	  and a new verion of GPM at:
+		http://www.geocities.com/dt_or/gpm/gpm.html
+	  to take advantage of the advanced features of the touchpad.
+
 	  If unsure, say Y.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called psmouse.
 
-config MOUSE_PS2_SYNAPTICS
-	bool "Synaptics TouchPad"
-	default n
-	depends on INPUT && INPUT_MOUSE && MOUSE_PS2
-	---help---
-	  Say Y here if you have a Synaptics TouchPad connected to your system.
-	  This touchpad is found on many modern laptop computers.
-
-	  Note that you also need a user space driver to interpret the data
-	  generated by the kernel. A compatible driver for XFree86 is available
-	  from http://w1.894.telia.com/~u89404340/touchpad/index.html
-
-	  The gpm program is not yet able to interpret the data from this
-	  driver, so if you need to use the touchpad in the console, you have to
-	  say N for now.
-
 config MOUSE_SERIAL
 	tristate "Serial mouse"
 	depends on INPUT && INPUT_MOUSE
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/logips2pp.c 001-linus.patch/drivers/input/mouse/logips2pp.c
--- 000-virgin/drivers/input/mouse/logips2pp.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/input/mouse/logips2pp.c	Tue Dec 30 16:38:57 2003
@@ -10,6 +10,7 @@
  */
 
 #include <linux/input.h>
+#include <linux/serio.h>
 #include "psmouse.h"
 #include "logips2pp.h"
 
@@ -142,7 +143,7 @@ void ps2pp_set_800dpi(struct psmouse *ps
  * touchpad.
  */
 
-int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
+static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param)
 {
 	int i;
 	static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
@@ -226,3 +227,22 @@ int ps2pp_detect_model(struct psmouse *p
 
 	return 0;
 }
+
+/*
+ * Logitech magic init.
+ */
+int ps2pp_detect(struct psmouse *psmouse)
+{
+	unsigned char param[4];
+
+	param[0] = 0;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
+	param[1] = 0;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+	return param[1] != 0 ? ps2pp_detect_model(psmouse, param) : 0;
+}
+
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/logips2pp.h 001-linus.patch/drivers/input/mouse/logips2pp.h
--- 000-virgin/drivers/input/mouse/logips2pp.h	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/drivers/input/mouse/logips2pp.h	Tue Dec 30 16:38:57 2003
@@ -13,5 +13,5 @@
 struct psmouse;
 void ps2pp_process_packet(struct psmouse *psmouse);
 void ps2pp_set_800dpi(struct psmouse *psmouse);
-int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param);
+int ps2pp_detect(struct psmouse *psmouse);
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/psmouse-base.c 001-linus.patch/drivers/input/mouse/psmouse-base.c
--- 000-virgin/drivers/input/mouse/psmouse-base.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/drivers/input/mouse/psmouse-base.c	Tue Dec 30 16:38:57 2003
@@ -12,35 +12,44 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/serio.h>
 #include <linux/init.h>
-#include <linux/pm.h>
 #include "psmouse.h"
 #include "synaptics.h"
 #include "logips2pp.h"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("PS/2 mouse driver");
-MODULE_PARM(psmouse_noext, "1i");
-MODULE_PARM_DESC(psmouse_noext, "Disable any protocol extensions. Useful for KVM switches.");
-MODULE_PARM(psmouse_resolution, "i");
-MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
-MODULE_PARM(psmouse_rate, "i");
-MODULE_PARM_DESC(psmouse_rate, "Report rate, in reports per second.");
-MODULE_PARM(psmouse_smartscroll, "i");
-MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
-MODULE_PARM(psmouse_resetafter, "i");
-MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
 MODULE_LICENSE("GPL");
 
 static int psmouse_noext;
+module_param(psmouse_noext, int, 0);
+MODULE_PARM_DESC(psmouse_noext, "[DEPRECATED] Disable any protocol extensions. Useful for KVM switches.");
+
+static char *psmouse_proto;
+static unsigned int psmouse_max_proto = -1UL;
+module_param(psmouse_proto, charp, 0);
+MODULE_PARM_DESC(psmouse_proto, "Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches.");
+
 int psmouse_resolution = 200;
+module_param(psmouse_resolution, uint, 0);
+MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
+
 unsigned int psmouse_rate = 100;
+module_param(psmouse_rate, uint, 0);
+MODULE_PARM_DESC(psmouse_rate, "Report rate, in reports per second.");
+
 int psmouse_smartscroll = 1;
+module_param(psmouse_smartscroll, bool, 0);
+MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+
 unsigned int psmouse_resetafter;
+module_param(psmouse_resetafter, uint, 0);
+MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
 
 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
 
@@ -139,7 +148,8 @@ static irqreturn_t psmouse_interrupt(str
 		goto out;
 	}
 
-	if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
+	if (psmouse->state == PSMOUSE_ACTIVATED &&
+	    psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
 		printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
 		       psmouse->name, psmouse->phys, psmouse->pktcnt);
 		psmouse->pktcnt = 0;
@@ -257,46 +267,12 @@ int psmouse_command(struct psmouse *psmo
 }
 
 /*
- * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
- * the mouse may have.
+ * Genius NetMouse magic init.
  */
-
-static int psmouse_extensions(struct psmouse *psmouse)
+static int genius_detect(struct psmouse *psmouse)
 {
 	unsigned char param[4];
 
-	param[0] = 0;
-	psmouse->vendor = "Generic";
-	psmouse->name = "Mouse";
-	psmouse->model = 0;
-
-	if (psmouse_noext)
-		return PSMOUSE_PS2;
-
-/*
- * Try Synaptics TouchPad magic ID
- */
-
-       param[0] = 0;
-       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-       psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-       psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
-
-       if (param[1] == 0x47) {
-		psmouse->vendor = "Synaptics";
-		psmouse->name = "TouchPad";
-		if (!synaptics_init(psmouse))
-			return PSMOUSE_SYNAPTICS;
-		else
-			return PSMOUSE_PS2;
-       }
-
-/*
- * Try Genius NetMouse magic init.
- */
-
 	param[0] = 3;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
 	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
@@ -304,65 +280,99 @@ static int psmouse_extensions(struct psm
 	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
 	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
 
-	if (param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55) {
-
-		set_bit(BTN_EXTRA, psmouse->dev.keybit);
-		set_bit(BTN_SIDE, psmouse->dev.keybit);
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
-
-		psmouse->vendor = "Genius";
-		psmouse->name = "Wheel Mouse";
-		return PSMOUSE_GENPS;
-	}
+	return param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55;
+}
 
 /*
- * Try Logitech magic ID.
+ * IntelliMouse magic init.
  */
+static int intellimouse_detect(struct psmouse *psmouse)
+{
+	unsigned char param[2];
 
-	param[0] = 0;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
-	param[1] = 0;
-	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+	param[0] = 200;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] = 100;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  80;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
 
-	if (param[1]) {
-		int type = ps2pp_detect_model(psmouse, param);
-		if (type)
-			return type;
-	}
+	return param[0] == 3;
+}
 
 /*
- * Try IntelliMouse magic init.
+ * Try IntelliMouse/Explorer magic init.
  */
+static int im_explorer_detect(struct psmouse *psmouse)
+{
+	unsigned char param[2];
 
 	param[0] = 200;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-	param[0] = 100;
+	param[0] = 200;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
 	param[0] =  80;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
 	psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
-	
-	if (param[0] == 3) {
 
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
+	return param[0] == 4;
+}
 
 /*
- * Try IntelliMouse/Explorer magic init.
+ * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
+ * the mouse may have.
+ */
+
+static int psmouse_extensions(struct psmouse *psmouse)
+{
+	int synaptics_hardware = 0;
+
+	psmouse->vendor = "Generic";
+	psmouse->name = "Mouse";
+	psmouse->model = 0;
+
+/*
+ * Try Synaptics TouchPad
  */
+	if (psmouse_max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) {
+		synaptics_hardware = 1;
+		psmouse->vendor = "Synaptics";
+		psmouse->name = "TouchPad";
 
-		param[0] = 200;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		param[0] = 200;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		param[0] =  80;
-		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
-		psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
+		if (psmouse_max_proto > PSMOUSE_IMEX) {
+			if (synaptics_init(psmouse) == 0)
+				return PSMOUSE_SYNAPTICS;
+/*
+ * Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
+ * Unfortunately Logitech/Genius probes confuse some firmware versions so
+ * we'll have to skip them.
+ */
+			psmouse_max_proto = PSMOUSE_IMEX;
+		}
+	}
 
-		if (param[0] == 4) {
+	if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
+		set_bit(BTN_EXTRA, psmouse->dev.keybit);
+		set_bit(BTN_SIDE, psmouse->dev.keybit);
+		set_bit(REL_WHEEL, psmouse->dev.relbit);
 
+		psmouse->vendor = "Genius";
+		psmouse->name = "Wheel Mouse";
+		return PSMOUSE_GENPS;
+	}
+
+	if (psmouse_max_proto > PSMOUSE_IMEX) {
+		int type = ps2pp_detect(psmouse);
+		if (type)
+			return type;
+	}
+
+	if (psmouse_max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) {
+		set_bit(REL_WHEEL, psmouse->dev.relbit);
+
+		if (psmouse_max_proto >= PSMOUSE_IMEX &&
+					im_explorer_detect(psmouse)) {
 			set_bit(BTN_SIDE, psmouse->dev.keybit);
 			set_bit(BTN_EXTRA, psmouse->dev.keybit);
 
@@ -378,6 +388,15 @@ static int psmouse_extensions(struct psm
  * Okay, all failed, we have a standard mouse here. The number of the buttons
  * is still a question, though. We assume 3.
  */
+	if (synaptics_hardware) {
+/*
+ * We detected Synaptics hardware but it did not respond to IMPS/2 probes.
+ * We need to reset the touchpad because if there is a track point on the
+ * pass through port it could get disabled while probing for protocol
+ * extensions.
+ */
+		psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS);
+	}
 
 	return PSMOUSE_PS2;
 }
@@ -468,7 +487,7 @@ static void psmouse_initialize(struct ps
  * We set the mouse report rate, resolution and scaling.
  */
 
-	if (!psmouse_noext) {
+	if (psmouse_max_proto != PSMOUSE_PS2) {
 		psmouse_set_rate(psmouse);
 		psmouse_set_resolution(psmouse);
 		psmouse_command(psmouse,  NULL, PSMOUSE_CMD_SETSCALE11);
@@ -513,45 +532,30 @@ static void psmouse_disconnect(struct se
 	struct psmouse *psmouse = serio->private;
 
 	psmouse->state = PSMOUSE_IGNORE;
-	synaptics_disconnect(psmouse);
-	input_unregister_device(&psmouse->dev);
-	serio_close(serio);
-	kfree(psmouse);
-}
-
-/*
- * Reinitialize mouse hardware after software suspend.
- */
-
-static int psmouse_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
-{
-	struct psmouse *psmouse = dev->data;
-	struct serio_dev *ser_dev = psmouse->serio->dev;
-
-	synaptics_disconnect(psmouse);
 
-	/* We need to reopen the serio port to reinitialize the i8042 controller */
-	serio_close(psmouse->serio);
-	serio_open(psmouse->serio, ser_dev);
+	if (psmouse->ptport) {
+		if (psmouse->ptport->deactivate)
+			psmouse->ptport->deactivate(psmouse);
+		__serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */
+		kfree(psmouse->ptport);
+		psmouse->ptport = NULL;
+	}
 
-	/* Probe and re-initialize the mouse */
-	psmouse_probe(psmouse);
-	psmouse_initialize(psmouse);
-	synaptics_pt_init(psmouse);
-	psmouse_activate(psmouse);
+	if (psmouse->disconnect)
+		psmouse->disconnect(psmouse);
 
-	return 0;
+	input_unregister_device(&psmouse->dev);
+	serio_close(serio);
+	kfree(psmouse);
 }
 
 /*
  * psmouse_connect() is a callback from the serio module when
  * an unhandled serio port is found.
  */
-
 static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
 {
 	struct psmouse *psmouse;
-	struct pm_dev *pmdev;
 	
 	if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
 	    (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
@@ -572,7 +576,6 @@ static void psmouse_connect(struct serio
 	psmouse->dev.private = psmouse;
 
 	serio->private = psmouse;
-
 	if (serio_open(serio, dev)) {
 		kfree(psmouse);
 		return;
@@ -584,12 +587,6 @@ static void psmouse_connect(struct serio
 		return;
 	}
 	
-	pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
-	if (pmdev) {
-		psmouse->dev.pm_dev = pmdev;
-		pmdev->data = psmouse;
-	}
-
 	sprintf(psmouse->devname, "%s %s %s",
 		psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
 	sprintf(psmouse->phys, "%s/input0",
@@ -608,59 +605,87 @@ static void psmouse_connect(struct serio
 
 	psmouse_initialize(psmouse);
 
-	synaptics_pt_init(psmouse);
+	if (psmouse->ptport) {
+		printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys);
+		__serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */
+		if (psmouse->ptport->activate)
+			psmouse->ptport->activate(psmouse);
+	}
+
+	psmouse_activate(psmouse);
+}
+
+
+static int psmouse_reconnect(struct serio *serio)
+{
+	struct psmouse *psmouse = serio->private;
+	struct serio_dev *dev = serio->dev;
+	int old_type = psmouse->type;
+
+	if (!dev) {
+		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
+		return -1;
+	}
+
+	psmouse->state = PSMOUSE_NEW_DEVICE;
+	psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0;
+	if (psmouse->reconnect) {
+	       if (psmouse->reconnect(psmouse))
+			return -1;
+	} else if (psmouse_probe(psmouse) != old_type)
+		return -1;
+
+	/* ok, the device type (and capabilities) match the old one,
+	 * we can continue using it, complete intialization
+	 */
+	psmouse->type = old_type;
+	psmouse_initialize(psmouse);
+
+	if (psmouse->ptport) {
+       		if (psmouse_reconnect(&psmouse->ptport->serio)) {
+			__serio_unregister_port(&psmouse->ptport->serio);
+			__serio_register_port(&psmouse->ptport->serio);
+			if (psmouse->ptport->activate)
+				psmouse->ptport->activate(psmouse);
+		}
+	}
 
 	psmouse_activate(psmouse);
+	return 0;
 }
 
+
 static struct serio_dev psmouse_dev = {
 	.interrupt =	psmouse_interrupt,
 	.connect =	psmouse_connect,
+	.reconnect =	psmouse_reconnect,
 	.disconnect =	psmouse_disconnect,
 	.cleanup =	psmouse_cleanup,
 };
 
-#ifndef MODULE
-static int __init psmouse_noext_setup(char *str)
-{
-	psmouse_noext = 1;
-	return 1;
-}
-
-static int __init psmouse_resolution_setup(char *str)
-{
-	get_option(&str, &psmouse_resolution);
-	return 1;
-}
-
-static int __init psmouse_smartscroll_setup(char *str)
+static inline void psmouse_parse_proto(void)
 {
-	get_option(&str, &psmouse_smartscroll);
-	return 1;
-}
-
-static int __init psmouse_resetafter_setup(char *str)
-{
-	get_option(&str, &psmouse_resetafter);
-	return 1;
-}
+	if (psmouse_noext) {
+		printk(KERN_WARNING "psmouse: 'psmouse_noext' option is deprecated, please use 'psmouse_proto'\n");
+		psmouse_max_proto = PSMOUSE_PS2;
+	}
 
-static int __init psmouse_rate_setup(char *str)
-{
-	get_option(&str, &psmouse_rate);
-	return 1;
+	/* even is psmouse_noext is present psmouse_proto overrides it */
+	if (psmouse_proto) {
+		if (!strcmp(psmouse_proto, "bare"))
+			psmouse_max_proto = PSMOUSE_PS2;
+		else if (!strcmp(psmouse_proto, "imps"))
+			psmouse_max_proto = PSMOUSE_IMPS;
+		else if (!strcmp(psmouse_proto, "exps"))
+			psmouse_max_proto = PSMOUSE_IMEX;
+		else
+			printk(KERN_ERR "psmouse: unknown protocol type '%s'\n", psmouse_proto);
+	}
 }
 
-__setup("psmouse_noext", psmouse_noext_setup);
-__setup("psmouse_resolution=", psmouse_resolution_setup);
-__setup("psmouse_smartscroll=", psmouse_smartscroll_setup);
-__setup("psmouse_resetafter=", psmouse_resetafter_setup);
-__setup("psmouse_rate=", psmouse_rate_setup);
-
-#endif
-
 int __init psmouse_init(void)
 {
+	psmouse_parse_proto();
 	serio_register_device(&psmouse_dev);
 	return 0;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/psmouse.h 001-linus.patch/drivers/input/mouse/psmouse.h
--- 000-virgin/drivers/input/mouse/psmouse.h	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/drivers/input/mouse/psmouse.h	Tue Dec 30 16:38:57 2003
@@ -22,10 +22,20 @@
 #define PSMOUSE_ACTIVATED	1
 #define PSMOUSE_IGNORE		2
 
+struct psmouse;
+
+struct psmouse_ptport {
+	struct serio serio;
+
+	void (*activate)(struct psmouse *parent);
+	void (*deactivate)(struct psmouse *parent);
+};
+
 struct psmouse {
 	void *private;
 	struct input_dev dev;
 	struct serio *serio;
+	struct psmouse_ptport *ptport;
 	char *vendor;
 	char *name;
 	unsigned char cmdbuf[8];
@@ -41,6 +51,9 @@ struct psmouse {
 	char error;
 	char devname[64];
 	char phys[32];
+
+	int (*reconnect)(struct psmouse *psmouse);
+	void (*disconnect)(struct psmouse *psmouse);
 };
 
 #define PSMOUSE_PS2		1
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/synaptics.c 001-linus.patch/drivers/input/mouse/synaptics.c
--- 000-virgin/drivers/input/mouse/synaptics.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/drivers/input/mouse/synaptics.c	Tue Dec 30 16:38:57 2003
@@ -2,7 +2,8 @@
  * Synaptics TouchPad PS/2 mouse driver
  *
  *   2003 Dmitry Torokhov <dtor@mail.ru>
- *     Added support for pass-through port
+ *     Added support for pass-through port. Special thanks to Peter Berg Larsen
+ *     for explaining various Synaptics quirks.
  *
  *   2003 Peter Osterlund <petero2@telia.com>
  *     Ported to 2.5 input device infrastructure.
@@ -194,9 +195,7 @@ static void print_ident(struct synaptics
 
 static int synaptics_query_hardware(struct psmouse *psmouse)
 {
-	struct synaptics_data *priv = psmouse->private;
 	int retries = 0;
-	int mode;
 
 	while ((retries++ < 3) && synaptics_reset(psmouse))
 		printk(KERN_ERR "synaptics reset failed\n");
@@ -208,7 +207,14 @@ static int synaptics_query_hardware(stru
 	if (synaptics_capability(psmouse))
 		return -1;
 
-	mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
+	return 0;
+}
+
+static int synaptics_set_mode(struct psmouse *psmouse, int mode)
+{
+	struct synaptics_data *priv = psmouse->private;
+
+	mode |= SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
 	if (SYN_ID_MAJOR(priv->identity) >= 4)
 		mode |= SYN_BIT_DISABLE_GESTURE;
 	if (SYN_CAP_EXTENDED(priv->capabilities))
@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(str
 	}
 }
 
-int synaptics_pt_init(struct psmouse *psmouse)
+static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-	struct synaptics_data *priv = psmouse->private;
-	struct serio *port;
-	struct psmouse *child;
+	struct psmouse *child = psmouse->ptport->serio.private;
 
-	if (psmouse->type != PSMOUSE_SYNAPTICS)
-		return -1;
-	if (!SYN_CAP_EXTENDED(priv->capabilities))
-		return -1;
-	if (!SYN_CAP_PASS_THROUGH(priv->capabilities))
-		return -1;
+	/* adjust the touchpad to child's choice of protocol */
+	if (child && child->type >= PSMOUSE_GENPS) {
+		if (synaptics_set_mode(psmouse, SYN_BIT_FOUR_BYTE_CLIENT))
+			printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
+	}
+}
+
+static void synaptics_pt_create(struct psmouse *psmouse)
+{
+	struct psmouse_ptport *port;
 
-	priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
 	if (!port) {
-		printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n");
-		return -1;
+		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
+		return;
 	}
 
-	memset(port, 0, sizeof(struct serio));
-	port->type = SERIO_PS_PSTHRU;
-	port->name = "Synaptics pass-through";
-	port->phys = "synaptics-pt/serio0";
-	port->write = synaptics_pt_write;
-	port->open = synaptics_pt_open;
-	port->close = synaptics_pt_close;
-	port->driver = psmouse;
-
-	printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys);
-	serio_register_slave_port(port);
+	memset(port, 0, sizeof(struct psmouse_ptport));
 
-	/* adjust the touchpad to child's choice of protocol */
-	child = port->private;
-	if (child && child->type >= PSMOUSE_GENPS) {
-		if (synaptics_mode_cmd(psmouse, (SYN_BIT_ABSOLUTE_MODE |
-					 	 SYN_BIT_HIGH_RATE |
-					 	 SYN_BIT_DISABLE_GESTURE |
-						 SYN_BIT_FOUR_BYTE_CLIENT |
-					 	 SYN_BIT_W_MODE)))
-			printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
-	}
+	port->serio.type = SERIO_PS_PSTHRU;
+	port->serio.name = "Synaptics pass-through";
+	port->serio.phys = "synaptics-pt/serio0";
+	port->serio.write = synaptics_pt_write;
+	port->serio.open = synaptics_pt_open;
+	port->serio.close = synaptics_pt_close;
+	port->serio.driver = psmouse;
 
-	return 0;
+	port->activate = synaptics_pt_activate;
 }
 
 /*****************************************************************************
@@ -371,27 +366,82 @@ static void set_input_params(struct inpu
 	clear_bit(REL_Y, dev->relbit);
 }
 
+static void synaptics_disconnect(struct psmouse *psmouse)
+{
+	synaptics_mode_cmd(psmouse, 0);
+	kfree(psmouse->private);
+}
+
+static int synaptics_reconnect(struct psmouse *psmouse)
+{
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_data old_priv = *priv;
+
+	if (!synaptics_detect(psmouse))
+		return -1;
+
+	if (synaptics_query_hardware(psmouse)) {
+		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		return -1;
+	}
+
+	if (old_priv.identity != priv->identity ||
+	    old_priv.model_id != priv->model_id ||
+	    old_priv.capabilities != priv->capabilities ||
+    	    old_priv.ext_cap != priv->ext_cap)
+    		return -1;
+
+	if (synaptics_set_mode(psmouse, 0)) {
+		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int synaptics_detect(struct psmouse *psmouse)
+{
+	unsigned char param[4];
+
+	param[0] = 0;
+
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+	return param[1] == 0x47;
+}
+
 int synaptics_init(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv;
 
-#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
-	return -1;
-#endif
-
 	psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 	if (!priv)
 		return -1;
 	memset(priv, 0, sizeof(struct synaptics_data));
 
 	if (synaptics_query_hardware(psmouse)) {
-		printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
+		printk(KERN_ERR "Unable to query Synaptics hardware.\n");
+		goto init_fail;
+	}
+
+	if (synaptics_set_mode(psmouse, 0)) {
+		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
 		goto init_fail;
 	}
 
+	if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
+       		synaptics_pt_create(psmouse);
+
 	print_ident(priv);
 	set_input_params(&psmouse->dev, priv);
 
+	psmouse->disconnect = synaptics_disconnect;
+	psmouse->reconnect = synaptics_reconnect;
+
 	return 0;
 
  init_fail:
@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmou
 	return -1;
 }
 
-void synaptics_disconnect(struct psmouse *psmouse)
-{
-	struct synaptics_data *priv = psmouse->private;
-
-	if (psmouse->type == PSMOUSE_SYNAPTICS && priv) {
-		synaptics_mode_cmd(psmouse, 0);
-		if (priv->ptport) {
-			serio_unregister_slave_port(priv->ptport);
-			kfree(priv->ptport);
-		}
-		kfree(priv);
-	}
-}
-
 /*****************************************************************************
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
 static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
 {
-	hw->up    = 0;
-	hw->down  = 0;
-	hw->b0    = 0;
-	hw->b1    = 0;
-	hw->b2    = 0;
-	hw->b3    = 0;
-	hw->b4    = 0;
-	hw->b5    = 0;
-	hw->b6    = 0;
-	hw->b7    = 0;
+	memset(hw, 0, sizeof(struct synaptics_hw_state));
 
 	if (SYN_MODEL_NEWABS(priv->model_id)) {
 		hw->x = (((buf[3] & 0x10) << 8) |
@@ -570,64 +597,47 @@ static void synaptics_process_packet(str
 	input_sync(dev);
 }
 
+static int synaptics_validate_byte(struct psmouse *psmouse)
+{
+	static unsigned char newabs_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
+	static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
+	static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
+	static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+	struct synaptics_data *priv = psmouse->private;
+	int idx = psmouse->pktcnt - 1;
+
+	if (SYN_MODEL_NEWABS(priv->model_id))
+		return (psmouse->packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
+	else
+		return (psmouse->packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
+}
+
 void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
 	struct input_dev *dev = &psmouse->dev;
 	struct synaptics_data *priv = psmouse->private;
-	unsigned char data = psmouse->packet[psmouse->pktcnt - 1];
-	int newabs = SYN_MODEL_NEWABS(priv->model_id);
 
 	input_regs(dev, regs);
 
-	switch (psmouse->pktcnt) {
-	case 1:
-		if (newabs ? ((data & 0xC8) != 0x80) : ((data & 0xC0) != 0xC0)) {
-			printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
-			goto bad_sync;
-		}
-		break;
-	case 2:
-		if (!newabs && ((data & 0x60) != 0x00)) {
-			printk(KERN_WARNING "Synaptics driver lost sync at 2nd byte\n");
-			goto bad_sync;
-		}
-		break;
-	case 4:
-		if (newabs ? ((data & 0xC8) != 0xC0) : ((data & 0xC0) != 0x80)) {
-			printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
-			goto bad_sync;
-		}
-		break;
-	case 5:
-		if (!newabs && ((data & 0x60) != 0x00)) {
-			printk(KERN_WARNING "Synaptics driver lost sync at 5th byte\n");
-			goto bad_sync;
-		}
-		break;
-	default:
-		if (psmouse->pktcnt < 6)
-			break;		    /* Wait for full packet */
-
+	if (psmouse->pktcnt >= 6) { /* Full packet received */
 		if (priv->out_of_sync) {
 			priv->out_of_sync = 0;
 			printk(KERN_NOTICE "Synaptics driver resynced.\n");
 		}
 
-		if (priv->ptport && synaptics_is_pt_packet(psmouse->packet))
-			synaptics_pass_pt_packet(priv->ptport, psmouse->packet);
+		if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
+			synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
 		else
 			synaptics_process_packet(psmouse);
-
 		psmouse->pktcnt = 0;
-		break;
-	}
-	return;
 
- bad_sync:
-	priv->out_of_sync++;
-	psmouse->pktcnt = 0;
-	if (psmouse_resetafter > 0 && priv->out_of_sync	== psmouse_resetafter) {
-		psmouse->state = PSMOUSE_IGNORE;
-		serio_rescan(psmouse->serio);
+	} else if (psmouse->pktcnt && !synaptics_validate_byte(psmouse)) {
+		printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
+		psmouse->pktcnt = 0;
+		if (++priv->out_of_sync == psmouse_resetafter) {
+			psmouse->state = PSMOUSE_IGNORE;
+			printk(KERN_NOTICE "synaptics: issuing reconnect request\n");
+			serio_reconnect(psmouse->serio);
+		}
 	}
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/mouse/synaptics.h 001-linus.patch/drivers/input/mouse/synaptics.h
--- 000-virgin/drivers/input/mouse/synaptics.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/input/mouse/synaptics.h	Tue Dec 30 16:38:57 2003
@@ -9,11 +9,9 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-
 extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
+extern int synaptics_detect(struct psmouse *psmouse);
 extern int synaptics_init(struct psmouse *psmouse);
-extern int synaptics_pt_init(struct psmouse *psmouse);
-extern void synaptics_disconnect(struct psmouse *psmouse);
 
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY		0x00
@@ -105,8 +103,6 @@ struct synaptics_data {
 	/* Data for normal processing */
 	unsigned int out_of_sync;		/* # of packets out of sync */
 	int old_w;				/* Previous w value */
-	
-	struct serio *ptport;			/* pass-through port */
 };
 
 #endif /* _SYNAPTICS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/serio/i8042.c 001-linus.patch/drivers/input/serio/i8042.c
--- 000-virgin/drivers/input/serio/i8042.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/drivers/input/serio/i8042.c	Tue Dec 30 16:38:57 2003
@@ -12,11 +12,14 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/config.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/pm.h>
 #include <linux/serio.h>
 
 #include <asm/io.h>
@@ -25,19 +28,23 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@s
 MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(i8042_noaux, "1i");
-MODULE_PARM(i8042_nomux, "1i");
-MODULE_PARM(i8042_unlock, "1i");
-MODULE_PARM(i8042_reset, "1i");
-MODULE_PARM(i8042_direct, "1i");
-MODULE_PARM(i8042_dumbkbd, "1i");
-
-static int i8042_reset;
-static int i8042_noaux;
-static int i8042_nomux;
-static int i8042_unlock;
-static int i8042_direct;
-static int i8042_dumbkbd;
+static unsigned int i8042_noaux;
+module_param(i8042_noaux, bool, 0);
+
+static unsigned int i8042_nomux;
+module_param(i8042_nomux, bool, 0);
+
+static unsigned int i8042_unlock;
+module_param(i8042_unlock, bool, 0);
+
+static unsigned int i8042_reset;
+module_param(i8042_reset, bool, 0);
+
+static unsigned int i8042_direct;
+module_param(i8042_direct, bool, 0);
+
+static unsigned int i8042_dumbkbd;
+module_param(i8042_dumbkbd, bool, 0);
 
 #undef DEBUG
 #include "i8042.h"
@@ -59,6 +66,9 @@ static struct serio i8042_aux_port;
 static unsigned char i8042_initial_ctr;
 static unsigned char i8042_ctr;
 static unsigned char i8042_mux_open;
+static unsigned char i8042_mux_present;
+static unsigned char i8042_sysdev_initialized;
+static struct pm_dev *i8042_pm_dev;
 struct timer_list i8042_timer;
 
 /*
@@ -214,16 +224,41 @@ static int i8042_aux_write(struct serio 
 }
 
 /*
- * i8042_open() is called when a port is open by the higher layer.
- * It allocates the interrupt and enables it in the chip.
+ * i8042_activate_port() enables port on a chip.
  */
 
-static int i8042_open(struct serio *port)
+static int i8042_activate_port(struct serio *port)
 {
 	struct i8042_values *values = port->driver;
 
 	i8042_flush();
 
+	/*
+	 * Enable port again here because it is disabled if we are
+	 * resuming (normally it is enabled already).
+	 */
+	i8042_ctr &= ~values->disable;
+
+	i8042_ctr |= values->irqen;
+
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+		i8042_ctr &= ~values->irqen;
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * i8042_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and calls i8042_enable_port.
+ */
+
+static int i8042_open(struct serio *port)
+{
+	struct i8042_values *values = port->driver;
+
 	if (values->mux != -1)
 		if (i8042_mux_open++)
 			return 0;
@@ -231,21 +266,26 @@ static int i8042_open(struct serio *port
 	if (request_irq(values->irq, i8042_interrupt,
 			SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
 		printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
-		values->exists = 0;
-		serio_unregister_port(port);
-		return -1;
+		goto irq_fail;
 	}
 
-	i8042_ctr |= values->irqen;
-
-	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_ERR "i8042.c: Can't write CTR while opening %s.\n", values->name);
-		return -1;
+	if (i8042_activate_port(port)) {
+		printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name);
+		goto activate_fail;
 	}
 
 	i8042_interrupt(0, NULL, NULL);
 
 	return 0;
+
+activate_fail:
+	free_irq(values->irq, i8042_request_irq_cookie);
+
+irq_fail:
+	values->exists = 0;
+	serio_unregister_port_delayed(port);
+
+	return -1;
 }
 
 /*
@@ -393,145 +433,78 @@ static irqreturn_t i8042_interrupt(int i
 }
 
 /*
- * i8042_controller init initializes the i8042 controller, and,
- * most importantly, sets it into non-xlated mode if that's
- * desired.
+ * i8042_enable_mux_mode checks whether the controller has an active
+ * multiplexor and puts the chip into Multiplexed (as opposed to
+ * Legacy) mode.
  */
-	
-static int __init i8042_controller_init(void)
+
+static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux_version)
 {
 
+	unsigned char param;
 /*
- * Test the i8042. We need to know if it thinks it's working correctly
- * before doing anything else.
+ * Get rid of bytes in the queue.
  */
 
 	i8042_flush();
 
-	if (i8042_reset) {
-
-		unsigned char param;
-
-		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
-			printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
-			return -1;
-		}
-
-		if (param != I8042_RET_CTL_TEST) {
-			printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
-				 param, I8042_RET_CTL_TEST);
-			return -1;
-		}
-	}
-
 /*
- * Save the CTR for restoral on unload / reboot.
+ * Internal loopback test - send three bytes, they should come back from the
+ * mouse interface, the last should be version. Note that we negate mouseport
+ * command responses for the i8042_check_aux() routine.
  */
 
-	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
-		printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
+	param = 0xf0;
+	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0x0f)
 		return -1;
-	}
-
-	i8042_initial_ctr = i8042_ctr;
-
-/*
- * Disable the keyboard interface and interrupt. 
- */
-
-	i8042_ctr |= I8042_CTR_KBDDIS;
-	i8042_ctr &= ~I8042_CTR_KBDINT;
-
-/*
- * Handle keylock.
- */
-
-	if (~i8042_read_status() & I8042_STR_KEYLOCK) {
-		if (i8042_unlock)
-			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
-		 else
-			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
-	}
-
-/*
- * If the chip is configured into nontranslated mode by the BIOS, don't
- * bother enabling translating and be happy.
- */
-
-	if (~i8042_ctr & I8042_CTR_XLATE)
-		i8042_direct = 1;
-
-/*
- * Set nontranslated mode for the kbd interface if requested by an option.
- * After this the kbd interface becomes a simple serial in/out, like the aux
- * interface is. We don't do this by default, since it can confuse notebook
- * BIOSes.
- */
-
-	if (i8042_direct) {
-		i8042_ctr &= ~I8042_CTR_XLATE;
-		i8042_kbd_port.type = SERIO_8042;
-	}
-
-/*
- * Write CTR back.
- */
-
-	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
+	param = 0x56;
+	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa9)
 		return -1;
-	}
+	param = 0xa4;
+	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b)
+		return -1;
+
+	if (mux_version)
+		*mux_version = ~param;
 
 	return 0;
 }
 
+
 /*
- * Here we try to reset everything back to a state in which the BIOS will be
- * able to talk to the hardware when rebooting.
+ * i8042_enable_mux_ports enables 4 individual AUX ports after
+ * the controller has been switched into Multiplexed mode
  */
 
-void i8042_controller_cleanup(void)
+static int i8042_enable_mux_ports(struct i8042_values *values)
 {
+	unsigned char param;
 	int i;
-
-	i8042_flush();
-
 /*
- * Reset anything that is connected to the ports.
- */
-
-	if (i8042_kbd_values.exists)
-		serio_cleanup(&i8042_kbd_port);
-
-	if (i8042_aux_values.exists)
-		serio_cleanup(&i8042_aux_port);
-
-	for (i = 0; i < 4; i++)
-		if (i8042_mux_values[i].exists)
-			serio_cleanup(i8042_mux_port + i);
-
-/*
- * Reset the controller.
+ * Disable all muxed ports by disabling AUX.
  */
 
-	if (i8042_reset) {
-		unsigned char param;
+	i8042_ctr |= I8042_CTR_AUXDIS;
+	i8042_ctr &= ~I8042_CTR_AUXINT;
 
-		if (i8042_command(&param, I8042_CMD_CTL_TEST))
-			printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+		printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");
+		return -1;
 	}
 
 /*
- * Restore the original control register setting.
+ * Enable all muxed ports.
  */
 
-	i8042_ctr = i8042_initial_ctr;
-
-	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
-		printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
+	for (i = 0; i < 4; i++) {
+		i8042_command(&param, I8042_CMD_MUX_PFX + i);
+		i8042_command(&param, I8042_CMD_AUX_ENABLE);
+	}
 
+	return 0;
 }
 
+
 /*
  * i8042_check_mux() checks whether the controller supports the PS/2 Active
  * Multiplexing specification by Synaptics, Phoenix, Insyde and
@@ -540,66 +513,31 @@ void i8042_controller_cleanup(void)
 
 static int __init i8042_check_mux(struct i8042_values *values)
 {
-	unsigned char param;
 	static int i8042_check_mux_cookie;
-	int i;
+	unsigned char mux_version;
 
 /*
  * Check if AUX irq is available.
  */
-
 	if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
 				"i8042", &i8042_check_mux_cookie))
                 return -1;
 	free_irq(values->irq, &i8042_check_mux_cookie);
 
-/*
- * Get rid of bytes in the queue.
- */
-
-	i8042_flush();
-
-/*
- * Internal loopback test - send three bytes, they should come back from the
- * mouse interface, the last should be version. Note that we negate mouseport
- * command responses for the i8042_check_aux() routine.
- */
-
-	param = 0xf0;
-	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0x0f)
-		return -1;
-	param = 0x56;
-	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa9)
-		return -1;
-	param = 0xa4;
-	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b)
+	if (i8042_enable_mux_mode(values, &mux_version))
 		return -1;
 
 	printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
-		(~param >> 4) & 0xf, ~param & 0xf);
-
-/*
- * Disable all muxed ports by disabling AUX.
- */
-
-	i8042_ctr |= I8042_CTR_AUXDIS;
-	i8042_ctr &= ~I8042_CTR_AUXINT;
+		(mux_version >> 4) & 0xf, mux_version & 0xf);
 
-	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
+	if (i8042_enable_mux_ports(values))
 		return -1;
 
-/*
- * Enable all muxed ports.
- */
-
-	for (i = 0; i < 4; i++) {
-		i8042_command(&param, I8042_CMD_MUX_PFX + i);
-		i8042_command(&param, I8042_CMD_AUX_ENABLE);
-	}
-
+	i8042_mux_present = 1;
 	return 0;
 }
 
+
 /*
  * i8042_check_aux() applies as much paranoia as it can at detecting
  * the presence of an AUX interface.
@@ -675,6 +613,7 @@ static int __init i8042_check_aux(struct
 	return 0;
 }
 
+
 /*
  * i8042_port_register() marks the device as existing,
  * registers it, and reports to the user.
@@ -691,63 +630,205 @@ static int __init i8042_port_register(st
 		return -1; 
 	}
 
-	serio_register_port(port);
-
 	printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
 	       values->name,
 	       (unsigned long) I8042_DATA_REG,
 	       (unsigned long) I8042_COMMAND_REG,
 	       values->irq);
 
+	serio_register_port(port);
+
 	return 0;
 }
 
+
 static void i8042_timer_func(unsigned long data)
 {
 	i8042_interrupt(0, NULL, NULL);
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 }
 
-#ifndef MODULE
-static int __init i8042_setup_reset(char *str)
-{
-	i8042_reset = 1;
-	return 1;
-}
-static int __init i8042_setup_noaux(char *str)
-{
-	i8042_noaux = 1;
-	i8042_nomux = 1;
-	return 1;
-}
-static int __init i8042_setup_nomux(char *str)
-{
-	i8042_nomux = 1;
-	return 1;
-}
-static int __init i8042_setup_unlock(char *str)
+
+/*
+ * i8042_controller init initializes the i8042 controller, and,
+ * most importantly, sets it into non-xlated mode if that's
+ * desired.
+ */
+
+static int i8042_controller_init(void)
 {
-	i8042_unlock = 1;
-	return 1;
+
+	if (i8042_noaux)
+		i8042_nomux = 1;
+/*
+ * Test the i8042. We need to know if it thinks it's working correctly
+ * before doing anything else.
+ */
+
+	i8042_flush();
+
+	if (i8042_reset) {
+
+		unsigned char param;
+
+		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
+			printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
+			return -1;
+		}
+
+		if (param != I8042_RET_CTL_TEST) {
+			printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
+				 param, I8042_RET_CTL_TEST);
+			return -1;
+		}
+	}
+
+/*
+ * Save the CTR for restoral on unload / reboot.
+ */
+
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
+		printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
+		return -1;
+	}
+
+	i8042_initial_ctr = i8042_ctr;
+
+/*
+ * Disable the keyboard interface and interrupt.
+ */
+
+	i8042_ctr |= I8042_CTR_KBDDIS;
+	i8042_ctr &= ~I8042_CTR_KBDINT;
+
+/*
+ * Handle keylock.
+ */
+
+	if (~i8042_read_status() & I8042_STR_KEYLOCK) {
+		if (i8042_unlock)
+			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
+		 else
+			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
+	}
+
+/*
+ * If the chip is configured into nontranslated mode by the BIOS, don't
+ * bother enabling translating and be happy.
+ */
+
+	if (~i8042_ctr & I8042_CTR_XLATE)
+		i8042_direct = 1;
+
+/*
+ * Set nontranslated mode for the kbd interface if requested by an option.
+ * After this the kbd interface becomes a simple serial in/out, like the aux
+ * interface is. We don't do this by default, since it can confuse notebook
+ * BIOSes.
+ */
+
+	if (i8042_direct) {
+		i8042_ctr &= ~I8042_CTR_XLATE;
+		i8042_kbd_port.type = SERIO_8042;
+	}
+
+/*
+ * Write CTR back.
+ */
+
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+		printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
+		return -1;
+	}
+
+	return 0;
 }
-static int __init i8042_setup_direct(char *str)
+
+
+/*
+ * Here we try to reset everything back to a state in which the BIOS will be
+ * able to talk to the hardware when rebooting.
+ */
+
+void i8042_controller_cleanup(void)
 {
-	i8042_direct = 1;
-	return 1;
+	int i;
+
+	i8042_flush();
+
+/*
+ * Reset anything that is connected to the ports.
+ */
+
+	if (i8042_kbd_values.exists)
+		serio_cleanup(&i8042_kbd_port);
+
+	if (i8042_aux_values.exists)
+		serio_cleanup(&i8042_aux_port);
+
+	for (i = 0; i < 4; i++)
+		if (i8042_mux_values[i].exists)
+			serio_cleanup(i8042_mux_port + i);
+
+/*
+ * Reset the controller.
+ */
+
+	if (i8042_reset) {
+		unsigned char param;
+
+		if (i8042_command(&param, I8042_CMD_CTL_TEST))
+			printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
+	}
+
+/*
+ * Restore the original control register setting.
+ */
+
+	i8042_ctr = i8042_initial_ctr;
+
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
+		printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
+
 }
-static int __init i8042_setup_dumbkbd(char *str)
+
+
+/*
+ * Here we try to reset everything back to a state in which suspended
+ */
+
+static int i8042_controller_resume(void)
 {
-	i8042_dumbkbd = 1;
-	return 1;
+	int i;
+
+	if (i8042_controller_init()) {
+		printk(KERN_ERR "i8042: resume failed\n");
+		return -1;
+	}
+
+	if (i8042_mux_present)
+		if (i8042_enable_mux_mode(&i8042_aux_values, NULL) ||
+		    i8042_enable_mux_ports(&i8042_aux_values)) {
+			printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't wotk.\n");
+		}
+
+/*
+ * Reconnect anything that was connected to the ports.
+ */
+
+	if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
+		serio_reconnect(&i8042_kbd_port);
+
+	if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
+		serio_reconnect(&i8042_aux_port);
+
+	for (i = 0; i < 4; i++)
+		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
+			serio_reconnect(i8042_mux_port + i);
+
+	return 0;
 }
 
-__setup("i8042_reset", i8042_setup_reset);
-__setup("i8042_noaux", i8042_setup_noaux);
-__setup("i8042_nomux", i8042_setup_nomux);
-__setup("i8042_unlock", i8042_setup_unlock);
-__setup("i8042_direct", i8042_setup_direct);
-__setup("i8042_dumbkbd", i8042_setup_dumbkbd);
-#endif
 
 /*
  * We need to reset the 8042 back to original mode on system shutdown,
@@ -769,6 +850,35 @@ static struct notifier_block i8042_notif
         0
 };
 
+/*
+ * Resume handler for the new PM scheme (driver model)
+ */
+static int i8042_resume(struct sys_device *dev)
+{
+	return i8042_controller_resume();
+}
+
+static struct sysdev_class kbc_sysclass = {
+       set_kset_name("i8042"),
+       .resume = i8042_resume,
+};
+
+static struct sys_device device_i8042 = {
+       .id     = 0,
+       .cls    = &kbc_sysclass,
+};
+
+/*
+ * Resume handler for the old PM scheme (APM)
+ */
+static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dummy)
+{
+	if (request == PM_RESUME)
+		return i8042_controller_resume();
+
+	return 0;
+}
+
 static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index)
 {
 	memcpy(port, &i8042_aux_port, sizeof(struct serio));
@@ -817,6 +927,15 @@ int __init i8042_init(void)
 	i8042_timer.function = i8042_timer_func;
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
+        if (sysdev_class_register(&kbc_sysclass) == 0) {
+                if (sys_device_register(&device_i8042) == 0)
+			i8042_sysdev_initialized = 1;
+		else
+			sysdev_class_unregister(&kbc_sysclass);
+        }
+
+	i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback);
+
 	register_reboot_notifier(&i8042_notifier);
 
 	return 0;
@@ -828,6 +947,14 @@ void __exit i8042_exit(void)
 
 	unregister_reboot_notifier(&i8042_notifier);
 
+	if (i8042_pm_dev)
+		pm_unregister(i8042_pm_dev);
+
+	if (i8042_sysdev_initialized) {
+		sys_device_unregister(&device_i8042);
+		sysdev_class_unregister(&kbc_sysclass);
+	}
+
 	del_timer(&i8042_timer);
 
 	i8042_controller_cleanup();
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/input/serio/serio.c 001-linus.patch/drivers/input/serio/serio.c
--- 000-virgin/drivers/input/serio/serio.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/drivers/input/serio/serio.c	Tue Dec 30 16:38:57 2003
@@ -49,14 +49,17 @@ MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(serio_register_port);
-EXPORT_SYMBOL(serio_register_slave_port);
+EXPORT_SYMBOL(serio_register_port_delayed);
+EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_slave_port);
+EXPORT_SYMBOL(serio_unregister_port_delayed);
+EXPORT_SYMBOL(__serio_unregister_port);
 EXPORT_SYMBOL(serio_register_device);
 EXPORT_SYMBOL(serio_unregister_device);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
 EXPORT_SYMBOL(serio_rescan);
+EXPORT_SYMBOL(serio_reconnect);
 
 struct serio_event {
 	int type;
@@ -82,11 +85,23 @@ static void serio_find_dev(struct serio 
 	}
 }
 
-#define SERIO_RESCAN	1
+#define SERIO_RESCAN		1
+#define SERIO_RECONNECT		2
+#define SERIO_REGISTER_PORT	3
+#define SERIO_UNREGISTER_PORT	4
 
 static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
 static DECLARE_COMPLETION(serio_exited);
 
+static void serio_invalidate_pending_events(struct serio *serio)
+{
+	struct serio_event *event;
+
+	list_for_each_entry(event, &serio_event_list, node)
+		if (event->serio == serio)
+			event->serio = NULL;
+}
+
 void serio_handle_events(void)
 {
 	struct list_head *node, *next;
@@ -95,17 +110,35 @@ void serio_handle_events(void)
 	list_for_each_safe(node, next, &serio_event_list) {
 		event = container_of(node, struct serio_event, node);	
 
+		down(&serio_sem);
+		if (event->serio == NULL)
+			goto event_done;
+
 		switch (event->type) {
+			case SERIO_REGISTER_PORT :
+				__serio_register_port(event->serio);
+				break;
+
+			case SERIO_UNREGISTER_PORT :
+				__serio_unregister_port(event->serio);
+				break;
+
+			case SERIO_RECONNECT :
+				if (event->serio->dev && event->serio->dev->reconnect)
+					if (event->serio->dev->reconnect(event->serio) == 0)
+						break;
+				/* reconnect failed - fall through to rescan */
+
 			case SERIO_RESCAN :
-				down(&serio_sem);
 				if (event->serio->dev && event->serio->dev->disconnect)
 					event->serio->dev->disconnect(event->serio);
 				serio_find_dev(event->serio);
-				up(&serio_sem);
 				break;
 			default:
 				break;
 		}
+event_done:
+		up(&serio_sem);
 		list_del_init(node);
 		kfree(event);
 	}
@@ -130,18 +163,27 @@ static int serio_thread(void *nothing)
 	complete_and_exit(&serio_exited, 0);
 }
 
-void serio_rescan(struct serio *serio)
+static void serio_queue_event(struct serio *serio, int event_type)
 {
 	struct serio_event *event;
 
-	if (!(event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC)))
-		return;
+	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+		event->type = event_type;
+		event->serio = serio;
+
+		list_add_tail(&event->node, &serio_event_list);
+		wake_up(&serio_wait);
+	}
+}
 
-	event->type = SERIO_RESCAN;
-	event->serio = serio;
+void serio_rescan(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RESCAN);
+}
 
-	list_add_tail(&event->node, &serio_event_list);
-	wake_up(&serio_wait);
+void serio_reconnect(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RECONNECT);
 }
 
 irqreturn_t serio_interrupt(struct serio *serio,
@@ -163,17 +205,26 @@ irqreturn_t serio_interrupt(struct serio
 void serio_register_port(struct serio *serio)
 {
 	down(&serio_sem);
-	list_add_tail(&serio->node, &serio_list);
-	serio_find_dev(serio);
+	__serio_register_port(serio);
 	up(&serio_sem);
 }
 
 /*
- * Same as serio_register_port but does not try to acquire serio_sem.
- * Should be used when registering a serio from other input device's
+ * Submits register request to kseriod for subsequent execution.
+ * Can be used when it is not obvious whether the serio_sem is
+ * taken or not and when delayed execution is feasible.
+ */
+void serio_register_port_delayed(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_REGISTER_PORT);
+}
+
+/*
+ * Should only be called directly if serio_sem has already been taken,
+ * for example when unregistering a serio from other input device's
  * connect() function.
  */
-void serio_register_slave_port(struct serio *serio)
+void __serio_register_port(struct serio *serio)
 {
 	list_add_tail(&serio->node, &serio_list);
 	serio_find_dev(serio);
@@ -182,19 +233,28 @@ void serio_register_slave_port(struct se
 void serio_unregister_port(struct serio *serio)
 {
 	down(&serio_sem);
-	list_del_init(&serio->node);
-	if (serio->dev && serio->dev->disconnect)
-		serio->dev->disconnect(serio);
+	__serio_unregister_port(serio);
 	up(&serio_sem);
 }
 
 /*
- * Same as serio_unregister_port but does not try to acquire serio_sem.
- * Should be used when unregistering a serio from other input device's
+ * Submits unregister request to kseriod for subsequent execution.
+ * Can be used when it is not obvious whether the serio_sem is
+ * taken or not and when delayed execution is feasible.
+ */
+void serio_unregister_port_delayed(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_UNREGISTER_PORT);
+}
+
+/*
+ * Should only be called directly if serio_sem has already been taken,
+ * for example when unregistering a serio from other input device's
  * disconnect() function.
  */
-void serio_unregister_slave_port(struct serio *serio)
+void __serio_unregister_port(struct serio *serio)
 {
+	serio_invalidate_pending_events(serio);
 	list_del_init(&serio->node);
 	if (serio->dev && serio->dev->disconnect)
 		serio->dev->disconnect(serio);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/isdn/eicon/Kconfig 001-linus.patch/drivers/isdn/eicon/Kconfig
--- 000-virgin/drivers/isdn/eicon/Kconfig	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/isdn/eicon/Kconfig	Tue Dec 30 16:38:57 2003
@@ -13,7 +13,7 @@ config ISDN_DRV_EICON
 choice
 	prompt "Eicon active card support"
 	optional
-	depends on ISDN_DRV_EICON && ISDN
+	depends on ISDN_DRV_EICON && ISDN && m
 
 config ISDN_DRV_EICON_DIVAS
 	tristate "Eicon driver"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/isdn/i4l/isdn_ppp_ccp.c 001-linus.patch/drivers/isdn/i4l/isdn_ppp_ccp.c
--- 000-virgin/drivers/isdn/i4l/isdn_ppp_ccp.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/drivers/isdn/i4l/isdn_ppp_ccp.c	Tue Dec 30 16:38:57 2003
@@ -557,7 +557,7 @@ ippp_ccp_send_ccp(struct ippp_ccp *ccp, 
 }
 
 static LIST_HEAD(ipc_head);
-static spinlock_t ipc_head_lock;
+static spinlock_t ipc_head_lock = SPIN_LOCK_UNLOCKED;
 
 int
 ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/Kconfig 001-linus.patch/drivers/md/Kconfig
--- 000-virgin/drivers/md/Kconfig	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/drivers/md/Kconfig	Tue Dec 30 16:38:57 2003
@@ -138,6 +138,7 @@ config BLK_DEV_DM
 config DM_IOCTL_V4
 	bool "ioctl interface version 4"
 	depends on BLK_DEV_DM
+	default y
 	---help---
 	  Recent tools use a new version of the ioctl interface, only
           select this option if you intend using such tools.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/dm-ioctl-v1.c 001-linus.patch/drivers/md/dm-ioctl-v1.c
--- 000-virgin/drivers/md/dm-ioctl-v1.c	Wed Dec 17 18:59:53 2003
+++ 001-linus.patch/drivers/md/dm-ioctl-v1.c	Tue Dec 30 16:38:57 2003
@@ -566,7 +566,7 @@ static int create(struct dm_ioctl *param
 	if (r)
 		return r;
 
-	r = dm_table_create(&t, get_mode(param));
+	r = dm_table_create(&t, get_mode(param), param->target_count);
 	if (r)
 		return r;
 
@@ -894,7 +894,7 @@ static int reload(struct dm_ioctl *param
 	struct mapped_device *md;
 	struct dm_table *t;
 
-	r = dm_table_create(&t, get_mode(param));
+	r = dm_table_create(&t, get_mode(param), param->target_count);
 	if (r)
 		return r;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/dm-ioctl-v4.c 001-linus.patch/drivers/md/dm-ioctl-v4.c
--- 000-virgin/drivers/md/dm-ioctl-v4.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/drivers/md/dm-ioctl-v4.c	Tue Dec 30 16:38:57 2003
@@ -872,7 +872,7 @@ static int table_load(struct dm_ioctl *p
 	struct hash_cell *hc;
 	struct dm_table *t;
 
-	r = dm_table_create(&t, get_mode(param));
+	r = dm_table_create(&t, get_mode(param), param->target_count);
 	if (r)
 		return r;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/dm-table.c 001-linus.patch/drivers/md/dm-table.c
--- 000-virgin/drivers/md/dm-table.c	Wed Dec 17 18:59:53 2003
+++ 001-linus.patch/drivers/md/dm-table.c	Tue Dec 30 16:38:57 2003
@@ -12,6 +12,7 @@
 #include <linux/namei.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
 #include <asm/atomic.h>
 
 #define MAX_DEPTH 16
@@ -202,7 +203,7 @@ static int alloc_targets(struct dm_table
 	return 0;
 }
 
-int dm_table_create(struct dm_table **result, int mode)
+int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
 {
 	struct dm_table *t = kmalloc(sizeof(*t), GFP_NOIO);
 
@@ -213,8 +214,12 @@ int dm_table_create(struct dm_table **re
 	INIT_LIST_HEAD(&t->devices);
 	atomic_set(&t->holders, 1);
 
-	/* allocate a single nodes worth of targets to begin with */
-	if (alloc_targets(t, KEYS_PER_NODE)) {
+	if (!num_targets)
+		num_targets = KEYS_PER_NODE;
+
+	num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
+
+	if (alloc_targets(t, num_targets)) {
 		kfree(t);
 		t = NULL;
 		return -ENOMEM;
@@ -626,6 +631,16 @@ static int split_args(int *argc, char **
 	return 0;
 }
 
+static void set_default_limits(struct io_restrictions *rs)
+{
+	rs->max_sectors = MAX_SECTORS;
+	rs->max_phys_segments = MAX_PHYS_SEGMENTS;
+	rs->max_hw_segments = MAX_HW_SEGMENTS;
+	rs->hardsect_size = 1 << SECTOR_SHIFT;
+	rs->max_segment_size = MAX_SEGMENT_SIZE;
+	rs->seg_boundary_mask = -1;
+}
+
 int dm_table_add_target(struct dm_table *t, const char *type,
 			sector_t start, sector_t len, char *params)
 {
@@ -638,6 +653,7 @@ int dm_table_add_target(struct dm_table 
 
 	tgt = t->targets + t->num_targets;
 	memset(tgt, 0, sizeof(*tgt));
+	set_default_limits(&tgt->limits);
 
 	tgt->type = dm_get_target_type(type);
 	if (!tgt->type) {
@@ -731,22 +747,28 @@ int dm_table_complete(struct dm_table *t
 	return r;
 }
 
-static spinlock_t _event_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_MUTEX(_event_lock);
 void dm_table_event_callback(struct dm_table *t,
 			     void (*fn)(void *), void *context)
 {
-	spin_lock_irq(&_event_lock);
+	down(&_event_lock);
 	t->event_fn = fn;
 	t->event_context = context;
-	spin_unlock_irq(&_event_lock);
+	up(&_event_lock);
 }
 
 void dm_table_event(struct dm_table *t)
 {
-	spin_lock(&_event_lock);
+	/*
+	 * You can no longer call dm_table_event() from interrupt
+	 * context, use a bottom half instead.
+	 */
+	BUG_ON(in_interrupt());
+
+	down(&_event_lock);
 	if (t->event_fn)
 		t->event_fn(t->event_context);
-	spin_unlock(&_event_lock);
+	up(&_event_lock);
 }
 
 sector_t dm_table_get_size(struct dm_table *t)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/dm.c 001-linus.patch/drivers/md/dm.c
--- 000-virgin/drivers/md/dm.c	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/drivers/md/dm.c	Tue Dec 30 16:38:57 2003
@@ -666,6 +666,20 @@ static void event_callback(void *context
 	up_write(&md->lock);
 }
 
+static void __set_size(struct gendisk *disk, sector_t size)
+{
+	struct block_device *bdev;
+
+	set_capacity(disk, size);
+	bdev = bdget_disk(disk, 0);
+	if (bdev) {
+		down(&bdev->bd_inode->i_sem);
+		i_size_write(bdev->bd_inode, size << SECTOR_SHIFT);
+		up(&bdev->bd_inode->i_sem);
+		bdput(bdev);
+	}
+}
+
 static int __bind(struct mapped_device *md, struct dm_table *t)
 {
 	request_queue_t *q = md->queue;
@@ -673,7 +687,7 @@ static int __bind(struct mapped_device *
 	md->map = t;
 
 	size = dm_table_get_size(t);
-	set_capacity(md->disk, size);
+	__set_size(md->disk, size);
 	if (size == 0)
 		return 0;
 
@@ -692,7 +706,6 @@ static void __unbind(struct mapped_devic
 	dm_table_event_callback(md->map, NULL, NULL);
 	dm_table_put(md->map);
 	md->map = NULL;
-	set_capacity(md->disk, 0);
 }
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/dm.h 001-linus.patch/drivers/md/dm.h
--- 000-virgin/drivers/md/dm.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/md/dm.h	Tue Dec 30 16:38:57 2003
@@ -95,7 +95,7 @@ int dm_suspended(struct mapped_device *m
  * Functions for manipulating a table.  Tables are also reference
  * counted.
  *---------------------------------------------------------------*/
-int dm_table_create(struct dm_table **result, int mode);
+int dm_table_create(struct dm_table **result, int mode, unsigned num_targets);
 
 void dm_table_get(struct dm_table *t);
 void dm_table_put(struct dm_table *t);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/linear.c 001-linus.patch/drivers/md/linear.c
--- 000-virgin/drivers/md/linear.c	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/drivers/md/linear.c	Tue Dec 30 16:38:57 2003
@@ -113,8 +113,17 @@ static int linear_run (mddev_t *mddev)
 		}
 
 		disk->rdev = rdev;
+
 		blk_queue_stack_limits(mddev->queue,
 				       rdev->bdev->bd_disk->queue);
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, so limit ->max_sector to one PAGE, as
+		 * a one page request is never in violation.
+		 */
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 		disk->size = rdev->size;
 		mddev->array_size += rdev->size;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/multipath.c 001-linus.patch/drivers/md/multipath.c
--- 000-virgin/drivers/md/multipath.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/md/multipath.c	Tue Dec 30 16:38:57 2003
@@ -273,6 +273,17 @@ static int multipath_add_disk(mddev_t *m
 			p->rdev = rdev;
 			blk_queue_stack_limits(mddev->queue,
 					       rdev->bdev->bd_disk->queue);
+
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, so limit ->max_sector to one PAGE, as
+		 * a one page request is never in violation.
+		 * (Note: it is very unlikely that a device with
+		 * merge_bvec_fn will be involved in multipath.)
+		 */
+			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 			conf->working_disks++;
 			rdev->raid_disk = path;
 			rdev->in_sync = 1;
@@ -410,8 +421,16 @@ static int multipath_run (mddev_t *mddev
 
 		disk = conf->multipaths + disk_idx;
 		disk->rdev = rdev;
+
 		blk_queue_stack_limits(mddev->queue,
 				       rdev->bdev->bd_disk->queue);
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, not that we ever expect a device with
+		 * a merge_bvec_fn to be involved in multipath */
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 		if (!rdev->faulty) 
 			conf->working_disks++;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/raid0.c 001-linus.patch/drivers/md/raid0.c
--- 000-virgin/drivers/md/raid0.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/md/raid0.c	Tue Dec 30 16:38:57 2003
@@ -112,8 +112,18 @@ static int create_strip_zones (mddev_t *
 			goto abort;
 		}
 		zone->dev[j] = rdev1;
+
 		blk_queue_stack_limits(mddev->queue,
 				       rdev1->bdev->bd_disk->queue);
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, so limit ->max_sector to one PAGE, as
+		 * a one page request is never in violation.
+		 */
+
+		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
+		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 		if (!smallest || (rdev1->size <smallest->size))
 			smallest = rdev1;
 		cnt++;
@@ -301,6 +311,22 @@ static int raid0_run (mddev_t *mddev)
 		conf->hash_spacing++;
 	}
 
+	/* calculate the max read-ahead size.
+	 * For read-ahead of large files to be effective, we need to
+	 * readahead at least a whole stripe. i.e. number of devices
+	 * multiplied by chunk size.
+	 * If an individual device has an ra_pages greater than the
+	 * chunk size, then we will not drive that device as hard as it
+	 * wants.  We consider this a configuration error: a larger
+	 * chunksize should be used in that case.
+	 */
+	{
+		int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+		if (mddev->queue->backing_dev_info.ra_pages < stripe)
+			mddev->queue->backing_dev_info.ra_pages = stripe;
+	}
+
+
 	blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
 	return 0;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/raid1.c 001-linus.patch/drivers/md/raid1.c
--- 000-virgin/drivers/md/raid1.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/md/raid1.c	Tue Dec 30 16:38:57 2003
@@ -677,8 +677,17 @@ static int raid1_add_disk(mddev_t *mddev
 	for (mirror=0; mirror < mddev->raid_disks; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 			p->rdev = rdev;
+
 			blk_queue_stack_limits(mddev->queue,
 					       rdev->bdev->bd_disk->queue);
+			/* as we don't honour merge_bvec_fn, we must never risk
+			 * violating it, so limit ->max_sector to one PAGE, as
+			 * a one page request is never in violation.
+			 */
+			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
 			found = 1;
@@ -1077,8 +1086,17 @@ static int run(mddev_t *mddev)
 		disk = conf->mirrors + disk_idx;
 
 		disk->rdev = rdev;
+
 		blk_queue_stack_limits(mddev->queue,
 				       rdev->bdev->bd_disk->queue);
+		/* as we don't honour merge_bvec_fn, we must never risk
+		 * violating it, so limit ->max_sector to one PAGE, as
+		 * a one page request is never in violation.
+		 */
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+
 		disk->head_position = 0;
 		if (!rdev->faulty && rdev->in_sync)
 			conf->working_disks++;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/md/raid5.c 001-linus.patch/drivers/md/raid5.c
--- 000-virgin/drivers/md/raid5.c	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/md/raid5.c	Tue Dec 30 16:38:57 2003
@@ -1587,6 +1587,16 @@ memory = conf->max_nr_stripes * (sizeof(
 
 	print_raid5_conf(conf);
 
+	/* read-ahead size must cover a whole stripe, which is
+	 * (n-1) * chunksize where 'n' is the number of raid devices
+	 */
+	{
+		int stripe = (mddev->raid_disks-1) * mddev->chunk_size
+			/ PAGE_CACHE_SIZE;
+		if (mddev->queue->backing_dev_info.ra_pages < stripe)
+			mddev->queue->backing_dev_info.ra_pages = stripe;
+	}
+
 	/* Ok, everything is just fine now */
 	mddev->array_size =  mddev->size * (mddev->raid_disks - 1);
 	return 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/media/common/saa7146_i2c.c 001-linus.patch/drivers/media/common/saa7146_i2c.c
--- 000-virgin/drivers/media/common/saa7146_i2c.c	Wed Dec 17 18:59:44 2003
+++ 001-linus.patch/drivers/media/common/saa7146_i2c.c	Tue Dec 30 16:38:57 2003
@@ -186,7 +186,7 @@ static int saa7146_i2c_writeout(struct s
 {
 	u32 status = 0, mc2 = 0;
 	int trial = 0;
-	int timeout;
+	unsigned long timeout;
 
 	/* write out i2c-command */
 	DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
@@ -218,7 +218,7 @@ static int saa7146_i2c_writeout(struct s
 			if( 0 != mc2 ) {
 				break;
 			}
-			if (jiffies > timeout) {
+			if (time_after(jiffies,timeout)) {
 				printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
 				return -EIO;
 			}
@@ -233,7 +233,7 @@ static int saa7146_i2c_writeout(struct s
 			status = saa7146_i2c_status(dev);
 			if ((status & 0x3) != 1)
 				break;
-			if (jiffies > timeout) {
+			if (time_after(jiffies,timeout)) {
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
 				 */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/media/video/video-buf.c 001-linus.patch/drivers/media/video/video-buf.c
--- 000-virgin/drivers/media/video/video-buf.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/media/video/video-buf.c	Tue Dec 30 16:38:57 2003
@@ -1078,7 +1078,7 @@ videobuf_vm_close(struct vm_area_struct 
  */
 static struct page*
 videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
-		  int write_access)
+		  int *type)
 {
 	struct page *page;
 
@@ -1090,6 +1090,8 @@ videobuf_vm_nopage(struct vm_area_struct
 	if (!page)
 		return NOPAGE_OOM;
 	clear_user_page(page_address(page), vaddr, page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/8139too.c 001-linus.patch/drivers/net/8139too.c
--- 000-virgin/drivers/net/8139too.c	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/drivers/net/8139too.c	Tue Dec 30 16:38:57 2003
@@ -2475,10 +2475,11 @@ static int rtl8139_suspend (struct pci_d
 	tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
 	RTL_W32 (RxMissed, 0);
 
+	spin_unlock_irqrestore (&tp->lock, flags);
+
 	pci_set_power_state (pdev, 3);
 	pci_save_state (pdev, tp->pci_state);
 
-	spin_unlock_irqrestore (&tp->lock, flags);
 	return 0;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/bonding/bond_main.c 001-linus.patch/drivers/net/bonding/bond_main.c
--- 000-virgin/drivers/net/bonding/bond_main.c	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/drivers/net/bonding/bond_main.c	Tue Dec 30 16:38:57 2003
@@ -3910,7 +3910,6 @@ static void bond_free_all(void)
 
 		unregister_netdevice(dev);
 		bond_deinit(dev);
-		free_netdev(dev);
 	}
 
 #ifdef CONFIG_PROC_FS
@@ -4008,6 +4007,8 @@ static int __init bond_init(struct net_d
 	bond_create_proc_info(bond);
 #endif
 
+	dev->destructor = free_netdev;
+
 	list_add_tail(&bond->bond_list, &bond_dev_list);
 
 	return 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/e100/e100_config.c 001-linus.patch/drivers/net/e100/e100_config.c
--- 000-virgin/drivers/net/e100/e100_config.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/drivers/net/e100/e100_config.c	Tue Dec 30 16:38:57 2003
@@ -60,7 +60,7 @@ static const u8 def_config[] = {
  * All other init functions will only set values that are
  * different from the 82557 default.
  */
-void __devinit
+void
 e100_config_init_82557(struct e100_private *bdp)
 {
 	/* initialize config block */
@@ -104,7 +104,7 @@ e100_config_init_82557(struct e100_priva
 	e100_config_mulcast_enbl(bdp, false);
 }
 
-static void __devinit
+static void
 e100_config_init_82558(struct e100_private *bdp)
 {
 	/* MWI enable. This should be turned on only if the adapter is a 82558/9
@@ -136,7 +136,7 @@ e100_config_init_82558(struct e100_priva
 	e100_config_long_rx(bdp, true);
 }
 
-static void __devinit
+static void
 e100_config_init_82550(struct e100_private *bdp)
 {
 	/* The D102 chip allows for 32 config bytes.  This value is
@@ -160,7 +160,7 @@ e100_config_init_82550(struct e100_priva
 }
 
 /* Initialize the adapter's configure block */
-void __devinit
+void
 e100_config_init(struct e100_private *bdp)
 {
 	e100_config_init_82557(bdp);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/e100/e100_main.c 001-linus.patch/drivers/net/e100/e100_main.c
--- 000-virgin/drivers/net/e100/e100_main.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/net/e100/e100_main.c	Tue Dec 30 16:38:57 2003
@@ -124,7 +124,7 @@ static void e100_free_nontx_list(struct 
 static void e100_non_tx_background(unsigned long);
 static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
-char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
+char e100_copyright[] = "Copyright (c) 2003 Intel Corporation";
 char e100_driver_version[]="2.3.30-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
@@ -539,7 +539,7 @@ e100_trigger_SWI(struct e100_private *bd
 	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
 }
 
-static int __devinit
+static int
 e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
 {
 	static int first_time = true;
@@ -823,7 +823,7 @@ module_exit(e100_cleanup_module);
  *
  * This routine does range checking on command-line options
  */
-void __devinit
+void
 e100_check_options(int board, struct e100_private *bdp)
 {
 	if (board >= E100_MAX_NIC) {
@@ -894,7 +894,7 @@ e100_check_options(int board, struct e10
  * If the option's value is '-1' use the specified default.
  * Otherwise, if the value is invalid, change it to the default.
  */
-void __devinit
+void
 e100_set_int_option(int *option, int val, int min, int max, int default_val,
 		    char *name)
 {
@@ -928,7 +928,7 @@ e100_set_int_option(int *option, int val
  * Otherwise, if the value is invalid (not 0 or 1), 
  * change it to the default.
  */
-void __devinit
+void
 e100_set_bool_option(struct e100_private *bdp, int val, u32 mask,
 		     int default_val, char *name)
 {
@@ -1241,7 +1241,7 @@ e100_ioctl(struct net_device *dev, struc
  *      true: if successful
  *      false: otherwise
  */
-static unsigned char __devinit
+static unsigned char
 e100_init(struct e100_private *bdp)
 {
 	u32 st_timeout = 0;
@@ -1290,7 +1290,7 @@ e100_init(struct e100_private *bdp)
  *      true: if S/W was successfully initialized
  *      false: otherwise
  */
-static unsigned char __devinit
+static unsigned char
 e100_sw_init(struct e100_private *bdp)
 {
 	bdp->next_cu_cmd = START_WAIT;	// init the next cu state
@@ -1318,7 +1318,7 @@ e100_sw_init(struct e100_private *bdp)
 	return 1;
 }
 
-static void __devinit
+static void
 e100_tco_workaround(struct e100_private *bdp)
 {
 	int i;
@@ -1519,7 +1519,7 @@ e100_setup_tcb_pool(tcb_t *head, unsigne
  *      0: if the operation was successful
  *      %-ENOMEM: if memory allocation failed
  */
-unsigned char __devinit
+unsigned char
 e100_alloc_space(struct e100_private *bdp)
 {
 	unsigned long off;
@@ -2508,7 +2508,7 @@ e100_cmd_complete_location(struct e100_p
  *      true: if successfully cleared stat counters
  *      false: otherwise
  */
-static unsigned char __devinit
+static unsigned char
 e100_clr_cntrs(struct e100_private *bdp)
 {
 	volatile u32 *pcmd_complete;
@@ -2873,7 +2873,7 @@ e100_load_microcode(struct e100_private 
 /***************************************************************************/
 
 /* Read PWA (printed wired assembly) number */
-void __devinit
+void
 e100_rd_pwa_no(struct e100_private *bdp)
 {
 	bdp->pwa_no = e100_eeprom_read(bdp, EEPROM_PWA_NO);
@@ -2882,7 +2882,7 @@ e100_rd_pwa_no(struct e100_private *bdp)
 }
 
 /* Read the permanent ethernet address from the eprom. */
-void __devinit
+void
 e100_rd_eaddr(struct e100_private *bdp)
 {
 	int i;
@@ -2947,7 +2947,7 @@ e100_D101M_checksum(struct e100_private 
 /***************************************************************************/
 
 /* Print the board's configuration */
-void __devinit
+void
 e100_print_brd_conf(struct e100_private *bdp)
 {
 	/* Print the string if checksum Offloading was enabled */
@@ -2975,7 +2975,7 @@ e100_print_brd_conf(struct e100_private 
  *      true: if successfull
  *      false: otherwise
  */
-static unsigned char __devinit
+static unsigned char
 e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp)
 {
 	struct net_device *dev = bdp->device;
@@ -3754,7 +3754,7 @@ e100_ethtool_led_blink(struct net_device
 	return 0;
 }
 
-static inline int __devinit
+static inline int
 e100_10BaseT_adapter(struct e100_private *bdp)
 {
 	return ((bdp->pdev->device == 0x1229) &&
@@ -3762,7 +3762,7 @@ e100_10BaseT_adapter(struct e100_private
 		(bdp->pdev->subsystem_device == 0x0003));
 }
 
-static void __devinit
+static void
 e100_get_speed_duplex_caps(struct e100_private *bdp)
 {
 	u16 status;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/e100/e100_phy.c 001-linus.patch/drivers/net/e100/e100_phy.c
--- 000-virgin/drivers/net/e100/e100_phy.c	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/drivers/net/e100/e100_phy.c	Tue Dec 30 16:38:57 2003
@@ -132,7 +132,7 @@ e100_mdi_read(struct e100_private *bdp, 
 	}
 }
 
-static unsigned char __devinit
+static unsigned char
 e100_phy_valid(struct e100_private *bdp, unsigned int phy_address)
 {
 	u16 ctrl_reg, stat_reg;
@@ -150,7 +150,7 @@ e100_phy_valid(struct e100_private *bdp,
 	return true;
 }
 
-static void __devinit
+static void
 e100_phy_address_detect(struct e100_private *bdp)
 {
 	unsigned int addr;
@@ -180,7 +180,7 @@ e100_phy_address_detect(struct e100_priv
 	}
 }
 
-static void __devinit
+static void
 e100_phy_id_detect(struct e100_private *bdp)
 {
 	u16 low_id_reg, high_id_reg;
@@ -204,7 +204,7 @@ e100_phy_id_detect(struct e100_private *
 		      ((unsigned int) high_id_reg << 16));
 }
 
-static void __devinit
+static void
 e100_phy_isolate(struct e100_private *bdp)
 {
 	unsigned int phy_address;
@@ -227,7 +227,7 @@ e100_phy_isolate(struct e100_private *bd
 	}
 }
 
-static unsigned char __devinit
+static unsigned char
 e100_phy_specific_setup(struct e100_private *bdp)
 {
 	u16 misc_reg;
@@ -380,7 +380,7 @@ e100_phy_fix_squelch(struct e100_private
  * Returns:
  *	NOTHING
  */
-static void __devinit
+static void
 e100_fix_polarity(struct e100_private *bdp)
 {
 	u16 status;
@@ -916,7 +916,7 @@ e100_phy_reset(struct e100_private *bdp)
 	schedule_timeout(HZ / 2);
 }
 
-unsigned char __devinit
+unsigned char
 e100_phy_init(struct e100_private *bdp)
 {
 	e100_phy_reset(bdp);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/hamradio/scc.c 001-linus.patch/drivers/net/hamradio/scc.c
--- 000-virgin/drivers/net/hamradio/scc.c	Wed Dec 17 18:59:27 2003
+++ 001-linus.patch/drivers/net/hamradio/scc.c	Tue Dec 30 16:38:57 2003
@@ -1196,11 +1196,7 @@ static void t_tail(unsigned long channel
  	if (scc->stat.tx_state == TXS_TIMEOUT)		/* we had a timeout? */
  	{
  		scc->stat.tx_state = TXS_WAIT;
-
- 		if (scc->kiss.mintime != TIMER_OFF)	/* try it again */
- 			scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
- 		else
- 			scc_start_tx_timer(scc, t_dwait, 0);
+		scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
  		return;
  	}
  	
@@ -1274,8 +1270,7 @@ static void t_idle(unsigned long channel
 	del_timer(&scc->tx_wdog);
 
 	scc_key_trx(scc, TX_OFF);
-
-	if (scc->kiss.mintime != TIMER_OFF)
+	if(scc->kiss.mintime)
 		scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
 	scc->stat.tx_state = TXS_WAIT;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/pcmcia/3c574_cs.c 001-linus.patch/drivers/net/pcmcia/3c574_cs.c
--- 000-virgin/drivers/net/pcmcia/3c574_cs.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/drivers/net/pcmcia/3c574_cs.c	Tue Dec 30 16:38:57 2003
@@ -1092,8 +1092,12 @@ static struct net_device_stats *el3_get_
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 
-	if (netif_device_present(dev))
+	if (netif_device_present(dev)) {
+		unsigned long flags;
+		spin_lock_irqsave(&lp->window_lock, flags);
 		update_stats(dev);
+		spin_unlock_irqrestore(&lp->window_lock, flags);
+	}
 	return &lp->stats;
 }
 
@@ -1105,7 +1109,6 @@ static void update_stats(struct net_devi
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	ioaddr_t ioaddr = dev->base_addr;
-	unsigned long flags;
 	u8 rx, tx, up;
 
 	DEBUG(2, "%s: updating the statistics.\n", dev->name);
@@ -1113,8 +1116,6 @@ static void update_stats(struct net_devi
 	if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */
 		return;
 		
-	spin_lock_irqsave(&lp->window_lock, flags);
-
 	/* Unlike the 3c509 we need not turn off stats updates while reading. */
 	/* Switch to the stats window, and read everything. */
 	EL3WINDOW(6);
@@ -1139,7 +1140,6 @@ static void update_stats(struct net_devi
 	lp->stats.tx_bytes 			+= tx + ((up & 0xf0) << 12);
 
 	EL3WINDOW(1);
-	spin_unlock_irqrestore(&lp->window_lock, flags);
 }
 
 static int el3_rx(struct net_device *dev, int worklimit)
@@ -1281,6 +1281,8 @@ static int el3_close(struct net_device *
 	DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
 	
 	if (DEV_OK(link)) {
+		unsigned long flags;
+
 		/* Turn off statistics ASAP.  We update lp->stats below. */
 		outw(StatsDisable, ioaddr + EL3_CMD);
 		
@@ -1290,8 +1292,9 @@ static int el3_close(struct net_device *
 		
 		/* Note: Switching to window 0 may disable the IRQ. */
 		EL3WINDOW(0);
-		
+		spin_lock_irqsave(&lp->window_lock, flags);
 		update_stats(dev);
+		spin_unlock_irqrestore(&lp->window_lock, flags);
 	}
 
 	link->open--;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/pppoe.c 001-linus.patch/drivers/net/pppoe.c
--- 000-virgin/drivers/net/pppoe.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/net/pppoe.c	Tue Dec 30 16:38:57 2003
@@ -1151,3 +1151,4 @@ module_exit(pppoe_exit);
 MODULE_AUTHOR("Michal Ostrowski <mostrows@speakeasy.net>");
 MODULE_DESCRIPTION("PPP over Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_PPPOX);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/sis900.c 001-linus.patch/drivers/net/sis900.c
--- 000-virgin/drivers/net/sis900.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/net/sis900.c	Tue Dec 30 16:38:57 2003
@@ -18,10 +18,11 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
-   Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary 
+   Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
-   Rev 1.08.03 Feb. 1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
+   Rev 1.08.03 Feb.  1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
    Rev 1.08.02 Nov. 30 2001 Hui-Fen Hsu workaround for EDB & bug fix for dhcp problem
    Rev 1.08.01 Aug. 25 2001 Hui-Fen Hsu update for 630ET & workaround for ICS1893 PHY
    Rev 1.08.00 Jun. 11 2001 Hui-Fen Hsu workaround for RTL8201 PHY and some bug fix
@@ -72,7 +73,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.06 9/24/2002"
+#define SIS900_DRV_VERSION "v1.08.07 11/02/2003"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -169,6 +170,7 @@ struct sis900_private {
 
 	unsigned int tx_full;			/* The Tx queue is full.    */
 	u8 host_bridge_rev;
+	u32 pci_state[16];
 };
 
 MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
@@ -305,7 +307,7 @@ static int __devinit sis635_get_mac_addr
 		*( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
 	}
 
-	/* enable packet filitering */
+	/* enable packet filtering */
 	outl(rfcrSave | RFEN, rfcr + ioaddr);
 
 	return 1;
@@ -994,7 +996,7 @@ sis900_init_rxfilter (struct net_device 
 		}
 	}
 
-	/* enable packet filitering */
+	/* enable packet filtering */
 	outl(rfcrSave | RFEN, rfcr + ioaddr);
 }
 
@@ -1466,7 +1468,7 @@ static void sis900_tx_timeout(struct net
  *	@net_dev: the net device to transmit with
  *
  *	Set the transmit buffer descriptor, 
- *	and write TxENA to enable transimt state machine.
+ *	and write TxENA to enable transmit state machine.
  *	tell upper layer if the buffer is full
  */
 
@@ -2184,11 +2186,72 @@ static void __devexit sis900_remove(stru
 	pci_set_drvdata(pci_dev, NULL);
 }
 
+#ifdef CONFIG_PM
+
+static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
+{
+	struct net_device *net_dev = pci_get_drvdata(pci_dev);
+	struct sis900_private *sis_priv = net_dev->priv;
+	long ioaddr = net_dev->base_addr;
+
+	if(!netif_running(net_dev))
+		return 0;
+
+	netif_stop_queue(net_dev);
+
+	/* Stop the chip's Tx and Rx Status Machine */
+	outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+
+	pci_set_power_state(pci_dev, 3);
+	pci_save_state(pci_dev, sis_priv->pci_state);
+
+	return 0;
+}
+
+static int sis900_resume(struct pci_dev *pci_dev)
+{
+	struct net_device *net_dev = pci_get_drvdata(pci_dev);
+	struct sis900_private *sis_priv = net_dev->priv;
+	long ioaddr = net_dev->base_addr;
+
+	if(!netif_running(net_dev))
+		return 0;
+	pci_restore_state(pci_dev, sis_priv->pci_state);
+	pci_set_power_state(pci_dev, 0);
+
+	sis900_init_rxfilter(net_dev);
+
+	sis900_init_tx_ring(net_dev);
+	sis900_init_rx_ring(net_dev);
+
+	set_rx_mode(net_dev);
+
+	netif_device_attach(net_dev);
+	netif_start_queue(net_dev);
+
+	/* Workaround for EDB */
+	sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+
+	/* Enable all known interrupts by setting the interrupt mask. */
+	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
+	outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
+	outl(IE, ioaddr + ier);
+
+	sis900_check_mode(net_dev, sis_priv->mii);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static struct pci_driver sis900_pci_driver = {
 	.name		= SIS900_MODULE_NAME,
 	.id_table	= sis900_pci_tbl,
 	.probe		= sis900_probe,
 	.remove		= __devexit_p(sis900_remove),
+#ifdef CONFIG_PM
+	.suspend	= sis900_suspend,
+	.resume		= sis900_resume,
+#endif /* CONFIG_PM */
 };
 
 static int __init sis900_init_module(void)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/tokenring/Kconfig 001-linus.patch/drivers/net/tokenring/Kconfig
--- 000-virgin/drivers/net/tokenring/Kconfig	Wed Dec 17 18:58:30 2003
+++ 001-linus.patch/drivers/net/tokenring/Kconfig	Tue Dec 30 16:38:57 2003
@@ -107,7 +107,7 @@ config TMS380TR
 
 config TMSPCI
 	tristate "Generic TMS380 PCI support"
-	depends on TR && TMS380TR!=n && PCI
+	depends on TR && TMS380TR && PCI
 	---help---
 	  This tms380 module supports generic TMS380-based PCI cards.
 
@@ -122,7 +122,7 @@ config TMSPCI
 
 config SKISA
 	tristate "SysKonnect TR4/16 ISA support"
-	depends on TR && TMS380TR!=n && ISA
+	depends on TR && TMS380TR && ISA
 	help
 	  This tms380 module supports SysKonnect TR4/16 ISA cards.
 
@@ -134,7 +134,7 @@ config SKISA
 
 config PROTEON
 	tristate "Proteon ISA support"
-	depends on TR && TMS380TR!=n && ISA
+	depends on TR && TMS380TR && ISA
 	help
 	  This tms380 module supports Proteon ISA cards.
 
@@ -147,7 +147,7 @@ config PROTEON
 
 config ABYSS
 	tristate "Madge Smart 16/4 PCI Mk2 support"
-	depends on TR && TMS380TR!=n && PCI
+	depends on TR && TMS380TR && PCI
 	help
 	  This tms380 module supports the Madge Smart 16/4 PCI Mk2
 	  cards (51-02).
@@ -157,7 +157,7 @@ config ABYSS
 
 config MADGEMC
 	tristate "Madge Smart 16/4 Ringnode MicroChannel"
-	depends on TR && TMS380TR!=n && MCA
+	depends on TR && TMS380TR && MCA
 	help
 	  This tms380 module supports the Madge Smart 16/4 MC16 and MC32
 	  MicroChannel adapters.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/typhoon.c 001-linus.patch/drivers/net/typhoon.c
--- 000-virgin/drivers/net/typhoon.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/net/typhoon.c	Tue Dec 30 16:38:57 2003
@@ -85,8 +85,8 @@ static const int multicast_filter_limit 
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.5.1"
-#define DRV_MODULE_RELDATE	"03/06/26"
+#define DRV_MODULE_VERSION 	"1.5.2"
+#define DRV_MODULE_RELDATE	"03/11/25"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -127,7 +127,7 @@ static const int multicast_filter_limit 
 static char version[] __devinitdata =
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
-MODULE_AUTHOR("David Dillow <dillowd@y12.doe.gov>");
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
 MODULE_PARM(rx_copybreak, "i");
@@ -146,11 +146,12 @@ struct typhoon_card_info {
 	int capabilities;
 };
 
-#define TYPHOON_CRYPTO_NONE		0
-#define TYPHOON_CRYPTO_DES		1
-#define TYPHOON_CRYPTO_3DES		2
-#define	TYPHOON_CRYPTO_VARIABLE		4
-#define TYPHOON_FIBER			8
+#define TYPHOON_CRYPTO_NONE		0x00
+#define TYPHOON_CRYPTO_DES		0x01
+#define TYPHOON_CRYPTO_3DES		0x02
+#define	TYPHOON_CRYPTO_VARIABLE		0x04
+#define TYPHOON_FIBER			0x08
+#define TYPHOON_WAKEUP_NEEDS_RESET	0x10
 
 enum typhoon_cards {
 	TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
@@ -307,7 +308,8 @@ enum state_values {
 /* We'll wait up to six seconds for a reset, and half a second normally.
  */
 #define TYPHOON_UDELAY			50
-#define TYPHOON_RESET_TIMEOUT		(6 * HZ)
+#define TYPHOON_RESET_TIMEOUT_SLEEP	(6 * HZ)
+#define TYPHOON_RESET_TIMEOUT_NOSLEEP	((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT		((1000000 / 2) / TYPHOON_UDELAY)
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
@@ -375,10 +377,12 @@ static int
 typhoon_reset(unsigned long ioaddr, int wait_type)
 {
 	int i, err = 0;
-	int timeout = TYPHOON_RESET_TIMEOUT;
+	int timeout;
 
 	if(wait_type == WaitNoSleep)
-		timeout = (timeout * 1000000) / (HZ * TYPHOON_UDELAY);
+		timeout = TYPHOON_RESET_TIMEOUT_NOSLEEP;
+	else
+		timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
 
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
@@ -1858,6 +1862,11 @@ typhoon_sleep(struct typhoon *tp, int st
 	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_SLEEPING) < 0)
 		return -ETIMEDOUT;
 
+	/* Since we cannot monitor the status of the link while sleeping,
+	 * tell the world it went away.
+	 */
+	netif_carrier_off(tp->dev);
+
 	pci_enable_wake(tp->pdev, state, 1);
 	pci_disable_device(pdev);
 	return pci_set_power_state(pdev, state);
@@ -1872,8 +1881,13 @@ typhoon_wakeup(struct typhoon *tp, int w
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
 
+	/* Post 2.x.x versions of the Sleep Image require a reset before
+	 * we can download the Runtime Image. But let's not make users of
+	 * the old firmware pay for the reset.
+	 */
 	writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
-	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0)
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
+			(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
 		return typhoon_reset(ioaddr, wait_type);
 
 	return 0;
@@ -2251,7 +2265,7 @@ typhoon_init_one(struct pci_dev *pdev, c
 	void *shared;
 	dma_addr_t shared_dma;
 	struct cmd_desc xp_cmd;
-	struct resp_desc xp_resp;
+	struct resp_desc xp_resp[3];
 	int i;
 	int err = 0;
 
@@ -2380,15 +2394,15 @@ typhoon_init_one(struct pci_dev *pdev, c
 	}
 
 	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS);
-	if(typhoon_issue_command(tp, 1, &xp_cmd, 1, &xp_resp) < 0) {
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) {
 		printk(ERR_PFX "%s: cannot read MAC address\n",
 		       pci_name(pdev));
 		err = -EIO;
 		goto error_out_reset;
 	}
 
-	*(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp.parm1));
-	*(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp.parm2));
+	*(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
+	*(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
 
 	if(!is_valid_ether_addr(dev->dev_addr)) {
 		printk(ERR_PFX "%s: Could not obtain valid ethernet address, "
@@ -2396,6 +2410,28 @@ typhoon_init_one(struct pci_dev *pdev, c
 		goto error_out_reset;
 	}
 
+	/* Read the Sleep Image version last, so the response is valid
+	 * later when we print out the version reported.
+	 */
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
+		printk(ERR_PFX "%s: Could not get Sleep Image version\n",
+			pdev->slot_name);
+		goto error_out_reset;
+	}
+
+	tp->capabilities = typhoon_card_info[card_id].capabilities;
+	tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
+
+	/* Typhoon 1.0 Sleep Images return one response descriptor to the
+	 * READ_VERSIONS command. Those versions are OK after waking up
+	 * from sleep without needing a reset. Typhoon 1.1+ Sleep Images
+	 * seem to need a little extra help to get started. Since we don't
+	 * know how to nudge it along, just kick it.
+	 */
+	if(xp_resp[0].numDesc != 0)
+		tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
+
 	if(typhoon_sleep(tp, 3, 0) < 0) {
 		printk(ERR_PFX "%s: cannot put adapter to sleep\n",
 		       pci_name(pdev));
@@ -2403,9 +2439,6 @@ typhoon_init_one(struct pci_dev *pdev, c
 		goto error_out_reset;
 	}
 
-	tp->capabilities = typhoon_card_info[card_id].capabilities;
-	tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
-
 	/* The chip-specific entries in the device structure. */
 	dev->open		= typhoon_open;
 	dev->hard_start_xmit	= typhoon_start_tx;
@@ -2442,6 +2475,32 @@ typhoon_init_one(struct pci_dev *pdev, c
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x\n", dev->dev_addr[i]);
 
+	/* xp_resp still contains the response to the READ_VERSIONS command.
+	 * For debugging, let the user know what version he has.
+	 */
+	if(xp_resp[0].numDesc == 0) {
+		/* This is the Typhoon 1.0 type Sleep Image, last 16 bits
+		 * of version is Month/Day of build.
+		 */
+		u16 monthday = le32_to_cpu(xp_resp[0].parm2) & 0xffff;
+		printk(KERN_INFO "%s: Typhoon 1.0 Sleep Image built "
+			"%02u/%02u/2000\n", dev->name, monthday >> 8,
+			monthday & 0xff);
+	} else if(xp_resp[0].numDesc == 2) {
+		/* This is the Typhoon 1.1+ type Sleep Image
+		 */
+		u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
+		u8 *ver_string = (u8 *) &xp_resp[1];
+		ver_string[25] = 0;
+		printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
+			"%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver),
+			ver_string);
+	} else {
+		printk(KERN_WARNING "%s: Unknown Sleep Image version "
+			"(%u:%04x)\n", dev->name, xp_resp[0].numDesc,
+			le32_to_cpu(xp_resp[0].parm2));
+	}
+		
 	return 0;
 
 error_out_reset:
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/wan/cycx_drv.c 001-linus.patch/drivers/net/wan/cycx_drv.c
--- 000-virgin/drivers/net/wan/cycx_drv.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/net/wan/cycx_drv.c	Tue Dec 30 16:38:57 2003
@@ -425,8 +425,8 @@ static int load_cyc2x(struct cycx_hw *hw
 	if (cksum != cfm->checksum) {
 		printk(KERN_ERR "%s:%s: firmware corrupted!\n",
 				modname, __FUNCTION__);
-		printk(KERN_ERR " cdsize = 0x%lx (expected 0x%lx)\n",
-				len - sizeof(struct cycx_firmware) - 1,
+		printk(KERN_ERR " cdsize = 0x%x (expected 0x%x)\n",
+				len - (int)sizeof(struct cycx_firmware) - 1,
 				cfm->info.codesize);
 		printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
 				cksum, cfm->checksum);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/net/wireless/atmel.c 001-linus.patch/drivers/net/wireless/atmel.c
--- 000-virgin/drivers/net/wireless/atmel.c	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/drivers/net/wireless/atmel.c	Tue Dec 30 16:38:57 2003
@@ -748,13 +748,13 @@ static int start_tx (struct sk_buff *skb
 	
 	if(priv->station_state != STATION_STATE_READY) {
 		priv->stats.tx_errors++;
-		return 0;
+		goto done;
 	}
 	
 	if (priv->card && priv->present_callback && 
 	    !(*priv->present_callback)(priv->card)) {
 		priv->stats.tx_errors++;
-		return 0;
+		goto done;
 	}
 	
 	/* first ensure the timer func cannot run */
@@ -804,6 +804,8 @@ static int start_tx (struct sk_buff *skb
 	
 	spin_unlock_irqrestore(&priv->irqlock, flags);
 	spin_unlock_bh(&priv->timerlock);
+
+done:
 	dev_kfree_skb(skb);
 	
 	return 0;	
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/parisc/Kconfig 001-linus.patch/drivers/parisc/Kconfig
--- 000-virgin/drivers/parisc/Kconfig	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/parisc/Kconfig	Tue Dec 30 16:38:57 2003
@@ -109,7 +109,7 @@ config IOMMU_SBA
 
 config SUPERIO
 	bool "SuperIO (SuckyIO) support"
-	depends on PCI
+	depends on PCI_LBA
 	default y
 	help
 	  Say Y here to support the SuperIO chip found in Bxxxx, C3xxx and
@@ -124,10 +124,23 @@ config CHASSIS_LCD_LED
 	  Disk/Network activities LEDs on some PA-RISC machines,
 	  or support for the LCD that can be found on recent material.
 	
-	  This has nothing to do with LED State support for A, J and E class.
+	  This has nothing to do with LED State support for A and E class.
 	
 	  If unsure, say Y.
 
+config PDC_CHASSIS
+	bool "PDC chassis State Panel support"
+	default y
+	help
+	  Say Y here if you want to enable support for the LED State front
+	  panel as found on E class, and support for the GSP Virtual Front
+	  Panel (LED State and message logging)  as found on high end
+	  servers such as A, L and N-class.
+	  
+	  This has nothing to do with Chassis LCD and LED support.
+	  
+	  If unsure, say Y.
+ 
 config HOTPLUG
 	bool "Support for hot-pluggable devices"
 	---help---
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/parisc/ccio-dma.c 001-linus.patch/drivers/parisc/ccio-dma.c
--- 000-virgin/drivers/parisc/ccio-dma.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/drivers/parisc/ccio-dma.c	Tue Dec 30 16:38:57 2003
@@ -483,7 +483,7 @@ typedef unsigned long space_t;
 */
 #define IOPDIR_VALID    0x01UL
 #define HINT_SAFE_DMA   0x02UL	/* used for pci_alloc_consistent() pages */
-#ifdef CONFIG_ISA	/* EISA support really */
+#ifdef CONFIG_EISA
 #define HINT_STOP_MOST  0x04UL	/* LSL support */
 #else
 #define HINT_STOP_MOST  0x00UL	/* only needed for "some EISA devices" */
@@ -617,7 +617,7 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_a
 		WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
 		iovp += chain_size;
 		byte_cnt -= chain_size;
-      }
+	}
 }
 
 /**
@@ -1312,8 +1312,8 @@ static struct ioc * ccio_find_ioc(int hw
  * ccio_get_iommu - Find the iommu which controls this device
  * @dev: The parisc device.
  *
- * This function searches through the registerd IOMMU's and returns the
- * appropriate IOMMU for the device based upon the devices hardware path.
+ * This function searches through the registered IOMMU's and returns
+ * the appropriate IOMMU for the device based on its hardware path.
  */
 void * ccio_get_iommu(const struct parisc_device *dev)
 {
@@ -1509,12 +1509,13 @@ ccio_init_resource(struct resource *res,
 {
 	int result;
 
+	res->parent = NULL;
 	res->flags = IORESOURCE_MEM;
 	res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
 	res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
+	res->name = name;
 	if (res->end + 1 == res->start)
 		return;
-	res->name = name;
 	result = request_resource(&iomem_resource, res);
 	if (result < 0) {
 		printk(KERN_ERR "%s: failed to claim CCIO bus address space (%08lx,%08lx)\n", 
@@ -1534,120 +1535,111 @@ static void __init ccio_init_resources(s
 			(unsigned long)&ioc->ioc_hpa->io_io_low_hv);
 }
 
-static int expand_resource(struct resource *res, unsigned long size,
-			   unsigned long align)
+static int new_ioc_area(struct resource *res, unsigned long size,
+		unsigned long min, unsigned long max, unsigned long align)
 {
-	struct resource *temp_res;
-	unsigned long start = res->start;
-	unsigned long end ;
+	if (max <= min)
+		return -EBUSY;
 
-	/* see if we can expand above */
-	end = (res->end + size + align - 1) & ~(align - 1);;
-	
-	temp_res = __request_region(res->parent, res->end, end - res->end,
-				    "expansion");
-	if(!temp_res) {
-		/* now try below */
-		start = ((res->start - size + align) & ~(align - 1)) - align;
-		end = res->end;
-		temp_res = __request_region(res->parent, start, size,
-					    "expansion");	
-		if(!temp_res) {
-			return -ENOMEM;
-		}
-	} 
-	release_resource(temp_res);
-	temp_res = res->parent;
-	release_resource(res);
-	res->start = start;
-	res->end = end;
-
-	/* This could be caused by some sort of race.  Basically, if
-	 * this tripped something stole the region we just reserved
-	 * and then released to check for expansion */
-	BUG_ON(request_resource(temp_res, res) != 0);
-
-	return 0;
-}
-
-static void expand_ioc_area(struct resource *parent, struct ioc *ioc,
-			    unsigned long size,	unsigned long min,
-			    unsigned long max, unsigned long align)
+	res->start = (max - size + 1) &~ (align - 1);
+	res->end = res->start + size;
+	if (!request_resource(&iomem_resource, res))
+		return 0;
+
+	return new_ioc_area(res, size, min, max - size, align);
+}
+
+static int expand_ioc_area(struct resource *res, unsigned long size,
+		unsigned long min, unsigned long max, unsigned long align)
 {
-	if(ioc == NULL)
-		/* no IOC, so nothing to expand */
-		return;
+	unsigned long start, len;
 
-	if (expand_resource(parent, size, align) != 0) {
-		printk(KERN_ERR "Unable to expand %s window by 0x%lx\n",
-		       parent->name, size);
-		return;
+	if (!res->parent)
+		return new_ioc_area(res, size, min, max, align);
+
+	start = (res->start - size) &~ (align - 1);
+	len = res->end - start + 1;
+	if (start >= min) {
+		if (!adjust_resource(res, start, len))
+			return 0;
+	}
+
+	start = res->start;
+	len = ((size + res->end + align) &~ (align - 1)) - start;
+	if (start + len <= max) {
+		if (!adjust_resource(res, start, len))
+			return 0;
 	}
 
-	/* OK, we have the memory, now expand the window */
-	if (parent == &ioc->mmio_region[0]) {
+	return -EBUSY;
+}
+
+/*
+ * Dino calls this function.  Beware that we may get called on systems
+ * which have no IOC (725, B180, C160L, etc) but do have a Dino.
+ * So it's legal to find no parent IOC.
+ *
+ * Some other issues: one of the resources in the ioc may be unassigned.
+ */
+int ccio_allocate_resource(const struct parisc_device *dev,
+		struct resource *res, unsigned long size,
+		unsigned long min, unsigned long max, unsigned long align)
+{
+	struct resource *parent = &iomem_resource;
+	struct ioc *ioc = ccio_get_iommu(dev);
+	if (!ioc)
+		goto out;
+
+	parent = ioc->mmio_region;
+	if (parent->parent &&
+	    !allocate_resource(parent, res, size, min, max, align, NULL, NULL))
+		return 0;
+
+	if ((parent + 1)->parent &&
+	    !allocate_resource(parent + 1, res, size, min, max, align,
+				NULL, NULL))
+		return 0;
+
+	if (!expand_ioc_area(parent, size, min, max, align)) {
 		__raw_writel(((parent->start)>>16) | 0xffff0000,
 			     (unsigned long)&(ioc->ioc_hpa->io_io_low));
 		__raw_writel(((parent->end)>>16) | 0xffff0000,
 			     (unsigned long)&(ioc->ioc_hpa->io_io_high));
-	} else if (parent == &ioc->mmio_region[1]) {
+	} else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
+		parent++;
 		__raw_writel(((parent->start)>>16) | 0xffff0000,
 			     (unsigned long)&(ioc->ioc_hpa->io_io_low_hv));
 		__raw_writel(((parent->end)>>16) | 0xffff0000,
 			     (unsigned long)&(ioc->ioc_hpa->io_io_high_hv));
 	} else {
-		/* This should be impossible.  It means
-		 * expand_ioc_area got called with a resource that
-		 * didn't belong to the ioc
-		 */
-		BUG();
+		return -EBUSY;
 	}
+
+ out:
+	return allocate_resource(parent, res, size, min, max, align, NULL,NULL);
 }
 
-static struct resource *ccio_get_resource(struct ioc* ioc,
-		const struct parisc_device *dev)
+int ccio_request_resource(const struct parisc_device *dev,
+		struct resource *res)
 {
+	struct resource *parent;
+	struct ioc *ioc = ccio_get_iommu(dev);
+
 	if (!ioc) {
-		return &iomem_resource;
+		parent = &iomem_resource;
 	} else if ((ioc->mmio_region->start <= dev->hpa) &&
 			(dev->hpa < ioc->mmio_region->end)) {
-		return ioc->mmio_region;
+		parent = ioc->mmio_region;
 	} else if (((ioc->mmio_region + 1)->start <= dev->hpa) &&
 			(dev->hpa < (ioc->mmio_region + 1)->end)) {
-		return ioc->mmio_region + 1;
+		parent = ioc->mmio_region + 1;
 	} else {
-		return NULL;
-	}
-}
-
-int ccio_allocate_resource(const struct parisc_device *dev,
-		struct resource *res, unsigned long size,
-		unsigned long min, unsigned long max, unsigned long align,
-		void (*alignf)(void *, struct resource *, unsigned long, unsigned long),
-		void *alignf_data)
-{
-	struct ioc *ioc = ccio_get_iommu(dev);
-	struct resource *parent = ccio_get_resource(ioc, dev);
-	if (!parent)
 		return -EBUSY;
-
-	if (!allocate_resource(parent, res, size, min, max, align, alignf,
-			alignf_data))
-		return 0;
-
-	expand_ioc_area(parent, ioc, size, min, max, align);
-	return allocate_resource(parent, res, size, min, max, align, alignf,
-			alignf_data);
-}
-
-int ccio_request_resource(const struct parisc_device *dev,
-		struct resource *res)
-{
-	struct ioc *ioc = ccio_get_iommu(dev);
-	struct resource *parent = ccio_get_resource(ioc, dev);
+	}
 
 	return request_resource(parent, res);
 }
+
 /**
  * ccio_probe - Determine if ccio should claim this device.
  * @dev: The device which has been found
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/parisc/dino.c 001-linus.patch/drivers/parisc/dino.c
--- 000-virgin/drivers/parisc/dino.c	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/drivers/parisc/dino.c	Tue Dec 30 16:38:57 2003
@@ -165,6 +165,13 @@ struct dino_device
 
 #define DINO_CFG_TOK(bus,dfn,pos) ((u32) ((bus)<<16 | (dfn)<<8 | (pos)))
 
+/*
+ * keep the current highest bus count to assist in allocating busses.  This
+ * tries to keep a global bus count total so that when we discover an 
+ * entirely new bus, it can be given a unique bus number.
+ */
+static int dino_current_bus = 0;
+
 static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
 		int size, u32 *val)
 {
@@ -478,8 +485,7 @@ dino_card_setup(struct pci_bus *bus, uns
 
 	if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB,
 				F_EXTEND(0xf0000000UL) | _8MB,
-				F_EXTEND(0xffffffffUL) &~ _8MB, _8MB,
-				NULL, NULL) < 0) {
+				F_EXTEND(0xffffffffUL) &~ _8MB, _8MB) < 0) {
 		struct list_head *ln, *tmp_ln;
 
 		printk(KERN_ERR "Dino: cannot attach bus %s\n",
@@ -505,8 +511,6 @@ dino_card_setup(struct pci_bus *bus, uns
 	DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n",
 	    i, res->start, base_addr + DINO_IO_ADDR_EN);
 	gsc_writel(1 << i, base_addr + DINO_IO_ADDR_EN);
-
-	pci_bus_assign_resources(bus);
 }
 
 static void __init
@@ -547,6 +551,9 @@ dino_card_fixup(struct pci_dev *dev)
 	dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); 
 }
 
+/* The alignment contraints for PCI bridges under dino */
+#define DINO_BRIDGE_ALIGN 0x100000
+
 
 static void __init
 dino_fixup_bus(struct pci_bus *bus)
@@ -560,13 +567,48 @@ dino_fixup_bus(struct pci_bus *bus)
 			__FUNCTION__, bus, bus->secondary, bus->dev->platform_data);
 
 	/* Firmware doesn't set up card-mode dino, so we have to */
-	if (is_card_dino(&dino_dev->hba.dev->id))
+	if (is_card_dino(&dino_dev->hba.dev->id)) {
 		dino_card_setup(bus, dino_dev->hba.base_addr);
+	} else if(bus->parent == NULL) {
+		/* must have a dino above it, reparent the resources
+		 * into the dino window */
+		bus->resource[0] = &(dino_dev->hba.io_space);
+		bus->resource[1] = &(dino_dev->hba.lmmio_space); 
+	} else if(bus->self) {
+		int i;
 
-	/* If this is a PCI-PCI Bridge, read the window registers etc */
-	if (bus->self)
 		pci_read_bridge_bases(bus);
 
+
+		for(i = 0; i < PCI_NUM_RESOURCES; i++) {
+			if((bus->self->resource[i].flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+				continue;
+			
+			if(bus->self->resource[i].flags & IORESOURCE_MEM) {
+				/* There's a quirk to alignment of
+				 * bridge memory resources: the start
+				 * is the alignment and start-end is
+				 * the size.  However, firmware will
+				 * have assigned start and end, so we
+				 * need to take this into account */
+				bus->self->resource[i].end = bus->self->resource[i].end - bus->self->resource[i].start + DINO_BRIDGE_ALIGN;
+				bus->self->resource[i].start = DINO_BRIDGE_ALIGN;
+				
+			}
+					
+			DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n",
+			    bus->self->dev.bus_id, i,
+			    bus->self->resource[i].start,
+			    bus->self->resource[i].end);
+			pci_assign_resource(bus->self, i);
+			DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n",
+			    bus->self->dev.bus_id, i,
+			    bus->self->resource[i].start,
+			    bus->self->resource[i].end);
+		}
+	}
+
+
 	list_for_each(ln, &bus->devices) {
 		int i;
 
@@ -596,9 +638,39 @@ dino_fixup_bus(struct pci_bus *bus)
 			}
 #endif
 		}
+		/* null out the ROM resource if there is one (we don't
+		 * care about an expansion rom on parisc, since it
+		 * usually contains (x86) bios code) */
+		dev->resource[PCI_ROM_RESOURCE].flags = 0;
+		dev->resource[PCI_ROM_RESOURCE].start = 0;
+		dev->resource[PCI_ROM_RESOURCE].end = 0;
+				
+		if(dev->irq == 255) {
+
+#ifdef DINO_FIX_UNASSIGNED_INTERRUPTS
+
+			/* This code tries to assign an unassigned
+			 * interrupt.  Leave it disabled unless you
+			 * *really* know what you're doing since the
+			 * pin<->interrupt line mapping varies by bus
+			 * and machine */
+
+			u32 irq_pin;
+			
+			dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin);
+			dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
+			dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq);
+			dev->irq += dino_dev->dino_region->data.irqbase
+			printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin);
+#else
+			dev->irq = 65535;
+			printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name);	
+#endif
+		} else {
 
-		/* Adjust INT_LINE for that busses region */
-		dev->irq = dino_dev->dino_region->data.irqbase + dev->irq;
+			/* Adjust INT_LINE for that busses region */
+			dev->irq += dino_dev->dino_region->data.irqbase;
+		}
 	}
 }
 
@@ -827,6 +899,7 @@ dino_driver_callback(struct parisc_devic
 	const int name_len = 32;
 	char *name;
 	int is_cujo = 0;
+	struct pci_bus *bus;
 
 	name = kmalloc(name_len, GFP_KERNEL);
 	if(name)
@@ -912,9 +985,20 @@ dino_driver_callback(struct parisc_devic
 	** It's not used to avoid chicken/egg problems
 	** with configuration accessor functions.
 	*/
-	dino_dev->hba.hba_bus = 
-		pci_scan_bus_parented(&dev->dev, dino_dev->hba.hba_num,
-				      &dino_cfg_ops, NULL);
+	bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
+				    &dino_cfg_ops, NULL);
+	if(bus) {
+		/* This code *depends* on scanning being single threaded
+		 * if it isn't, this global bus number count will fail
+		 */
+		dino_current_bus = bus->subordinate + 1;
+		pci_bus_assign_resources(bus);
+	} else {
+		printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus);
+		/* increment the bus number in case of duplicates */
+		dino_current_bus++;
+	}
+	dino_dev->hba.hba_bus = bus;
 	return 0;
 }
 
@@ -923,10 +1007,13 @@ dino_driver_callback(struct parisc_devic
  * the same sversion as Dino, so we have to check hversion as well.
  * Unfortunately, the J2240 PDC reports the wrong hversion for the first
  * Dino, so we have to test for Dino, Cujo and Dino-in-a-J2240.
+ * For card-mode Dino, most machines report an sversion of 9D.  But 715
+ * and 725 firmware misreport it as 0x08080 for no adequately explained
+ * reason.
  */
 static struct parisc_device_id dino_tbl[] = {
-	{ HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x004, 0x0009D }, /* Card-mode Dino. */
-	{ HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x444, 0x08080 }, /* Same card in a 715.  Bug? */
+	{ HPHW_A_DMA, HVERSION_REV_ANY_ID, 0x004, 0x0009D },/* Card-mode Dino */
+	{ HPHW_A_DMA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x08080 }, /* XXX */
 	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x680, 0xa }, /* Bridge-mode Dino */
 	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x682, 0xa }, /* Bridge-mode Cujo */
 	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x05d, 0xa }, /* Dino in a J2240 */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/parisc/led.c 001-linus.patch/drivers/parisc/led.c
--- 000-virgin/drivers/parisc/led.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/drivers/parisc/led.c	Tue Dec 30 16:38:57 2003
@@ -441,7 +441,6 @@ static __inline__ int led_get_diskio_act
 #if HZ==100
  #define NORMALIZED_COUNT(count) (count)
 #else
- #warning "Untested situation HZ != 100 !!"
  #define NORMALIZED_COUNT(count) (count/(HZ/100))
 #endif
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/parisc/superio.c 001-linus.patch/drivers/parisc/superio.c
--- 000-virgin/drivers/parisc/superio.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/parisc/superio.c	Tue Dec 30 16:38:57 2003
@@ -65,7 +65,9 @@
 #include <linux/ioport.h>
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
-#include <linux/serial_reg.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -387,11 +389,27 @@ int superio_fixup_irq(struct pci_dev *pc
 	return(sio_dev.irq_region->data.irqbase + local_irq);
 }
 
+static struct uart_port serial[] = {
+	{
+		.iotype		= UPIO_PORT,
+		.line		= 0,
+		.type		= PORT_16550A,
+		.uartclk	= 115200*16,
+		.fifosize	= 16,
+	},
+	{
+		.iotype		= UPIO_PORT,
+		.line		= 1,
+		.type		= PORT_16550A,
+		.uartclk	= 115200*16,
+		.fifosize	= 16,
+	}
+};
+
 void __devinit
 superio_serial_init(void)
 {
 #ifdef CONFIG_SERIAL_8250
-	struct serial_struct *serial;
 	int retval;
 	
 	if (!sio_dev.irq_region)
@@ -400,47 +418,15 @@ superio_serial_init(void)
 	if (!sio_dev.iosapic_irq_enabled)
 		superio_init(&sio_dev);
 
-	serial = kmalloc(2 * sizeof (struct serial_struct), GFP_KERNEL);
-
-	if (!serial) {
-		printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n");
-		return;
-	}
-
-	memset(serial, 0, 2 * sizeof (struct serial_struct));
-
-	serial->type = PORT_16550A;
-	serial->line = 0;
-	serial->port = sio_dev.sp1_base;
-	serial->port_high = 0;
-	serial->irq = sio_dev.irq_region->data.irqbase + SP1_IRQ;
-	serial->io_type = SERIAL_IO_PORT;
-	serial->flags = 0;
-	serial->xmit_fifo_size = 16;
-	serial->custom_divisor = 0;
-	serial->baud_base = 115200;
+	serial[0].iobase = sio_dev.sp1_base;
+	retval = early_serial_setup(&serial[0]);
 
-	retval = register_serial(serial);
-	if (retval < 0) {
+	if (retval < 0)
 		printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");
-		kfree (serial);
-		return;
-	}
-
-	serial++;
 
-	serial->type = PORT_16550A;
-	serial->line = 1;
-	serial->port = sio_dev.sp2_base;
-	serial->port_high = 0;
-	serial->irq = sio_dev.irq_region->data.irqbase + SP2_IRQ;
-	serial->io_type = SERIAL_IO_PORT;
-	serial->flags = 0;
-	serial->xmit_fifo_size = 16;
-	serial->custom_divisor = 0;
-	serial->baud_base = 115200;
+	serial[1].iobase = sio_dev.sp2_base;
+	retval = early_serial_setup(&serial[1]);
 
-	retval = register_serial(serial);
 	if (retval < 0)
 		printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");
 #endif /* CONFIG_SERIAL_8250 */
@@ -543,5 +529,5 @@ static void __exit superio_exit(void)
  *
  * FIXME: does this break the superio console?
  */
-late_initcall(superio_modinit);
+module_init(superio_modinit);
 module_exit(superio_exit);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pci/Makefile 001-linus.patch/drivers/pci/Makefile
--- 000-virgin/drivers/pci/Makefile	Wed Dec 17 18:59:37 2003
+++ 001-linus.patch/drivers/pci/Makefile	Tue Dec 30 16:38:57 2003
@@ -27,6 +27,7 @@ obj-$(CONFIG_PPC64) += setup-bus.o
 obj-$(CONFIG_SGI_IP27) += setup-irq.o
 obj-$(CONFIG_SGI_IP32) += setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
+obj-$(CONFIG_PCI_USE_VECTOR) += msi.o
 
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pci/msi.c 001-linus.patch/drivers/pci/msi.c
--- 000-virgin/drivers/pci/msi.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/pci/msi.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,1068 @@
+/*
+ * linux/drivers/pci/msi.c
+ */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/desc.h>
+#include <asm/io_apic.h>
+#include <mach_apic.h>
+
+#include <linux/pci_msi.h>
+
+_DEFINE_DBG_BUFFER
+
+static spinlock_t msi_lock = SPIN_LOCK_UNLOCKED;
+static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
+static kmem_cache_t* msi_cachep;
+
+static int pci_msi_enable = 1;
+static int nr_alloc_vectors = 0;
+static int nr_released_vectors = 0;
+static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;
+static int nr_msix_devices = 0;
+
+#ifndef CONFIG_X86_IO_APIC
+int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};
+u8 irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
+#endif
+
+static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
+{
+	memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
+}
+
+static int msi_cache_init(void)
+{
+	msi_cachep = kmem_cache_create("msi_cache",
+			NR_IRQS * sizeof(struct msi_desc),
+		       	0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
+	if (!msi_cachep)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void msi_set_mask_bit(unsigned int vector, int flag)
+{
+	struct msi_desc *entry;
+
+	entry = (struct msi_desc *)msi_desc[vector];
+	if (!entry || !entry->dev || !entry->mask_base)
+		return;
+	switch (entry->msi_attrib.type) {
+	case PCI_CAP_ID_MSI:
+	{
+		int		pos;
+		unsigned int	mask_bits;
+
+		pos = entry->mask_base;
+	        entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
+				pos, 4, &mask_bits);
+		mask_bits &= ~(1);
+		mask_bits |= flag;
+	        entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
+				pos, 4, mask_bits);
+		break;
+	}
+	case PCI_CAP_ID_MSIX:
+	{
+		int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
+		writel(flag, entry->mask_base + offset);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_SMP
+static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
+{
+	struct msi_desc *entry;
+	struct msg_address address;
+	unsigned int dest_id;
+
+	entry = (struct msi_desc *)msi_desc[vector];
+	if (!entry || !entry->dev)
+		return;
+
+	switch (entry->msi_attrib.type) {
+	case PCI_CAP_ID_MSI:
+	{
+		int pos;
+
+   		if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
+			return;
+
+	        entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
+			msi_lower_address_reg(pos), 4,
+			&address.lo_address.value);
+		dest_id = (address.lo_address.u.dest_id &
+			MSI_ADDRESS_HEADER_MASK) |
+			(cpu_mask_to_apicid(cpu_mask) << MSI_TARGET_CPU_SHIFT);
+		address.lo_address.u.dest_id = dest_id;
+		entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
+		entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
+			msi_lower_address_reg(pos), 4,
+			address.lo_address.value);
+		break;
+	}
+	case PCI_CAP_ID_MSIX:
+	{
+		int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+
+		address.lo_address.value = readl(entry->mask_base + offset);
+		dest_id = (address.lo_address.u.dest_id &
+			MSI_ADDRESS_HEADER_MASK) |
+			(cpu_mask_to_apicid(cpu_mask) << MSI_TARGET_CPU_SHIFT);
+		address.lo_address.u.dest_id = dest_id;
+		entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
+		writel(address.lo_address.value, entry->mask_base + offset);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static inline void move_msi(int vector)
+{
+	if (!cpus_empty(pending_irq_balance_cpumask[vector])) {
+		set_msi_affinity(vector, pending_irq_balance_cpumask[vector]);
+		cpus_clear(pending_irq_balance_cpumask[vector]);
+	}
+}
+#endif
+
+static void mask_MSI_irq(unsigned int vector)
+{
+	msi_set_mask_bit(vector, 1);
+}
+
+static void unmask_MSI_irq(unsigned int vector)
+{
+	msi_set_mask_bit(vector, 0);
+}
+
+static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
+{
+	return 0;	/* never anything pending */
+}
+
+static void pci_disable_msi(unsigned int vector);
+static void shutdown_msi_irq(unsigned int vector)
+{
+	pci_disable_msi(vector);
+}
+
+#define shutdown_msi_irq_wo_maskbit	shutdown_msi_irq
+static void enable_msi_irq_wo_maskbit(unsigned int vector) {}
+static void disable_msi_irq_wo_maskbit(unsigned int vector) {}
+static void ack_msi_irq_wo_maskbit(unsigned int vector) {}
+static void end_msi_irq_wo_maskbit(unsigned int vector)
+{
+	move_msi(vector);
+	ack_APIC_irq();
+}
+
+static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
+{
+	unmask_MSI_irq(vector);
+	return 0;	/* never anything pending */
+}
+
+#define shutdown_msi_irq_w_maskbit	shutdown_msi_irq
+#define enable_msi_irq_w_maskbit	unmask_MSI_irq
+#define disable_msi_irq_w_maskbit	mask_MSI_irq
+#define ack_msi_irq_w_maskbit		mask_MSI_irq
+
+static void end_msi_irq_w_maskbit(unsigned int vector)
+{
+	move_msi(vector);
+	unmask_MSI_irq(vector);
+	ack_APIC_irq();
+}
+
+/*
+ * Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI-X Capability Structure.
+ */
+static struct hw_interrupt_type msix_irq_type = {
+	.typename	= "PCI MSI-X",
+	.startup	= startup_msi_irq_w_maskbit,
+	.shutdown	= shutdown_msi_irq_w_maskbit,
+	.enable		= enable_msi_irq_w_maskbit,
+	.disable	= disable_msi_irq_w_maskbit,
+	.ack		= ack_msi_irq_w_maskbit,
+	.end		= end_msi_irq_w_maskbit,
+	.set_affinity	= set_msi_irq_affinity
+};
+
+/*
+ * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI Capability Structure with
+ * Mask-and-Pending Bits.
+ */
+static struct hw_interrupt_type msi_irq_w_maskbit_type = {
+	.typename	= "PCI MSI",
+	.startup	= startup_msi_irq_w_maskbit,
+	.shutdown	= shutdown_msi_irq_w_maskbit,
+	.enable		= enable_msi_irq_w_maskbit,
+	.disable	= disable_msi_irq_w_maskbit,
+	.ack		= ack_msi_irq_w_maskbit,
+	.end		= end_msi_irq_w_maskbit,
+	.set_affinity	= set_msi_irq_affinity
+};
+
+/*
+ * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI Capability Structure without
+ * Mask-and-Pending Bits.
+ */
+static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
+	.typename	= "PCI MSI",
+	.startup	= startup_msi_irq_wo_maskbit,
+	.shutdown	= shutdown_msi_irq_wo_maskbit,
+	.enable		= enable_msi_irq_wo_maskbit,
+	.disable	= disable_msi_irq_wo_maskbit,
+	.ack		= ack_msi_irq_wo_maskbit,
+	.end		= end_msi_irq_wo_maskbit,
+	.set_affinity	= set_msi_irq_affinity
+};
+
+static void msi_data_init(struct msg_data *msi_data,
+			  unsigned int vector)
+{
+	memset(msi_data, 0, sizeof(struct msg_data));
+	msi_data->vector = (u8)vector;
+	msi_data->delivery_mode = MSI_DELIVERY_MODE;
+	msi_data->level = MSI_LEVEL_MODE;
+	msi_data->trigger = MSI_TRIGGER_MODE;
+}
+
+static void msi_address_init(struct msg_address *msi_address)
+{
+	unsigned int	dest_id;
+
+	memset(msi_address, 0, sizeof(struct msg_address));
+	msi_address->hi_address = (u32)0;
+	dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT) |
+		 (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT);
+	msi_address->lo_address.u.dest_mode = MSI_LOGICAL_MODE;
+	msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
+	msi_address->lo_address.u.dest_id = dest_id;
+}
+
+static int pci_vector_resources(void)
+{
+	static int res = -EINVAL;
+	int nr_free_vectors;
+
+	if (res == -EINVAL) {
+		int i, repeat;
+		for (i = NR_REPEATS; i > 0; i--) {
+			if ((FIRST_DEVICE_VECTOR + i * 8) > FIRST_SYSTEM_VECTOR)
+				continue;
+			break;
+		}
+		i++;
+		repeat = (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR)/i;
+		res = i * repeat - NR_RESERVED_VECTORS + 1;
+	}
+
+	nr_free_vectors = res + nr_released_vectors - nr_alloc_vectors;
+
+	return nr_free_vectors;
+}
+
+int assign_irq_vector(int irq)
+{
+	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+
+	if (irq != MSI_AUTO && IO_APIC_VECTOR(irq) > 0)
+		return IO_APIC_VECTOR(irq);
+next:
+	current_vector += 8;
+	if (current_vector == SYSCALL_VECTOR)
+		goto next;
+
+	if (current_vector > FIRST_SYSTEM_VECTOR) {
+		offset++;
+		current_vector = FIRST_DEVICE_VECTOR + offset;
+	}
+
+	if (current_vector == FIRST_SYSTEM_VECTOR)
+		return -ENOSPC;
+
+	vector_irq[current_vector] = irq;
+	if (irq != MSI_AUTO)
+		IO_APIC_VECTOR(irq) = current_vector;
+
+	nr_alloc_vectors++;
+
+	return current_vector;
+}
+
+static int assign_msi_vector(void)
+{
+	static int new_vector_avail = 1;
+	int vector;
+	unsigned long flags;
+
+	/*
+	 * msi_lock is provided to ensure that successful allocation of MSI
+	 * vector is assigned unique among drivers.
+	 */
+	spin_lock_irqsave(&msi_lock, flags);
+	if (!(pci_vector_resources() > 0)) {
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EBUSY;
+	}
+
+	if (!new_vector_avail) {
+		/*
+	 	 * vector_irq[] = -1 indicates that this specific vector is:
+	 	 * - assigned for MSI (since MSI have no associated IRQ) or
+	 	 * - assigned for legacy if less than 16, or
+	 	 * - having no corresponding 1:1 vector-to-IOxAPIC IRQ mapping
+	 	 * vector_irq[] = 0 indicates that this vector, previously
+		 * assigned for MSI, is freed by hotplug removed operations.
+		 * This vector will be reused for any subsequent hotplug added
+		 * operations.
+	 	 * vector_irq[] > 0 indicates that this vector is assigned for
+		 * IOxAPIC IRQs. This vector and its value provides a 1-to-1
+		 * vector-to-IOxAPIC IRQ mapping.
+	 	 */
+		for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
+			if (vector_irq[vector] != 0)
+				continue;
+			vector_irq[vector] = -1;
+			nr_released_vectors--;
+			spin_unlock_irqrestore(&msi_lock, flags);
+			return vector;
+		}
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EBUSY;
+	}
+
+	vector = assign_irq_vector(MSI_AUTO);
+	if (vector  == (FIRST_SYSTEM_VECTOR - 8))
+		new_vector_avail = 0;
+
+	spin_unlock_irqrestore(&msi_lock, flags);
+	return vector;
+}
+
+static int get_new_vector(void)
+{
+	int vector;
+
+	if ((vector = assign_msi_vector()) > 0)
+		set_intr_gate(vector, interrupt[vector]);
+
+	return vector;
+}
+
+static int msi_init(void)
+{
+	static int status = -ENOMEM;
+
+	if (!status)
+		return status;
+
+	if ((status = msi_cache_init()) < 0) {
+		pci_msi_enable = 0;
+		printk(KERN_INFO "WARNING: MSI INIT FAILURE\n");
+		return status;
+	}
+	printk(KERN_INFO "MSI INIT SUCCESS\n");
+
+	return status;
+}
+
+static int get_msi_vector(struct pci_dev *dev)
+{
+	return get_new_vector();
+}
+
+static struct msi_desc* alloc_msi_entry(void)
+{
+	struct msi_desc *entry;
+
+	entry = (struct msi_desc*) kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
+	if (!entry)
+		return NULL;
+
+	memset(entry, 0, sizeof(struct msi_desc));
+	entry->link.tail = entry->link.head = 0;	/* single message */
+	entry->dev = NULL;
+
+	return entry;
+}
+
+static void attach_msi_entry(struct msi_desc *entry, int vector)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	msi_desc[vector] = entry;
+	spin_unlock_irqrestore(&msi_lock, flags);
+}
+
+static void irq_handler_init(int cap_id, int pos, int mask)
+{
+	spin_lock(&irq_desc[pos].lock);
+	if (cap_id == PCI_CAP_ID_MSIX)
+		irq_desc[pos].handler = &msix_irq_type;
+	else {
+		if (!mask)
+			irq_desc[pos].handler = &msi_irq_wo_maskbit_type;
+		else
+			irq_desc[pos].handler = &msi_irq_w_maskbit_type;
+	}
+	spin_unlock(&irq_desc[pos].lock);
+}
+
+static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
+{
+	u32 control;
+
+	dev->bus->ops->read(dev->bus, dev->devfn,
+		msi_control_reg(pos), 2, &control);
+	if (type == PCI_CAP_ID_MSI) {
+		/* Set enabled bits to single MSI & enable MSI_enable bit */
+		msi_enable(control, 1);
+	        dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_control_reg(pos), 2, control);
+	} else {
+		msix_enable(control);
+	        dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_control_reg(pos), 2, control);
+	}
+    	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
+		/* PCI Express Endpoint device detected */
+		u32 cmd;
+	        dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
+		cmd |= PCI_COMMAND_INTX_DISABLE;
+	        dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
+	}
+}
+
+static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
+{
+	u32 control;
+
+	dev->bus->ops->read(dev->bus, dev->devfn,
+		msi_control_reg(pos), 2, &control);
+	if (type == PCI_CAP_ID_MSI) {
+		/* Set enabled bits to single MSI & enable MSI_enable bit */
+		msi_disable(control);
+	        dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_control_reg(pos), 2, control);
+	} else {
+		msix_disable(control);
+	        dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_control_reg(pos), 2, control);
+	}
+    	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
+		/* PCI Express Endpoint device detected */
+		u32 cmd;
+	        dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
+		cmd &= ~PCI_COMMAND_INTX_DISABLE;
+	        dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
+	}
+}
+
+static int msi_lookup_vector(struct pci_dev *dev)
+{
+	int vector;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
+		if (!msi_desc[vector] || msi_desc[vector]->dev != dev ||
+			msi_desc[vector]->msi_attrib.entry_nr ||
+			msi_desc[vector]->msi_attrib.default_vector != dev->irq)
+			continue;	/* not entry 0, skip */
+		spin_unlock_irqrestore(&msi_lock, flags);
+		/* This pre-assigned entry-0 MSI vector for this device
+		   already exits. Override dev->irq with this vector */
+		dev->irq = vector;
+		return 0;
+	}
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	return -EACCES;
+}
+
+void pci_scan_msi_device(struct pci_dev *dev)
+{
+	if (!dev)
+		return;
+
+   	if (pci_find_capability(dev, PCI_CAP_ID_MSIX) > 0) {
+		nr_reserved_vectors++;
+		nr_msix_devices++;
+	} else if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0)
+		nr_reserved_vectors++;
+}
+
+/**
+ * msi_capability_init - configure device's MSI capability structure
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ *
+ * Setup the MSI capability structure of device funtion with a single
+ * MSI vector, regardless of device function is capable of handling
+ * multiple messages. A return of zero indicates the successful setup
+ * of an entry zero with the new MSI vector or non-zero for otherwise.
+ **/
+static int msi_capability_init(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+	struct msg_address address;
+	struct msg_data data;
+	int pos, vector;
+	u32 control;
+
+   	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!pos)
+		return -EINVAL;
+
+	dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
+		2, &control);
+	if (control & PCI_MSI_FLAGS_ENABLE)
+		return 0;
+
+	if (!msi_lookup_vector(dev)) {
+		/* Lookup Sucess */
+		enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+		return 0;
+	}
+	/* MSI Entry Initialization */
+	if (!(entry = alloc_msi_entry()))
+		return -ENOMEM;
+
+	if ((vector = get_msi_vector(dev)) < 0) {
+		kmem_cache_free(msi_cachep, entry);
+		return -EBUSY;
+	}
+	entry->msi_attrib.type = PCI_CAP_ID_MSI;
+	entry->msi_attrib.entry_nr = 0;
+	entry->msi_attrib.maskbit = is_mask_bit_support(control);
+	entry->msi_attrib.default_vector = dev->irq;
+	dev->irq = vector;	/* save default pre-assigned ioapic vector */
+	entry->dev = dev;
+	if (is_mask_bit_support(control)) {
+		entry->mask_base = msi_mask_bits_reg(pos,
+				is_64bit_address(control));
+	}
+	/* Replace with MSI handler */
+	irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
+	/* Configure MSI capability structure */
+	msi_address_init(&address);
+	msi_data_init(&data, vector);
+	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+	dev->bus->ops->write(dev->bus, dev->devfn, msi_lower_address_reg(pos),
+				4, address.lo_address.value);
+	if (is_64bit_address(control)) {
+		dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_upper_address_reg(pos), 4, address.hi_address);
+		dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_data_reg(pos, 1), 2, *((u32*)&data));
+	} else
+		dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_data_reg(pos, 0), 2, *((u32*)&data));
+	if (entry->msi_attrib.maskbit) {
+		unsigned int maskbits, temp;
+		/* All MSIs are unmasked by default, Mask them all */
+	        dev->bus->ops->read(dev->bus, dev->devfn,
+			msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
+			&maskbits);
+		temp = (1 << multi_msi_capable(control));
+		temp = ((temp - 1) & ~temp);
+		maskbits |= temp;
+		dev->bus->ops->write(dev->bus, dev->devfn,
+			msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
+			maskbits);
+	}
+	attach_msi_entry(entry, vector);
+	/* Set MSI enabled bits	 */
+	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+
+	return 0;
+}
+
+/**
+ * msix_capability_init - configure device's MSI-X capability
+ * @dev: pointer to the pci_dev data structure of MSI-X device function
+ *
+ * Setup the MSI-X capability structure of device funtion with a
+ * single MSI-X vector. A return of zero indicates the successful setup
+ * of an entry zero with the new MSI-X vector or non-zero for otherwise.
+ * To request for additional MSI-X vectors, the device drivers are
+ * required to utilize the following supported APIs:
+ * 1) msi_alloc_vectors(...) for requesting one or more MSI-X vectors
+ * 2) msi_free_vectors(...) for releasing one or more MSI-X vectors
+ *    back to PCI subsystem before calling free_irq(...)
+ **/
+static int msix_capability_init(struct pci_dev	*dev)
+{
+	struct msi_desc *entry;
+	struct msg_address address;
+	struct msg_data data;
+	int vector = 0, pos, dev_msi_cap;
+	u32 phys_addr, table_offset;
+	u32 control;
+	u8 bir;
+	void *base;
+
+   	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (!pos)
+		return -EINVAL;
+
+	/* Request & Map MSI-X table region */
+	dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2,
+		&control);
+	if (control & PCI_MSIX_FLAGS_ENABLE)
+		return 0;
+
+	if (!msi_lookup_vector(dev)) {
+		/* Lookup Sucess */
+		enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+		return 0;
+	}
+
+	dev_msi_cap = multi_msix_capable(control);
+	dev->bus->ops->read(dev->bus, dev->devfn,
+		msix_table_offset_reg(pos), 4, &table_offset);
+	bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+	phys_addr = pci_resource_start (dev, bir);
+	phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
+	if (!request_mem_region(phys_addr,
+		dev_msi_cap * PCI_MSIX_ENTRY_SIZE,
+		"MSI-X iomap Failure"))
+		return -ENOMEM;
+	base = ioremap_nocache(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
+	if (base == NULL)
+		goto free_region;
+	/* MSI Entry Initialization */
+	entry = alloc_msi_entry();
+	if (!entry)
+		goto free_iomap;
+	if ((vector = get_msi_vector(dev)) < 0)
+		goto free_entry;
+
+	entry->msi_attrib.type = PCI_CAP_ID_MSIX;
+	entry->msi_attrib.entry_nr = 0;
+	entry->msi_attrib.maskbit = 1;
+	entry->msi_attrib.default_vector = dev->irq;
+	dev->irq = vector;	/* save default pre-assigned ioapic vector */
+	entry->dev = dev;
+	entry->mask_base = (unsigned long)base;
+	/* Replace with MSI handler */
+	irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
+	/* Configure MSI-X capability structure */
+	msi_address_init(&address);
+	msi_data_init(&data, vector);
+	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+	writel(address.lo_address.value, base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+	writel(address.hi_address, base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+	writel(*(u32*)&data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
+	/* Initialize all entries from 1 up to 0 */
+	for (pos = 1; pos < dev_msi_cap; pos++) {
+		writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+		writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+		writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_DATA_OFFSET);
+	}
+	attach_msi_entry(entry, vector);
+	/* Set MSI enabled bits	 */
+	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+
+	return 0;
+
+free_entry:
+	kmem_cache_free(msi_cachep, entry);
+free_iomap:
+	iounmap(base);
+free_region:
+	release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
+
+	return ((vector < 0) ? -EBUSY : -ENOMEM);
+}
+
+/**
+ * pci_enable_msi - configure device's MSI(X) capability structure
+ * @dev: pointer to the pci_dev data structure of MSI(X) device function
+ *
+ * Setup the MSI/MSI-X capability structure of device function with
+ * a single MSI(X) vector upon its software driver call to request for
+ * MSI(X) mode enabled on its hardware device function. A return of zero
+ * indicates the successful setup of an entry zero with the new MSI(X)
+ * vector or non-zero for otherwise.
+ **/
+int pci_enable_msi(struct pci_dev* dev)
+{
+	int status = -EINVAL;
+
+	if (!pci_msi_enable || !dev)
+ 		return status;
+
+	if (msi_init() < 0)
+		return -ENOMEM;
+
+	if ((status = msix_capability_init(dev)) == -EINVAL)
+		status = msi_capability_init(dev);
+	if (!status)
+		nr_reserved_vectors--;
+
+	return status;
+}
+
+static int msi_free_vector(struct pci_dev* dev, int vector);
+static void pci_disable_msi(unsigned int vector)
+{
+	int head, tail, type, default_vector;
+	struct msi_desc *entry;
+	struct pci_dev *dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[vector];
+	if (!entry || !entry->dev) {
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return;
+	}
+	dev = entry->dev;
+	type = entry->msi_attrib.type;
+	head = entry->link.head;
+	tail = entry->link.tail;
+	default_vector = entry->msi_attrib.default_vector;
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	disable_msi_mode(dev, pci_find_capability(dev, type), type);
+	/* Restore dev->irq to its default pin-assertion vector */
+	dev->irq = default_vector;
+	if (type == PCI_CAP_ID_MSIX && head != tail) {
+		/* Bad driver, which do not call msi_free_vectors before exit.
+		   We must do a cleanup here */
+		while (1) {
+			spin_lock_irqsave(&msi_lock, flags);
+			entry = msi_desc[vector];
+			head = entry->link.head;
+			tail = entry->link.tail;
+			spin_unlock_irqrestore(&msi_lock, flags);
+			if (tail == head)
+				break;
+			if (msi_free_vector(dev, entry->link.tail))
+				break;
+		}
+	}
+}
+
+static int msi_alloc_vector(struct pci_dev* dev, int head)
+{
+	struct msi_desc *entry;
+	struct msg_address address;
+	struct msg_data data;
+	int i, offset, pos, dev_msi_cap, vector;
+	u32 low_address, control;
+	unsigned long base = 0L;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[dev->irq];
+	if (!entry) {
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EINVAL;
+	}
+	base = entry->mask_base;
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+   	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
+		2, &control);
+	dev_msi_cap = multi_msix_capable(control);
+	for (i = 1; i < dev_msi_cap; i++) {
+		if (!(low_address = readl(base + i * PCI_MSIX_ENTRY_SIZE)))
+			 break;
+	}
+	if (i >= dev_msi_cap)
+		return -EINVAL;
+
+	/* MSI Entry Initialization */
+	if (!(entry = alloc_msi_entry()))
+		return -ENOMEM;
+
+	if ((vector = get_new_vector()) < 0) {
+		kmem_cache_free(msi_cachep, entry);
+		return vector;
+	}
+	entry->msi_attrib.type = PCI_CAP_ID_MSIX;
+	entry->msi_attrib.entry_nr = i;
+	entry->msi_attrib.maskbit = 1;
+	entry->dev = dev;
+	entry->link.head = head;
+	entry->mask_base = base;
+	irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
+	/* Configure MSI-X capability structure */
+	msi_address_init(&address);
+	msi_data_init(&data, vector);
+	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+	offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
+	writel(address.lo_address.value, base + offset +
+		PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+	writel(address.hi_address, base + offset +
+		PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+	writel(*(u32*)&data, base + offset + PCI_MSIX_ENTRY_DATA_OFFSET);
+	writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+	attach_msi_entry(entry, vector);
+
+	return vector;
+}
+
+static int msi_free_vector(struct pci_dev* dev, int vector)
+{
+	struct msi_desc *entry;
+	int entry_nr, type;
+	unsigned long base = 0L;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[vector];
+	if (!entry || entry->dev != dev) {
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EINVAL;
+	}
+	type = entry->msi_attrib.type;
+	entry_nr = entry->msi_attrib.entry_nr;
+	base = entry->mask_base;
+	if (entry->link.tail != entry->link.head) {
+		msi_desc[entry->link.head]->link.tail = entry->link.tail;
+		if (entry->link.tail)
+			msi_desc[entry->link.tail]->link.head = entry->link.head;
+	}
+	entry->dev = NULL;
+	vector_irq[vector] = 0;
+	nr_released_vectors++;
+	msi_desc[vector] = NULL;
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	kmem_cache_free(msi_cachep, entry);
+	if (type == PCI_CAP_ID_MSIX) {
+		int offset;
+
+		offset = entry_nr * PCI_MSIX_ENTRY_SIZE;
+		writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+		writel(0, base + offset + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+	}
+
+	return 0;
+}
+
+/**
+ * msi_alloc_vectors - allocate additional MSI-X vectors
+ * @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @vector: pointer to an array of new allocated MSI-X vectors
+ * @nvec: number of MSI-X vectors requested for allocation by device driver
+ *
+ * Allocate additional MSI-X vectors requested by device driver. A
+ * return of zero indicates the successful setup of MSI-X capability
+ * structure with new allocated MSI-X vectors or non-zero for otherwise.
+ **/
+int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec)
+{
+	struct msi_desc *entry;
+	int i, head, pos, vec, free_vectors, alloc_vectors;
+	int *vectors = (int *)vector;
+	u32 control;
+	unsigned long flags;
+
+	if (!pci_msi_enable || !dev)
+ 		return -EINVAL;
+
+   	if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
+ 		return -EINVAL;
+
+	dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 			2, &control);
+	if (nvec > multi_msix_capable(control))
+		return -EINVAL;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[dev->irq];
+	if (!entry || entry->dev != dev ||		/* legal call */
+	   entry->msi_attrib.type != PCI_CAP_ID_MSIX || /* must be MSI-X */
+	   entry->link.head != entry->link.tail) {	/* already multi */
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EINVAL;
+	}
+	/*
+	 * msi_lock is provided to ensure that enough vectors resources are
+	 * available before granting.
+	 */
+	free_vectors = pci_vector_resources();
+	/* Ensure that each MSI/MSI-X device has one vector reserved by
+	   default to avoid any MSI-X driver to take all available
+ 	   resources */
+	free_vectors -= nr_reserved_vectors;
+	/* Find the average of free vectors among MSI-X devices */
+	if (nr_msix_devices > 0)
+		free_vectors /= nr_msix_devices;
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	if (nvec > free_vectors)
+		return -EBUSY;
+
+	alloc_vectors = 0;
+	head = dev->irq;
+	for (i = 0; i < nvec; i++) {
+		if ((vec = msi_alloc_vector(dev, head)) < 0)
+			break;
+		*(vectors + i) = vec;
+		head = vec;
+		alloc_vectors++;
+	}
+	if (alloc_vectors != nvec) {
+		for (i = 0; i < alloc_vectors; i++) {
+			vec = *(vectors + i);
+			msi_free_vector(dev, vec);
+		}
+		spin_lock_irqsave(&msi_lock, flags);
+		msi_desc[dev->irq]->link.tail = msi_desc[dev->irq]->link.head;
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EBUSY;
+	}
+	if (nr_msix_devices > 0)
+		nr_msix_devices--;
+
+	return 0;
+}
+
+/**
+ * msi_free_vectors - reclaim MSI-X vectors to unused state
+ * @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @vector: pointer to an array of released MSI-X vectors
+ * @nvec: number of MSI-X vectors requested for release by device driver
+ *
+ * Reclaim MSI-X vectors released by device driver to unused state,
+ * which may be used later on. A return of zero indicates the
+ * success or non-zero for otherwise. Device driver should call this
+ * before calling function free_irq.
+ **/
+int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec)
+{
+	struct msi_desc *entry;
+	int i;
+	unsigned long flags;
+
+	if (!pci_msi_enable)
+ 		return -EINVAL;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[dev->irq];
+	if (!entry || entry->dev != dev ||
+	   	entry->msi_attrib.type != PCI_CAP_ID_MSIX ||
+		entry->link.head == entry->link.tail) {	/* Nothing to free */
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	for (i = 0; i < nvec; i++) {
+		if (*(vector + i) == dev->irq)
+			continue;/* Don't free entry 0 if mistaken by driver */
+		msi_free_vector(dev, *(vector + i));
+	}
+
+	return 0;
+}
+
+/**
+ * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
+ * @dev: pointer to the pci_dev data structure of MSI(X) device function
+ *
+ * Being called during hotplug remove, from which the device funciton
+ * is hot-removed. All previous assigned MSI/MSI-X vectors, if
+ * allocated for this device function, are reclaimed to unused state,
+ * which may be used later on.
+ **/
+void msi_remove_pci_irq_vectors(struct pci_dev* dev)
+{
+	struct msi_desc *entry;
+	int type, temp;
+	unsigned long flags;
+
+	if (!pci_msi_enable || !dev)
+ 		return;
+
+   	if (!pci_find_capability(dev, PCI_CAP_ID_MSI)) {
+   		if (!pci_find_capability(dev, PCI_CAP_ID_MSIX))
+			return;
+	}
+	temp = dev->irq;
+	if (msi_lookup_vector(dev))
+		return;
+
+	spin_lock_irqsave(&msi_lock, flags);
+	entry = msi_desc[dev->irq];
+	if (!entry || entry->dev != dev) {
+		spin_unlock_irqrestore(&msi_lock, flags);
+		return;
+	}
+	type = entry->msi_attrib.type;
+	spin_unlock_irqrestore(&msi_lock, flags);
+
+	msi_free_vector(dev, dev->irq);
+	if (type == PCI_CAP_ID_MSIX) {
+		int i, pos, dev_msi_cap;
+		u32 phys_addr, table_offset;
+		u32 control;
+		u8 bir;
+
+   		pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+		dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 			2, &control);
+		dev_msi_cap = multi_msix_capable(control);
+		dev->bus->ops->read(dev->bus, dev->devfn,
+			msix_table_offset_reg(pos), 4, &table_offset);
+		bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+		phys_addr = pci_resource_start (dev, bir);
+		phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
+		for (i = FIRST_DEVICE_VECTOR; i < NR_IRQS; i++) {
+			spin_lock_irqsave(&msi_lock, flags);
+			if (!msi_desc[i] || msi_desc[i]->dev != dev) {
+				spin_unlock_irqrestore(&msi_lock, flags);
+				continue;
+			}
+			spin_unlock_irqrestore(&msi_lock, flags);
+			msi_free_vector(dev, i);
+		}
+		writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+		iounmap((void*)entry->mask_base);
+		release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
+	}
+	dev->irq = temp;
+	nr_reserved_vectors++;
+}
+
+EXPORT_SYMBOL(pci_enable_msi);
+EXPORT_SYMBOL(msi_alloc_vectors);
+EXPORT_SYMBOL(msi_free_vectors);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pci/probe.c 001-linus.patch/drivers/pci/probe.c
--- 000-virgin/drivers/pci/probe.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/drivers/pci/probe.c	Tue Dec 30 16:38:57 2003
@@ -552,6 +552,7 @@ int __devinit pci_scan_slot(struct pci_b
 		struct pci_dev *dev;
 
 		dev = pci_scan_device(bus, devfn);
+		pci_scan_msi_device(dev);
 		if (func == 0) {
 			if (!dev)
 				break;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pci/proc.c 001-linus.patch/drivers/pci/proc.c
--- 000-virgin/drivers/pci/proc.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/pci/proc.c	Tue Dec 30 16:38:57 2003
@@ -25,7 +25,7 @@ proc_bus_pci_lseek(struct file *file, lo
 {
 	loff_t new = -1;
 
-	lock_kernel();
+	down(&file->f_dentry->d_inode->i_sem);
 	switch (whence) {
 	case 0:
 		new = off;
@@ -37,10 +37,12 @@ proc_bus_pci_lseek(struct file *file, lo
 		new = PCI_CFG_SPACE_SIZE + off;
 		break;
 	}
-	unlock_kernel();
 	if (new < 0 || new > PCI_CFG_SPACE_SIZE)
-		return -EINVAL;
-	return (file->f_pos = new);
+		new = -EINVAL;
+	else
+		file->f_pos = new;
+	up(&file->f_dentry->d_inode->i_sem);
+	return new;
 }
 
 static ssize_t
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pci/remove.c 001-linus.patch/drivers/pci/remove.c
--- 000-virgin/drivers/pci/remove.c	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/pci/remove.c	Tue Dec 30 16:38:57 2003
@@ -14,6 +14,8 @@ static void pci_free_resources(struct pc
 {
 	int i;
 
+ 	msi_remove_pci_irq_vectors(dev);
+
 	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 		struct resource *res = dev->resource + i;
 		if (res->parent)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/pcmcia/i82365.c 001-linus.patch/drivers/pcmcia/i82365.c
--- 000-virgin/drivers/pcmcia/i82365.c	Wed Dec 17 18:59:35 2003
+++ 001-linus.patch/drivers/pcmcia/i82365.c	Tue Dec 30 16:38:57 2003
@@ -1211,6 +1211,7 @@ static int i365_set_mem_map(u_short sock
     return 0;
 } /* i365_set_mem_map */
 
+#if 0 /* driver model ordering issue */
 /*======================================================================
 
     Routines for accessing socket information and register dumps via
@@ -1250,6 +1251,7 @@ static ssize_t show_exca(struct class_de
 
 static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
 static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
+#endif
 
 /*====================================================================*/
 
@@ -1414,10 +1416,12 @@ static int __init init_i82365(void)
 			    pcmcia_unregister_socket(&socket[i].socket);
 		    break;
 	    }
+#if 0 /* driver model ordering issue */
 	   class_device_create_file(&socket[i].socket.dev,
 			   	    &class_device_attr_info);
 	   class_device_create_file(&socket[i].socket.dev,
 			   	    &class_device_attr_exca);
+#endif
     }
 
     /* Finally, schedule a polling interrupt */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/ata_piix.c 001-linus.patch/drivers/scsi/ata_piix.c
--- 000-virgin/drivers/scsi/ata_piix.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/scsi/ata_piix.c	Tue Dec 30 16:38:57 2003
@@ -97,6 +97,7 @@ static Scsi_Host_Template piix_sht = {
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
 };
 
 static struct ata_port_operations piix_pata_ops = {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/hosts.c 001-linus.patch/drivers/scsi/hosts.c
--- 000-virgin/drivers/scsi/hosts.c	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/drivers/scsi/hosts.c	Tue Dec 30 16:38:57 2003
@@ -109,7 +109,7 @@ int scsi_add_host(struct Scsi_Host *shos
 	}
 
 	if (!shost->shost_gendev.parent)
-		shost->shost_gendev.parent = dev ? dev : &legacy_bus;
+		shost->shost_gendev.parent = dev ? dev : &platform_bus;
 
 	error = device_add(&shost->shost_gendev);
 	if (error)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/libata-core.c 001-linus.patch/drivers/scsi/libata-core.c
--- 000-virgin/drivers/scsi/libata-core.c	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/drivers/scsi/libata-core.c	Tue Dec 30 16:38:57 2003
@@ -1619,7 +1619,7 @@ static void ata_dev_set_pio(struct ata_p
 static void ata_sg_clean(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct scatterlist *sg = qc->sg;
 	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
 
@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queu
 	if (cmd->use_sg)
 		pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
 	else
-		pci_unmap_single(ap->host_set->pdev, sg[0].dma_address,
-				 sg[0].length, dir);
+		pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
+				 sg_dma_len(&sg[0]), dir);
 
 	qc->flags &= ~ATA_QCFLAG_SG;
 	qc->sg = NULL;
@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *
 	assert(qc->n_elem > 0);
 
 	for (i = 0; i < qc->n_elem; i++) {
-		ap->prd[i].addr = cpu_to_le32(sg[i].dma_address);
-		ap->prd[i].flags_len = cpu_to_le32(sg[i].length);
+		ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i]));
+		ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i]));
 		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n",
 			i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len));
 	}
@@ -1681,7 +1681,7 @@ void ata_fill_sg(struct ata_queued_cmd *
 static int ata_sg_setup_one(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
 	struct scatterlist *sg = qc->sg;
 	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_q
 
 	sg->page = virt_to_page(cmd->request_buffer);
 	sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
-	sg->length = cmd->request_bufflen;
+	sg_dma_len(sg) = cmd->request_bufflen;
 
 	if (!have_sg)
 		return 0;
 
-	sg->dma_address = pci_map_single(ap->host_set->pdev,
+	sg_dma_address(sg) = pci_map_single(ap->host_set->pdev,
 					 cmd->request_buffer,
 					 cmd->request_bufflen, dir);
 
@@ -1720,7 +1720,7 @@ static int ata_sg_setup_one(struct ata_q
 static int ata_sg_setup(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct scatterlist *sg;
 	int n_elem;
 	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
@@ -1872,7 +1872,7 @@ static void ata_pio_sector(struct ata_po
 {
 	struct ata_queued_cmd *qc;
 	struct scatterlist *sg;
-	Scsi_Cmnd *cmd;
+	struct scsi_cmnd *cmd;
 	unsigned char *buf;
 	u8 status;
 
@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_po
 	qc->cursg_ofs++;
 
 	if (cmd->use_sg)
-		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg[qc->cursg].length) {
+		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
 			qc->cursg++;
 			qc->cursg_ofs = 0;
 		}
@@ -2092,7 +2092,7 @@ struct ata_queued_cmd *ata_qc_new_init(s
 void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late)
 {
 	struct ata_port *ap = qc->ap;
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 	unsigned int tag, do_clear = 0;
 
 	assert(qc != NULL);	/* ata_qc_from_tag _might_ return NULL */
@@ -2163,7 +2163,7 @@ static void ata_qc_push (struct ata_queu
 int ata_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 	unsigned int dma = qc->flags & ATA_QCFLAG_DMA;
 
 	ata_dev_select(ap, qc->dev->devno, 1, 0);
@@ -2719,7 +2719,7 @@ static void ata_host_remove(struct ata_p
 	DPRINTK("ENTER\n");
 
 	if (do_unregister)
-		scsi_remove_host(sh); /* FIXME: check return val */
+		scsi_remove_host(sh);
 
 	ata_thread_kill(ap);	/* FIXME: check return val */
 
@@ -3204,7 +3204,6 @@ void ata_pci_remove_one (struct pci_dev 
 	for (i = 0; i < host_set->n_ports; i++) {
 		ap = host_set->ports[i];
 
-		/* FIXME: check return val */
 		scsi_remove_host(ap->host);
 	}
 
@@ -3215,13 +3214,10 @@ void ata_pci_remove_one (struct pci_dev 
 		host_set->ports[0]->ops->host_stop(host_set);
 
 	for (i = 0; i < host_set->n_ports; i++) {
-		Scsi_Host_Template *sht;
-
 		ap = host_set->ports[i];
-		sht = ap->host->hostt;
 
 		ata_scsi_release(ap->host);
-		scsi_host_put(ap->host); /* FIXME: check return val */
+		scsi_host_put(ap->host);
 	}
 
 	pci_release_regions(pdev);
@@ -3279,6 +3275,7 @@ int pci_test_config_bits(struct pci_dev 
 	return (tmp == bits->val) ? 1 : 0;
 }
 
+
 /**
  *	ata_init -
  *
@@ -3304,6 +3301,7 @@ module_init(ata_init);
  */
 
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
 EXPORT_SYMBOL_GPL(ata_qc_complete);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/libata-scsi.c 001-linus.patch/drivers/scsi/libata-scsi.c
--- 000-virgin/drivers/scsi/libata-scsi.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/drivers/scsi/libata-scsi.c	Tue Dec 30 16:38:57 2003
@@ -32,10 +32,34 @@
 
 #include "libata.h"
 
+
+/**
+ *	ata_std_bios_param - generic bios head/sector/cylinder calculator
+ *	    used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS) 
+ *	    mapping. Some situations may arise where the disk is not 
+ *	    bootable if this is not used.
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+		       sector_t capacity, int geom[]) 
+{
+	geom[0] = 255;
+	geom[1] = 63;
+	sector_div(capacity, 255*63);
+	geom[2] = capacity;
+
+	return 0;
+}
+
+
 struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
 				       struct ata_device *dev,
-				       Scsi_Cmnd *cmd,
-				       void (*done)(Scsi_Cmnd *))
+				       struct scsi_cmnd *cmd,
+				       void (*done)(struct scsi_cmnd *))
 {
 	struct ata_queued_cmd *qc;
 
@@ -69,7 +93,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
 
 void ata_to_sense_error(struct ata_queued_cmd *qc)
 {
-	Scsi_Cmnd *cmd = qc->scsicmd;
+	struct scsi_cmnd *cmd = qc->scsicmd;
 
 	cmd->result = SAM_STAT_CHECK_CONDITION;
 
@@ -282,7 +306,7 @@ static unsigned int ata_scsi_rw_xlat(str
  */
 
 void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
-		      Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *),
+		      struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
 		      unsigned int cmd_size)
 {
 	struct ata_queued_cmd *qc;
@@ -332,7 +356,7 @@ err_out:
  *	Length of response buffer.
  */
 
-static unsigned int ata_scsi_rbuf_get(Scsi_Cmnd *cmd, u8 **buf_out)
+static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
 {
 	u8 *buf;
 	unsigned int buflen;
@@ -363,7 +387,7 @@ static unsigned int ata_scsi_rbuf_get(Sc
  *	spin_lock_irqsave(host_set lock)
  */
 
-static inline void ata_scsi_rbuf_put(Scsi_Cmnd *cmd)
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
 {
 	if (cmd->use_sg) {
 		struct scatterlist *sg;
@@ -394,7 +418,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_
 {
 	u8 *rbuf;
 	unsigned int buflen, rc;
-	Scsi_Cmnd *cmd = args->cmd;
+	struct scsi_cmnd *cmd = args->cmd;
 
 	buflen = ata_scsi_rbuf_get(cmd, &rbuf);
 	rc = actor(args, rbuf, buflen);
@@ -817,7 +841,7 @@ unsigned int ata_scsiop_report_luns(stru
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_scsi_badcmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *), u8 asc, u8 ascq)
+void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
 {
 	DPRINTK("ENTER\n");
 	cmd->result = SAM_STAT_CHECK_CONDITION;
@@ -847,7 +871,7 @@ void ata_scsi_badcmd(Scsi_Cmnd *cmd, voi
  */
 
 static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
-			       Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+			       struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct ata_queued_cmd *qc;
 	u8 *scsicmd = cmd->cmnd, status;
@@ -958,7 +982,7 @@ err_out:
  *	Zero.
  */
 
-int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	u8 *scsicmd = cmd->cmnd;
 	struct ata_port *ap;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/libata.h 001-linus.patch/drivers/scsi/libata.h
--- 000-virgin/drivers/scsi/libata.h	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/scsi/libata.h	Tue Dec 30 16:38:57 2003
@@ -31,8 +31,8 @@
 struct ata_scsi_args {
 	struct ata_port		*ap;
 	struct ata_device	*dev;
-	Scsi_Cmnd		*cmd;
-	void			(*done)(Scsi_Cmnd *);
+	struct scsi_cmnd		*cmd;
+	void			(*done)(struct scsi_cmnd *);
 };
 
 
@@ -51,7 +51,7 @@ extern void ata_thread_wake(struct ata_p
 /* libata-scsi.c */
 extern void ata_to_sense_error(struct ata_queued_cmd *qc);
 extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
-		      Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *),
+		      struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
 		      unsigned int cmd_size);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
@@ -74,19 +74,19 @@ extern unsigned int ata_scsiop_read_cap(
 			        unsigned int buflen);
 extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
 				   unsigned int buflen);
-extern void ata_scsi_badcmd(Scsi_Cmnd *cmd,
-			    void (*done)(Scsi_Cmnd *),
+extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
+			    void (*done)(struct scsi_cmnd *),
 			    u8 asc, u8 ascq);
 extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 
-static inline void ata_bad_scsiop(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	ata_scsi_badcmd(cmd, done, 0x20, 0x00);
 }
 
-static inline void ata_bad_cdb(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	ata_scsi_badcmd(cmd, done, 0x24, 0x00);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/sata_promise.c 001-linus.patch/drivers/scsi/sata_promise.c
--- 000-virgin/drivers/scsi/sata_promise.c	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/drivers/scsi/sata_promise.c	Tue Dec 30 16:38:57 2003
@@ -34,10 +34,8 @@
 #include <linux/libata.h>
 #include <asm/io.h>
 
-#undef DIRECT_HDMA
-
 #define DRV_NAME	"sata_promise"
-#define DRV_VERSION	"0.86"
+#define DRV_VERSION	"0.89"
 
 
 enum {
@@ -82,6 +80,42 @@ enum {
 
 	PDC_FLAG_20621		= (1 << 30), /* we have a 20621 */
 	PDC_HDMA_RESET		= (1 << 11), /* HDMA reset */
+
+	PDC_MAX_HDMA		= 32,
+	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
+
+	PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
+	PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
+	PDC_MAX_DIMM_MODULE           = 0x02,
+	PDC_I2C_CONTROL_OFFSET        = 0x48,
+	PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
+	PDC_DIMM0_CONTROL_OFFSET      = 0x80,
+	PDC_DIMM1_CONTROL_OFFSET      = 0x84,
+	PDC_SDRAM_CONTROL_OFFSET      = 0x88,
+	PDC_I2C_WRITE                 = 0x00000000,
+	PDC_I2C_READ                  = 0x00000040,	
+	PDC_I2C_START                 = 0x00000080,
+	PDC_I2C_MASK_INT              = 0x00000020,
+	PDC_I2C_COMPLETE              = 0x00010000,
+	PDC_I2C_NO_ACK                = 0x00100000,
+	PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
+	PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
+	PDC_DIMM_SPD_ROW_NUM          = 3,
+	PDC_DIMM_SPD_COLUMN_NUM       = 4,
+	PDC_DIMM_SPD_MODULE_ROW       = 5,
+	PDC_DIMM_SPD_TYPE             = 11,
+	PDC_DIMM_SPD_FRESH_RATE       = 12,         
+	PDC_DIMM_SPD_BANK_NUM         = 17,	
+	PDC_DIMM_SPD_CAS_LATENCY      = 18,
+	PDC_DIMM_SPD_ATTRIBUTE        = 21,    
+	PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
+	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,      
+	PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
+	PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
+	PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
+	PDC_CTL_STATUS		      = 0x08,	
+	PDC_DIMM_WINDOW_CTLR	      = 0x0C,
+	PDC_GENERAL_CTLR	      = 0x484,
 };
 
 
@@ -91,6 +125,19 @@ struct pdc_port_priv {
 	dma_addr_t		pkt_dma;
 };
 
+struct pdc_host_priv {
+	void			*dimm_mmio;
+
+	unsigned int		doing_hdma;
+	unsigned int		hdma_prod;
+	unsigned int		hdma_cons;
+	struct {
+		struct ata_queued_cmd *qc;
+		unsigned int	seq;
+		unsigned long	pkt_ofs;
+	} hdma[32];
+};
+
 
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
@@ -114,6 +161,18 @@ static void pdc_exec_command_mmio(struct
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static inline void pdc_dma_complete (struct ata_port *ap,
                                      struct ata_queued_cmd *qc);
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
+				      u32 device, u32 subaddr, u32 *pdata);
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, 
+				   void *psource, u32 offset, u32 size);
+#endif
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
+				 void *psource, u32 offset, u32 size);
 
 
 static Scsi_Host_Template pdc_sata_sht = {
@@ -131,6 +190,7 @@ static Scsi_Host_Template pdc_sata_sht =
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
 };
 
 static struct ata_port_operations pdc_sata_ops = {
@@ -235,10 +295,11 @@ static struct pci_driver pdc_sata_pci_dr
 
 static void pdc20621_host_stop(struct ata_host_set *host_set)
 {
-	void *mmio = host_set->private_data;
+	struct pdc_host_priv *hpriv = host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
 
-	assert(mmio != NULL);
-	iounmap(mmio);
+	iounmap(dimm_mmio);
+	kfree(hpriv);
 }
 
 static int pdc_port_start(struct ata_port *ap)
@@ -256,6 +317,7 @@ static int pdc_port_start(struct ata_por
 		rc = -ENOMEM;
 		goto err_out;
 	}
+	memset(pp, 0, sizeof(*pp));
 
 	pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
 	if (!pp->pkt) {
@@ -589,7 +651,8 @@ static void pdc20621_fill_sg(struct ata_
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
 	void *mmio = ap->host_set->mmio_base;
-	void *dimm_mmio = ap->host_set->private_data;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
 	unsigned int portno = ap->port_no;
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
@@ -605,8 +668,8 @@ static void pdc20621_fill_sg(struct ata_
 	last = qc->n_elem;
 	idx = 0;
 	for (i = 0; i < last; i++) {
-		buf[idx++] = cpu_to_le32(sg[i].dma_address);
-		buf[idx++] = cpu_to_le32(sg[i].length);
+		buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
+		buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
 		total_len += sg[i].length;
 	}
 	buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
@@ -643,49 +706,68 @@ static void pdc20621_fill_sg(struct ata_
 	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
 }
 
-#ifdef DIRECT_HDMA
-static void pdc20621_push_hdma(struct ata_queued_cmd *qc)
+static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
+				 unsigned int seq,
+				 u32 pkt_ofs)
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
-	unsigned int port_no = ap->port_no;
 	void *mmio = host_set->mmio_base;
-	unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
-	u32 tmp;
-
-	unsigned int host_sg = PDC_20621_DIMM_BASE +
-			       (PDC_DIMM_WINDOW_STEP * port_no) +
-			       PDC_DIMM_HOST_PRD;
-	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
-			       (PDC_DIMM_WINDOW_STEP * port_no) +
-			       PDC_DIMM_HPKT_PRD;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
-	tmp = readl(mmio + PDC_HDMA_CTLSTAT) & 0xffffff00;
-	tmp |= port_no + 1 + 4;		/* seq. ID */
-	if (!rw)
-		tmp |= (1 << 6);	/* hdma data direction */
-	writel(tmp, mmio + PDC_HDMA_CTLSTAT); /* note: stops DMA, if active */
-	readl(mmio + PDC_HDMA_CTLSTAT);	/* flush */
-
-	writel(host_sg, mmio + 0x108);
-	writel(dimm_sg, mmio + 0x10C);
-	writel(0, mmio + 0x128);
+	writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+	readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
 
-	tmp |= (1 << 7);
-	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
-	readl(mmio + PDC_HDMA_CTLSTAT);	/* flush */
+	writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
+	readl(mmio + PDC_HDMA_PKT_SUBMIT);	/* flush */
+}
+
+static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
+				unsigned int seq,
+				u32 pkt_ofs)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_host_priv *pp = ap->host_set->private_data;
+	unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
+
+	if (!pp->doing_hdma) {
+		__pdc20621_push_hdma(qc, seq, pkt_ofs);
+		pp->doing_hdma = 1;
+		return;
+	}
+
+	pp->hdma[idx].qc = qc;
+	pp->hdma[idx].seq = seq;
+	pp->hdma[idx].pkt_ofs = pkt_ofs;
+	pp->hdma_prod++;
+}
+
+static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_host_priv *pp = ap->host_set->private_data;
+	unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
+
+	/* if nothing on queue, we're done */
+	if (pp->hdma_prod == pp->hdma_cons) {
+		pp->doing_hdma = 0;
+		return;
+	}
+
+	__pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
+			     pp->hdma[idx].pkt_ofs);
+	pp->hdma_cons++;
 }
-#endif
 
 #ifdef ATA_VERBOSE_DEBUG
 static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int port_no = ap->port_no;
-	void *dimm_mmio = ap->host_set->private_data;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
 
 	dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
 	dimm_mmio += PDC_DIMM_HOST_PKT;
@@ -724,23 +806,17 @@ static void pdc20621_dma_start(struct at
 
 	wmb();			/* flush PRD, pkt writes */
 
-	writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
-	readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
-
 	if (doing_hdma) {
 		pdc20621_dump_hdma(qc);
-#ifdef DIRECT_HDMA
-		pdc20621_push_hdma(qc);
-#else
-		writel(port_ofs + PDC_DIMM_HOST_PKT,
-		       mmio + PDC_HDMA_PKT_SUBMIT);
-		readl(mmio + PDC_HDMA_PKT_SUBMIT);	/* flush */
-#endif
-		VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
-		port_ofs + PDC_DIMM_HOST_PKT,
-		port_ofs + PDC_DIMM_HOST_PKT,
-		seq);
+		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
+		VPRINTK("queued ofs 0x%x (%u), seq %u\n",
+			port_ofs + PDC_DIMM_HOST_PKT,
+			port_ofs + PDC_DIMM_HOST_PKT,
+			seq);
 	} else {
+		writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
+
 		writel(port_ofs + PDC_DIMM_ATA_PKT,
 		       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
@@ -771,6 +847,7 @@ static inline unsigned int pdc20621_host
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			pdc_dma_complete(ap, qc);
+			pdc20621_pop_hdma(qc);
 		}
 
 		/* step one - exec ATA command */
@@ -781,15 +858,8 @@ static inline unsigned int pdc20621_host
 
 			/* submit hdma pkt */
 			pdc20621_dump_hdma(qc);
-			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
-			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
-#ifdef DIRECT_HDMA
-			pdc20621_push_hdma(qc);
-#else
-			writel(port_ofs + PDC_DIMM_HOST_PKT,
-			       mmio + PDC_HDMA_PKT_SUBMIT);
-			readl(mmio + PDC_HDMA_PKT_SUBMIT);
-#endif
+			pdc20621_push_hdma(qc, seq,
+					   port_ofs + PDC_DIMM_HOST_PKT);
 		}
 		handled = 1;
 		break;
@@ -814,6 +884,7 @@ static inline unsigned int pdc20621_host
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			pdc_dma_complete(ap, qc);
+			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
 		break;
@@ -1098,11 +1169,373 @@ static void pdc_sata_setup_port(struct a
 	port->ctl_addr		= base + 0x38;
 }
 
+
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, 
+				   u32 offset, u32 size)
+{
+	u32 window_size;
+	u16 idx;
+	u8 page_mask;
+	long dist;
+	void *mmio = pe->mmio_base;
+	struct pdc_host_priv *hpriv = pe->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	page_mask = 0x00;	
+   	window_size = 0x2000 * 4; /* 32K byte uchar size */  
+	idx = (u16) (offset / window_size); 
+
+	writel(0x01, mmio + PDC_GENERAL_CTLR);
+	readl(mmio + PDC_GENERAL_CTLR);
+	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+	readl(mmio + PDC_DIMM_WINDOW_CTLR);
+
+	offset -= (idx * window_size);
+	idx++;
+	dist = ((long) (window_size - (offset + size))) >= 0 ? size : 
+		(long) (window_size - offset);
+	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), 
+		      dist);
+
+	psource += dist;    
+	size -= dist;
+	for (; (long) size >= (long) window_size ;) {
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+			      window_size / 4);
+		psource += window_size;
+		size -= window_size;
+		idx ++;
+	}
+
+	if (size) {
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+			      size / 4);
+	}
+}
+#endif
+
+
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, 
+				 u32 offset, u32 size)
+{
+	u32 window_size;
+	u16 idx;
+	u8 page_mask;
+	long dist;
+	void *mmio = pe->mmio_base;
+	struct pdc_host_priv *hpriv = pe->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	/* hard-code chip #0 */   
+	mmio += PDC_CHIP0_OFS;
+
+	page_mask = 0x00;	
+   	window_size = 0x2000 * 4;       /* 32K byte uchar size */  
+	idx = (u16) (offset / window_size);
+
+	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+	readl(mmio + PDC_DIMM_WINDOW_CTLR);
+	offset -= (idx * window_size); 
+	idx++;
+	dist = ((long) (window_size - (offset + size))) >= 0 ? size : 
+		(long) (window_size - offset);
+	memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+	writel(0x01, mmio + PDC_GENERAL_CTLR);
+	readl(mmio + PDC_GENERAL_CTLR);
+
+	psource += dist;    
+	size -= dist;
+	for (; (long) size >= (long) window_size ;) {
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_toio((char *) (dimm_mmio), (char *) psource, 
+			    window_size / 4);
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		psource += window_size;
+		size -= window_size;
+		idx ++;
+	}
+    
+	if (size) {
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+	}
+}
+
+
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, 
+				      u32 subaddr, u32 *pdata)
+{
+	void *mmio = pe->mmio_base;
+	u32 i2creg  = 0;
+	u32 status;     
+	u32 count =0;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	i2creg |= device << 24;
+	i2creg |= subaddr << 16;
+
+	/* Set the device and subaddress */
+	writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
+	readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+
+	/* Write Control to perform read operation, mask int */
+	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, 
+	       mmio + PDC_I2C_CONTROL_OFFSET);
+
+	for (count = 0; count <= 1000; count ++) {
+		status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+		if (status & PDC_I2C_COMPLETE) {
+			status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+			break;
+		} else if (count == 1000)
+			return 0;
+	}
+
+	*pdata = (status >> 8) & 0x000000ff;
+	return 1;           
+}
+
+
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
+{
+	u32 data=0 ;
+  	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			     PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
+   		if (data == 100)
+			return 100;
+  	} else
+		return 0;
+ 	
+   	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
+		if(data <= 0x75) 
+			return 133;
+   	} else
+		return 0;
+   	
+   	return 0;
+}
+
+
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
+{
+	u32 spd0[50];
+	u32 data = 0;
+   	int size, i;
+   	u8 bdimmsize; 
+   	void *mmio = pe->mmio_base;
+	static const struct {
+		unsigned int reg;
+		unsigned int ofs;
+	} pdc_i2c_read_data [] = {
+		{ PDC_DIMM_SPD_TYPE, 11 },		
+		{ PDC_DIMM_SPD_FRESH_RATE, 12 },
+		{ PDC_DIMM_SPD_COLUMN_NUM, 4 }, 
+		{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
+		{ PDC_DIMM_SPD_ROW_NUM, 3 },
+		{ PDC_DIMM_SPD_BANK_NUM, 17 },
+		{ PDC_DIMM_SPD_MODULE_ROW, 5 },
+		{ PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
+		{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
+		{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
+		{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
+		{ PDC_DIMM_SPD_CAS_LATENCY, 18 },       
+	};
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
+		pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+				  pdc_i2c_read_data[i].reg, 
+				  &spd0[pdc_i2c_read_data[i].ofs]);
+  
+   	data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
+   	data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | 
+		((((spd0[27] + 9) / 10) - 1) << 8) ;
+   	data |= (((((spd0[29] > spd0[28]) 
+		    ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; 
+   	data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
+   
+   	if (spd0[18] & 0x08) 
+		data |= ((0x03) << 14);
+   	else if (spd0[18] & 0x04)
+		data |= ((0x02) << 14);
+   	else if (spd0[18] & 0x01)
+		data |= ((0x01) << 14);
+   	else
+		data |= (0 << 14);
+
+  	/* 
+	   Calculate the size of bDIMMSize (power of 2) and
+	   merge the DIMM size by program start/end address.
+	*/
+
+   	bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
+   	size = (1 << bdimmsize) >> 20;	/* size = xxx(MB) */
+   	data |= (((size / 16) - 1) << 16);
+   	data |= (0 << 23);
+	data |= 8;
+   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); 
+	readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+   	return size;                          
+}
+
+
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
+{
+	u32 data, spd0;
+   	int error, i;
+   	void *mmio = pe->mmio_base;
+
+	/* hard-code chip #0 */
+   	mmio += PDC_CHIP0_OFS;
+
+   	/*
+	  Set To Default : DIMM Module Global Control Register (0x022259F1)
+	  DIMM Arbitration Disable (bit 20)
+	  DIMM Data/Control Output Driving Selection (bit12 - bit15)
+	  Refresh Enable (bit 17)
+	*/
+
+	data = 0x022259F1;   
+	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+	readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+	/* Turn on for ECC */
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			  PDC_DIMM_SPD_TYPE, &spd0);
+	if (spd0 == 0x02) {
+		data |= (0x01 << 16);
+		writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+		readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		printk(KERN_ERR "Local DIMM ECC Enabled\n");
+   	}
+
+   	/* DIMM Initialization Select/Enable (bit 18/19) */
+   	data &= (~(1<<18));
+   	data |= (1<<19);
+   	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+   	error = 1;                     
+   	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
+		data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		if (!(data & (1<<19))) {
+	   		error = 0;
+	   		break;     
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout((i * 100) * HZ / 1000);
+   	}
+   	return error;
+}
+	
+
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
+{
+	int speed, size, length; 
+	u32 addr,spd0,pci_status;
+	u32 tmp=0;
+   	void *mmio = pe->mmio_base;
+
+	/* hard-code chip #0 */
+   	mmio += PDC_CHIP0_OFS;
+
+	/* Initialize PLL. */
+	pci_status = 0x8a531824;
+	writel(pci_status, mmio + PDC_CTL_STATUS);
+	readl(mmio + PDC_CTL_STATUS);
+
+	/* 
+	   Read SPD of DIMM by I2C interface,
+	   and program the DIMM Module Controller.
+	*/
+ 	if (!(speed = pdc20621_detect_dimm(pe))) {
+		printk(KERN_ERR "Detect Local DIMM Fail\n");  
+		return 1;	/* DIMM error */
+   	}
+   	VPRINTK("Local DIMM Speed = %d\n", speed);
+
+   	/* Programming DIMM0 Module Control Register (index_CID0:80h) */ 
+   	size = pdc20621_prog_dimm0(pe);
+   	VPRINTK("Local DIMM Size = %dMB\n",size);
+
+   	/* Programming DIMM Module Global Control Register (index_CID0:88h) */ 
+   	if (pdc20621_prog_dimm_global(pe)) {
+		printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
+		return 1;
+   	}
+
+#ifdef ATA_VERBOSE_DEBUG
+	{
+		u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
+  				'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
+ 				 '1','.','1','0',
+  				'9','8','0','3','1','6','1','2',0,0};
+		u8 test_parttern2[40] = {0};
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
+		pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, 
+				       40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+	}
+#endif
+
+	/* ECC initiliazation. */
+
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			  PDC_DIMM_SPD_TYPE, &spd0);
+	if (spd0 == 0x02) {
+		VPRINTK("Start ECC initialization\n");
+		addr = 0;
+		length = size * 1024 * 1024;
+		while (addr < length) {
+			pdc20621_put_to_dimm(pe, (void *) &tmp, addr, 
+					     sizeof(u32));
+			addr += sizeof(u32);
+		}
+		VPRINTK("Finish ECC initialization\n");
+	}
+	return 0;
+}
+
+
 static void pdc_20621_init(struct ata_probe_ent *pe)
 {
 	u32 tmp;
 	void *mmio = pe->mmio_base;
 
+	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
 	/*
@@ -1170,6 +1603,7 @@ static int pdc_sata_init_one (struct pci
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
 	void *mmio_base, *dimm_mmio = NULL;
+	struct pdc_host_priv *hpriv = NULL;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	unsigned int have_20621 = (board_idx == board_20621);
 	int rc;
@@ -1212,12 +1646,22 @@ static int pdc_sata_init_one (struct pci
 	base = (unsigned long) mmio_base;
 
 	if (have_20621) {
+		hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+		if (!hpriv) {
+			rc = -ENOMEM;
+			goto err_out_iounmap;
+		}
+		memset(hpriv, 0, sizeof(*hpriv));
+
 		dimm_mmio = ioremap(pci_resource_start(pdev, 4),
 				    pci_resource_len(pdev, 4));
 		if (!dimm_mmio) {
+			kfree(hpriv);
 			rc = -ENOMEM;
 			goto err_out_iounmap;
 		}
+
+		hpriv->dimm_mmio = dimm_mmio;
 	}
 
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
@@ -1231,7 +1675,7 @@ static int pdc_sata_init_one (struct pci
 	probe_ent->mmio_base = mmio_base;
 
 	if (have_20621) {
-		probe_ent->private_data = dimm_mmio;
+		probe_ent->private_data = hpriv;
 		base += PDC_CHIP0_OFS;
 	}
 
@@ -1268,9 +1712,14 @@ static int pdc_sata_init_one (struct pci
 	pci_set_master(pdev);
 
 	/* initialize adapter */
-	if (have_20621)
+	if (have_20621) {
+		/* initialize local dimm */
+		if (pdc20621_dimm_init(probe_ent)) {
+			rc = -ENOMEM;
+			goto err_out_iounmap_dimm;
+		}
 		pdc_20621_init(probe_ent);
-	else
+	} else
 		pdc_host_init(board_idx, probe_ent);
 
 	/* FIXME: check ata_device_add return value */
@@ -1279,6 +1728,9 @@ static int pdc_sata_init_one (struct pci
 
 	return 0;
 
+err_out_iounmap_dimm:		/* only get to this label if 20621 */
+	kfree(hpriv);
+	iounmap(dimm_mmio);
 err_out_iounmap:
 	iounmap(mmio_base);
 err_out_free_ent:
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/sata_sil.c 001-linus.patch/drivers/scsi/sata_sil.c
--- 000-virgin/drivers/scsi/sata_sil.c	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/drivers/scsi/sata_sil.c	Tue Dec 30 16:38:57 2003
@@ -87,6 +87,7 @@ static Scsi_Host_Template sil_sht = {
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
 };
 
 static struct ata_port_operations sil_ops = {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/sata_svw.c 001-linus.patch/drivers/scsi/sata_svw.c
--- 000-virgin/drivers/scsi/sata_svw.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/scsi/sata_svw.c	Tue Dec 30 16:38:57 2003
@@ -219,6 +219,7 @@ static Scsi_Host_Template k2_sata_sht = 
 #ifdef CONFIG_ALL_PPC
 	.proc_info		= k2_sata_proc_info
 #endif
+	.bios_param		= ata_std_bios_param,
 };
 
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/sata_via.c 001-linus.patch/drivers/scsi/sata_via.c
--- 000-virgin/drivers/scsi/sata_via.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/drivers/scsi/sata_via.c	Tue Dec 30 16:38:57 2003
@@ -78,6 +78,7 @@ static Scsi_Host_Template svia_sht = {
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
 };
 
 static struct ata_port_operations svia_sata_ops = {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/scsi/sg.c 001-linus.patch/drivers/scsi/sg.c
--- 000-virgin/drivers/scsi/sg.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/scsi/sg.c	Tue Dec 30 16:38:57 2003
@@ -1118,7 +1118,7 @@ sg_rb_correct4mmap(Sg_scatter_hold * rsv
 }
 
 static struct page *
-sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int unused)
+sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
 {
 	Sg_fd *sfp;
 	struct page *page = NOPAGE_SIGBUS;
@@ -1158,6 +1158,8 @@ sg_vma_nopage(struct vm_area_struct *vma
 		page = virt_to_page(page_ptr);
 		get_page(page);	/* increment page count */
 	}
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
@@ -2974,3 +2976,4 @@ sg_proc_version_info(char *buffer, int *
 
 module_init(init_sg);
 module_exit(exit_sg);
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/serial/8250.c 001-linus.patch/drivers/serial/8250.c
--- 000-virgin/drivers/serial/8250.c	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/drivers/serial/8250.c	Tue Dec 30 16:38:57 2003
@@ -530,10 +530,10 @@ static void autoconfig_16550a(struct uar
 			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
 			serial_outp(up, 0x04, status1);
 			serial_outp(up, UART_LCR, 0);
+			up->port.uartclk = 921600*16;
 #endif
 
 			up->port.type = PORT_NS16550A;
-			up->port.uartclk = 921600*16;
 			return;
 		}
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/serial/sa1100.c 001-linus.patch/drivers/serial/sa1100.c
--- 000-virgin/drivers/serial/sa1100.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/drivers/serial/sa1100.c	Tue Dec 30 16:38:57 2003
@@ -852,6 +852,7 @@ static struct uart_driver sa1100_reg = {
 	.owner			= THIS_MODULE,
 	.driver_name		= "ttySA",
 	.dev_name		= "ttySA",
+	.devfs_name		= "ttySA",
 	.major			= SERIAL_SA1100_MAJOR,
 	.minor			= MINOR_START,
 	.nr			= NR_PORTS,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/serial/serial_core.c 001-linus.patch/drivers/serial/serial_core.c
--- 000-virgin/drivers/serial/serial_core.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/drivers/serial/serial_core.c	Tue Dec 30 16:38:57 2003
@@ -1862,6 +1862,9 @@ uart_set_options(struct uart_port *port,
 	if (flow == 'r')
 		termios.c_cflag |= CRTSCTS;
 
+	if (!port->ops)
+		return 0;	/* "console=" on ia64 */
+
 	port->ops->set_termios(port, &termios, NULL);
 	co->cflag = termios.c_cflag;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/serial/sunsu.c 001-linus.patch/drivers/serial/sunsu.c
--- 000-virgin/drivers/serial/sunsu.c	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/serial/sunsu.c	Tue Dec 30 16:38:57 2003
@@ -97,9 +97,6 @@ struct uart_sunsu_port {
 	int			port_node;
 	unsigned int		irq;
 
-	/* L1-A keyboard break state.  */
-	int			kbd_id;
-	int			l1_down;
 #ifdef CONFIG_SERIO
 	struct serio		serio;
 	int			serio_open;
@@ -508,25 +505,8 @@ static void receive_kbd_ms_chars(struct 
 	do {
 		unsigned char ch = serial_inp(up, UART_RX);
 
+		/* Stop-A is handled by drivers/char/keyboard.c now. */
 		if (up->su_type == SU_PORT_KBD) {
-			if (ch == SUNKBD_RESET) {
-				up->kbd_id = 1;
-				up->l1_down = 0;
-			} else if (up->kbd_id) {
-				up->kbd_id = 0;
-			} else if (ch == SUNKBD_L1) {
-				up->l1_down = 1;
-			} else if (ch == (SUNKBD_L1|SUNKBD_UP)) {
-				up->l1_down = 0;
-			} else if (ch == SUNKBD_A && up->l1_down) {
-				/* whee... */
-				sun_do_break();
-
-				/* Continue execution... */
-				up->l1_down = 0;
-				up->kbd_id = 0;
-				return;
-			}
 #ifdef CONFIG_SERIO
 			serio_interrupt(&up->serio, ch, 0, regs);
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/serial/sunzilog.c 001-linus.patch/drivers/serial/sunzilog.c
--- 000-virgin/drivers/serial/sunzilog.c	Wed Dec 17 18:59:55 2003
+++ 001-linus.patch/drivers/serial/sunzilog.c	Tue Dec 30 16:38:57 2003
@@ -103,10 +103,6 @@ struct uart_sunzilog_port {
 
 	unsigned int cflag;
 
-	/* L1-A keyboard break state.  */
-	int				kbd_id;
-	int				l1_down;
-
 	unsigned char			parity_mask;
 	unsigned char			prev_status;
 
@@ -292,23 +288,10 @@ static void sunzilog_kbdms_receive_chars
 					 struct pt_regs *regs)
 {
 	if (ZS_IS_KEYB(up)) {
-		if (ch == SUNKBD_RESET) {
-			up->kbd_id = 1;
-			up->l1_down = 0;
-		} else if (up->kbd_id) {
-			up->kbd_id = 0;
-		} else if (ch == SUNKBD_L1) {
-			up->l1_down = 1;
-		} else if (ch == (SUNKBD_L1 | SUNKBD_UP)) {
-			up->l1_down = 0;
-		} else if (ch == SUNKBD_A && up->l1_down) {
-			sun_do_break();
-			up->l1_down = 0;
-			up->kbd_id = 0;
-			return;
-		}
+		/* Stop-A is handled by drivers/char/keyboard.c now. */
 #ifdef CONFIG_SERIO
-		serio_interrupt(&up->serio, ch, 0, regs);
+		if (up->serio_open)
+			serio_interrupt(&up->serio, ch, 0, regs);
 #endif
 	} else if (ZS_IS_MOUSE(up)) {
 		int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -322,7 +305,8 @@ static void sunzilog_kbdms_receive_chars
 
 		case 0:
 #ifdef CONFIG_SERIO
-			serio_interrupt(&up->serio, ch, 0, regs);
+			if (up->serio_open)
+				serio_interrupt(&up->serio, ch, 0, regs);
 #endif
 			break;
 		};
@@ -333,16 +317,15 @@ static void sunzilog_receive_chars(struc
 				   struct zilog_channel *channel,
 				   struct pt_regs *regs)
 {
-	struct tty_struct *tty = up->port.info->tty;	/* XXX info==NULL? */
+	struct tty_struct *tty;
+	unsigned char ch, r1;
 
-	while (1) {
-		unsigned char ch, r1;
+	tty = NULL;
+	if (up->port.info != NULL &&		/* Unopened serial console */
+	    up->port.info->tty != NULL)		/* Keyboard || mouse */
+		tty = up->port.info->tty;
 
-		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-			tty->flip.work.func((void *)tty);
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				return;		/* XXX Ignores SysRq when we need it most. Fix. */
-		}
+	for (;;) {
 
 		r1 = read_zsreg(channel, R1);
 		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -360,6 +343,9 @@ static void sunzilog_receive_chars(struc
 		if (ch & BRK_ABRT)
 			r1 |= BRK_ABRT;
 
+		if (!(ch & Rx_CH_AV))
+			break;
+
 		ch = sbus_readb(&channel->data);
 		ZSDELAY();
 
@@ -367,21 +353,22 @@ static void sunzilog_receive_chars(struc
 
 		if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) {
 			sunzilog_kbdms_receive_chars(up, ch, 0, regs);
-			goto next_char;
+			continue;
 		}
 
-		if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) {
-			/* Wait for BREAK to deassert to avoid potentially
-			 * confusing the PROM.
+		if (tty == NULL) {
+			uart_handle_sysrq_char(&up->port, ch, regs);
+			continue;
+		}
+
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			tty->flip.work.func((void *)tty);
+			/*
+			 * The 8250 bails out of the loop here,
+			 * but we need to read everything, or die.
 			 */
-			while (1) {
-				ch = sbus_readb(&channel->control);
-				ZSDELAY();
-				if (!(ch & BRK_ABRT))
-					break;
-			}
-			sun_do_break();
-			return;
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				continue;
 		}
 
 		/* A real serial line, record the character and status.  */
@@ -393,7 +380,7 @@ static void sunzilog_receive_chars(struc
 				r1 &= ~(PAR_ERR | CRC_ERR);
 				up->port.icount.brk++;
 				if (uart_handle_break(&up->port))
-					goto next_char;
+					continue;
 			}
 			else if (r1 & PAR_ERR)
 				up->port.icount.parity++;
@@ -410,7 +397,7 @@ static void sunzilog_receive_chars(struc
 				*tty->flip.flag_buf_ptr = TTY_FRAME;
 		}
 		if (uart_handle_sysrq_char(&up->port, ch, regs))
-			goto next_char;
+			continue;
 
 		if (up->port.ignore_status_mask == 0xff ||
 		    (r1 & up->port.ignore_status_mask) == 0) {
@@ -425,14 +412,10 @@ static void sunzilog_receive_chars(struc
 			tty->flip.char_buf_ptr++;
 			tty->flip.count++;
 		}
-	next_char:
-		ch = sbus_readb(&channel->control);
-		ZSDELAY();
-		if (!(ch & Rx_CH_AV))
-			break;
 	}
 
-	tty_flip_buffer_push(tty);
+	if (tty)
+		tty_flip_buffer_push(tty);
 }
 
 static void sunzilog_status_handle(struct uart_sunzilog_port *up,
@@ -448,8 +431,23 @@ static void sunzilog_status_handle(struc
 	ZSDELAY();
 	ZS_WSYNC(channel);
 
-	if ((status & BRK_ABRT) && ZS_IS_MOUSE(up))
-		sunzilog_kbdms_receive_chars(up, 0, 1, regs);
+	if (status & BRK_ABRT) {
+		if (ZS_IS_MOUSE(up))
+			sunzilog_kbdms_receive_chars(up, 0, 1, regs);
+		if (ZS_IS_CONS(up)) {
+			/* Wait for BREAK to deassert to avoid potentially
+			 * confusing the PROM.
+			 */
+			while (1) {
+				status = sbus_readb(&channel->control);
+				ZSDELAY();
+				if (!(status & BRK_ABRT))
+					break;
+			}
+			sun_do_break();
+			return;
+		}
+	}
 
 	if (ZS_WANTS_MODEM_STATUS(up)) {
 		if (status & SYNC)
@@ -1364,8 +1362,8 @@ static int __init sunzilog_console_setup
 	unsigned long flags;
 	int baud, brg;
 
-	printk("Console: ttyS%d (SunZilog)\n",
-	       (sunzilog_reg.minor - 64) + con->index);
+	printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
+	       (sunzilog_reg.minor - 64) + con->index, con->index);
 
 	/* Get firmware console settings.  */
 	sunserial_console_termios(con);
@@ -1596,6 +1594,8 @@ static void __init sunzilog_init_hw(void
 
 		if (i == KEYBOARD_LINE || i == MOUSE_LINE) {
 			sunzilog_init_kbdms(up, i);
+			up->curregs[R9] |= (NV | MIE);
+			write_zsreg(channel, R9, up->curregs[R9]);
 		} else {
 			/* Normal serial TTY. */
 			up->parity_mask = 0xff;
@@ -1632,7 +1632,7 @@ static int __init sunzilog_ports_init(vo
 	struct zs_probe_scan scan;
 	int ret;
 
-	printk(KERN_INFO "Serial: Sun Zilog driver (%d chips).\n", NUM_SUNZILOG);
+	printk(KERN_DEBUG "SunZilog: %d chips.\n", NUM_SUNZILOG);
 
 	scan.scanner = sunzilog_scan_probe;
 	scan.depth = 0;
@@ -1668,7 +1668,10 @@ static int __init sunzilog_ports_init(vo
 			if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
 				continue;
 
-			uart_add_one_port(&sunzilog_reg, &up->port);
+			if (uart_add_one_port(&sunzilog_reg, &up->port)) {
+				printk(KERN_ERR
+				    "SunZilog: failed to add port zs%d\n", i);
+			}
 		}
 	}
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/Makefile 001-linus.patch/drivers/usb/Makefile
--- 000-virgin/drivers/usb/Makefile	Wed Dec 17 18:59:41 2003
+++ 001-linus.patch/drivers/usb/Makefile	Tue Dec 30 16:38:57 2003
@@ -34,6 +34,7 @@ obj-$(CONFIG_USB_PWC)		+= media/
 obj-$(CONFIG_USB_SE401)		+= media/
 obj-$(CONFIG_USB_STV680)	+= media/
 obj-$(CONFIG_USB_VICAM)		+= media/
+obj-$(CONFIG_USB_W9968CF)	+= media/
 
 obj-$(CONFIG_USB_CATC)		+= net/
 obj-$(CONFIG_USB_KAWETH)	+= net/
@@ -58,4 +59,3 @@ obj-$(CONFIG_USB_SPEEDTOUCH)	+= misc/
 obj-$(CONFIG_USB_TEST)		+= misc/
 obj-$(CONFIG_USB_TIGL)		+= misc/
 obj-$(CONFIG_USB_USS720)	+= misc/
-
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/class/audio.h 001-linus.patch/drivers/usb/class/audio.h
--- 000-virgin/drivers/usb/class/audio.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/usb/class/audio.h	Tue Dec 30 16:38:57 2003
@@ -1,9 +1,3 @@
-#define USB_DT_CS_DEVICE                0x21
-#define USB_DT_CS_CONFIG                0x22
-#define USB_DT_CS_STRING                0x23
-#define USB_DT_CS_INTERFACE             0x24
-#define USB_DT_CS_ENDPOINT              0x25
-
 #define CS_AUDIO_UNDEFINED		0x20
 #define CS_AUDIO_DEVICE			0x21
 #define CS_AUDIO_CONFIGURATION		0x22
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/class/cdc-acm.c 001-linus.patch/drivers/usb/class/cdc-acm.c
--- 000-virgin/drivers/usb/class/cdc-acm.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/usb/class/cdc-acm.c	Tue Dec 30 16:38:57 2003
@@ -1,5 +1,5 @@
 /*
- * acm.c  Version 0.22
+ * cdc-acm.c
  *
  * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
@@ -26,6 +26,7 @@
  *	v0.21 - revert to probing on device for devices with multiple configs
  *	v0.22 - probe only the control interface. if usbcore doesn't choose the
  *		config we want, sysadmin changes bConfigurationValue in sysfs.
+ *	v0.23 - use softirq for rx processing, as needed by tty layer
  */
 
 /*
@@ -44,6 +45,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -54,14 +57,13 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
-#undef DEBUG
 #include <linux/usb.h>
 #include <asm/byteorder.h>
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.21"
+#define DRIVER_VERSION "v0.23"
 #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
@@ -146,7 +148,8 @@ struct acm {
 	struct tty_struct *tty;				/* the corresponding tty */
 	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
 	struct acm_line line;				/* line coding (bits, stop, parity) */
-	struct work_struct work;					/* work queue entry for line discipline waking up */
+	struct work_struct work;			/* work queue entry for line discipline waking up */
+	struct tasklet_struct bh;			/* rx processing */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
 	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
 	unsigned int writesize;				/* max packet size for the output bulk endpoint */
@@ -184,9 +187,10 @@ static int acm_ctrl_msg(struct acm *acm,
 #define acm_send_break(acm, ms)		acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
 
 /*
- * Interrupt handler for various ACM control events
+ * Interrupt handlers for various ACM device responses
  */
 
+/* control interface reports status changes with "interrupt" transfers */
 static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct acm *acm = urb->context;
@@ -251,20 +255,30 @@ exit:
 		     __FUNCTION__, status);
 }
 
+/* data interface returns incoming bytes, or we got unthrottled */
 static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
 {
 	struct acm *acm = urb->context;
-	struct tty_struct *tty = acm->tty;
-	unsigned char *data = urb->transfer_buffer;
-	int i = 0;
 
 	if (!ACM_READY(acm))
 		return;
 
 	if (urb->status)
-		dbg("nonzero read bulk status received: %d", urb->status);
+		dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
+
+	/* calling tty_flip_buffer_push() in_irq() isn't allowed */
+	tasklet_schedule(&acm->bh);
+}
+
+static void acm_rx_tasklet(unsigned long _acm)
+{
+	struct acm *acm = (void *)_acm;
+	struct urb *urb = acm->readurb;
+	struct tty_struct *tty = acm->tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i = 0;
 
-	if (!urb->status && !acm->throttle)  {
+	if (urb->actual_length > 0 && !acm->throttle)  {
 		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters,
 			 * we drop them. */
@@ -285,10 +299,12 @@ static void acm_read_bulk(struct urb *ur
 	urb->actual_length = 0;
 	urb->dev = acm->dev;
 
-	if (usb_submit_urb(urb, GFP_ATOMIC))
-		dbg("failed resubmitting read urb");
+	i = usb_submit_urb(urb, GFP_ATOMIC);
+	if (i)
+		dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
 }
 
+/* data interface wrote those outgoing bytes */
 static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
 {
 	struct acm *acm = (struct acm *)urb->context;
@@ -621,6 +637,8 @@ static int acm_probe (struct usb_interfa
 			acm->minor = minor;
 			acm->dev = dev;
 
+			acm->bh.func = acm_rx_tasklet;
+			acm->bh.data = (unsigned long) acm;
 			INIT_WORK(&acm->work, acm_softint, acm);
 
 			if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/class/usb-midi.h 001-linus.patch/drivers/usb/class/usb-midi.h
--- 000-virgin/drivers/usb/class/usb-midi.h	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/usb/class/usb-midi.h	Tue Dec 30 16:38:57 2003
@@ -28,12 +28,6 @@
 #define USB_SUBCLASS_MIDISTREAMING	3
 #endif
 
-#define USB_DT_CS_DEVICE		0x21
-#define USB_DT_CS_CONFIG		0x22
-#define USB_DT_CS_STRING		0x23
-#define USB_DT_CS_INTERFACE		0x24
-#define USB_DT_CS_ENDPOINT		0x25
-
 /* ------------------------------------------------------------------------- */
 /* Roland MIDI Devices */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/class/usblp.c 001-linus.patch/drivers/usb/class/usblp.c
--- 000-virgin/drivers/usb/class/usblp.c	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/drivers/usb/class/usblp.c	Tue Dec 30 16:38:57 2003
@@ -610,7 +610,7 @@ static ssize_t usblp_write(struct file *
 		if (!usblp->wcomplete) {
 			barrier();
 			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
+				return writecount ? writecount : -EAGAIN;
 
 			timeout = USBLP_WRITE_TIMEOUT;
 			add_wait_queue(&usblp->wait, &wait);
@@ -673,8 +673,12 @@ static ssize_t usblp_write(struct file *
 
 		usblp->writeurb->dev = usblp->dev;
 		usblp->wcomplete = 0;
-		if (usb_submit_urb(usblp->writeurb, GFP_KERNEL)) {
-			count = -EIO;
+		err = usb_submit_urb(usblp->writeurb, GFP_KERNEL);
+		if (err) {
+			if (err != -ENOMEM)
+				count = -EIO;
+			else
+				count = writecount ? writecount : -ENOMEM;
 			up (&usblp->sem);
 			break;
 		}
@@ -706,8 +710,6 @@ static ssize_t usblp_read(struct file *f
 			goto done;
 		}
 
-		// FIXME:  only use urb->status inside completion
-		// callbacks; this way is racey...
 		add_wait_queue(&usblp->wait, &wait);
 		while (1==1) {
 			if (signal_pending(current)) {
@@ -1093,7 +1095,7 @@ static int usblp_cache_device_id_string(
 	/* First two bytes are length in big-endian.
 	 * They count themselves, and we copy them into
 	 * the user's buffer. */
-	length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
+	length = be16_to_cpu(*((u16 *)usblp->device_id_string));
 	if (length < 2)
 		length = 2;
 	else if (length >= USBLP_DEVICE_ID_SIZE)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/core/hcd.c 001-linus.patch/drivers/usb/core/hcd.c
--- 000-virgin/drivers/usb/core/hcd.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/usb/core/hcd.c	Tue Dec 30 16:38:57 2003
@@ -1165,6 +1165,7 @@ static int hcd_unlink_urb (struct urb *u
 	struct device			*sys = 0;
 	unsigned long			flags;
 	struct completion_splice	splice;
+	struct list_head		*tmp;
 	int				retval;
 
 	if (!urb)
@@ -1203,7 +1204,12 @@ static int hcd_unlink_urb (struct urb *u
 	 */
 	WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
 
-	if (!urb->hcpriv) {
+	/* insist the urb is still queued */
+	list_for_each(tmp, &dev->urb_list) {
+		if (tmp == &urb->urb_list)
+			break;
+	}
+	if (tmp != &urb->urb_list) {
 		retval = -EINVAL;
 		goto done;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/core/hub.c 001-linus.patch/drivers/usb/core/hub.c
--- 000-virgin/drivers/usb/core/hub.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/usb/core/hub.c	Tue Dec 30 16:38:57 2003
@@ -126,14 +126,20 @@ static int get_port_status(struct usb_de
 static void hub_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_hub *hub = (struct usb_hub *)urb->context;
-	unsigned long flags;
 	int status;
 
+	spin_lock(&hub_event_lock);
+	hub->urb_active = 0;
+	if (hub->urb_complete) {	/* disconnect or rmmod */
+		complete(hub->urb_complete);
+		goto done;
+	}
+
 	switch (urb->status) {
 	case -ENOENT:		/* synchronous unlink */
 	case -ECONNRESET:	/* async unlink */
 	case -ESHUTDOWN:	/* hardware going away */
-		return;
+		goto done;
 
 	default:		/* presumably an error */
 		/* Cause a hub reset after 10 consecutive errors */
@@ -151,18 +157,20 @@ static void hub_irq(struct urb *urb, str
 	hub->nerrors = 0;
 
 	/* Something happened, let khubd figure it out */
-	spin_lock_irqsave(&hub_event_lock, flags);
 	if (list_empty(&hub->event_list)) {
 		list_add(&hub->event_list, &hub_event_list);
 		wake_up(&khubd_wait);
 	}
-	spin_unlock_irqrestore(&hub_event_lock, flags);
 
 resubmit:
 	if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
 			/* ENODEV means we raced disconnect() */
 			&& status != -ENODEV)
 		dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status);
+	if (status == 0)
+		hub->urb_active = 1;
+done:
+	spin_unlock(&hub_event_lock);
 }
 
 /* USB 2.0 spec Section 11.24.2.3 */
@@ -467,7 +475,8 @@ static int hub_configure(struct usb_hub 
 		message = "couldn't submit status urb";
 		goto fail;
 	}
-		
+	hub->urb_active = 1;
+
 	/* Wake up khubd */
 	wake_up(&khubd_wait);
 
@@ -485,6 +494,7 @@ fail:
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
+	DECLARE_COMPLETION(urb_complete);
 	unsigned long flags;
 
 	if (!hub)
@@ -492,12 +502,11 @@ static void hub_disconnect(struct usb_in
 
 	usb_set_intfdata (intf, NULL);
 	spin_lock_irqsave(&hub_event_lock, flags);
+	hub->urb_complete = &urb_complete;
 
 	/* Delete it and then reset it */
-	list_del(&hub->event_list);
-	INIT_LIST_HEAD(&hub->event_list);
-	list_del(&hub->hub_list);
-	INIT_LIST_HEAD(&hub->hub_list);
+	list_del_init(&hub->event_list);
+	list_del_init(&hub->hub_list);
 
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
@@ -510,6 +519,8 @@ static void hub_disconnect(struct usb_in
 
 	if (hub->urb) {
 		usb_unlink_urb(hub->urb);
+		if (hub->urb_active)
+			wait_for_completion(&urb_complete);
 		usb_free_urb(hub->urb);
 		hub->urb = NULL;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/core/hub.h 001-linus.patch/drivers/usb/core/hub.h
--- 000-virgin/drivers/usb/core/hub.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/drivers/usb/core/hub.h	Tue Dec 30 16:38:57 2003
@@ -172,6 +172,8 @@ extern void usb_hub_tt_clear_buffer (str
 struct usb_hub {
 	struct usb_interface	*intf;		/* the "real" device */
 	struct urb		*urb;		/* for interrupt polling pipe */
+	struct completion	*urb_complete;	/* wait for urb to end */
+	unsigned int		urb_active:1;
 
 	/* buffer for urb ... 1 bit each for hub and children, rounded up */
 	char			(*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/core/message.c 001-linus.patch/drivers/usb/core/message.c
--- 000-virgin/drivers/usb/core/message.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/drivers/usb/core/message.c	Tue Dec 30 16:38:57 2003
@@ -1086,6 +1086,11 @@ int usb_set_configuration(struct usb_dev
 		ret = -EINVAL;
 		goto out;
 	}
+
+	/* The USB spec says configuration 0 means unconfigured.
+	 * But if a device includes a configuration numbered 0,
+	 * we will accept it as a correctly configured state.
+	 */
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
 
@@ -1101,7 +1106,7 @@ int usb_set_configuration(struct usb_dev
 		goto out;
 
 	dev->actconfig = cp;
-	if (!configuration)
+	if (!cp)
 		dev->state = USB_STATE_ADDRESS;
 	else {
 		dev->state = USB_STATE_CONFIGURED;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/core/usb.c 001-linus.patch/drivers/usb/core/usb.c
--- 000-virgin/drivers/usb/core/usb.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/usb/core/usb.c	Tue Dec 30 16:38:57 2003
@@ -80,7 +80,7 @@ static struct device_driver usb_generic_
 
 static int usb_generic_driver_data;
 
-/* needs to be called with BKL held */
+/* called from driver core with usb_bus_type.subsys writelock */
 int usb_probe_interface(struct device *dev)
 {
 	struct usb_interface * intf = to_usb_interface(dev);
@@ -93,12 +93,14 @@ int usb_probe_interface(struct device *d
 	if (!driver->probe)
 		return error;
 
+	/* driver claim() doesn't yet affect dev->driver... */
+	if (intf->driver)
+		return error;
+
 	id = usb_match_id (intf, driver->id_table);
 	if (id) {
 		dev_dbg (dev, "%s - got id\n", __FUNCTION__);
-		down (&driver->serialize);
 		error = driver->probe (intf, id);
-		up (&driver->serialize);
 	}
 	if (!error)
 		intf->driver = driver;
@@ -106,23 +108,24 @@ int usb_probe_interface(struct device *d
 	return error;
 }
 
+/* called from driver core with usb_bus_type.subsys writelock */
 int usb_unbind_interface(struct device *dev)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
-	struct usb_driver *driver = to_usb_driver(dev->driver);
-
-	down(&driver->serialize);
+	struct usb_driver *driver = intf->driver;
 
 	/* release all urbs for this interface */
 	usb_disable_interface(interface_to_usbdev(intf), intf);
 
-	if (intf->driver && intf->driver->disconnect)
-		intf->driver->disconnect(intf);
-
-	/* force a release and re-initialize the interface */
-	usb_driver_release_interface(driver, intf);
+	if (driver && driver->disconnect)
+		driver->disconnect(intf);
 
-	up(&driver->serialize);
+	/* reset other interface state */
+	usb_set_interface(interface_to_usbdev(intf),
+			intf->altsetting[0].desc.bInterfaceNumber,
+			0);
+	usb_set_intfdata(intf, NULL);
+	intf->driver = NULL;
 
 	return 0;
 }
@@ -152,8 +155,6 @@ int usb_register(struct usb_driver *new_
 	new_driver->driver.probe = usb_probe_interface;
 	new_driver->driver.remove = usb_unbind_interface;
 
-	init_MUTEX(&new_driver->serialize);
-
 	retval = driver_register(&new_driver->driver);
 
 	if (!retval) {
@@ -170,7 +171,7 @@ int usb_register(struct usb_driver *new_
 /**
  * usb_deregister - unregister a USB driver
  * @driver: USB operations of the driver to unregister
- * Context: !in_interrupt (), must be called with BKL held
+ * Context: must be able to sleep
  *
  * Unlinks the specified driver from the internal USB driver list.
  * 
@@ -264,26 +265,22 @@ usb_epnum_to_ep_desc(struct usb_device *
  * Few drivers should need to use this routine, since the most natural
  * way to bind to an interface is to return the private data from
  * the driver's probe() method.
+ *
+ * Callers must own the driver model's usb bus writelock.  So driver
+ * probe() entries don't need extra locking, but other call contexts
+ * may need to explicitly claim that lock.
  */
 int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
 {
 	if (!iface || !driver)
 		return -EINVAL;
 
-	/* this is mainly to lock against usbfs */
-	lock_kernel();
-	if (iface->driver) {
-		unlock_kernel();
-		err ("%s driver booted %s off interface %p",
-			driver->name, iface->driver->name, iface);
+	if (iface->driver)
 		return -EBUSY;
-	} else {
-	    dbg("%s driver claimed interface %p", driver->name, iface);
-	}
 
+	/* FIXME should device_bind_driver() */
 	iface->driver = driver;
 	usb_set_intfdata(iface, priv);
-	unlock_kernel();
 	return 0;
 }
 
@@ -323,13 +320,22 @@ int usb_interface_claimed(struct usb_int
  * usually won't need to call this.
  *
  * This call is synchronous, and may not be used in an interrupt context.
+ * Callers must own the driver model's usb bus writelock.  So driver
+ * disconnect() entries don't need extra locking, but other call contexts
+ * may need to explicitly claim that lock.
  */
 void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
 {
 	/* this should never happen, don't release something that's not ours */
-	if (iface->driver && iface->driver != driver)
+	if (!iface || !iface->driver || iface->driver != driver)
 		return;
 
+	if (iface->dev.driver) {
+		/* FIXME should be the ONLY case here */
+		device_release_driver(&iface->dev);
+		return;
+	}
+
 	usb_set_interface(interface_to_usbdev(iface),
 			iface->altsetting[0].desc.bInterfaceNumber,
 			0);
@@ -991,6 +997,7 @@ int usb_new_device(struct usb_device *de
 	int err = -EINVAL;
 	int i;
 	int j;
+	int config;
 
 	/*
 	 * Set the driver for the usb device to point to the "generic" driver.
@@ -1108,18 +1115,30 @@ int usb_new_device(struct usb_device *de
 
 	/* choose and set the configuration. that registers the interfaces
 	 * with the driver core, and lets usb device drivers bind to them.
+	 * NOTE:  should interact with hub power budgeting.
 	 */
+	config = dev->config[0].desc.bConfigurationValue;
 	if (dev->descriptor.bNumConfigurations != 1) {
+		for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+			/* heuristic:  Linux is more likely to have class
+			 * drivers, so avoid vendor-specific interfaces.
+			 */
+			if (dev->config[i].interface[0]->altsetting
+						->desc.bInterfaceClass
+					== USB_CLASS_VENDOR_SPEC)
+				continue;
+			config = dev->config[i].desc.bConfigurationValue;
+			break;
+		}
 		dev_info(&dev->dev,
 			"configuration #%d chosen from %d choices\n",
-			dev->config[0].desc.bConfigurationValue,
+			config,
 			dev->descriptor.bNumConfigurations);
 	}
-	err = usb_set_configuration(dev,
-			dev->config[0].desc.bConfigurationValue);
+	err = usb_set_configuration(dev, config);
 	if (err) {
 		dev_err(&dev->dev, "can't set config #%d, error %d\n",
-			dev->config[0].desc.bConfigurationValue, err);
+			config, err);
 		device_del(&dev->dev);
 		goto fail;
 	}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/gadget/ether.c 001-linus.patch/drivers/usb/gadget/ether.c
--- 000-virgin/drivers/usb/gadget/ether.c	Wed Dec 17 18:59:45 2003
+++ 001-linus.patch/drivers/usb/gadget/ether.c	Tue Dec 30 16:38:57 2003
@@ -226,6 +226,27 @@ static const char EP_IN_NAME [] = "ep2in
 #define hw_optimize(g) do {} while (0)
 #endif
 
+/*
+ * Toshiba TC86C001 ("Goku-S") UDC
+ *
+ * This has three semi-configurable full speed bulk/interrupt endpoints.
+ */
+#ifdef	CONFIG_USB_ETH_GOKU
+#define CHIP			"goku"
+#define DRIVER_VERSION_NUM	0x0106
+#define EP0_MAXPACKET		8
+static const char EP_OUT_NAME [] = "ep1-bulk";
+#define EP_OUT_NUM	1
+static const char EP_IN_NAME [] = "ep2-bulk";
+#define EP_IN_NUM	2
+static const char EP_STATUS_NAME [] = "ep3-bulk";
+#define EP_STATUS_NUM	3
+#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
+/* doesn't support remote wakeup */
+
+#define hw_optimize(g) do {} while (0)
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 #ifndef EP0_MAXPACKET
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/gadget/zero.c 001-linus.patch/drivers/usb/gadget/zero.c
--- 000-virgin/drivers/usb/gadget/zero.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/usb/gadget/zero.c	Tue Dec 30 16:38:57 2003
@@ -108,18 +108,14 @@ static const char loopback [] = "loop in
  *
  * CHIP ... hardware identifier
  * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP0_MAXPACKET ... controls packetization of control requests
  * EP_*_NAME ... which endpoints do we use for which purpose?
  * EP_*_NUM ... numbers for them (often limited by hardware)
  * HIGHSPEED ... define if ep0 and descriptors need high speed support
  * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... unless we can run on bus power, USB_CONFIG_ATT_SELFPOWER
+ * SELFPOWER ... if we can run on bus power, zero
  * WAKEUP ... if hardware supports remote wakeup AND we will issue the
  * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
  *
- * hw_optimize(gadget) ... for any hardware tweaks we want to kick in
- * 	before we enable our endpoints
- *
  * add other defines for other portability issues, like hardware that
  * for some reason doesn't handle full speed bulk maxpacket of 64.
  */
@@ -138,25 +134,13 @@ static const char loopback [] = "loop in
 #ifdef	CONFIG_USB_ZERO_NET2280
 #define CHIP			"net2280"
 #define DRIVER_VERSION_NUM	0x0101
-#define EP0_MAXPACKET		64
 static const char EP_OUT_NAME [] = "ep-a";
 #define EP_OUT_NUM	2
 static const char EP_IN_NAME [] = "ep-b";
 #define EP_IN_NUM	2
 #define HIGHSPEED
 /* specific hardware configs could be bus-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
 /* supports remote wakeup, but this driver doesn't */
-
-extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
-
-static inline void hw_optimize (struct usb_gadget *gadget)
-{
-	/* we can have bigger ep-a/ep-b fifos (2KB each, 4 packets
-	 * for highspeed bulk) because we're not using ep-c/ep-d.
-	 */
-	net2280_set_fifo_mode (gadget, 1);
-}
 #endif
 
 /*
@@ -173,17 +157,12 @@ static inline void hw_optimize (struct u
 #ifdef	CONFIG_USB_ZERO_PXA2XX
 #define CHIP			"pxa2xx"
 #define DRIVER_VERSION_NUM	0x0103
-#define EP0_MAXPACKET		16
 static const char EP_OUT_NAME [] = "ep12out-bulk";
 #define EP_OUT_NUM	12
 static const char EP_IN_NAME [] = "ep11in-bulk";
 #define EP_IN_NUM	11
 /* doesn't support bus-powered operation */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
 /* supports remote wakeup, but this driver doesn't */
-
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
 #endif
 
 /*
@@ -200,22 +179,32 @@ static const char EP_IN_NAME [] = "ep11i
 #ifdef	CONFIG_USB_ZERO_SA1100
 #define CHIP			"sa1100"
 #define DRIVER_VERSION_NUM	0x0105
-#define EP0_MAXPACKET		8
 static const char EP_OUT_NAME [] = "ep1out-bulk";
 #define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep2in-bulk";
 #define EP_IN_NUM	2
 /* doesn't support bus-powered operation */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
 /* doesn't support remote wakeup? */
+#endif
 
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0);
+/*
+ * Toshiba TC86C001 ("Goku-S") UDC
+ *
+ * This has three semi-configurable full speed bulk/interrupt endpoints.
+ */
+#ifdef	CONFIG_USB_ZERO_GOKU
+#define CHIP			"goku"
+#define DRIVER_VERSION_NUM	0x0106
+static const char EP_OUT_NAME [] = "ep1-bulk";
+#define EP_OUT_NUM	1
+static const char EP_IN_NAME [] = "ep2-bulk";
+#define EP_IN_NUM	2
+/* doesn't support remote wakeup */
 #endif
 
 /*-------------------------------------------------------------------------*/
 
-#ifndef EP0_MAXPACKET
+#ifndef EP_OUT_NUM
 #	error Configure some USB peripheral controller driver!
 #endif
 
@@ -224,10 +213,10 @@ static const char EP_IN_NAME [] = "ep2in
  */
 
 #ifndef	SELFPOWER
-/* default: say we rely on bus power */
-#define SELFPOWER	0
+/* default: say we're self-powered */
+#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
 /* else:
- * - SELFPOWER value must be USB_CONFIG_ATT_SELFPOWER
+ * - SELFPOWER value must be zero
  * - MAX_USB_POWER may be nonzero.
  */
 #endif
@@ -338,14 +327,13 @@ module_param (loopdefault, bool, S_IRUGO
 #define	CONFIG_SOURCE_SINK	3
 #define	CONFIG_LOOPBACK		2
 
-static const struct usb_device_descriptor
+static struct usb_device_descriptor
 device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
 
 	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
@@ -457,7 +445,7 @@ hs_sink_desc = {
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
 
-static const struct usb_qualifier_descriptor
+static struct usb_qualifier_descriptor
 dev_qualifier = {
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
@@ -465,9 +453,6 @@ dev_qualifier = {
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
-	/* assumes ep0 uses the same value for both speeds ... */
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
-
 	.bNumConfigurations =	2,
 };
 
@@ -959,7 +944,6 @@ zero_set_config (struct zero_dev *dev, u
 	}
 #endif
 	zero_reset_config (dev);
-	hw_optimize (gadget);
 
 	switch (number) {
 	case CONFIG_SOURCE_SINK:
@@ -1028,7 +1012,7 @@ zero_setup (struct usb_gadget *gadget, c
 
 	case USB_REQ_GET_DESCRIPTOR:
 		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
+			goto unknown;
 		switch (ctrl->wValue >> 8) {
 
 		case USB_DT_DEVICE:
@@ -1068,14 +1052,14 @@ zero_setup (struct usb_gadget *gadget, c
 	/* currently two configs, two speeds */
 	case USB_REQ_SET_CONFIGURATION:
 		if (ctrl->bRequestType != 0)
-			break;
+			goto unknown;
 		spin_lock (&dev->lock);
 		value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
+			goto unknown;
 		*(u8 *)req->buf = dev->config;
 		value = min (ctrl->wLength, (u16) 1);
 		break;
@@ -1086,7 +1070,7 @@ zero_setup (struct usb_gadget *gadget, c
 	 */
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
-			break;
+			goto unknown;
 		spin_lock (&dev->lock);
 		if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {
 			u8		config = dev->config;
@@ -1106,7 +1090,7 @@ zero_setup (struct usb_gadget *gadget, c
 		break;
 	case USB_REQ_GET_INTERFACE:
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
-			break;
+			goto unknown;
 		if (!dev->config)
 			break;
 		if (ctrl->wIndex != 0) {
@@ -1117,7 +1101,35 @@ zero_setup (struct usb_gadget *gadget, c
 		value = min (ctrl->wLength, (u16) 1);
 		break;
 
+	/*
+	 * These are the same vendor-specific requests supported by
+	 * Intel's USB 2.0 compliance test devices.  We exceed that
+	 * device spec by allowing multiple-packet requests.
+	 */
+	case 0x5b:	/* control WRITE test -- fill the buffer */
+		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
+			goto unknown;
+		if (ctrl->wValue || ctrl->wIndex)
+			break;
+		/* just read that many bytes into the buffer */
+		if (ctrl->wLength > USB_BUFSIZ)
+			break;
+		value = ctrl->wLength;
+		break;
+	case 0x5c:	/* control READ test -- return the buffer */
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
+			goto unknown;
+		if (ctrl->wValue || ctrl->wIndex)
+			break;
+		/* expect those bytes are still in the buffer; send back */
+		if (ctrl->wLength > USB_BUFSIZ
+				|| ctrl->wLength != req->length)
+			break;
+		value = ctrl->wLength;
+		break;
+
 	default:
+unknown:
 		VDEBUG (dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
@@ -1199,6 +1211,12 @@ zero_bind (struct usb_gadget *gadget)
 
 	dev->req->complete = zero_setup_complete;
 
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+#ifdef HIGHSPEED
+	/* assume ep0 uses the same value for both speeds ... */
+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+#endif
+
 	gadget->ep0->driver_data = dev;
 
 	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/host/ohci-dbg.c 001-linus.patch/drivers/usb/host/ohci-dbg.c
--- 000-virgin/drivers/usb/host/ohci-dbg.c	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/drivers/usb/host/ohci-dbg.c	Tue Dec 30 16:38:57 2003
@@ -269,18 +269,19 @@ static void ohci_dump (struct ohci_hcd *
 	ohci_dump_status (controller, NULL, 0);
 	if (controller->hcca)
 		ohci_dbg (controller,
-			"hcca frame #%04x\n", controller->hcca->frame_no);
+			"hcca frame #%04x\n", OHCI_FRAME_NO(controller->hcca));
 	ohci_dump_roothub (controller, 1, NULL, 0);
 }
 
 static const char data0 [] = "DATA0";
 static const char data1 [] = "DATA1";
 
-static void ohci_dump_td (struct ohci_hcd *ohci, char *label, struct td *td)
+static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
+		const struct td *td)
 {
 	u32	tmp = le32_to_cpup (&td->hwINFO);
 
-	ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x",
+	ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n",
 		label, td,
 		(tmp & TD_DONE) ? " (DONE)" : "",
 		td->urb, td->index,
@@ -301,28 +302,28 @@ static void ohci_dump_td (struct ohci_hc
 		case TD_DP_OUT: pid = "OUT"; break;
 		default: pid = "(bad pid)"; break;
 		}
-		ohci_dbg (ohci, "     info %08x CC=%x %s DI=%d %s %s", tmp,
+		ohci_dbg (ohci, "     info %08x CC=%x %s DI=%d %s %s\n", tmp,
 			TD_CC_GET(tmp), /* EC, */ toggle,
 			(tmp & TD_DI) >> 21, pid,
 			(tmp & TD_R) ? "R" : "");
 		cbp = le32_to_cpup (&td->hwCBP);
 		be = le32_to_cpup (&td->hwBE);
-		ohci_dbg (ohci, "     cbp %08x be %08x (len %d)", cbp, be,
+		ohci_dbg (ohci, "     cbp %08x be %08x (len %d)\n", cbp, be,
 			cbp ? (be + 1 - cbp) : 0);
 	} else {
 		unsigned	i;
-		ohci_dbg (ohci, "     info %08x CC=%x FC=%d DI=%d SF=%04x", tmp,
+		ohci_dbg (ohci, "  info %08x CC=%x FC=%d DI=%d SF=%04x\n", tmp,
 			TD_CC_GET(tmp),
 			(tmp >> 24) & 0x07,
 			(tmp & TD_DI) >> 21,
 			tmp & 0x0000ffff);
-		ohci_dbg (ohci, "     bp0 %08x be %08x",
+		ohci_dbg (ohci, "  bp0 %08x be %08x\n",
 			le32_to_cpup (&td->hwCBP) & ~0x0fff,
 			le32_to_cpup (&td->hwBE));
 		for (i = 0; i < MAXPSW; i++) {
 			u16	psw = le16_to_cpup (&td->hwPSW [i]);
 			int	cc = (psw >> 12) & 0x0f;
-			ohci_dbg (ohci, "       psw [%d] = %2x, CC=%x %s=%d", i,
+			ohci_dbg (ohci, "    psw [%d] = %2x, CC=%x %s=%d\n", i,
 				psw, cc,
 				(cc >= 0x0e) ? "OFFSET" : "SIZE",
 				psw & 0x0fff);
@@ -332,12 +333,13 @@ static void ohci_dump_td (struct ohci_hc
 
 /* caller MUST own hcd spinlock if verbose is set! */
 static void __attribute__((unused))
-ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
+ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
+		const struct ed *ed, int verbose)
 {
 	u32	tmp = ed->hwINFO;
 	char	*type = "";
 
-	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x",
+	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
 		label,
 		ed, ed->state, edstring (ed->type),
 		le32_to_cpup (&ed->hwNextED));
@@ -347,7 +349,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, cha
 	/* else from TDs ... control */
 	}
 	ohci_dbg (ohci,
-		"  info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp),
+		"  info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", le32_to_cpu (tmp),
 		0x03ff & (le32_to_cpu (tmp) >> 16),
 		(tmp & ED_DEQUEUE) ? " DQ" : "",
 		(tmp & ED_ISO) ? " ISO" : "",
@@ -356,7 +358,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, cha
 		0x000f & (le32_to_cpu (tmp) >> 7),
 		type,
 		0x007f & le32_to_cpu (tmp));
-	ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s",
+	ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s\n",
 		tmp = le32_to_cpup (&ed->hwHeadP),
 		(ed->hwHeadP & ED_C) ? data1 : data0,
 		(ed->hwHeadP & ED_H) ? " HALT" : "",
@@ -541,24 +543,29 @@ show_periodic (struct class_device *clas
 			if (temp == seen_count) {
 				u32	info = ed->hwINFO;
 				u32	scratch = cpu_to_le32p (&ed->hwINFO);
+				struct list_head	*entry;
+				unsigned		qlen = 0;
+
+				/* qlen measured here in TDs, not urbs */
+				list_for_each (entry, &ed->td_list)
+					qlen++;
 
 				temp = snprintf (next, size,
-					" (%cs dev%d%s ep%d%s"
+					" (%cs dev%d ep%d%s-%s qlen %u"
 					" max %d %08x%s%s)",
 					(info & ED_LOWSPEED) ? 'l' : 'f',
 					scratch & 0x7f,
-					(info & ED_ISO) ? " iso" : "",
 					(scratch >> 7) & 0xf,
 					(info & ED_IN) ? "in" : "out",
+					(info & ED_ISO) ? "iso" : "int",
+					qlen,
 					0x03ff & (scratch >> 16),
 					scratch,
-					(info & ED_SKIP) ? " s" : "",
+					(info & ED_SKIP) ? " K" : "",
 					(ed->hwHeadP & ED_H) ? " H" : "");
 				size -= temp;
 				next += temp;
 
-				// FIXME some TD info too
-
 				if (seen_count < DBG_SCHED_LIMIT)
 					seen [seen_count++] = ed;
 
@@ -617,7 +624,7 @@ show_registers (struct class_device *cla
 	/* hcca */
 	if (ohci->hcca)
 		ohci_dbg_sw (ohci, &next, &size,
-			"hcca frame 0x%04x\n", ohci->hcca->frame_no);
+			"hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca));
 
 	/* other registers mostly affect frame timings */
 	rdata = readl (&regs->fminterval);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/host/ohci-hcd.c 001-linus.patch/drivers/usb/host/ohci-hcd.c
--- 000-virgin/drivers/usb/host/ohci-hcd.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/drivers/usb/host/ohci-hcd.c	Tue Dec 30 16:38:57 2003
@@ -226,7 +226,7 @@ static int ohci_urb_enqueue (
 		if (retval < 0)
 			goto fail;
 		if (ed->type == PIPE_ISOCHRONOUS) {
-			u16	frame = le16_to_cpu (ohci->hcca->frame_no);
+			u16	frame = OHCI_FRAME_NO(ohci->hcca);
 
 			/* delay a few frames before the first TD */
 			frame += max_t (u16, 8, ed->interval);
@@ -281,7 +281,7 @@ static int ohci_urb_dequeue (struct usb_
 		urb_priv = urb->hcpriv;
 		if (urb_priv) {
 			if (urb_priv->ed->state == ED_OPER)
-				start_urb_unlink (ohci, urb_priv->ed);
+				start_ed_unlink (ohci, urb_priv->ed);
 		}
 	} else {
 		/*
@@ -363,7 +363,7 @@ static int ohci_get_frame (struct usb_hc
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	return le16_to_cpu (ohci->hcca->frame_no);
+	return OHCI_FRAME_NO(ohci->hcca);
 }
 
 /*-------------------------------------------------------------------------*
@@ -591,7 +591,7 @@ static void ohci_irq (struct usb_hcd *hc
 	 */
 	spin_lock (&ohci->lock);
 	if (ohci->ed_rm_list)
-		finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no),
+		finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca),
 				ptregs);
 	if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
 			&& HCD_IS_RUNNING(ohci->hcd.state))
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/host/ohci-q.c 001-linus.patch/drivers/usb/host/ohci-q.c
--- 000-virgin/drivers/usb/host/ohci-q.c	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/drivers/usb/host/ohci-q.c	Tue Dec 30 16:38:57 2003
@@ -430,7 +430,7 @@ done:
  * put the ep on the rm_list
  * real work is done at the next start frame (SF) hardware interrupt
  */
-static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
+static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
 {    
 	ed->hwINFO |= ED_DEQUEUE;
 	ed->state = ED_UNLINK;
@@ -441,7 +441,7 @@ static void start_urb_unlink (struct ohc
 	 * behave.  frame_no wraps every 2^16 msec, and changes right before
 	 * SF is triggered.
 	 */
-	ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1;
+	ed->tick = OHCI_FRAME_NO(ohci->hcca) + 1;
 
 	/* rm_list is just singly linked, for simplicity */
 	ed->ed_next = ohci->ed_rm_list;
@@ -479,7 +479,8 @@ td_fill (struct ohci_hcd *ohci, u32 info
 	 * and iso; other urbs rarely need more than one TD per urb.
 	 * this way, only final tds (or ones with an error) cause IRQs.
 	 * at least immediately; use DI=6 in case any control request is
-	 * tempted to die part way through.
+	 * tempted to die part way through.  (and to force the hc to flush
+	 * its donelist soonish, even on unlink paths.)
 	 *
 	 * NOTE: could delay interrupts even for the last TD, and get fewer
 	 * interrupts ... increasing per-urb latency by sharing interrupts.
@@ -879,12 +880,27 @@ rescan_all:
 		u32			*prev;
 
 		/* only take off EDs that the HC isn't using, accounting for
-		 * frame counter wraps.
+		 * frame counter wraps and EDs with partially retired TDs
 		 */
-		if (tick_before (tick, ed->tick)
-				&& HCD_IS_RUNNING(ohci->hcd.state)) {
-			last = &ed->ed_next;
-			continue;
+		if (likely (HCD_IS_RUNNING(ohci->hcd.state))) {
+			if (tick_before (tick, ed->tick)) {
+skip_ed:
+				last = &ed->ed_next;
+				continue;
+			}
+
+			if (!list_empty (&ed->td_list)) {
+				struct td	*td;
+				u32		head;
+
+				td = list_entry (ed->td_list.next, struct td,
+							td_list);
+				head = cpu_to_le32 (ed->hwHeadP) & TD_MASK;
+
+				/* INTR_WDH may need to clean up first */
+				if (td->td_dma != head)
+					goto skip_ed;
+			}
 		}
 
 		/* reentrancy:  if we drop the schedule lock, someone might
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/host/ohci.h 001-linus.patch/drivers/usb/host/ohci.h
--- 000-virgin/drivers/usb/host/ohci.h	Wed Dec 17 18:59:58 2003
+++ 001-linus.patch/drivers/usb/host/ohci.h	Tue Dec 30 16:38:57 2003
@@ -172,8 +172,14 @@ static const int cc_to_error [16] = { 
 struct ohci_hcca {
 #define NUM_INTS 32
 	__u32	int_table [NUM_INTS];	/* periodic schedule */
-	__u16	frame_no;		/* current frame number */
-	__u16	pad1;			/* set to 0 on each frame_no change */
+
+	/* 
+	 * OHCI defines u16 frame_no, followed by u16 zero pad.
+	 * Since some processors can't do 16 bit bus accesses,
+	 * portable access must be a 32 bit byteswapped access.
+	 */
+	u32	frame_no;		/* current frame number */
+#define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no))
 	__u32	done_head;		/* info returned for an interrupt */
 	u8	reserved_for_hc [116];
 	u8	what [4];		/* spec only identifies 252 bytes :) */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/host/uhci-hcd.c 001-linus.patch/drivers/usb/host/uhci-hcd.c
--- 000-virgin/drivers/usb/host/uhci-hcd.c	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/drivers/usb/host/uhci-hcd.c	Tue Dec 30 16:38:57 2003
@@ -2182,6 +2182,9 @@ static int uhci_reset(struct usb_hcd *hc
 
 	uhci->io_addr = (unsigned long) hcd->regs;
 
+	/* Turn off all interrupts */
+	outw(0, uhci->io_addr + USBINTR);
+
 	/* Maybe kick BIOS off this hardware.  Then reset, so we won't get
 	 * interrupts from any previous setup.
 	 */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/image/scanner.c 001-linus.patch/drivers/usb/image/scanner.c
--- 000-virgin/drivers/usb/image/scanner.c	Wed Dec 17 18:58:31 2003
+++ 001-linus.patch/drivers/usb/image/scanner.c	Tue Dec 30 16:38:57 2003
@@ -380,6 +380,10 @@
  *      Visioneer scanners.
  *    - Added test for USB_CLASS_CDC_DATA which is used by some fingerprint scanners.
  *
+ * 0.4.16  2003-11-04
+ *    - Added vendor/product ids for Epson, Genius, Microtek, Plustek, Reflecta, and
+ *      Visioneer scanners. Removed ids for HP PSC devices as these are supported by
+ *      the hpoj userspace driver.
  *
  * TODO
  *    - Performance
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/image/scanner.h 001-linus.patch/drivers/usb/image/scanner.h
--- 000-virgin/drivers/usb/image/scanner.h	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/drivers/usb/image/scanner.h	Tue Dec 30 16:38:57 2003
@@ -43,7 +43,7 @@
 
 // #define DEBUG
 
-#define DRIVER_VERSION "0.4.15"
+#define DRIVER_VERSION "0.4.16"
 #define DRIVER_DESC "USB Scanner Driver"
 
 #include <linux/usb.h>
@@ -146,7 +146,12 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x0458, 0x2015) }, /* ColorPage HR7LE */
 	{ USB_DEVICE(0x0458, 0x2016) }, /* ColorPage HR6X */
 	{ USB_DEVICE(0x0458, 0x2018) },	/* ColorPage HR7X */
+	{ USB_DEVICE(0x0458, 0x201b) },	/* Colorpage Vivid 4x */
 	/* Hewlett Packard */
+	/* IMPORTANT: Hewlett-Packard multi-function peripherals (OfficeJet, 
+	   Printer/Scanner/Copier (PSC), LaserJet, or PhotoSmart printer)
+	   should not be added to this table because they are accessed by a
+	   userspace driver (hpoj) */
 	{ USB_DEVICE(0x03f0, 0x0101) },	/* ScanJet 4100C */
 	{ USB_DEVICE(0x03f0, 0x0102) },	/* PhotoSmart S20 */
 	{ USB_DEVICE(0x03f0, 0x0105) },	/* ScanJet 4200C */
@@ -168,10 +173,10 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x03F0, 0x1105) },	/* ScanJet 5470C */
 	{ USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */
 	{ USB_DEVICE(0x03f0, 0x1305) },	/* Scanjet 4570c */
-	{ USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */
+	//	{ USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 - NOT SUPPORTED - use hpoj userspace driver */
 	{ USB_DEVICE(0x03f0, 0x2005) },	/* ScanJet 3570c */
 	{ USB_DEVICE(0x03f0, 0x2205) },	/* ScanJet 3500c */
-	{ USB_DEVICE(0x03f0, 0x2f11) }, /* PSC 1210 */
+	//	{ USB_DEVICE(0x03f0, 0x2f11) }, /* PSC 1210 - NOT SUPPORTED - use hpoj userspace driver */
 	/* Lexmark */
 	{ USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */
 	{ USB_DEVICE(0x043d, 0x003d) }, /* X83 */
@@ -187,6 +192,7 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x05da, 0x30ce) },	/* ScanMaker 3800 */
 	{ USB_DEVICE(0x05da, 0x30cf) },	/* ScanMaker 4800 */
 	{ USB_DEVICE(0x05da, 0x30d4) },	/* ScanMaker 3830 + 3840 */
+	{ USB_DEVICE(0x05da, 0x30d8) },	/* ScanMaker 5900 */
 	{ USB_DEVICE(0x04a7, 0x0224) },	/* Scanport 3000 (actually Visioneer?)*/
 	/* The following SCSI-over-USB Microtek devices are supported by the
 	   microtek driver: Enable SCSI and USB Microtek in kernel config */
@@ -245,6 +251,7 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x07b3, 0x0400) }, /* OpticPro 1248U */
 	{ USB_DEVICE(0x07b3, 0x0401) }, /* OpticPro 1248U (another one) */
 	{ USB_DEVICE(0x07b3, 0x0403) },	/* U16B */
+	{ USB_DEVICE(0x07b3, 0x0413) },	/* OpticSlim 1200 */
 	/* Primax/Colorado */
 	{ USB_DEVICE(0x0461, 0x0300) },	/* G2-300 #1 */
 	{ USB_DEVICE(0x0461, 0x0301) },	/* G2E-300 #1 */
@@ -261,6 +268,8 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x0461, 0x0383) },	/* G2E-600 */
 	/* Prolink */
 	{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
+	/* Reflecta  */
+	{ USB_DEVICE(0x05e3, 0x0120) },	/* iScan 1800 */
 	/* Relisis */
 	// { USB_DEVICE(0x0475, 0x0103) },	/* Episode - undetected endpoint */
 	{ USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */
@@ -285,6 +294,7 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x04b8, 0x011c) }, /* Perfection 3200 */
 	{ USB_DEVICE(0x04b8, 0x011d) }, /* Perfection 1260 */
 	{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
+	{ USB_DEVICE(0x04b8, 0x011f) },	/* Perfection 1670 */
 	{ USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */
 	{ USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */
 	/* Siemens */
@@ -309,6 +319,7 @@ static struct usb_device_id scanner_devi
 	{ USB_DEVICE(0x04a7, 0x0221) },	/* OneTouch 5300 USB */
 	{ USB_DEVICE(0x04a7, 0x0224) },	/* OneTouch 4800 USB */
 	{ USB_DEVICE(0x04a7, 0x0226) },	/* OneTouch 5800 USB */
+	{ USB_DEVICE(0x04a7, 0x0229) }, /* OneTouch 7100 USB */
 	{ USB_DEVICE(0x04a7, 0x022c) },	/* OneTouch 9020 USB */
 	{ USB_DEVICE(0x04a7, 0x0231) },	/* 6100 USB */
 	{ USB_DEVICE(0x04a7, 0x0311) },	/* 6200 EPP/USB */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/input/hid-core.c 001-linus.patch/drivers/usb/input/hid-core.c
--- 000-virgin/drivers/usb/input/hid-core.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/drivers/usb/input/hid-core.c	Tue Dec 30 16:38:57 2003
@@ -1354,6 +1354,9 @@ void hid_init_reports(struct hid_device 
 #define USB_VENDOR_ID_A4TECH		0x09DA
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 
+#define USB_VENDOR_ID_BERKSHIRE		0x0c98
+#define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
+
 struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1388,8 +1391,8 @@ struct hid_blacklist {
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_HIDDEV },
-	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_HIDDEV },
+	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
@@ -1403,6 +1406,7 @@ struct hid_blacklist {
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
+	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
 	{ 0, 0 }
 };
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/input/hiddev.c 001-linus.patch/drivers/usb/input/hiddev.c
--- 000-virgin/drivers/usb/input/hiddev.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/usb/input/hiddev.c	Tue Dec 30 16:38:57 2003
@@ -213,6 +213,7 @@ void hiddev_report_event(struct hid_devi
 	  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : 
 	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
 	uref.report_id = report->id;
+	uref.field_index = HID_FIELD_INDEX_NONE;
 
 	hiddev_send_event(hid, &uref);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/Kconfig 001-linus.patch/drivers/usb/media/Kconfig
--- 000-virgin/drivers/usb/media/Kconfig	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/drivers/usb/media/Kconfig	Tue Dec 30 16:38:57 2003
@@ -113,16 +113,17 @@ config USB_PWC
           webcams:
            * Philips PCA645, PCA646
            * Philips PCVC675, PCVC680, PCVC690
-           * Philips PCVC730, PCVC740, PCVC750
+           * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
 	   * Askey VC010
-	   * Logitech QuickCam Pro 3000, 4000, 'Zoom' and 'Notebook'
-	   * Samsung MPC-C10, MPC-C30
-	   * Creative Webcam 5
-	   * SOTECT Afina Eye
+	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' 
+             and 'Orbit'/'Sphere'
+           * Samsung MPC-C10, MPC-C30
+	   * Creative Webcam 5, Pro Ex
+	   * SOTEC Afina Eye
 	   * Visionite VCS-UC300, VCS-UM100
 	   
-	  The PCA635, PCVC665 and PCVC720 are not supported by this driver
-	  and never will be, but the 665 and 720 are supported by other 
+	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+	  and never will be, but the 665 and 720/20 are supported by other 
 	  drivers.
 
 	  This driver has an optional plugin (called PWCX), which is 
@@ -177,3 +178,30 @@ config USB_STV680
 	  To compile this driver as a module, choose M here: the
 	  module will be called stv680.
 
+config USB_W9968CF
+	tristate "USB W996[87]CF JPEG Dual Mode Camera support"
+	depends on USB && VIDEO_DEV && I2C
+	---help---
+	  Say Y here if you want support for cameras based on
+	  Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
+	
+	  This driver has an optional plugin, which is distributed as a
+	  separate module only (released under GPL). It contains code that 
+	  allows you to use higher resolutions and framerates, and can't
+	  be included into the official Linux kernel for performance 
+	  purposes.
+	  At the moment the driver needs a third-part module for the CMOS 
+	  sensors, which is available on internet: it is recommended to read
+	  <file:Documentation/usb/w9968cf.txt> for more informations and for
+	  a list of supported cameras.
+	
+	  This driver uses the Video For Linux and the I2C APIs. 
+	  You must say Y or M to both "Video For Linux" and 
+	  "I2C Support" to use this driver.
+	  Information on this API and pointers to "v4l" programs may be found
+	  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+	
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called w9968cf.o. If you want to compile it as a
+	  module, say M here and read <file:Documentation/modules.txt>.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/Makefile 001-linus.patch/drivers/usb/media/Makefile
--- 000-virgin/drivers/usb/media/Makefile	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/drivers/usb/media/Makefile	Tue Dec 30 16:38:57 2003
@@ -13,3 +13,4 @@ obj-$(CONFIG_USB_PWC)		+= pwc.o
 obj-$(CONFIG_USB_SE401)		+= se401.o
 obj-$(CONFIG_USB_STV680)	+= stv680.o
 obj-$(CONFIG_USB_VICAM)		+= vicam.o usbvideo.o
+obj-$(CONFIG_USB_W9968CF)	+= w9968cf.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/pwc-ctrl.c 001-linus.patch/drivers/usb/media/pwc-ctrl.c
--- 000-virgin/drivers/usb/media/pwc-ctrl.c	Wed Dec 17 18:59:43 2003
+++ 001-linus.patch/drivers/usb/media/pwc-ctrl.c	Tue Dec 30 16:38:57 2003
@@ -44,6 +44,8 @@
 #define GET_STATUS_CTL			0x06
 #define SET_EP_STREAM_CTL		0x07
 #define GET_EP_STREAM_CTL		0x08
+#define SET_MPT_CTL			0x0D
+#define GET_MPT_CTL			0x0E
 
 /* Selectors for the Luminance controls [GS]ET_LUM_CTL */
 #define AGC_MODE_FORMATTER			0x2000
@@ -88,6 +90,11 @@
 /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
 #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
 
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER		0x01
+#define PT_RESET_CONTROL_FORMATTER		0x02
+#define PT_STATUS_FORMATTER			0x03
+
 static char *size2name[PSZ_MAX] =
 {
 	"subQCIF",
@@ -435,6 +442,7 @@ int pwc_set_video_mode(struct pwc_device
 		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
 		break;
 		
+	case 720:
 	case 730:
 	case 740:
 	case 750:
@@ -745,6 +753,7 @@ static inline int pwc_set_shutter_speed(
 			buf[1] = speed >> 8;
 			buf[0] = speed & 0xff;
 			break;
+		case 720:
 		case 730:
 		case 740:
 		case 750:
@@ -1243,6 +1252,46 @@ static inline int pwc_get_dynamic_noise(
 	return buf;
 }
 
+int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+	unsigned char buf;
+	
+	buf = flags & 0x03; // only lower two bits are currently used 
+	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+	unsigned char buf[4];
+	
+	/* set new relative angle; angles are expressed in degrees * 100,
+	   but cam as .5 degree resolution, hence devide by 200. Also
+	   the angle must be multiplied by 64 before it's send to
+	   the cam (??)
+	 */
+	pan  =  64 * pan  / 100;
+	tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
+	buf[0] = pan & 0xFF;
+	buf[1] = (pan >> 8) & 0xFF;
+	buf[2] = tilt & 0xFF;
+	buf[3] = (tilt >> 8) & 0xFF;
+	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
+}
+
+static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
+{
+	int ret;
+	unsigned char buf[5];
+	
+	ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
+	if (ret < 0)
+		return ret;
+	status->status = buf[0] & 0x7; // 3 bits are used for reporting
+	status->time_pan = (buf[1] << 8) + buf[2];
+	status->time_tilt = (buf[3] << 8) + buf[4];
+	return 0;
+}
+
 
 int pwc_get_cmos_sensor(struct pwc_device *pdev)
 {
@@ -1512,8 +1561,128 @@ int pwc_ioctl(struct pwc_device *pdev, u
 		size->width = pdev->image.x;
 		size->height = pdev->image.y;
 		break;
-	}	
-
+ 	}
+ 	
+ 	case VIDIOCPWCMPTRESET:
+ 	{
+ 		int *flags = arg;
+ 		
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+			ret = pwc_mpt_reset(pdev, *flags);
+ 			if (ret >= 0)
+ 			{
+ 				pdev->pan_angle = 0;
+ 				pdev->tilt_angle = 0;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;		
+ 	}
+ 	case VIDIOCPWCMPTGRANGE:
+ 	{
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+ 			memcpy(arg, &pdev->angle_range, sizeof(struct pwc_mpt_range));
+ 		}
+ 		else
+ 		{	
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	}
+ 	
+ 	case VIDIOCPWCMPTSANGLE:
+ 	{
+ 		struct pwc_mpt_angles *angles = arg;
+ 		int new_pan, new_tilt;
+ 		
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+			/* The camera can only set relative angles, so
+			   do some calculations when getting an absolute angle .
+			 */
+			if (angles->absolute)
+			{
+ 				new_pan  = angles->pan; 
+ 				new_tilt = angles->tilt;
+ 			}
+ 			else
+ 			{
+ 				new_pan  = pdev->pan_angle  + angles->pan;
+ 				new_tilt = pdev->tilt_angle + angles->tilt;
+			}
+			/* check absolute ranges */
+			if (new_pan  < pdev->angle_range.pan_min  ||
+			    new_pan  > pdev->angle_range.pan_max  ||
+			    new_tilt < pdev->angle_range.tilt_min ||
+			    new_tilt > pdev->angle_range.tilt_max)
+			{
+				ret = -ERANGE;
+			}
+			else
+			{
+				/* go to relative range, check again */
+				new_pan  -= pdev->pan_angle;
+				new_tilt -= pdev->tilt_angle;
+				/* angles are specified in degrees * 100, thus the limit = 36000 */
+				if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
+					ret = -ERANGE;
+			}
+			if (ret == 0) /* no errors so far */
+			{
+				ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
+				if (ret >= 0)
+				{
+					pdev->pan_angle  += new_pan;
+					pdev->tilt_angle += new_tilt;
+				}
+				if (ret == -EPIPE) /* stall -> out of range */
+					ret = -ERANGE;				
+			}
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	} 
+ 	
+ 	case VIDIOCPWCMPTGANGLE:
+ 	{
+ 		struct pwc_mpt_angles *angles = arg;
+ 		
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+ 			angles->absolute = 1;
+ 			angles->pan  = pdev->pan_angle;
+ 			angles->tilt = pdev->tilt_angle;
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	}
+ 
+ 	case VIDIOCPWCMPTSTATUS:
+ 	{
+ 		struct pwc_mpt_status *status = arg;
+ 	
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+ 			ret = pwc_mpt_get_status(pdev, status);
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+  		break;
+  	}
+  	
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/pwc-if.c 001-linus.patch/drivers/usb/media/pwc-if.c
--- 000-virgin/drivers/usb/media/pwc-if.c	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/drivers/usb/media/pwc-if.c	Tue Dec 30 16:38:57 2003
@@ -79,9 +79,9 @@ static struct usb_device_id pwc_device_t
 	{ USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
 	{ USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
 	{ USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
-	{ USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom */
-	{ USB_DEVICE(0x046D, 0x08B4) }, /* Logitech (reserved) */
-	{ USB_DEVICE(0x046D, 0x08B5) }, /* Logitech (reserved) */
+	{ USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
+	{ USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
+	{ USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
 	{ USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
 	{ USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
 	{ USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
@@ -129,6 +129,7 @@ static struct {
 
 static int pwc_video_open(struct inode *inode, struct file *file);
 static int pwc_video_close(struct inode *inode, struct file *file);
+static int pwc_video_release(struct video_device *);			  
 static ssize_t pwc_video_read(struct file *file, char *buf,
 			  size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
@@ -918,21 +919,32 @@ static void pwc_isoc_cleanup(struct pwc_
 
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
 {
-	int ret;
+	int ret, start;
 
 	/* Stop isoc stuff */
 	pwc_isoc_cleanup(pdev);
 	/* Reset parameters */
 	pwc_reset_buffers(pdev);
 	/* Try to set video mode... */
-	ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
-	if (ret) /* That failed... restore old mode (we know that worked) */
-		ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-	if (!ret)
-		if (pwc_isoc_init(pdev) < 0)
-			Info("Failed to restart ISOC transfer in pwc_try_video_mode.\n");
+	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+	if (ret) { 
+	        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+		/* That failed... restore old mode (we know that worked) */
+		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+		if (start) {
+		        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+		}
+	}
+	if (start == 0) 
+	{
+		if (pwc_isoc_init(pdev) < 0) 
+		{
+			Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+			ret = -EAGAIN; /* let's try again, who knows if it works a second time */
+		}
+	}
 	pdev->drop_frames++; /* try to avoid garbage during switch */
-	return ret;
+	return ret; /* Return original error code */
 }
 
 
@@ -997,6 +1009,7 @@ static int pwc_video_open(struct inode *
 #if PWC_DEBUG	
 	Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
 #endif
+	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* So far, so good. Allocate memory. */
 	i = pwc_allocate_buffers(pdev);
@@ -1018,6 +1031,7 @@ static int pwc_video_open(struct inode *
 #if PWC_DEBUG
 	pdev->sequence = 0;
 #endif
+	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* Set some defaults */
 	pdev->vsnapshot = 0;
@@ -1104,6 +1118,12 @@ static int pwc_video_close(struct inode 
 	return 0;
 }
 
+static int pwc_video_release(struct video_device *vfd)
+{
+	Trace(TRACE_OPEN, "pwc_video_release() called. Now what?\n");
+}
+		
+
 /*
  *	FIXME: what about two parallel reads ????
  *      ANSWER: Not supported. You can't open the device more than once,
@@ -1124,7 +1144,7 @@ static ssize_t pwc_video_read(struct fil
 	int noblock = file->f_flags & O_NONBLOCK;
 	DECLARE_WAITQUEUE(wait, current);
 
-	Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count);
+	Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
 	if (vdev == NULL)
 		return -EFAULT;
 	pdev = vdev->priv;
@@ -1568,6 +1588,7 @@ static int usb_pwc_probe(struct usb_inte
 	struct pwc_device *pdev = NULL;
 	int vendor_id, product_id, type_id;
 	int i, hint;
+	int features = 0;
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
 
@@ -1677,8 +1698,17 @@ static int usb_pwc_probe(struct usb_inte
 			name = "Logitech QuickCam Zoom";
 			type_id = 740; /* CCD sensor */
 			break;
-		case 0x08b4:
+		case 0x08B4:
+			Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+			name = "Logitech QuickCam Zoom";
+			type_id = 740; /* CCD sensor */
+			break;
 		case 0x08b5:
+			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+			name = "Logitech QuickCam Orbit";
+			type_id = 740; /* CCD sensor */
+			features |= FEATURE_MOTOR_PANTILT;
+			break;
 		case 0x08b6:
 		case 0x08b7:
 		case 0x08b8:
@@ -1776,9 +1806,22 @@ static int usb_pwc_probe(struct usb_inte
 	}
 	memset(pdev, 0, sizeof(struct pwc_device));
 	pdev->type = type_id;
-	pwc_construct(pdev);
 	pdev->vsize = default_size;
 	pdev->vframes = default_fps;
+	pdev->features = features;
+	if (vendor_id == 0x046D && product_id == 0x08B5)
+	{
+		/* Logitech QuickCam Orbit
+	           The ranges have been determined experimentally; they may differ from cam to cam.
+	           Also, the exact ranges left-right and up-down are different for my cam
+	          */
+		pdev->angle_range.pan_min  = -7000;
+		pdev->angle_range.pan_max  =  7000;
+		pdev->angle_range.tilt_min = -3000;
+		pdev->angle_range.tilt_max =  2500;
+		pdev->angle_range.zoom_min = -1;
+		pdev->angle_range.zoom_max = -1;
+	}
 
 	init_MUTEX(&pdev->modlock);
 	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
@@ -1791,7 +1834,7 @@ static int usb_pwc_probe(struct usb_inte
 	strcpy(pdev->vdev.name, name);
 	pdev->vdev.owner = THIS_MODULE;
 	pdev->vdev.priv = pdev;
-
+	
 	pdev->release = udev->descriptor.bcdDevice;
 	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
 
@@ -1809,6 +1852,7 @@ static int usb_pwc_probe(struct usb_inte
 		}
 	}
 
+	pdev->vdev.release = pwc_video_release;
 	i = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
 	if (i < 0) {
 		Err("Failed to register as video device (%d).\n", i);
@@ -1818,6 +1862,7 @@ static int usb_pwc_probe(struct usb_inte
 	else {
 		Info("Registered as /dev/video%d.\n", pdev->vdev.minor & 0x3F);
 	}
+
 	/* occupy slot */
 	if (hint < MAX_DEV_HINTS) 
 		device_hint[hint].pdev = pdev;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/pwc-ioctl.h 001-linus.patch/drivers/usb/media/pwc-ioctl.h
--- 000-virgin/drivers/usb/media/pwc-ioctl.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/usb/media/pwc-ioctl.h	Tue Dec 30 16:38:57 2003
@@ -112,6 +112,43 @@ struct pwc_imagesize
 	int height;
 };
 
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN		0x01
+#define PWC_MPT_TILT		0x02
+#define PWC_MPT_TIMEOUT		0x04 /* for status */
+
+/* Set angles; when absolute = 1, the angle is absolute and the 
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */   
+struct pwc_mpt_angles
+{
+	int absolute;		/* write-only */
+	int pan;		/* degrees * 100 */
+	int tilt;		/* degress * 100 */
+	int zoom;		/* N/A, set to -1 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+   The zoom is not used, maybe in the future...
+
+ */
+struct pwc_mpt_range
+{
+	int pan_min, pan_max;		/* degrees * 100 */
+	int tilt_min, tilt_max;
+	int zoom_min, zoom_max;		/* -1, -1 */
+};
+
+struct pwc_mpt_status
+{
+	int status;
+	int time_pan;
+	int time_tilt;
+};
+
+
  /* Restore user settings */
 #define VIDIOCPWCRUSER		_IO('v', 192)
  /* Save user settings */
@@ -181,5 +218,12 @@ struct pwc_imagesize
 
  /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
 #define VIDIOCPWCGREALSIZE	_IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */ 
+#define VIDIOCPWCMPTRESET	_IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE	_IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE	_IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE	_IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS	_IOR('v', 213, struct pwc_mpt_status)
  
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/pwc-misc.c 001-linus.patch/drivers/usb/media/pwc-misc.c
--- 000-virgin/drivers/usb/media/pwc-misc.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/drivers/usb/media/pwc-misc.c	Tue Dec 30 16:38:57 2003
@@ -52,7 +52,7 @@ int pwc_decode_size(struct pwc_device *p
 	return find;
 }
 
-/* initialize variables depending on type */
+/* initialize variables depending on type and decompressor*/
 void pwc_construct(struct pwc_device *pdev)
 {
 	switch(pdev->type) {
@@ -73,9 +73,17 @@ void pwc_construct(struct pwc_device *pd
 	case 690:
 		pdev->view_min.x = 128;
 		pdev->view_min.y =  96;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+		/* Anthill bug #38: PWC always reports max size, even without PWCX */
+		if (pdev->decompressor != NULL) {
+			pdev->view_max.x = 640;
+			pdev->view_max.y = 480;
+			pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+		}
+		else {
+			pdev->view_max.x = 352;
+			pdev->view_max.y = 288;
+			pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF;
+		}
 		pdev->vcinterface = 3;
 		pdev->vendpoint = 4;
 		pdev->frame_header_size = 0;
@@ -87,9 +95,18 @@ void pwc_construct(struct pwc_device *pd
 	case 750:
 		pdev->view_min.x = 160;
 		pdev->view_min.y = 120;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+		/* Anthill bug #38: PWC always reports max size, even without PWCX */
+		if (pdev->decompressor != NULL) {
+			pdev->view_max.x = 640;
+			pdev->view_max.y = 480;
+			pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+		}
+		else {
+			/* Tell CIF, even though SIF really is the maximum, but some tools really need CIF */
+			pdev->view_max.x = 352;
+			pdev->view_max.y = 288;
+			pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF;
+		}
 		pdev->vcinterface = 3;
 		pdev->vendpoint = 5;
 		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/pwc.h 001-linus.patch/drivers/usb/media/pwc.h
--- 000-virgin/drivers/usb/media/pwc.h	Wed Dec 17 18:58:58 2003
+++ 001-linus.patch/drivers/usb/media/pwc.h	Tue Dec 30 16:38:57 2003
@@ -18,17 +18,21 @@
 #ifndef PWC_H
 #define PWC_H
 
+#include <linux/version.h>
+
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/usb.h>
+#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 #include <linux/videodev.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>
 
 #include <asm/semaphore.h>
 #include <asm/errno.h>
 
+#include "pwc-ioctl.h"
+
 /* Defines and structures for the Philips webcam */
 /* Used for checking memory corruption/pointer validation */
 #define PWC_MAGIC 0x89DC10ABUL
@@ -58,10 +62,12 @@
 #define TOUCAM_HEADER_SIZE		8
 #define TOUCAM_TRAILER_SIZE		4
 
+#define FEATURE_MOTOR_PANTILT		0x0001
+
 /* Version block */
 #define PWC_MAJOR	8
-#define PWC_MINOR	11
-#define PWC_VERSION 	"8.11"
+#define PWC_MINOR	12
+#define PWC_VERSION 	"8.12"
 #define PWC_NAME 	"pwc"
 
 /* Turn certain features on/off */
@@ -119,8 +125,9 @@ struct pwc_device
    /* Pointer to our usb_device */
    struct usb_device *udev;
    
-   int type;                    /* type of cam (645, 646, 675, 680, 690) */
+   int type;                    /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
    int release;			/* release number */
+   int features;		/* feature bits */
    int error_status;		/* set when something goes wrong with the cam (unplugged, USB errors) */
    int usb_init;		/* set when the cam has been initialized over USB */
 
@@ -194,6 +201,11 @@ struct pwc_device
    struct semaphore modlock;		/* to prevent races in video_open(), etc */
    spinlock_t ptrlock;			/* for manipulating the buffer pointers */
 
+   /*** motorized pan/tilt feature */
+   struct pwc_mpt_range angle_range;
+   int pan_angle;			/* in degrees * 100 */
+   int tilt_angle;			/* absolute angle; 0,0 is home position */
+
    /*** Misc. data ***/
    wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
 #if PWC_INT_PIPE
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/w9968cf.c 001-linus.patch/drivers/usb/media/w9968cf.c
--- 000-virgin/drivers/usb/media/w9968cf.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/usb/media/w9968cf.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,3712 @@
+/***************************************************************************
+ * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip.       *
+ *                                                                         *
+ * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ *                                                                         *
+ * - Memory management code from bttv driver by Ralph Metzler,             *
+ *   Marcus Metzler and Gerd Knorr.                                        *
+ * - I2C interface to kernel, high-level CMOS sensor control routines and  *
+ *   some symbolic names from OV511 driver by Mark W. McClelland.          *
+ * - Low-level I2C fast write function by Piotr Czerczak.                  *
+ * - Low-level I2C read function by FrÃ©dÃ©ric Jouault.                      *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+
+#include "w9968cf.h"
+#include "w9968cf_decoder.h"
+
+
+
+/****************************************************************************
+ * Modules paramaters                                                       *
+ ****************************************************************************/
+
+static u8 vppmod_load = W9968CF_VPPMOD_LOAD;
+static u8 simcams = W9968CF_SIMCAMS;
+static int video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /* -1=first free */
+static u16 packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_PACKET_SIZE};
+static u8 max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BUFFERS};
+static u8 double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = 
+                             W9968CF_DOUBLE_BUFFER};
+static u8 clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING};
+static u8 filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FILTER_TYPE};
+static u8 largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW};
+static u8 decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = 
+                             W9968CF_DECOMPRESSION};
+static u8 upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING};
+static u8 force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0};
+static u8 force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB};
+static u8 autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT};
+static u8 autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP};
+static u8 lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LIGHTFREQ};
+static u8 bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]=
+                             W9968CF_BANDINGFILTER};
+static int clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV};
+static u8 backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT};
+static u8 mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR};
+static u8 sensor_mono[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_SENSOR_MONO};
+static u16 brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BRIGHTNESS};
+static u16 hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE};
+static u16 colour[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR};
+static u16 contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CONTRAST};
+static u16 whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_WHITENESS};
+#ifdef W9968CF_DEBUG
+static u8 debug = W9968CF_DEBUG_LEVEL;
+static u8 specific_debug = W9968CF_SPECIFIC_DEBUG;
+#endif
+
+MODULE_AUTHOR("Luca Risolia <luca_ing@libero.it>");
+
+MODULE_DESCRIPTION("Video4Linux driver for "
+                   "W996[87]CF JPEG USB Dual Mode Camera Chip");
+
+MODULE_SUPPORTED_DEVICE("Video");
+
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(vppmod_load, "i");
+MODULE_PARM(simcams, "i");
+MODULE_PARM(video_nr, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(packet_size, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(max_buffers, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(double_buffer, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(clamping, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(filter_type, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(largeview, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(decompression, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(upscaling, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(force_palette, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(force_rgb, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "i");
+MODULE_PARM(autobright, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(autoexp, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(lightfreq, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(bandingfilter, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(clockdiv, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(backlight, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(mirror, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(sensor_mono, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(brightness, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(hue, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(colour, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(contrast, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+MODULE_PARM(whiteness, "0-" __MODULE_STRING(W9968CF_MAX_DEVICES) "l");
+#ifdef W9968CF_DEBUG
+MODULE_PARM(debug, "i");
+MODULE_PARM(specific_debug, "i");
+#endif
+
+MODULE_PARM_DESC(vppmod_load, 
+                 "\n<0|1> Automatic 'w9968cf-vpp' module loading."
+                 "\n0 disable, 1 enable."
+                 "\nIf enabled, every time an application attempts to open a"
+                 "\ncamera, 'insmod' searches for the video post-processing"
+                 "\nmodule in the system and loads it automatically (if"
+                 "\npresent). The 'w9968cf-vpp' module adds extra image"
+                 "\nmanipulation functions to the 'w9968cf' module, like"
+                 "\nsoftware up-scaling,colour conversions and video decoding."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_VPPMOD_LOAD)"."
+                 "\n");
+MODULE_PARM_DESC(simcams, 
+                 "\n<n> Number of cameras allowed to stream simultaneously."
+                 "\nn may vary from 0 to "
+                 __MODULE_STRING(W9968CF_MAX_DEVICES)"."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"."
+                 "\n");
+MODULE_PARM_DESC(video_nr,
+                 "\n<-1|n[,...]> Specify V4L minor mode number."
+                 "\n -1 = use next available (default)"
+                 "\n  n = use minor number n (integer >= 0)"
+                 "\nYou can specify " __MODULE_STRING(W9968CF_MAX_DEVICES)
+                 " cameras this way."
+                 "\nFor example:"
+                 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+                 "\nthe second camera and use auto for the first"
+                 "\none and for every other camera."
+                 "\n");
+MODULE_PARM_DESC(packet_size,
+                 "\n<n[,...]> Specify the maximum data payload"
+                 "\nsize in bytes for alternate settings, for each device."
+                 "\nn is scaled between 63 and 1023 "
+                 "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")."
+                 "\n");
+MODULE_PARM_DESC(max_buffers,
+                 "\n<n[,...]> Only for advanced users."
+                 "\nSpecify the maximum number of video frame buffers"
+                 "\nto allocate for each device, from 2 to "
+                 __MODULE_STRING(W9968CF_MAX_BUFFERS)
+                 ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")."
+                 "\n");
+MODULE_PARM_DESC(double_buffer, 
+                 "\n<0|1[,...]> "
+                 "Hardware double buffering: 0 disabled, 1 enabled."
+                 "\nIt should be enabled if you want smooth video output: if"
+                 "\nyou obtain out of sync. video, disable it at all, or try"
+                 "\nto decrease the 'clockdiv' module paramater value."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(clamping, 
+                 "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(filter_type, 
+                 "\n<0|1|2[,...]> Video filter type."
+                 "\n0 none, 1 (1-2-1) 3-tap filter, "
+                 "2 (2-3-6-3-2) 5-tap filter."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE)
+                 " for every device."
+                 "\nThe filter is used to reduce noise and aliasing artifacts"
+                 "\nproduced by the CCD or CMOS sensor, and the scaling"
+                 " process."
+                 "\n");
+MODULE_PARM_DESC(largeview, 
+                 "\n<0|1[,...]> Large view: 0 disabled, 1 enabled."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(upscaling, 
+                 "\n<0|1[,...]> Software scaling (for non-compressed video):"
+                 "\n0 disabled, 1 enabled."
+                 "\nDisable it if you have a slow CPU or you don't have"
+                 " enough memory."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING)
+                 " for every device."
+                 "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
+                 " set to 0.");
+MODULE_PARM_DESC(decompression,
+                 "\n<0|1|2[,...]> Software video decompression:"
+                 "\n- 0 disables decompression (doesn't allow formats needing"
+                 " decompression)"
+                 "\n- 1 forces decompression (allows formats needing"
+                 " decompression only);"
+                 "\n- 2 allows any permitted formats."
+                 "\nFormats supporting compressed video are YUV422P and"
+                 " YUV420P/YUV420 "
+                 "\nin any resolutions where both width and height are "
+                 "a multiple of 16."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION)
+                 " for every device."
+                 "\nIf 'w9968cf-vpp' is not loaded, forcing decompression is "
+                 "\nnot allowed; in this case this paramater is set to 2.");
+MODULE_PARM_DESC(force_palette,
+                 "\n<0"
+                 "|" __MODULE_STRING(VIDEO_PALETTE_UYVY)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_YUV420)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_YUYV)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_YUV422)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_GREY)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_RGB555)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_RGB565)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_RGB24)
+                 "|" __MODULE_STRING(VIDEO_PALETTE_RGB32)
+                 "[,...]>"
+                 " Force picture palette."
+                 "\nIn order:"
+                 "\n- 0 allows any of the following formats:"
+                 "\n- UYVY    16 bpp - Original video, compression disabled"
+                 "\n- YUV420  12 bpp - Original video, compression enabled"
+                 "\n- YUV422P 16 bpp - Original video, compression enabled"
+                 "\n- YUV420P 12 bpp - Original video, compression enabled"
+                 "\n- YUVY    16 bpp - Software conversion from UYVY"
+                 "\n- YUV422  16 bpp - Software conversion from UYVY"
+                 "\n- GREY     8 bpp - Software conversion from UYVY"
+                 "\n- RGB555  16 bpp - Software conversion from UYVY"
+                 "\n- RGB565  16 bpp - Software conversion from UYVY"
+                 "\n- RGB24   24 bpp - Software conversion from UYVY"
+                 "\n- RGB32   32 bpp - Software conversion from UYVY"
+                 "\nWhen not 0, this paramater will override 'decompression'."
+                 "\nDefault value is 0 for every device."
+                 "\nInitial palette is "
+                 __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"."
+                 "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
+                 " set to 9 (UYVY).");
+MODULE_PARM_DESC(force_rgb, 
+                 "\n<0|1[,...]> Read RGB video data instead of BGR:"
+                 "\n 1 = use RGB component ordering."
+                 "\n 0 = use BGR component ordering."
+                 "\nThis parameter has effect when using RGBX palettes only."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(autobright,
+                 "\n<0|1[,...]> CMOS sensor automatically changes brightness:"
+                 "\n 0 = no, 1 = yes"
+                 "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(autoexp,
+                 "\n<0|1[,...]> CMOS sensor automatically changes exposure:"
+                 "\n 0 = no, 1 = yes"
+                 "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(lightfreq,
+                 "\n<50|60[,...]> Light frequency in Hz:"
+                 "\n 50 for European and Asian lighting,"
+                 " 60 for American lighting."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(bandingfilter,
+                 "\n<0|1[,...]> Banding filter to reduce effects of"
+                 " fluorescent lighting:"
+                 "\n 0 disabled, 1 enabled."
+                 "\nThis filter tries to reduce the pattern of horizontal"
+                 "\nlight/dark bands caused by some (usually fluorescent)"
+                 " lighting."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(clockdiv,
+                 "\n<-1|n[,...]> "
+                 "Force pixel clock divisor to a specific value (for experts):"
+                 "\n  n may vary from 0 to 127."
+                 "\n -1 for automatic value."
+                 "\nSee also the 'double_buffer' module paramater."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(backlight,
+                 "\n<0|1[,...]> Objects are lit from behind:"
+                 "\n 0 = no, 1 = yes"
+                 "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(mirror,
+                 "\n<0|1[,...]> Reverse image horizontally:"
+                 "\n 0 = no, 1 = yes"
+                 "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(sensor_mono,
+                 "\n<0|1[,...]> The OV CMOS sensor is monochrome:"
+                 "\n 0 = no, 1 = yes"
+                 "\nDefault value is "__MODULE_STRING(W9968CF_SENSOR_MONO)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(brightness, 
+                 "\n<n[,...]> Set picture brightness (0-65535)."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS)
+                 " for every device."
+                 "\nThis parameter has no effect if 'autobright' is enabled."
+                 "\n");
+MODULE_PARM_DESC(hue, 
+                 "\n<n[,...]> Set picture hue (0-65535)."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_HUE)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(colour, 
+                 "\n<n[,...]> Set picture saturation (0-65535)."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(contrast, 
+                 "\n<n[,...]> Set picture contrast (0-65535)."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST)
+                 " for every device."
+                 "\n");
+MODULE_PARM_DESC(whiteness, 
+                 "\n<n[,...]> Set picture whiteness (0-65535)."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS)
+                 " for every device."
+                 "\n");
+#ifdef W9968CF_DEBUG
+MODULE_PARM_DESC(debug,
+                 "\n<n> Debugging information level, from 0 to 6:"
+                 "\n0 = none (be cautious)"
+                 "\n1 = critical errors"
+                 "\n2 = significant informations"
+                 "\n3 = configuration or general messages"
+                 "\n4 = warnings"
+                 "\n5 = called functions"
+                 "\n6 = function internals"
+                 "\nLevel 5 and 6 are useful for testing only, when just "
+                 "one device is used."
+                 "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"."
+                 "\n");
+MODULE_PARM_DESC(specific_debug,
+                 "\n<0|1> Enable or disable specific debugging messages:"
+                 "\n0 = print messages concerning every level"
+                 " <= 'debug' level."
+                 "\n1 = print messages concerning the level"
+                 " indicated by 'debug'."
+                 "\nDefault value is "
+                 __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"."
+                 "\n");
+#endif /* W9968CF_DEBUG */
+
+
+
+/****************************************************************************
+ * Some prototypes                                                          *
+ ****************************************************************************/
+
+/* Video4linux interface */
+static struct file_operations w9968cf_fops;
+static int w9968cf_open(struct inode*, struct file*);
+static int w9968cf_release(struct inode*, struct file*);
+static ssize_t w9968cf_read(struct file*, char*, size_t, loff_t*);
+static int w9968cf_mmap(struct file*, struct vm_area_struct*);
+static int w9968cf_ioctl(struct inode*, struct file*,
+                         unsigned int, unsigned long);
+static int w9968cf_do_ioctl(struct w9968cf_device*, unsigned int, void*);
+
+/* USB-specific */
+static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs);
+static int w9968cf_start_transfer(struct w9968cf_device*);
+static int w9968cf_stop_transfer(struct w9968cf_device*);
+static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index);
+static int w9968cf_read_reg(struct w9968cf_device*, u16 index);
+static int w9968cf_write_fsb(struct w9968cf_device*, u16* data);
+static int w9968cf_write_sb(struct w9968cf_device*, u16 value);
+static int w9968cf_read_sb(struct w9968cf_device*);
+static int w9968cf_upload_quantizationtables(struct w9968cf_device*);
+
+/* Low-level I2C (SMBus) I/O */
+static int w9968cf_smbus_start(struct w9968cf_device*);
+static int w9968cf_smbus_stop(struct w9968cf_device*);
+static int w9968cf_smbus_write_byte(struct w9968cf_device*, u8 v);
+static int w9968cf_smbus_read_byte(struct w9968cf_device*, u8* v);
+static int w9968cf_smbus_write_ack(struct w9968cf_device*);
+static int w9968cf_smbus_read_ack(struct w9968cf_device*);
+static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
+                                      u16 address, u8* value);
+static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, 
+                                           u8 subaddress, u8* value);
+static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*,
+                                       u16 address, u8 subaddress);
+static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*,
+                                                u16 address, u8 subaddress,
+                                                u8 value);
+
+/* I2C interface to kernel */
+static int w9968cf_i2c_init(struct w9968cf_device*);
+static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, 
+                                  unsigned short flags, char read_write, 
+                                  u8 command, int size, union i2c_smbus_data*);
+static u32 w9968cf_i2c_func(struct i2c_adapter*);
+static int w9968cf_i2c_attach_inform(struct i2c_client*);
+static int w9968cf_i2c_detach_inform(struct i2c_client*);
+static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd,
+                               unsigned long arg);
+
+/* Memory management */
+static inline unsigned long kvirt_to_pa(unsigned long adr);
+static void* rvmalloc(unsigned long size);
+static void rvfree(void *mem, unsigned long size);
+static void w9968cf_deallocate_memory(struct w9968cf_device*);
+static int  w9968cf_allocate_memory(struct w9968cf_device*);
+static inline unsigned long w9968cf_get_max_bufsize(struct w9968cf_device*);
+
+/* High-level CMOS sensor control functions */
+static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val);
+static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
+static inline int w9968cf_sensor_cmd(struct w9968cf_device*, 
+                                     unsigned int cmd, void *arg);
+static void w9968cf_sensor_configure(struct w9968cf_device*);
+static int w9968cf_sensor_change_settings(struct w9968cf_device*);
+static int w9968cf_sensor_get_picture(struct w9968cf_device*, 
+                                      struct video_picture*);
+static int w9968cf_sensor_set_picture(struct w9968cf_device*, 
+                                      struct video_picture pict);
+
+/* Other helper functions */
+static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*,
+                                     enum w9968cf_model_id, 
+                                     const unsigned short dev_nr);
+static int w9968cf_turn_on_led(struct w9968cf_device*);
+static int w9968cf_init_chip(struct w9968cf_device*);
+static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
+static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
+static inline u16 w9968cf_valid_palette(u16 palette);
+static inline u16 w9968cf_valid_depth(u16 palette);
+static inline u8 w9968cf_need_decompression(u16 palette);
+static int w9968cf_postprocess_frame(struct w9968cf_device*, 
+                                     struct w9968cf_frame_t*);
+static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h);
+static void w9968cf_init_framelist(struct w9968cf_device*);
+static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num);
+static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
+static void w9968cf_release_resources(struct w9968cf_device*);
+
+/* Intermodule communication */
+static int w9968cf_vppmod_detect(void);
+static void w9968cf_vppmod_release(void);
+
+/* Pointers to registered video post-processing functions */
+static void (*w9968cf_vpp_init_decoder)(void);
+static int (*w9968cf_vpp_check_headers)(const unsigned char*,
+                                        const unsigned long);
+static int (*w9968cf_vpp_decode)(const char*, const unsigned, 
+                                 const unsigned, const unsigned, char*);
+static void (*w9968cf_vpp_swap_yuvbytes)(void*, unsigned long);
+static void (*w9968cf_vpp_uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8);
+static void (*w9968cf_vpp_scale_up)(u8*, u8*, u16, u16, u16, u16, u16);
+
+
+
+/****************************************************************************
+ * Symbolic names                                                           *
+ ****************************************************************************/
+
+/* Used to represent a list of values and their respective symbolic names */
+struct w9968cf_symbolic_list {
+	const int num;
+	const char *name;
+};
+
+/*-------------------------------------------------------------------------- 
+  Returns the name of the matching element in the symbolic_list array. The
+  end of the list must be marked with an element that has a NULL name.
+  --------------------------------------------------------------------------*/
+static inline const char * 
+symbolic(struct w9968cf_symbolic_list list[], const int num)
+{
+	int i;
+
+	for (i = 0; list[i].name != NULL; i++)
+		if (list[i].num == num)
+			return (list[i].name);
+
+	return "Unknown";
+}
+
+static struct w9968cf_symbolic_list camlist[] = {
+	{ W9968CF_MOD_GENERIC, "W996[87]CF JPEG USB Dual Mode Camera" },
+	{ W9968CF_MOD_CLVBWGP, "Creative Labs Video Blaster WebCam Go Plus" },
+
+	/* Other cameras (having the same descriptors as Generic W996[87]CF) */
+	{ W9968CF_MOD_ADPA5R, "Aroma Digi Pen ADG-5000 Refurbished" },
+	{ W9986CF_MOD_AU, "AVerTV USB" },
+	{ W9968CF_MOD_CLVBWG, "Creative Labs Video Blaster WebCam Go" },
+	{ W9968CF_MOD_DLLDK, "Die Lebon LDC-D35A Digital Kamera" },
+	{ W9968CF_MOD_EEEMC, "Ezonics EZ-802 EZMega Cam" },
+	{ W9968CF_MOD_ODPVDMPC, "OPCOM Digi Pen VGA Dual Mode Pen Camera" },
+
+	{  -1, NULL }
+};
+
+static struct w9968cf_symbolic_list senlist[] = {
+	{ CC_OV76BE,   "OV76BE" },
+	{ CC_OV7610,   "OV7610" },
+	{ CC_OV7620,   "OV7620" },
+	{ CC_OV7620AE, "OV7620AE" },
+	{ CC_OV6620,   "OV6620" },
+	{ CC_OV6630,   "OV6630" },
+	{ CC_OV6630AE, "OV6630AE" },
+	{ CC_OV6630AF, "OV6630AF" },
+	{ -1, NULL }
+};
+
+/* Video4Linux1 palettes */
+static struct w9968cf_symbolic_list v4l1_plist[] = {
+	{ VIDEO_PALETTE_GREY,    "GREY" },
+	{ VIDEO_PALETTE_HI240,   "HI240" },
+	{ VIDEO_PALETTE_RGB565,  "RGB565" },
+	{ VIDEO_PALETTE_RGB24,   "RGB24" },
+	{ VIDEO_PALETTE_RGB32,   "RGB32" },
+	{ VIDEO_PALETTE_RGB555,  "RGB555" },
+	{ VIDEO_PALETTE_YUV422,  "YUV422" },
+	{ VIDEO_PALETTE_YUYV,    "YUYV" },
+	{ VIDEO_PALETTE_UYVY,    "UYVY" },
+	{ VIDEO_PALETTE_YUV420,  "YUV420" },
+	{ VIDEO_PALETTE_YUV411,  "YUV411" },
+	{ VIDEO_PALETTE_RAW,     "RAW" },
+	{ VIDEO_PALETTE_YUV422P, "YUV422P" },
+	{ VIDEO_PALETTE_YUV411P, "YUV411P" },
+	{ VIDEO_PALETTE_YUV420P, "YUV420P" },
+	{ VIDEO_PALETTE_YUV410P, "YUV410P" },
+	{ -1, NULL }
+};
+
+/* Decoder error codes: */
+static struct w9968cf_symbolic_list decoder_errlist[] = {
+	{ W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" },
+	{ W9968CF_DEC_ERR_BUF_OVERFLOW,   "Buffer overflow" },
+	{ W9968CF_DEC_ERR_NO_SOI,         "SOI marker not found" },     
+	{ W9968CF_DEC_ERR_NO_SOF0,        "SOF0 marker not found" },
+	{ W9968CF_DEC_ERR_NO_SOS,         "SOS marker not found" },
+	{ W9968CF_DEC_ERR_NO_EOI,         "EOI marker not found" },
+	{ -1, NULL }
+};
+
+/* URB error codes: */
+static struct w9968cf_symbolic_list urb_errlist[] = {
+	{ -ENOMEM,    "No memory for allocation of internal structures" },
+	{ -ENOSPC,    "The host controller's bandwidth is already consumed" },
+	{ -ENOENT,    "URB was canceled by unlink_urb" },
+	{ -EXDEV,     "ISO transfer only partially completed" },
+	{ -EAGAIN,    "Too match scheduled for the future" },
+	{ -ENXIO,     "URB already queued" },
+	{ -EFBIG,     "Too much ISO frames requested" },
+	{ -ENOSR,     "Buffer error (overrun)" },
+	{ -EPIPE,     "Specified endpoint is stalled (device not responding)"},
+	{ -EOVERFLOW, "Babble (bad cable?)" },
+	{ -EPROTO,    "Bit-stuff error (bad cable?)" },
+	{ -EILSEQ,    "CRC/Timeout" },
+	{ -ETIMEDOUT, "NAK (device does not respond)" },
+	{ -1, NULL }
+};
+
+
+
+/****************************************************************************
+ * Memory management functions                                              *
+ ****************************************************************************/
+
+/* Shameless copy from bttv-driver.c */
+
+/* Here we want the physical address of the memory.
+   This is used when initializing the contents of the area. */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+
+static void* rvmalloc(unsigned long size)
+{
+	void* mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		SetPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+
+static void rvfree(void* mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		ClearPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+/* End of shameless copy */
+
+
+/*--------------------------------------------------------------------------
+  Return the maximum size (in bytes) of a frame buffer.
+  --------------------------------------------------------------------------*/
+static inline unsigned long w9968cf_get_max_bufsize(struct w9968cf_device* cam)
+{
+	u8 bpp = (w9968cf_vppmod_present) ? 4 : 2;
+	return (cam->upscaling) ? W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp :
+	                          cam->maxwidth*cam->maxheight*bpp;
+}
+
+
+/*--------------------------------------------------------------------------
+  Deallocate previously allocated memory.
+  --------------------------------------------------------------------------*/
+static void w9968cf_deallocate_memory(struct w9968cf_device* cam)
+{
+	u8 i;
+
+	/* Free the isochronous transfer buffers */
+	for (i = 0; i < W9968CF_URBS; i++) {
+		kfree(cam->transfer_buffer[i]);
+		cam->transfer_buffer[i] = NULL;
+	}
+
+	/* Free temporary frame buffer */
+	if (cam->frame_tmp.buffer) {
+		rvfree(cam->frame_tmp.buffer, W9968CF_HW_BUF_SIZE);
+		cam->frame_tmp.buffer = NULL;
+	}
+
+	/* Free helper buffer */
+	if (cam->vpp_buffer) {
+		rvfree(cam->vpp_buffer, w9968cf_get_max_bufsize(cam));
+		cam->vpp_buffer = NULL;
+	}
+	
+	/* Free video frame buffers */
+	if (cam->frame[0].buffer) {
+		rvfree(cam->frame[0].buffer, 
+		       cam->nbuffers * w9968cf_get_max_bufsize(cam));
+		cam->frame[0].buffer = NULL;
+	}
+
+	cam->nbuffers = 0;
+
+	DBG(5, "Memory successfully deallocated.")
+}
+
+
+/*--------------------------------------------------------------------------
+  Allocate memory buffers for USB transfers and video frames.
+  This function is called by open() only.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_allocate_memory(struct w9968cf_device* cam)
+{
+	const unsigned long bufsize = w9968cf_get_max_bufsize(cam);
+	const u16 p_size = wMaxPacketSize[cam->altsetting-1];
+	void* buff = NULL;
+	u8 i;
+
+	/* NOTE: Deallocation is done elsewhere in case of error */
+
+	/* Allocate memory for the isochronous transfer buffers */
+	for (i = 0; i < W9968CF_URBS; i++) {
+		if (!(cam->transfer_buffer[i] =
+		      kmalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) {
+			DBG(1, "Couldn't allocate memory for the isochronous "
+			       "transfer buffers (%d bytes).", 
+			    p_size * W9968CF_ISO_PACKETS)
+			return -ENOMEM;
+		}
+		memset(cam->transfer_buffer[i], 0, W9968CF_ISO_PACKETS*p_size);
+	}
+
+	/* Allocate memory for the temporary frame buffer */
+	if (!(cam->frame_tmp.buffer = rvmalloc(W9968CF_HW_BUF_SIZE))) {
+		DBG(1, "Couldn't allocate memory for the temporary "
+		       "video frame buffer (%i bytes).", W9968CF_HW_BUF_SIZE)
+		return -ENOMEM;
+	}
+
+	/* Allocate memory for the helper buffer */
+	if (w9968cf_vppmod_present) {
+		if (!(cam->vpp_buffer = rvmalloc(bufsize))) {
+			DBG(1, "Couldn't allocate memory for the helper buffer"
+			       " (%li bytes).", bufsize)
+			return -ENOMEM;
+		}
+	} else
+		cam->vpp_buffer = NULL;
+
+	/* Allocate memory for video frame buffers */	
+	cam->nbuffers = cam->max_buffers;
+	while (cam->nbuffers >= 2) {
+		if ((buff = rvmalloc(cam->nbuffers * bufsize)))
+			break;
+		else
+			cam->nbuffers--;
+	}
+
+	if (!buff) {
+		DBG(1, "Couldn't allocate memory for the video frame buffers.")
+		cam->nbuffers = 0;
+		return -ENOMEM;
+	}
+
+	if (cam->nbuffers != cam->max_buffers)
+		DBG(2, "Couldn't allocate memory for %d video frame buffers. "
+		       "Only memory for %d buffers has been allocated.",
+		    cam->max_buffers, cam->nbuffers)
+
+	for (i = 0; i < cam->nbuffers; i++) {
+		cam->frame[i].buffer = buff + i*bufsize;
+		/* Circular list */
+		if (i != cam->nbuffers-1)
+			cam->frame[i].next = &cam->frame[i+1];
+		else
+			cam->frame[i].next = &cam->frame[0];
+		cam->frame[i].status = F_UNUSED;
+	}
+
+	DBG(5, "Memory successfully allocated.")
+	return 0;
+}
+
+
+
+/****************************************************************************
+ * USB-specific functions                                                   *
+ ****************************************************************************/
+
+/*--------------------------------------------------------------------------
+  This is an handler function which is called after the URBs are completed.
+  It collects multiple data packets coming from the camera by putting them
+  into frame buffers: one or more zero data length data packets are used to
+  mark the end of a video frame; the first non-zero data packet is the start
+  of the next video frame; if an error is encountered in a packet, the entire
+  video frame is discarded and grabbed again.
+  If there are no requested frames in the FIFO list, packets are collected into
+  a temporary buffer. 
+  --------------------------------------------------------------------------*/
+static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct w9968cf_device* cam = (struct w9968cf_device*)urb->context;
+	struct w9968cf_frame_t** f;
+	unsigned long maxbufsize;
+	unsigned int len, status;
+	void* pos;
+	u8 i;
+	int err = 0;
+
+	if ((!cam->streaming) || cam->disconnected) {
+		DBG(4, "Got interrupt, but not streaming.")
+		return;
+	}
+
+	maxbufsize = min( (unsigned long)W9968CF_HW_BUF_SIZE, 
+	                  w9968cf_get_max_bufsize(cam) );
+
+	/* "(*f)" will be used instead of "cam->frame_current" */
+	f = &cam->frame_current;
+
+	/* If a frame has been requested and we are grabbing into  
+	   the temporary frame, we'll switch to that requested frame */
+	if ((*f) == &cam->frame_tmp && *cam->requested_frame) {
+		if (cam->frame_tmp.status == F_GRABBING) {
+			w9968cf_pop_frame(cam, &cam->frame_current);
+			(*f)->status = F_GRABBING;
+			(*f)->length = cam->frame_tmp.length;
+			memcpy((*f)->buffer, cam->frame_tmp.buffer,
+			       (*f)->length);
+			DBG(6, "Switched from temp. frame to frame #%d", 
+			    (*f) - &cam->frame[0])
+		}
+	}
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		len    = urb->iso_frame_desc[i].actual_length;
+		status = urb->iso_frame_desc[i].status;
+		pos    = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
+
+		if (status && len != 0) {
+			DBG(4, "URB failed, error in data packet "
+			       "(error #%d, %s).",
+			    status, symbolic(urb_errlist, status))
+			(*f)->status = F_ERROR;
+			continue;
+		}
+
+		if (len) { /* start of frame */
+
+			if ((*f)->status == F_UNUSED) {
+				(*f)->status = F_GRABBING;
+				(*f)->length = 0;
+			}
+
+			/* Buffer overflows shouldn't happen, however...*/
+			if ((*f)->length + len > maxbufsize) {
+				DBG(4, "Buffer overflow: bad data packets.")
+				(*f)->status = F_ERROR;
+			}
+
+			if ((*f)->status == F_GRABBING) {
+				memcpy((*f)->buffer + (*f)->length, pos, len);
+				(*f)->length += len;
+			}
+
+		} else if ((*f)->status == F_GRABBING) { /* end of frame */
+
+			DBG(6, "Frame #%d successfully grabbed.",
+			    ((*f)==&cam->frame_tmp ? -1 : (*f)-&cam->frame[0]))
+
+			if (cam->vpp_flag & VPP_DECOMPRESSION) {
+				err=(*w9968cf_vpp_check_headers)((*f)->buffer,
+				                                 (*f)->length);
+				if (err) {
+					DBG(4, "Skip corrupted frame: %s",
+					    symbolic(decoder_errlist, err))
+					(*f)->status = F_UNUSED;
+					continue; /* grab this frame again */
+				}
+			}
+
+			(*f)->status = F_READY;
+			(*f)->queued = 0;
+
+			/* Take a pointer to the new frame from the FIFO list.
+			   If the list is empty,we'll use the temporary frame*/
+			if (*cam->requested_frame)
+				w9968cf_pop_frame(cam, &cam->frame_current);
+			else {
+				cam->frame_current = &cam->frame_tmp;
+				(*f)->status = F_UNUSED;
+			}
+
+		} else if ((*f)->status == F_ERROR)
+			(*f)->status = F_UNUSED; /* grab it again */
+
+		PDBGG("Frame length %li | pack.#%d | pack.len. %d | state %d",
+		      (unsigned long)(*f)->length, i, len, (*f)->status)
+
+	} /* end for */
+
+	/* Resubmit this URB */
+	urb->dev = cam->usbdev;
+	urb->status = 0;
+	spin_lock(&cam->urb_lock);
+	if (cam->streaming)
+		if ((err = usb_submit_urb(urb, GFP_ATOMIC))) {
+			cam->misconfigured = 1;
+			DBG(1, "Couldn't resubmit the URB: error %d, %s",
+			    err, symbolic(urb_errlist, err));
+		}
+	spin_unlock(&cam->urb_lock);
+
+	/* Wake up the user process */
+	if (waitqueue_active(&cam->wait_queue))
+		wake_up_interruptible(&cam->wait_queue);
+}
+
+
+/*---------------------------------------------------------------------------
+  Setup the URB structures for the isochronous transfer.
+  Submit the URBs so that the data transfer begins.
+  Return 0 on success, a negative number otherwise.
+  ---------------------------------------------------------------------------*/
+static int w9968cf_start_transfer(struct w9968cf_device* cam)
+{
+	struct usb_device *udev = cam->usbdev;
+	struct urb* urb;
+	const u16 p_size = wMaxPacketSize[cam->altsetting-1];
+	u16 w, h, d;
+	int vidcapt;
+	u32 t_size;
+	int err = 0;
+	s8 i, j;
+
+	for (i = 0; i < W9968CF_URBS; i++) {
+		urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
+		cam->urb[i] = urb;
+
+		if (!urb) {
+			for (j = 0; j < i; j++)
+				usb_free_urb(cam->urb[j]);
+			DBG(1, "Couldn't allocate the URB structures.")
+			return -ENOMEM;
+		}
+
+		urb->dev = udev;
+		urb->context = (void*)cam;
+		urb->pipe = usb_rcvisocpipe(udev, 1);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->number_of_packets = W9968CF_ISO_PACKETS;
+		urb->complete = w9968cf_urb_complete;
+		urb->transfer_buffer = cam->transfer_buffer[i];
+		urb->transfer_buffer_length = p_size*W9968CF_ISO_PACKETS;
+		urb->interval = 1;
+		for (j = 0; j < W9968CF_ISO_PACKETS; j++) {
+			urb->iso_frame_desc[j].offset = p_size*j;
+			urb->iso_frame_desc[j].length = p_size;
+		}
+	}
+
+	/* Transfer size per frame, in WORD ! */
+	d = cam->hw_depth;
+	w = cam->hw_width;
+	h = cam->hw_height;
+
+	t_size = (w*h*d)/16;
+
+	err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset  everything */
+	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */
+
+	/* Transfer size */
+	err += w9968cf_write_reg(cam, t_size & 0xffff, 0x3d); /* low bits */
+	err += w9968cf_write_reg(cam, t_size >> 16, 0x3e);    /* high bits */
+
+	if (cam->vpp_flag & VPP_DECOMPRESSION)
+		err += w9968cf_upload_quantizationtables(cam);
+
+	vidcapt = w9968cf_read_reg(cam, 0x16); /* read picture settings */
+	err += w9968cf_write_reg(cam, vidcapt|0x8000, 0x16); /* capt. enable */
+
+	err += usb_set_interface(udev, 0, cam->altsetting);
+	err += w9968cf_write_reg(cam, 0x8a05, 0x3c); /* USB FIFO enable */
+
+	if (err || (vidcapt < 0)) {
+		for (i = 0; i < W9968CF_URBS; i++)
+			usb_free_urb(cam->urb[i]);
+		DBG(1, "Couldn't tell the camera to start the data transfer.")
+		return err;
+	}
+
+	w9968cf_init_framelist(cam);
+
+	/* Begin to grab into the temporary buffer */
+	cam->frame_tmp.status = F_UNUSED;
+	cam->frame_tmp.queued = 0;
+	cam->frame_current = &cam->frame_tmp;
+
+	if (!(cam->vpp_flag & VPP_DECOMPRESSION))
+		DBG(5, "Isochronous transfer size: %li bytes/frame.",
+		    (unsigned long)t_size*2)
+
+	DBG(5, "Starting the isochronous transfer...")
+
+	/* Submit the URBs */
+	for (i = 0; i < W9968CF_URBS; i++) {
+		err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
+		if (err) {
+			for (j = i-1; j >= 0; j--)
+				if (!usb_unlink_urb(cam->urb[j]))
+					usb_free_urb(cam->urb[j]);
+			DBG(1, "Couldn't send a transfer request to the "
+			       "USB core (error #%d, %s).", err, 
+			    symbolic(urb_errlist, err))
+		}
+	}
+
+	cam->streaming = 1;
+
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Stop the isochronous transfer and set alternate setting to 0 (0Mb/s).
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_stop_transfer(struct w9968cf_device* cam)
+{
+	struct usb_device *udev = cam->usbdev;
+	unsigned long lock_flags;
+	int err = 0;
+	s8 i;
+
+	/* This avoids race conditions with usb_submit_urb() 
+	   in the URB completition handler */
+	spin_lock_irqsave(&cam->urb_lock, lock_flags);
+	cam->streaming = 0;
+	spin_unlock_irqrestore(&cam->urb_lock, lock_flags);
+
+	for (i = W9968CF_URBS-1; i >= 0; i--)
+		if (cam->urb[i])
+			if (!usb_unlink_urb(cam->urb[i])) {
+				usb_free_urb(cam->urb[i]);
+				cam->urb[i] = NULL;
+			}
+
+	if (cam->disconnected)
+		goto exit;
+
+	err = w9968cf_write_reg(cam, 0x0a05, 0x3c); /* stop USB transfer */
+	err += usb_set_interface(udev, 0, 0); /* 0 Mb/s */
+	err += w9968cf_write_reg(cam, 0x0000, 0x39); /* disable JPEG encoder */
+	err += w9968cf_write_reg(cam, 0x0000, 0x16); /* stop video capture */
+
+	if (err) {
+		DBG(2, "Failed to tell the camera to stop the isochronous "
+		       "transfer. However this is not a critical error.")
+		return -EIO;
+	}
+
+exit:
+	DBG(5, "Isochronous transfer stopped.")
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Write a W9968CF register. 
+  Return 0 on success, -1 otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index)
+{
+	struct usb_device* udev = cam->usbdev;
+	int res;
+
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
+	                      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+	                      value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT);
+
+	if (res < 0)
+		DBG(4, "Failed to write a register "
+		       "(value 0x%04X, index 0x%02X, error #%d, %s).",
+		    value, index, res, symbolic(urb_errlist, res))
+
+	return (res >= 0) ? 0 : -1;
+}
+
+
+/*--------------------------------------------------------------------------
+  Read a W9968CF register. 
+  Return the register value on success, -1 otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index)
+{
+	struct usb_device* udev = cam->usbdev;
+	u16* buff = cam->control_buffer;
+	int res;
+
+	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1,
+	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      0, index, (void*)buff,
+	                      2, W9968CF_USB_CTRL_TIMEOUT);
+
+	if (res < 0)
+		DBG(4, "Failed to read a register "
+		       "(index 0x%02X, error #%d, %s).",
+		    index, res, symbolic(urb_errlist, res))
+
+	return (res >= 0) ? (int)(*buff) : -1;
+}
+
+
+/*--------------------------------------------------------------------------
+  Write data to the fast serial bus registers.
+  Return 0 on success, -1 otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data)
+{
+	struct usb_device* udev = cam->usbdev;
+	u16 value;
+	int res;
+
+	value = *data++;
+
+	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
+	                      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+	                      value, 0x06, (void*)data, 6,
+	                      W9968CF_USB_CTRL_TIMEOUT);
+
+	if (res < 0)
+		DBG(4, "Failed to write the FSB registers "
+		       "(error #%d, %s).", res, symbolic(urb_errlist, res))
+
+	return (res >= 0) ? 0 : -1;
+}
+
+
+/*--------------------------------------------------------------------------
+  Write data to the serial bus control register.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_write_sb(struct w9968cf_device* cam, u16 value)
+{
+	int err = 0;
+
+	err = w9968cf_write_reg(cam, value, 0x01);
+	udelay(W9968CF_I2C_BUS_DELAY);
+
+	return err;
+}
+
+
+/*--------------------------------------------------------------------------
+  Read data from the serial bus control register.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_read_sb(struct w9968cf_device* cam)
+{
+	int v = 0;
+
+	v = w9968cf_read_reg(cam, 0x01);
+	udelay(W9968CF_I2C_BUS_DELAY);
+
+	return v;
+}
+
+
+/*--------------------------------------------------------------------------
+  Upload quantization tables for the JPEG compression.
+  This function is called by w9968cf_start_transfer().
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_upload_quantizationtables(struct w9968cf_device* cam)
+{
+	u16 a, b;
+	int err = 0, i, j;
+
+	err += w9968cf_write_reg(cam, 0x0010, 0x39); /* JPEG clock enable */
+
+	for (i = 0, j = 0; i < 32; i++, j += 2) {
+		a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8);
+		b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8);
+		err += w9968cf_write_reg(cam, a, 0x40+i);
+		err += w9968cf_write_reg(cam, b, 0x60+i);
+	}
+	err += w9968cf_write_reg(cam, 0x0012, 0x39); /* JPEG encoder enable */
+
+	return err;
+}
+
+
+
+/****************************************************************************
+ * Low-level I2C I/O functions.                                             *
+ * The adapter supports the following I2C transfer functions:               *
+ * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only)           *
+ * i2c_adap_read_byte_data()                                                *
+ * i2c_adap_read_byte()                                                     *
+ ****************************************************************************/
+
+static int w9968cf_smbus_start(struct w9968cf_device* cam)
+{
+	int err = 0;
+
+	err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+	err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+
+	return err;
+}
+
+
+static int w9968cf_smbus_stop(struct w9968cf_device* cam)
+{
+	int err = 0;
+
+	err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+	err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+
+	return err;
+}
+
+
+static int w9968cf_smbus_write_byte(struct w9968cf_device* cam, u8 v)
+{
+	u8 bit;
+	int err = 0, sda;
+
+	for (bit = 0 ; bit < 8 ; bit++) {
+		sda = (v & 0x80) ? 2 : 0;
+		v <<= 1;
+		/* SDE=1, SDA=sda, SCL=0 */
+		err += w9968cf_write_sb(cam, 0x10 | sda);
+		/* SDE=1, SDA=sda, SCL=1 */
+		err += w9968cf_write_sb(cam, 0x11 | sda);
+		/* SDE=1, SDA=sda, SCL=0 */
+		err += w9968cf_write_sb(cam, 0x10 | sda);
+	}
+
+	return err;
+}
+
+
+static int w9968cf_smbus_read_byte(struct w9968cf_device* cam, u8* v)
+{
+	u8 bit;
+	int err = 0;
+
+	*v = 0;
+	for (bit = 0 ; bit < 8 ; bit++) {
+		*v <<= 1;
+		err += w9968cf_write_sb(cam, 0x0013);
+		*v |= (w9968cf_read_sb(cam) & 0x0008) ? 1 : 0;
+		err += w9968cf_write_sb(cam, 0x0012);
+	}
+
+	return err;
+}
+
+
+static int w9968cf_smbus_write_ack(struct w9968cf_device* cam)
+{
+	int err = 0;
+
+	err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+	err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+	err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+
+	return err;
+}
+
+
+static int w9968cf_smbus_read_ack(struct w9968cf_device* cam)
+{
+	int err = 0, sda;
+
+	err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+	sda = (w9968cf_read_sb(cam) & 0x08) ? 1 : 0; /* sda = SDA */
+	err += w9968cf_write_sb(cam, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+	if (sda < 0)
+		err += sda;
+	if (sda == 1) {
+		DBG(6, "Couldn't receive the ACK.")
+		err += -1;
+	}
+
+	return err;
+}
+
+
+/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
+static int 
+w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, 
+                                     u16 address, u8 subaddress,u8 value)
+{
+	u16* data = cam->data_buffer;
+	int err = 0;
+
+	 /* Enable SBUS outputs */
+	err += w9968cf_write_reg(cam, 0x0020, 0x01);
+
+	data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0);
+	data[0] |= (address & 0x40) ? 0x4000 : 0x0;
+	data[1] = 0x2082 | ((address & 0x40) ? 0x0005 : 0x0);
+	data[1] |= (address & 0x20) ? 0x0150 : 0x0;
+	data[1] |= (address & 0x10) ? 0x5400 : 0x0;
+	data[2] = 0x8208 | ((address & 0x08) ? 0x0015 : 0x0);
+	data[2] |= (address & 0x04) ? 0x0540 : 0x0;
+	data[2] |= (address & 0x02) ? 0x5000 : 0x0;
+	data[3] = 0x1d20 | ((address & 0x02) ? 0x0001 : 0x0);
+	data[3] |= (address & 0x01) ? 0x0054 : 0x0;
+
+	err += w9968cf_write_fsb(cam, data);
+
+	data[0] = 0x8208 | ((subaddress & 0x80) ? 0x0015 : 0x0);
+	data[0] |= (subaddress & 0x40) ? 0x0540 : 0x0;
+	data[0] |= (subaddress & 0x20) ? 0x5000 : 0x0;
+	data[1] = 0x0820 | ((subaddress & 0x20) ? 0x0001 : 0x0);
+	data[1] |= (subaddress & 0x10) ? 0x0054 : 0x0;
+	data[1] |= (subaddress & 0x08) ? 0x1500 : 0x0;
+	data[1] |= (subaddress & 0x04) ? 0x4000 : 0x0;
+	data[2] = 0x2082 | ((subaddress & 0x04) ? 0x0005 : 0x0);
+	data[2] |= (subaddress & 0x02) ? 0x0150 : 0x0;
+	data[2] |= (subaddress & 0x01) ? 0x5400 : 0x0;
+	data[3] = 0x001d;
+
+	err += w9968cf_write_fsb(cam, data);
+
+	data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
+	data[0] |= (value & 0x40) ? 0x0540 : 0x0;
+	data[0] |= (value & 0x20) ? 0x5000 : 0x0;
+	data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0);
+	data[1] |= (value & 0x10) ? 0x0054 : 0x0;
+	data[1] |= (value & 0x08) ? 0x1500 : 0x0;
+	data[1] |= (value & 0x04) ? 0x4000 : 0x0;
+	data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0);
+	data[2] |= (value & 0x02) ? 0x0150 : 0x0;
+	data[2] |= (value & 0x01) ? 0x5400 : 0x0;
+	data[3] = 0xfe1d;
+
+	err += w9968cf_write_fsb(cam, data);
+
+	/* Disable SBUS outputs */
+	err += w9968cf_write_reg(cam, 0x0000, 0x01);
+
+	if (!err)
+		DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X "
+		       "value 0x%02X.", address, subaddress, value)
+	else
+		DBG(5, "I2C write byte data failed, addr.0x%04X, "
+		       "subaddr.0x%02X, value 0x%02X.", 
+	            address, subaddress, value)
+
+	return err;
+}
+
+
+/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
+static int 
+w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, 
+                                u16 address, u8 subaddress, 
+                                u8* value)
+{
+	int err = 0;
+
+	/* Serial data enable */
+	err += w9968cf_write_sb(cam, 0x0013); /* don't change ! */
+
+	err += w9968cf_smbus_start(cam);
+	err += w9968cf_smbus_write_byte(cam, address);
+	err += w9968cf_smbus_read_ack(cam);
+	err += w9968cf_smbus_write_byte(cam, subaddress);
+	err += w9968cf_smbus_read_ack(cam);
+	err += w9968cf_smbus_stop(cam);
+	err += w9968cf_smbus_start(cam);
+	err += w9968cf_smbus_write_byte(cam, address + 1);
+	err += w9968cf_smbus_read_ack(cam);
+	err += w9968cf_smbus_read_byte(cam, value);
+	err += w9968cf_smbus_write_ack(cam);
+	err += w9968cf_smbus_stop(cam);
+ 
+	/* Serial data disable */
+	err += w9968cf_write_sb(cam, 0x0000);
+
+	if (!err)
+		DBG(5, "I2C read byte data done, addr.0x%04X, "
+		       "subaddr.0x%02X, value 0x%02X.", 
+		    address, subaddress, *value)
+	else
+		DBG(5, "I2C read byte data failed, addr.0x%04X, "
+		       "subaddr.0x%02X, wrong value 0x%02X.",
+		    address, subaddress, *value)
+
+	return err;
+}
+
+
+/* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */
+static int 
+w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
+                           u16 address, u8* value)
+{
+	int err = 0;
+
+	/* Serial data enable */
+	err += w9968cf_write_sb(cam, 0x0013);
+
+	err += w9968cf_smbus_start(cam);
+	err += w9968cf_smbus_write_byte(cam, address + 1);
+	err += w9968cf_smbus_read_ack(cam);
+	err += w9968cf_smbus_read_byte(cam, value);
+	err += w9968cf_smbus_write_ack(cam);
+	err += w9968cf_smbus_stop(cam);
+ 
+	/* Serial data disable */
+	err += w9968cf_write_sb(cam, 0x0000);
+
+	if (!err)
+		DBG(5, "I2C read byte done, addr.0x%04X."
+		       "value 0x%02X.", address, *value)
+	else
+		DBG(5, "I2C read byte failed, addr.0x%04X."
+		       "wrong value 0x%02X.", address, *value)
+
+	return err;
+}
+
+
+/* SMBus protocol: S Addr Wr [A] Value [A] P */
+static int 
+w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam,
+                            u16 address, u8 value)
+{
+	DBG(4, "i2c_write_byte() is an unsupported transfer mode.")
+	return -EINVAL;
+}
+
+
+
+/****************************************************************************
+ * I2C interface to kernel                                                  *
+ ****************************************************************************/
+
+static int
+w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, 
+                       unsigned short flags, char read_write, u8 command,
+                       int size, union i2c_smbus_data *data)
+{
+	struct w9968cf_device* cam = i2c_get_adapdata(adapter);
+	u8 i, j;
+	int rc = 0, err = 0; 
+
+	switch (addr) {
+		case OV6xx0_SID:
+		case OV7xx0_SID:
+			break;
+		default:
+			DBG(4, "Rejected slave ID 0x%04X", addr)
+			return -EINVAL;
+	}
+
+	if (size == I2C_SMBUS_BYTE) {
+		/* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */
+		addr <<= 1;
+
+		if (read_write == I2C_SMBUS_WRITE)
+ 			rc = w9968cf_i2c_adap_write_byte(cam, addr, command);
+		else if (read_write == I2C_SMBUS_READ) 
+			rc = w9968cf_i2c_adap_read_byte(cam,addr, &data->byte);
+
+	} else if (size == I2C_SMBUS_BYTE_DATA) {
+		addr <<= 1;
+
+		if (read_write == I2C_SMBUS_WRITE)
+ 			rc = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,
+			                                  command, data->byte);
+		else if (read_write == I2C_SMBUS_READ) {
+			for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
+				rc = w9968cf_i2c_adap_read_byte_data(cam, addr, 
+				                         command, &data->byte);
+				if (rc < 0) {
+					/* Work around: this seems to wake up  
+					   the EEPROM from the stall state */
+					for (j = 0; j <= 10; j++) {
+					   err += w9968cf_write_sb(cam,0x0020);
+					   err += w9968cf_write_sb(cam,0x0000);
+					   if (err)
+					   	break;
+					}
+				}
+				else
+					break;
+			}
+
+		} else
+			return -EINVAL;
+
+	} else {
+		DBG(4, "Unsupported I2C transfer mode (%d)", size)
+		return -EINVAL;
+	}
+
+	/* This works around a bug in the I2C core */
+	if (rc > 0)
+		rc = 0;
+
+	return rc;
+}
+
+
+static u32 w9968cf_i2c_func(struct i2c_adapter* adap)
+{
+	return I2C_FUNC_SMBUS_READ_BYTE |
+	       I2C_FUNC_SMBUS_READ_BYTE_DATA  |
+	       I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+
+static int w9968cf_i2c_attach_inform(struct i2c_client* client)
+{
+	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
+	const char* clientname = i2c_clientname(client);
+	int id = client->driver->id;
+
+	if (id == I2C_DRIVERID_OVCAMCHIP) {
+		int rc = 0;
+
+		cam->sensor_client = client;
+
+		rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, 
+		                        &cam->sensor_mono);
+		if (rc < 0) {
+			DBG(1, "CMOS sensor initialization failed (rc=%d)",rc);
+			cam->sensor_client = NULL;
+			return rc;
+		}
+
+		if (w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, 
+		                       &cam->sensor) < 0)
+			rc = -EIO;
+		else if (client->addr==OV7xx0_SID || client->addr==OV6xx0_SID)
+			w9968cf_sensor_configure(cam);
+		else
+			rc = -EINVAL;
+
+		if (rc < 0) {
+			cam->sensor_client = NULL;
+			cam->sensor = CC_UNKNOWN;
+			return rc;
+		}
+	} else	{
+		DBG(4, "Rejected client [%s] with [%s]", 
+		    clientname, client->driver->name)
+		return -1;
+	}
+
+	DBG(2, "I2C attach client [%s] with [%s]",
+	    clientname, client->driver->name)
+
+	return 0;
+}
+
+
+static int w9968cf_i2c_detach_inform(struct i2c_client* client)
+{
+	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
+	const char* clientname = i2c_clientname(client);
+
+	if (cam->sensor_client == client) {
+		cam->sensor_client = NULL;
+	}
+
+	DBG(2, "I2C detach [%s]", clientname)
+
+	return 0;
+}
+
+
+static int 
+w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd,
+                    unsigned long arg)
+{
+	return 0;
+}
+
+
+static int w9968cf_i2c_init(struct w9968cf_device* cam)
+{
+	int rc = 0;
+
+	static struct i2c_algorithm algo = {
+		.name =          "W996[87]CF algorithm",
+		.id =            I2C_ALGO_SMBUS,
+		.smbus_xfer =    w9968cf_i2c_smbus_xfer,
+		.algo_control =  w9968cf_i2c_control,
+		.functionality = w9968cf_i2c_func,
+	};
+
+	static struct i2c_adapter adap = {
+		.id =                I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
+		.class =             I2C_ADAP_CLASS_CAM_DIGITAL,
+		.owner =             THIS_MODULE,
+		.client_register =   w9968cf_i2c_attach_inform,
+		.client_unregister = w9968cf_i2c_detach_inform,
+		.algo =              &algo,
+	};
+
+	memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
+	strcpy(cam->i2c_adapter.name, "w9968cf");
+	i2c_set_adapdata(&cam->i2c_adapter, cam);
+
+	DBG(6, "Registering I2C bus with kernel...")
+
+	rc = i2c_add_adapter(&cam->i2c_adapter);
+	if (rc)
+		DBG(5, "Failed to register the I2C bus.")
+	else
+		DBG(5, "I2C bus registered.")
+
+	return rc;
+}
+
+
+
+/****************************************************************************
+ * Helper functions                                                         *
+ ****************************************************************************/
+
+/*--------------------------------------------------------------------------
+  Turn on the LED on some webcams. A beep should be heard too.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_turn_on_led(struct w9968cf_device* cam)
+{
+	int err = 0;
+
+	err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power-down */
+	err += w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */
+	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */
+	err += w9968cf_write_reg(cam, 0x0010, 0x01); /* serial bus, SDS high */
+	err += w9968cf_write_reg(cam, 0x0000, 0x01); /* serial bus, SDS low */
+	err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */
+
+	if (err)
+		DBG(2, "Couldn't turn on the LED.")
+
+	DBG(5, "LED turned on.")
+
+	return err;
+}
+
+
+/*--------------------------------------------------------------------------
+  Write some registers for the device initialization.
+  This function is called once on open().
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_init_chip(struct w9968cf_device* cam)
+{
+	int err = 0, rc = 0;
+
+	err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */
+	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */
+
+	err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */
+	err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */
+
+	err += w9968cf_write_reg(cam, 0x0000, 0x20); /* Y frame buf.0, low */
+	err += w9968cf_write_reg(cam, 0x0000, 0x21); /* Y frame buf.0, high */
+	err += w9968cf_write_reg(cam, 0xb000, 0x22); /* Y frame buf.1, low */
+	err += w9968cf_write_reg(cam, 0x0004, 0x23); /* Y frame buf.1, high */
+	err += w9968cf_write_reg(cam, 0x5800, 0x24); /* U frame buf.0, low */
+	err += w9968cf_write_reg(cam, 0x0002, 0x25); /* U frame buf.0, high */
+	err += w9968cf_write_reg(cam, 0x0800, 0x26); /* U frame buf.1, low */
+	err += w9968cf_write_reg(cam, 0x0007, 0x27); /* U frame buf.1, high */
+	err += w9968cf_write_reg(cam, 0x8400, 0x28); /* V frame buf.0, low */
+	err += w9968cf_write_reg(cam, 0x0003, 0x29); /* V frame buf.0, high */
+	err += w9968cf_write_reg(cam, 0x3400, 0x2a); /* V frame buf.1, low */
+	err += w9968cf_write_reg(cam, 0x0008, 0x2b); /* V frame buf.1, high */
+
+	err += w9968cf_write_reg(cam, 0x6000, 0x32); /* JPEG bitstream buf 0 */
+	err += w9968cf_write_reg(cam, 0x0009, 0x33); /* JPEG bitstream buf 0 */
+	err += w9968cf_write_reg(cam, 0x2000, 0x34); /* JPEG bitstream buf 1 */
+	err += w9968cf_write_reg(cam, 0x000d, 0x35); /* JPEG bitstream buf 1 */
+
+	err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */
+	err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/
+	err += w9968cf_write_reg(cam, 0x0000, 0x38);/* disable hw up-scaling */
+	err += w9968cf_write_reg(cam, 0x0000, 0x3f); /* JPEG/MCTL test data */
+
+	err += w9968cf_set_picture(cam, cam->picture); /* this before */
+	err += w9968cf_set_window(cam, cam->window);
+
+	if (err)
+		goto error;
+
+	rc = w9968cf_sensor_change_settings(cam);
+	if (rc)
+		goto error;
+
+	DBG(5, "Chip successfully initialized.");
+	
+	return 0;
+
+error:
+	DBG(1, "Chip initialization failed.")
+	if (err)
+		return err;
+	else
+		return rc;
+}
+
+
+/*--------------------------------------------------------------------------
+  Change the picture settings of the camera.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int
+w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict)
+{
+	u16 fmt, hw_depth, hw_palette, reg_v = 0x0000;
+	int err = 0, rc = 0;
+
+	/* Make sure we are using a valid depth */
+	pict.depth = w9968cf_valid_depth(pict.palette);
+
+	fmt = pict.palette;
+
+	hw_depth = pict.depth; /* depth used by the winbond chip */
+	hw_palette = pict.palette; /* palette used by the winbond chip */
+
+	/* VS & HS polarities */
+	reg_v = (cam->vs_polarity << 12) | (cam->hs_polarity << 11);
+
+	switch (fmt)
+	{
+		case VIDEO_PALETTE_UYVY:
+			reg_v |= 0x0000;
+			cam->vpp_flag = VPP_NONE;
+			break;
+		case VIDEO_PALETTE_YUV422P:
+			reg_v |= 0x0002;
+			cam->vpp_flag = VPP_DECOMPRESSION;
+			break;
+		case VIDEO_PALETTE_YUV420:
+		case VIDEO_PALETTE_YUV420P:
+			reg_v |= 0x0003;
+			cam->vpp_flag = VPP_DECOMPRESSION;
+			break;
+		case VIDEO_PALETTE_YUYV:
+		case VIDEO_PALETTE_YUV422:
+			reg_v |= 0x0000;
+			cam->vpp_flag = VPP_SWAP_YUV_BYTES;
+			hw_palette = VIDEO_PALETTE_UYVY;
+			break;
+		/* Original video is used instead of RGBX palettes. 
+		   Software conversion later. */
+		case VIDEO_PALETTE_GREY:
+		case VIDEO_PALETTE_RGB555:
+		case VIDEO_PALETTE_RGB565:
+		case VIDEO_PALETTE_RGB24:
+		case VIDEO_PALETTE_RGB32:
+			reg_v |= 0x0000; /* UYVY 16 bit is used */
+			hw_depth = 16;
+			hw_palette = VIDEO_PALETTE_UYVY;
+			cam->vpp_flag = VPP_UYVY_TO_RGBX;
+			break;
+	}
+
+	/* FIXME: 'hardware double buffer' doesn't work when compressed video
+	          is enabled (corrupted frames). */
+	if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION))
+		reg_v |= 0x0080;
+
+	if (cam->clamping)
+		reg_v |= 0x0020;
+
+	if (cam->filter_type == 1)
+		reg_v |= 0x0008;
+	else if (cam->filter_type == 2)
+		reg_v |= 0x000c;
+
+	err = w9968cf_write_reg(cam, reg_v, 0x16);
+	if (err)
+		goto error;
+
+	rc = w9968cf_sensor_set_picture(cam, pict);
+	if (rc)
+		goto error;
+
+	/* If all went well, update the device data structure */
+	memcpy(&cam->picture, &pict, sizeof(pict));
+	cam->hw_depth = hw_depth;
+	cam->hw_palette = hw_palette;
+
+	/* Settings changed, so we clear the frame buffers */
+	memset(cam->frame[0].buffer, 0, 
+	       cam->nbuffers*w9968cf_get_max_bufsize(cam));
+
+	DBG(4, "Palette is %s, depth is %d bpp.",
+	    symbolic(v4l1_plist, pict.palette), pict.depth)
+
+	return 0;
+
+error:
+	DBG(1, "Failed to change picture settings.")
+	if (err)
+		return err;
+	else 
+		return rc;
+}
+
+
+/*--------------------------------------------------------------------------
+  Change the capture area size of the camera.
+  This function _must_ be called _after_ w9968cf_set_picture().
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int
+w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
+{
+	u16 x, y, w, h, scx, scy, cw, ch, ax, ay;
+	unsigned long fw, fh;
+	struct ovcamchip_window s_win;
+	int err=0, rc=0;
+
+	/* Work around to avoid FP arithmetics */
+	#define __SC(x) ((x) << 10)
+	#define __UNSC(x) ((x) >> 10)
+
+	/* Make sure we are using a supported resolution */
+	if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, 
+	                                      (u16*)&win.height)))
+		goto error;
+
+	/* Scaling factors */
+	fw = __SC(win.width) / cam->maxwidth;
+	fh = __SC(win.height) / cam->maxheight;
+
+	/* Set up the width and height values used by the chip */
+	if ((win.width > cam->maxwidth) || (win.height > cam->maxheight)) {
+		cam->vpp_flag |= VPP_UPSCALE;
+		/* Calculate largest w,h mantaining the same w/h ratio */
+		w = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh;
+		h = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight;
+		if (w < cam->minwidth) /* just in case */
+			w = cam->minwidth;
+		if (h < cam->minheight) /* just in case */
+			h = cam->minheight;
+	} else {
+		cam->vpp_flag &= ~VPP_UPSCALE;
+		w = win.width;
+		h = win.height;
+	}
+
+	/* x,y offsets of the cropped area */
+	scx = cam->start_cropx;
+	scy = cam->start_cropy;
+
+	/* Calculate cropped area manteining the right w/h ratio */
+	if (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) {
+		cw = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh;
+		ch = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight;
+	} else {
+		cw = w;
+		ch = h;
+	}
+
+	/* Setup the sensor window */
+	s_win.format = SENSOR_FORMAT;
+	s_win.width = cam->maxwidth;
+	s_win.height = cam->maxheight;
+	s_win.quarter = 0; /* full progressive video */
+
+	/* Center it */
+	s_win.x = (s_win.width - cw) / 2;
+	s_win.y = (s_win.height - ch) / 2;
+
+	/* Clock divisor */
+	if (cam->clockdiv >= 0)
+		s_win.clockdiv = cam->clockdiv; /* manual override */
+	else
+		switch (cam->sensor) {
+			case CC_OV6620:
+				s_win.clockdiv = 0;
+				break;
+			case CC_OV6630:
+				s_win.clockdiv = 0;
+				break;
+			case CC_OV76BE:
+			case CC_OV7610:
+			case CC_OV7620:
+				s_win.clockdiv = 0;
+				break;
+			default:
+				s_win.clockdiv = W9968CF_DEF_CLOCKDIVISOR;
+		}
+
+	/* We have to scale win.x and win.y offsets */	
+	if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE))
+	     || (cam->vpp_flag & VPP_UPSCALE) ) {
+		ax = __SC(win.x)/fw;
+		ay = __SC(win.y)/fh;
+	} else {
+		ax = win.x;
+		ay = win.y;
+	}
+
+	if ((ax + cw) > cam->maxwidth)
+		ax = cam->maxwidth - cw;
+
+	if ((ay + ch) > cam->maxheight)
+		ay = cam->maxheight - ch;
+
+	/* Adjust win.x, win.y */
+	if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE))
+	     || (cam->vpp_flag & VPP_UPSCALE) ) {
+		win.x = __UNSC(ax*fw);
+		win.y = __UNSC(ay*fh);
+	} else {
+		win.x = ax;
+		win.y = ay;
+	}
+
+	/* Offsets used by the chip */
+	x = ax + s_win.x;
+	y = ay + s_win.y;
+
+	/* Go ! */
+	if ((rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win)))
+		goto error;
+
+	err += w9968cf_write_reg(cam, scx + x, 0x10);
+	err += w9968cf_write_reg(cam, scy + y, 0x11);
+	err += w9968cf_write_reg(cam, scx + x + cw, 0x12);
+	err += w9968cf_write_reg(cam, scy + y + ch, 0x13);
+	err += w9968cf_write_reg(cam, w, 0x14);
+	err += w9968cf_write_reg(cam, h, 0x15);
+
+	/* JPEG width & height */
+	err += w9968cf_write_reg(cam, w, 0x30);
+	err += w9968cf_write_reg(cam, h, 0x31);
+
+	/* Y & UV frame buffer strides (in WORD) */
+	if (cam->vpp_flag & VPP_DECOMPRESSION) {
+		err += w9968cf_write_reg(cam, w/2, 0x2c);
+		err += w9968cf_write_reg(cam, w/4, 0x2d);
+	} else
+		err += w9968cf_write_reg(cam, w, 0x2c);
+
+	if (err)
+		goto error;
+
+	/* If all went well, update the device data structure */
+	memcpy(&cam->window, &win, sizeof(win));
+	cam->hw_width = w;
+	cam->hw_height = h;
+
+	/* Settings changed, so we clear the frame buffers */
+	memset(cam->frame[0].buffer, 0, 
+	       cam->nbuffers*w9968cf_get_max_bufsize(cam));
+
+	DBG(4, "The capture area is %dx%d, Offset (x,y)=(%d,%d).", 
+	    win.width, win.height, win.x, win.y)
+
+	PDBGG("x=%d ,y=%d, w=%d, h=%d, ax=%d, ay=%d, s_win.x=%d, s_win.y=%d, "
+	      "cw=%d, ch=%d, win.x=%d ,win.y=%d, win.width=%d, win.height=%d",
+	      x, y, w, h, ax, ay, s_win.x, s_win.y, cw, ch, win.x, win.y,
+	      win.width, win.height)
+
+	return 0;
+
+error:
+	DBG(1, "Failed to change the capture area size.")
+	if (err)
+		return err;
+	else
+		return rc;
+}
+
+
+/*--------------------------------------------------------------------------
+  Return non-zero if the palette is supported, 0 otherwise.
+  --------------------------------------------------------------------------*/
+static inline u16 w9968cf_valid_palette(u16 palette)
+{
+	u8 i = 0;
+	while (w9968cf_formatlist[i].palette != 0) {
+		if (palette == w9968cf_formatlist[i].palette)
+			return palette;
+		i++;
+	}
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Return the depth corresponding to the given palette.
+  Palette _must_ be supported !
+  --------------------------------------------------------------------------*/
+static inline u16 w9968cf_valid_depth(u16 palette)
+{
+	u8 i=0;
+	while (w9968cf_formatlist[i].palette != palette)
+		i++;
+
+	return w9968cf_formatlist[i].depth;
+}
+
+
+/*--------------------------------------------------------------------------
+  Return non-zero if the format requires decompression, 0 otherwise.
+  --------------------------------------------------------------------------*/
+static inline u8 w9968cf_need_decompression(u16 palette)
+{
+	u8 i = 0;
+	while (w9968cf_formatlist[i].palette != 0) {
+		if (palette == w9968cf_formatlist[i].palette)
+			return w9968cf_formatlist[i].compression;
+		i++;
+	}
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------- 
+  Adjust the asked values for window width and height.
+  Return 0 on success, -1 otherwise.
+  --------------------------------------------------------------------------*/
+static int 
+w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
+{
+	u16 maxw, maxh;
+
+	if ((*width < cam->minwidth) || (*height < cam->minheight))
+		return -ERANGE;
+
+	maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION)
+	       && w9968cf_vppmod_present ? W9968CF_MAX_WIDTH : cam->maxwidth;
+	maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION)
+	       && w9968cf_vppmod_present ? W9968CF_MAX_HEIGHT : cam->maxheight;
+
+	if (*width > maxw)
+		*width = maxw;
+	if (*height > maxh)
+		*height = maxh;
+
+	if (cam->vpp_flag & VPP_DECOMPRESSION) {
+		*width  &= ~15L; /* multiple of 16 */
+		*height &= ~15L;
+	}
+
+	PDBGG("Window size adjusted w=%d, h=%d ", *width, *height)
+
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Initialize the FIFO list of requested frames.
+  --------------------------------------------------------------------------*/
+static void w9968cf_init_framelist(struct w9968cf_device* cam)
+{
+	u8 i;
+
+	for (i = 0; i < cam->nbuffers; i++) {
+		cam->requested_frame[i] = NULL;
+		cam->frame[i].queued = 0;
+		cam->frame[i].status = F_UNUSED;
+	}
+}
+
+
+/*--------------------------------------------------------------------------
+  Add a frame in the FIFO list of requested frames.
+  This function is called in process context.
+  --------------------------------------------------------------------------*/
+static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num)
+{
+	u8 f;
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&cam->flist_lock, lock_flags);
+
+	for (f=0; cam->requested_frame[f] != NULL; f++);
+	cam->requested_frame[f] = &cam->frame[f_num];
+	cam->frame[f_num].queued = 1;
+	cam->frame[f_num].status = F_UNUSED; /* clear the status */
+
+	spin_unlock_irqrestore(&cam->flist_lock, lock_flags);
+
+	DBG(6, "Frame #%d pushed into the FIFO list. Position %d.", f_num, f)
+}
+
+
+/*--------------------------------------------------------------------------
+  Read, store and remove the first pointer in the FIFO list of requested
+  frames. This function is called in interrupt context.
+  --------------------------------------------------------------------------*/
+static void 
+w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep)
+{
+	u8 i;
+
+	spin_lock(&cam->flist_lock);
+
+	*framep = cam->requested_frame[0];
+
+	/* Shift the list of pointers */
+	for (i = 0; i < cam->nbuffers-1; i++)
+		cam->requested_frame[i] = cam->requested_frame[i+1];
+	cam->requested_frame[i] = NULL;
+
+	spin_unlock(&cam->flist_lock);
+
+	DBG(6,"Popped frame #%d from the list.",*framep-&cam->frame[0])
+}
+
+
+/*--------------------------------------------------------------------------
+  High-level video post-processing routine on grabbed frames.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int 
+w9968cf_postprocess_frame(struct w9968cf_device* cam, 
+                          struct w9968cf_frame_t* fr)
+{
+	void *pIn = fr->buffer, *pOut = cam->vpp_buffer, *tmp;
+	u16 w = cam->window.width,
+	    h = cam->window.height,
+	    d = cam->picture.depth,
+	    fmt = cam->picture.palette,
+	    rgb = cam->force_rgb,
+	    hw_w = cam->hw_width,
+	    hw_h = cam->hw_height,
+	    hw_d = cam->hw_depth;
+	int err = 0;
+
+	#define _PSWAP(pIn, pOut) {tmp = (pIn); (pIn) = (pOut); (pOut) = tmp;}
+
+	if (cam->vpp_flag & VPP_DECOMPRESSION) {
+		memcpy(pOut, pIn, fr->length);
+		_PSWAP(pIn, pOut)
+		err = (*w9968cf_vpp_decode)(pIn, fr->length, hw_w, hw_h, pOut);
+		PDBGG("Compressed frame length: %li",(unsigned long)fr->length)
+		fr->length = (hw_w*hw_h*hw_d)/8;
+		_PSWAP(pIn, pOut)
+		if (err) {
+			DBG(4, "An error occurred while decoding the frame: "
+			       "%s.", symbolic(decoder_errlist, err))
+			return err;
+		} else
+			DBG(6, "Frame decoded")
+	}
+
+	if (cam->vpp_flag & VPP_SWAP_YUV_BYTES) {
+		(*w9968cf_vpp_swap_yuvbytes)(pIn, fr->length);
+		DBG(6, "Original UYVY component ordering changed.")
+	}
+
+	if (cam->vpp_flag & VPP_UPSCALE) {
+		(*w9968cf_vpp_scale_up)(pIn, pOut, hw_w, hw_h, hw_d, w, h);
+		fr->length = (w*h*hw_d)/8;
+		_PSWAP(pIn, pOut)
+		DBG(6, "Vertical up-scaling done: %d,%d,%dbpp->%d,%d",
+		    hw_w, hw_h, hw_d, w, h)
+	}
+
+	if (cam->vpp_flag & VPP_UYVY_TO_RGBX) {
+		(*w9968cf_vpp_uyvy_to_rgbx)(pIn, fr->length, pOut, fmt, rgb);
+		fr->length = (w*h*d)/8;
+		_PSWAP(pIn, pOut)
+		DBG(6, "UYVY-16bit to %s conversion done.", 
+		    symbolic(v4l1_plist, fmt))
+	}
+
+	if (pOut == fr->buffer)
+		memcpy(fr->buffer, cam->vpp_buffer, fr->length);
+
+	return 0;
+}
+
+
+
+/****************************************************************************
+ * CMOS sensor control routines                                             *
+ ****************************************************************************/
+
+static int 
+w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val)
+{
+	struct ovcamchip_control ctl;
+	int rc;
+
+	ctl.id = cid;
+	ctl.value = val;
+
+	rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl);
+
+	return rc;
+}
+
+static int 
+w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int *val)
+{
+	struct ovcamchip_control ctl;
+	int rc;
+
+	ctl.id = cid;
+
+	rc = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl);
+	if (rc >= 0)
+		*val = ctl.value;
+
+	return rc;
+}
+
+
+static inline int
+w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void *arg)
+{
+	struct i2c_client* c = cam->sensor_client;
+
+	DBG(6, "Executing CMOS sensor command...")
+
+	if (c && c->driver->command)
+		return c->driver->command(cam->sensor_client, cmd, arg);
+	else
+		return -ENODEV;
+}
+
+
+/*--------------------------------------------------------------------------
+  Change some settings of the CMOS sensor.
+  Returns: 0 for success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_sensor_change_settings(struct w9968cf_device* cam)
+{
+	int rc;
+
+	/* Auto brightness */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, 
+	                                cam->auto_brt);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	/* Auto exposure */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, 
+	                                cam->auto_exp);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	/* Banding filter */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, 
+	                                cam->bandfilt);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	/* Light frequency */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ,
+	                                cam->lightfreq);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	/* Back light */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT,
+	                                cam->backlight);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	/* Mirror */
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR,
+	                                cam->mirror);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Get some current picture settings from the CMOS sensor.
+  Returns: 0 for success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int
+w9968cf_sensor_get_picture(struct w9968cf_device* cam, 
+                           struct video_picture* pict)
+{
+	int rc, v;
+
+	/* Don't return error if a setting is unsupported, or rest of settings
+	   will not be performed */
+
+	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+	pict->contrast = v;
+
+	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+	pict->brightness = v;
+
+	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+	pict->colour = v;
+
+	rc = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+	pict->hue = v;
+
+	pict->whiteness = W9968CF_WHITENESS; /* to do! */
+
+	DBG(5, "Got picture settings from the CMOS sensor.")
+
+	PDBGG("Brightness, contrast, hue, colour, whiteness are "
+	      "%d,%d,%d,%d,%d.", pict->brightness, pict->contrast,
+	      pict->hue, pict->colour, pict->whiteness)
+
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+  Change picture settings of the CMOS sensor.
+  Returns: 0 for success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int
+w9968cf_sensor_set_picture(struct w9968cf_device* cam, 
+                           struct video_picture pict)
+{
+	int rc;
+
+	rc = w9968cf_sensor_set_control(cam,OVCAMCHIP_CID_CONT, pict.contrast);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	if (!cam->auto_brt) {
+		rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, 
+	                                        pict.brightness);
+		if (SENSOR_FATAL_ERROR(rc))
+			return rc;
+	}
+
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, pict.colour);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	rc = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, pict.hue);
+	if (SENSOR_FATAL_ERROR(rc))
+		return rc;
+
+	PDBGG("Brightness, contrast, hue, colour, whiteness are "
+	      "%d,%d,%d,%d,%d.", pict.brightness, pict.contrast,
+	      pict.hue, pict.colour, pict.whiteness)
+
+	return 0;
+}
+
+
+
+/****************************************************************************
+ * Camera configuration                                                     *
+ ****************************************************************************/
+
+/*--------------------------------------------------------------------------
+  This function is called when the CMOS sensor is detected.
+  --------------------------------------------------------------------------*/
+static void w9968cf_sensor_configure(struct w9968cf_device* cam)
+{
+	/* NOTE: Make sure width and height are a multiple of 16 */
+
+	switch (cam->sensor_client->addr) {
+		case OV6xx0_SID:
+			cam->maxwidth = 352;
+			cam->maxheight = 288;
+			cam->minwidth = 64;
+			cam->minheight = 48;
+			break;
+		case OV7xx0_SID:
+			cam->maxwidth = 640;
+			cam->maxheight = 480;
+			cam->minwidth = 64;
+			cam->minheight = 48;
+			break;
+	}
+
+	/* These values depend on the ones in the ovxxx0.c sources */
+	switch (cam->sensor) {
+		case CC_OV7620:
+			cam->start_cropx = 287;
+			cam->start_cropy = 35;
+			/* Seems to work around a bug in the CMOS sensor */
+			cam->vs_polarity = 1;
+			cam->hs_polarity = 1;
+			break;
+		default:
+			cam->start_cropx = 320;
+			cam->start_cropy = 35;
+			cam->vs_polarity = 1;
+			cam->hs_polarity = 0;
+	}
+
+	DBG(5, "CMOS sensor %s configured.", symbolic(senlist, cam->sensor))
+}
+
+
+/*--------------------------------------------------------------------------
+  Fill some basic fields in the main device data structure.
+  This function is called once on w9968cf_usb_probe() for each recognized 
+  camera.
+  --------------------------------------------------------------------------*/
+static void
+w9968cf_configure_camera(struct w9968cf_device* cam,
+                         struct usb_device* udev,
+                         enum w9968cf_model_id mod_id,
+                         const unsigned short dev_nr)
+{
+	init_MUTEX(&cam->fileop_sem);
+	init_waitqueue_head(&cam->open);
+	spin_lock_init(&cam->urb_lock);
+	spin_lock_init(&cam->flist_lock);
+
+	cam->users = 0;
+	cam->disconnected = 0;
+	cam->usbdev = udev;
+	cam->id = mod_id;
+	cam->sensor = CC_UNKNOWN;
+
+	strcpy(cam->v4ldev.name, symbolic(camlist, mod_id));
+	cam->v4ldev.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
+	cam->v4ldev.hardware = VID_HARDWARE_W9968CF;
+	cam->v4ldev.fops = &w9968cf_fops;
+	cam->v4ldev.priv = (void*)cam;
+	cam->v4ldev.minor = video_nr[dev_nr];
+
+	/* Calculate the alternate setting number (from 1 to 16)
+	   according to the 'packet_size' module parameter */
+	if (packet_size[dev_nr] < W9968CF_MIN_PACKET_SIZE)
+		packet_size[dev_nr] = W9968CF_MIN_PACKET_SIZE;
+	for (cam->altsetting = 1;
+	     packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1];
+	     cam->altsetting++);
+
+	cam->max_buffers = (max_buffers[dev_nr] < 2 || 
+	                    max_buffers[dev_nr] > W9968CF_MAX_BUFFERS)
+	                   ? W9968CF_BUFFERS : max_buffers[dev_nr];
+
+	cam->double_buffer = (double_buffer[dev_nr] == 0 || 
+	                      double_buffer[dev_nr] == 1)
+	                     ? double_buffer[dev_nr] : W9968CF_DOUBLE_BUFFER;
+
+	cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1)
+	                ? clamping[dev_nr] : W9968CF_CLAMPING;
+	
+	cam->filter_type = (filter_type[dev_nr] == 0 ||
+	                    filter_type[dev_nr] == 1 ||
+	                    filter_type[dev_nr] == 2)
+	                   ? filter_type[dev_nr] : W9968CF_FILTER_TYPE;
+
+	cam->capture = 1;
+
+	cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1)
+	                 ? largeview[dev_nr] : W9968CF_LARGEVIEW;
+
+	cam->decompression = (decompression[dev_nr] == 0 || 
+	                      decompression[dev_nr] == 1 ||
+	                      decompression[dev_nr] == 2)
+	                     ? decompression[dev_nr] : W9968CF_DECOMPRESSION;
+
+	cam->upscaling = (upscaling[dev_nr] == 0 || 
+	                  upscaling[dev_nr] == 1)
+	                 ? upscaling[dev_nr] : W9968CF_UPSCALING;
+
+	cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1)
+	                ? autobright[dev_nr] : W9968CF_AUTOBRIGHT;
+
+	cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1)
+	                ? autoexp[dev_nr] : W9968CF_AUTOEXP;
+
+	cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60)
+	                 ? lightfreq[dev_nr] : W9968CF_LIGHTFREQ;
+
+	cam->bandfilt = (bandingfilter[dev_nr] == 0 || 
+	                 bandingfilter[dev_nr] == 1)
+	                ? bandingfilter[dev_nr] : W9968CF_BANDINGFILTER;
+
+	cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1)
+	                 ? backlight[dev_nr] : W9968CF_BACKLIGHT;
+
+	cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0)
+	                ? clockdiv[dev_nr] : W9968CF_CLOCKDIV;
+
+	cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1)
+	              ? mirror[dev_nr] : W9968CF_MIRROR;
+
+	cam->sensor_mono = (sensor_mono[dev_nr]==0 || sensor_mono[dev_nr]==1)
+	                   ? sensor_mono[dev_nr] : W9968CF_SENSOR_MONO;
+
+	cam->picture.brightness = brightness[dev_nr];
+	cam->picture.hue = hue[dev_nr];
+	cam->picture.colour = colour[dev_nr];
+	cam->picture.contrast = contrast[dev_nr];
+	cam->picture.whiteness = whiteness[dev_nr];
+	if (w9968cf_valid_palette(force_palette[dev_nr])) {
+		cam->picture.palette = force_palette[dev_nr];
+		cam->force_palette = 1;
+	} else {
+		cam->force_palette = 0;
+		if (cam->decompression == 0)
+			cam->picture.palette = W9968CF_PALETTE_DECOMP_OFF;
+		else if (cam->decompression == 1)
+			cam->picture.palette = W9968CF_PALETTE_DECOMP_FORCE;
+		else
+			cam->picture.palette = W9968CF_PALETTE_DECOMP_ON;
+	}
+
+	cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1)
+	                 ? force_rgb[dev_nr] : W9968CF_FORCE_RGB;
+
+	cam->window.x = 0;
+	cam->window.y = 0;
+	cam->window.width = W9968CF_WIDTH;
+	cam->window.height = W9968CF_HEIGHT;
+	cam->window.chromakey = 0;
+	cam->window.clipcount = 0;
+	cam->window.flags = 0;
+
+	/* If the video post-processing module is not present, some paramaters
+	   must be overridden: */
+	if (!w9968cf_vppmod_present) {
+		if (cam->decompression == 1)
+			cam->decompression = 2;
+		cam->upscaling = 0;
+		if (cam->picture.palette != VIDEO_PALETTE_UYVY)
+			cam->force_palette = 0;
+		cam->picture.palette = VIDEO_PALETTE_UYVY;
+	}
+
+	cam->picture.depth = w9968cf_valid_depth(cam->picture.palette);
+
+	DBG(3, "%s configured with settings #%d:", 
+	    symbolic(camlist, cam->id), dev_nr)
+	
+	DBG(3, "- Data packet size for USB isochrnous transfer: %d bytes.",
+	    wMaxPacketSize[cam->altsetting-1])
+	
+	DBG(3, "- Number of requested video frame buffers: %d", 
+	    cam->max_buffers)
+
+	if (cam->double_buffer)
+		DBG(3, "- Hardware double buffering enabled.")
+	else 
+		DBG(3, "- Hardware double buffering disabled.")
+
+	if (cam->filter_type == 0)
+		DBG(3, "- Video filtering disabled.")
+	else if (cam->filter_type == 1)
+		DBG(3, "- Video filtering enabled: type 1-2-1.")
+	else if (cam->filter_type == 2)
+		DBG(3, "- Video filtering enabled: type 2-3-6-3-2.")
+
+	if (cam->clamping)
+		DBG(3, "- Video data clamping (CCIR-601 format) enabled.")
+	else
+		DBG(3, "- Video data clamping (CCIR-601 format) disabled.")
+
+	if (cam->largeview)
+		DBG(3, "- Large view enabled.")
+	else
+		DBG(3, "- Large view disabled.")
+
+	if ((cam->decompression) == 0 && (!cam->force_palette))
+		DBG(3, "- Decompression disabled.")
+	else if ((cam->decompression) == 1 && (!cam->force_palette))
+		DBG(3, "- Decompression forced.")
+	else if ((cam->decompression) == 2 && (!cam->force_palette))
+		DBG(3, "- Decompression allowed.")
+
+	if (cam->upscaling)
+		DBG(3, "- Software image scaling enabled.")
+	else
+		DBG(3, "- Software image scaling disabled.")
+
+	if (cam->force_palette)
+		DBG(3, "- Image palette forced to %s.",
+		    symbolic(v4l1_plist, cam->picture.palette))
+
+	if (cam->force_rgb)
+		DBG(3, "- RGB component ordering will be used instead of BGR.")
+
+	if (cam->auto_brt)
+		DBG(3, "- Auto brightness enabled.")
+	else
+		DBG(3, "- Auto brightness disabled.")
+
+	if (cam->auto_exp)
+		DBG(3, "- Auto exposure enabled.")
+	else
+		DBG(3, "- Auto exposure disabled.")
+
+	if (cam->backlight)
+		DBG(3, "- Backlight exposure algorithm enabled.")
+	else
+		DBG(3, "- Backlight exposure algorithm disabled.")
+
+	if (cam->mirror)
+		DBG(3, "- Mirror enabled.")
+	else
+		DBG(3, "- Mirror disabled.")
+
+	if (cam->bandfilt)
+		DBG(3, "- Banding filter enabled.")
+	else
+		DBG(3, "- Banding filter disabled.")
+
+	DBG(3, "- Power lighting frequency: %d", cam->lightfreq)
+
+	if (cam->clockdiv == -1)
+		DBG(3, "- Automatic clock divisor enabled.")
+	else
+		DBG(3, "- Clock divisor: %d", cam->clockdiv)
+
+	if (cam->sensor_mono)
+		DBG(3, "- CMOS sensor used as monochrome.")
+	else
+		DBG(3, "- CMOS sensor not used as monochrome.")
+}
+
+
+/*--------------------------------------------------------------------------
+  Release the resources used by the driver.
+  This function is called on disconnect 
+  (or on close if deallocation has been deferred)
+  --------------------------------------------------------------------------*/
+static void w9968cf_release_resources(struct w9968cf_device* cam)
+{
+	down(&w9968cf_devlist_sem);
+
+	DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev.minor)
+
+	video_unregister_device(&cam->v4ldev);
+	list_del(&cam->v4llist);
+	i2c_del_adapter(&cam->i2c_adapter);
+	w9968cf_deallocate_memory(cam);
+	kfree(cam->control_buffer);
+	kfree(cam->data_buffer);
+
+	up(&w9968cf_devlist_sem);
+
+	DBG(5, "Resources released.")
+}
+
+
+
+/****************************************************************************
+ * Video4Linux interface                                                    *
+ ****************************************************************************/
+
+static int w9968cf_open(struct inode* inode, struct file* filp)
+{
+	struct w9968cf_device* cam =
+	  (struct w9968cf_device*)video_devdata(filp)->priv;    
+	int err;
+
+	down(&cam->dev_sem);
+
+	if (cam->sensor == CC_UNKNOWN) {
+		DBG(2, "No supported CMOS sensor has been detected by the "
+		       "'ovcamchip' module for the %s (/dev/video%d). Make "
+		       "sure it is loaded *before* the 'w9968cf' module.", 
+		    symbolic(camlist, cam->id),cam->v4ldev.minor)
+		up(&cam->dev_sem);
+		return -ENODEV;
+	}
+
+	if (cam->users) {
+		DBG(2, "%s (/dev/video%d) has been already occupied by '%s'.",
+		    symbolic(camlist, cam->id),cam->v4ldev.minor, cam->command)
+		if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
+			up(&cam->dev_sem);
+			return -EWOULDBLOCK;
+		}
+		up(&cam->dev_sem);
+		err = wait_event_interruptible(cam->open, cam->disconnected ||
+		                               (cam->users == 0));
+		if (err)
+			return err;
+		if (cam->disconnected)
+			return -ENODEV;
+		down(&cam->dev_sem);
+	}
+
+	DBG(5, "Opening the %s, /dev/video%d ...",
+	    symbolic(camlist, cam->id), cam->v4ldev.minor)
+
+	cam->streaming = 0;
+	cam->misconfigured = 0;
+
+	if (!w9968cf_vppmod_present)
+		w9968cf_vppmod_detect();
+
+	if ((err = w9968cf_allocate_memory(cam)))
+		goto deallocate_memory;
+
+	if ((err = w9968cf_init_chip(cam)))
+		goto deallocate_memory;
+
+	if ((err = w9968cf_start_transfer(cam)))
+		goto deallocate_memory;
+
+	filp->private_data = (void*)cam;
+
+	cam->users++;
+	strcpy(cam->command, current->comm);
+
+	init_waitqueue_head(&cam->wait_queue);
+
+	up(&cam->dev_sem);
+
+	DBG(5, "Video device is open.")
+	return 0;
+
+deallocate_memory:
+	w9968cf_deallocate_memory(cam);
+	DBG(2, "Failed to open the video device.")
+	up(&cam->dev_sem);
+	return err;
+}
+
+
+static int w9968cf_release(struct inode* inode, struct file* filp)
+{
+	struct w9968cf_device* cam = 
+	  (struct w9968cf_device*)video_devdata(filp)->priv;
+
+	down(&cam->dev_sem); /* prevent disconnect() to be called */
+
+	w9968cf_stop_transfer(cam);
+
+	if (cam->disconnected) {
+		w9968cf_release_resources(cam);
+		up(&cam->dev_sem);
+		kfree(cam);
+		return 0;
+	}
+
+	cam->users--;
+	w9968cf_deallocate_memory(cam);
+
+	if (waitqueue_active(&cam->open))
+		wake_up_interruptible(&cam->open);
+
+	DBG(5, "Video device closed.")
+	up(&cam->dev_sem);
+	return 0;
+}
+
+
+static ssize_t
+w9968cf_read(struct file* filp, char* buf, size_t count, loff_t* f_pos)
+{
+	struct w9968cf_device* cam =
+	  (struct w9968cf_device*)video_devdata(filp)->priv;
+	struct w9968cf_frame_t* fr;
+	int err = 0;
+
+	if (filp->f_flags & O_NONBLOCK)
+		return -EWOULDBLOCK;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return -ERESTARTSYS;
+
+	if (cam->disconnected) {
+		DBG(2, "Device not present.")
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	if (cam->misconfigured) {
+		DBG(2, "The camera is misconfigured. Close and open it again.")
+		up(&cam->fileop_sem);
+		return -EIO;
+	}
+
+	if (!cam->frame[0].queued)
+		w9968cf_push_frame(cam, 0);
+
+	if (!cam->frame[1].queued)
+		w9968cf_push_frame(cam, 1);
+
+	err = wait_event_interruptible(cam->wait_queue,
+	                               cam->frame[0].status == F_READY ||
+	                               cam->frame[1].status == F_READY ||
+	                               cam->disconnected);
+	if (err) {
+		up(&cam->fileop_sem);
+		return err;
+	}
+	if (cam->disconnected) {
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	fr = (cam->frame[0].status == F_READY) ? &cam->frame[0]:&cam->frame[1];
+
+	if (w9968cf_vppmod_present)
+		w9968cf_postprocess_frame(cam, fr);
+
+	if (count > fr->length)
+		count = fr->length;
+
+	if (copy_to_user(buf, fr->buffer, count)) {
+		fr->status = F_UNUSED;
+		up(&cam->fileop_sem);
+		return -EFAULT;
+	}
+	*f_pos += count;
+
+	fr->status = F_UNUSED;
+
+	DBG(5, "%d bytes read.", count)
+
+	up(&cam->fileop_sem);
+	return count;
+}
+
+
+static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
+{
+	struct w9968cf_device* cam =
+	  (struct w9968cf_device*)video_devdata(filp)->priv;
+
+	unsigned long vsize = vma->vm_end - vma->vm_start,
+	              psize = cam->nbuffers * w9968cf_get_max_bufsize(cam),
+	              start = vma->vm_start,
+	              pos = (unsigned long)cam->frame[0].buffer,
+	              page;
+
+	if (cam->disconnected) {
+		DBG(2, "Device not present.")
+		return -ENODEV;
+	}
+
+	if (cam->misconfigured) {
+		DBG(2, "The camera is misconfigured. Close and open it again.")
+		return -EIO;
+	}
+
+	PDBGG("mmapping %li bytes...", vsize)
+
+        if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT))
+		return -EAGAIN;
+
+	while (vsize > 0) {
+		page = kvirt_to_pa(pos) + vma->vm_pgoff;
+		if (remap_page_range(vma, start, page, PAGE_SIZE, 
+		                     vma->vm_page_prot))
+			return -EAGAIN;
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		vsize = (vsize > PAGE_SIZE) ? vsize-PAGE_SIZE : 0;
+	}
+
+	DBG(5, "mmap method successfully called.")
+	return 0;
+}
+
+
+static int
+w9968cf_ioctl(struct inode* inode, struct file* filp,
+              unsigned int cmd, unsigned long arg)
+{
+	struct w9968cf_device* cam =
+	  (struct w9968cf_device*)video_devdata(filp)->priv;
+	int err;
+
+	if (down_interruptible(&cam->fileop_sem))
+		return -ERESTARTSYS;
+
+	if (cam->disconnected) {
+		DBG(2, "Device not present.")
+		up(&cam->fileop_sem);
+		return -ENODEV;
+	}
+
+	if (cam->misconfigured) {
+		DBG(2, "The camera is misconfigured. Close and open it again.")
+		up(&cam->fileop_sem);
+		return -EIO;
+	}
+
+	err = w9968cf_do_ioctl(cam, cmd, (void*)arg);
+
+	up(&cam->fileop_sem);
+	return err;
+}
+
+
+static int 
+w9968cf_do_ioctl(struct w9968cf_device* cam, unsigned cmd, void* arg)
+{
+	const char* v4l1_ioctls[] = {
+		"?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", 
+		"GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF",
+		"SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO",
+		"SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE",
+		"SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", 
+		"GVBIFMT", "SVBIFMT" 
+	};
+
+	#define V4L1_IOCTL(cmd) \
+	        ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
+	        v4l1_ioctls[_IOC_NR((cmd))] : "???")
+
+	switch (cmd) {
+
+	case VIDIOCGCAP: /* get video capability */
+	{
+		struct video_capability cap = {
+			.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES,
+			.channels = 1,
+			.audios = 0,
+			.minwidth = cam->minwidth,
+			.minheight = cam->minheight,
+		};
+		sprintf(cap.name, "W996[87]CF USB Camera #%d", 
+		        cam->v4ldev.minor);
+		cap.maxwidth = (cam->upscaling && w9968cf_vppmod_present)
+		               ? W9968CF_MAX_WIDTH : cam->maxwidth;
+		cap.maxheight = (cam->upscaling && w9968cf_vppmod_present)
+		                ? W9968CF_MAX_HEIGHT : cam->maxheight;
+
+		if (copy_to_user(arg, &cap, sizeof(cap)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGCAP successfully called.")
+		return 0;
+	}
+
+	case VIDIOCGCHAN: /* get video channel informations */
+	{
+		struct video_channel chan;
+		if (copy_from_user(&chan, arg, sizeof(chan)))
+			return -EFAULT;
+
+		if (chan.channel != 0)
+			return -EINVAL;
+
+		strcpy(chan.name, "Camera");
+		chan.tuners = 0;
+		chan.flags = 0;
+		chan.type = VIDEO_TYPE_CAMERA;
+		chan.norm = VIDEO_MODE_AUTO;
+
+		if (copy_to_user(arg, &chan, sizeof(chan)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGCHAN successfully called.")
+		return 0;
+	}
+
+	case VIDIOCSCHAN: /* set active channel */
+	{
+		struct video_channel chan;
+
+		if (copy_from_user(&chan, arg, sizeof(chan)))
+			return -EFAULT;
+
+		if (chan.channel != 0)
+			return -EINVAL;
+
+		DBG(5, "VIDIOCSCHAN successfully called.")
+		return 0;
+	}
+
+	case VIDIOCGPICT: /* get image properties of the picture */
+	{
+		struct video_picture pict;
+
+		if (w9968cf_sensor_get_picture(cam, &pict))
+			return -EIO;
+
+		pict.depth = cam->picture.depth;
+		pict.palette = cam->picture.palette;
+
+		if (copy_to_user(arg, &pict, sizeof(pict)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGPICT successfully called.")
+		return 0;
+	}
+
+	case VIDIOCSPICT: /* change picture settings */
+	{
+		struct video_picture pict;
+		int err = 0;
+
+		if (copy_from_user(&pict, arg, sizeof(pict)))
+			return -EFAULT;
+
+		if ( (cam->force_palette || !w9968cf_vppmod_present) 
+		     && pict.palette != cam->picture.palette ) {
+			DBG(4, "Palette %s rejected. Only %s is allowed.",
+			    symbolic(v4l1_plist, pict.palette),
+			    symbolic(v4l1_plist, cam->picture.palette))
+			return -EINVAL;
+		}
+
+		if (!w9968cf_valid_palette(pict.palette)) {
+			DBG(4, "Palette %s not supported. VIDIOCSPICT failed.",
+			    symbolic(v4l1_plist, pict.palette))
+			return -EINVAL;
+		}
+
+		if (pict.depth != w9968cf_valid_depth(pict.palette)) {
+			DBG(4, "Depth %d bpp is not supported for %s palette. "
+			       "VIDIOCSPICT failed.", 
+			    pict.depth, symbolic(v4l1_plist, pict.palette))
+			return -EINVAL;
+		}
+
+		if (!cam->force_palette) {
+		   if (cam->decompression == 0) {
+		      if (w9968cf_need_decompression(pict.palette)) {
+		         DBG(4, "Decompression disabled: palette %s is not "
+		                "allowed. VIDIOCSPICT failed.",
+		             symbolic(v4l1_plist, pict.palette))
+		         return -EINVAL;
+		      }
+		   } else if (cam->decompression == 1) {
+		      if (!w9968cf_need_decompression(pict.palette)) {
+		         DBG(4, "Decompression forced: palette %s is not "
+		                "allowed. VIDIOCSPICT failed.",
+		             symbolic(v4l1_plist, pict.palette))
+		         return -EINVAL;
+		      }
+		   }
+		}
+
+		if (pict.palette != cam->picture.palette ||
+		    pict.depth   != cam->picture.depth)
+		{
+			if(*cam->requested_frame
+			   || cam->frame_current->queued) {
+				err = wait_event_interruptible
+				      ( cam->wait_queue,
+				        cam->disconnected ||
+				        (!*cam->requested_frame &&
+				         !cam->frame_current->queued) );
+				if (err)
+					return err;
+				if (cam->disconnected)
+					return -ENODEV;
+			}
+
+			if (w9968cf_stop_transfer(cam))
+				goto ioctl_fail;
+
+			if (w9968cf_set_picture(cam, pict))
+				goto ioctl_fail;
+
+			if (w9968cf_start_transfer(cam))
+				goto ioctl_fail;
+
+		} else if ( ((pict.brightness != cam->picture.brightness) &&
+		            (!cam->auto_brt)) ||
+		            pict.hue != cam->picture.hue ||
+		            pict.colour != cam->picture.colour ||
+		            pict.contrast != cam->picture.contrast ||
+		            pict.whiteness != cam->picture.whiteness ) {
+			if (w9968cf_sensor_set_picture(cam, pict))
+				return -EIO;
+		}
+
+		DBG(5, "VIDIOCSPICT successfully called.")
+		return 0;
+	}
+
+	case VIDIOCSWIN: /* set capture area */
+	{
+		struct video_window win;
+		int err = 0;
+
+		if (copy_from_user(&win, arg, sizeof(win)))
+			return -EFAULT;
+
+		DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%d, "
+		       "x=%d, y=%d, %dx%d", win.clipcount, win.flags,
+		    win.x, win.y, win.width, win.height)
+
+		if (win.clipcount != 0 || win.flags != 0)
+			return -EINVAL;
+
+		if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
+		                                      (u16*)&win.height))) {
+			DBG(4, "Resolution not supported (%dx%d)."
+			       "VIDIOCSWIN failed.", win.width, win.height)
+			return err;
+		}
+
+		if (win.x != cam->window.x ||
+		    win.y != cam->window.y ||
+		    win.width != cam->window.width ||
+		    win.height != cam->window.height) {
+
+			if(*cam->requested_frame
+			   || cam->frame_current->queued) {
+				err = wait_event_interruptible
+				      ( cam->wait_queue,
+				        cam->disconnected ||
+				        (!*cam->requested_frame &&
+				         !cam->frame_current->queued) );
+				if (err)
+					return err;
+				if (cam->disconnected)
+					return -ENODEV;
+			}
+
+			if (w9968cf_stop_transfer(cam))
+				goto ioctl_fail;
+
+			/* This _must_ be called before set_window() */
+			if (w9968cf_set_picture(cam, cam->picture))
+				goto ioctl_fail;
+
+			if (w9968cf_set_window(cam, win))
+				goto ioctl_fail;
+
+			if (w9968cf_start_transfer(cam))
+				goto ioctl_fail;
+		}
+
+		DBG(5, "VIDIOCSWIN successfully called. ")
+		return 0;
+	}
+
+	case VIDIOCGWIN: /* get current window properties */
+	{
+		if (copy_to_user(arg,&cam->window,sizeof(struct video_window)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGWIN successfully called.")
+		return 0;
+	}
+
+	case VIDIOCGMBUF: /* request for memory (mapped) buffer */
+	{
+		struct video_mbuf mbuf;
+		u8 i;
+
+		mbuf.size = cam->nbuffers * w9968cf_get_max_bufsize(cam);
+		mbuf.frames = cam->nbuffers;
+		for (i = 0; i < cam->nbuffers; i++)
+			mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer -
+			                  (unsigned long)cam->frame[0].buffer;
+
+		if (copy_to_user(arg, &mbuf, sizeof(mbuf)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGMBUF successfully called.")
+		return 0;
+	}
+
+	case VIDIOCMCAPTURE: /* start the capture to a frame */
+	{
+		struct video_mmap mmap;
+		struct w9968cf_frame_t* fr;
+		int err = 0;
+
+		if (copy_from_user(&mmap, arg, sizeof(mmap)))
+			return -EFAULT;
+
+		DBG(6, "VIDIOCMCAPTURE called: frame #%d, format=%s, %dx%d",
+		    mmap.frame, symbolic(v4l1_plist, mmap.format), 
+		    mmap.width, mmap.height)
+
+		if (mmap.frame >= cam->nbuffers) {
+			DBG(4, "Invalid frame number (%d). "
+			       "VIDIOCMCAPTURE failed.", mmap.frame)
+			return -EINVAL;
+		}
+
+		if (mmap.format!=cam->picture.palette && 
+		    (cam->force_palette || !w9968cf_vppmod_present)) {
+			DBG(4, "Palette %s rejected. Only %s is allowed.",
+			    symbolic(v4l1_plist, mmap.format),
+			    symbolic(v4l1_plist, cam->picture.palette))
+			return -EINVAL;
+		}
+
+		if (!w9968cf_valid_palette(mmap.format)) {
+			DBG(4, "Palette %s not supported. "
+			       "VIDIOCMCAPTURE failed.", 
+			    symbolic(v4l1_plist, mmap.format))
+			return -EINVAL;
+		}
+
+		if (!cam->force_palette) {
+		   if (cam->decompression == 0) {
+		      if (w9968cf_need_decompression(mmap.format)) {
+		         DBG(4, "Decompression disabled: palette %s is not "
+		                "allowed. VIDIOCSPICT failed.",
+		             symbolic(v4l1_plist, mmap.format))
+		         return -EINVAL;
+		      }
+		   } else if (cam->decompression == 1) {
+		      if (!w9968cf_need_decompression(mmap.format)) {
+		         DBG(4, "Decompression forced: palette %s is not "
+		                "allowed. VIDIOCSPICT failed.",
+		             symbolic(v4l1_plist, mmap.format))
+		         return -EINVAL;
+		      }
+		   }
+		}
+
+		if (w9968cf_adjust_window_size(cam, (u16*)&mmap.width, 
+		                               (u16*)&mmap.height)) {
+			DBG(4, "Resolution not supported (%dx%d). "
+			       "VIDIOCMCAPTURE failed.",
+			    mmap.width, mmap.height)
+			return -EINVAL;
+		}
+
+		fr = &cam->frame[mmap.frame];
+
+		if (mmap.width  != cam->window.width ||
+		    mmap.height != cam->window.height ||
+		    mmap.format != cam->picture.palette) {
+
+			struct video_window win;
+			struct video_picture pict;
+
+			if(*cam->requested_frame
+			   || cam->frame_current->queued) {
+				DBG(6, "VIDIOCMCAPTURE. Change settings for "
+				       "frame #%d: %dx%d, format %s. Wait...",
+				    mmap.frame, mmap.width, mmap.height,
+			            symbolic(v4l1_plist, mmap.format))
+				err = wait_event_interruptible
+				      ( cam->wait_queue,
+				        cam->disconnected ||
+				        (!*cam->requested_frame &&
+				         !cam->frame_current->queued) );
+				if (err)
+					return err;
+				if (cam->disconnected)
+					return -ENODEV;
+			}
+
+			memcpy(&win, &cam->window, sizeof(win));
+			memcpy(&pict, &cam->picture, sizeof(pict));
+			win.width = mmap.width;
+			win.height = mmap.height;
+			pict.palette = mmap.format;
+
+			if (w9968cf_stop_transfer(cam))
+				goto ioctl_fail;
+
+			/* This before set_window */
+			if (w9968cf_set_picture(cam, pict)) 
+				goto ioctl_fail;
+
+			if (w9968cf_set_window(cam, win))
+				goto ioctl_fail;
+
+			if (w9968cf_start_transfer(cam))
+				goto ioctl_fail;
+
+		} else 	if (fr->queued) {
+
+			DBG(6, "Wait until frame #%d is free.", mmap.frame)
+			
+			err = wait_event_interruptible(cam->wait_queue, 
+			                               cam->disconnected ||
+			                               (!fr->queued));
+			if (err)
+				return err;
+			if (cam->disconnected)
+				return -ENODEV;
+		}
+
+		w9968cf_push_frame(cam, mmap.frame);
+		DBG(5, "VIDIOCMCAPTURE(%d): successfully called.", mmap.frame)
+		return 0;
+	}
+
+	case VIDIOCSYNC: /* wait until the capture of a frame is finished */
+	{
+		unsigned int f_num = *((unsigned int *) arg);
+		struct w9968cf_frame_t* fr;
+		int err = 0;
+
+		if (f_num >= cam->nbuffers) {
+			DBG(4, "Invalid frame number (%d). "
+			       "VIDIOCMCAPTURE failed.", f_num)
+			return -EINVAL;
+		}
+
+		DBG(6, "VIDIOCSYNC called for frame #%d", f_num)
+
+		fr = &cam->frame[f_num];
+
+		switch (fr->status) {
+		case F_UNUSED:
+			if (!fr->queued) {
+				DBG(4, "VIDIOSYNC: Frame #%d not requested!",
+				    f_num)
+				return -EFAULT;
+			}
+		case F_ERROR:
+		case F_GRABBING:
+			err = wait_event_interruptible(cam->wait_queue, 
+			                               (fr->status == F_READY)
+			                               || cam->disconnected);
+			if (err)
+				return err;
+			if (cam->disconnected)
+				return -ENODEV;
+			break;
+		case F_READY:
+			break;
+		}
+
+		if (w9968cf_vppmod_present)
+			w9968cf_postprocess_frame(cam, fr);
+
+		fr->status = F_UNUSED;
+
+		DBG(5, "VIDIOCSYNC(%d) successfully called.", f_num)
+		return 0;
+	}
+
+	case VIDIOCGUNIT:/* report the unit numbers of the associated devices*/
+	{
+		struct video_unit unit = {
+			.video = cam->v4ldev.minor,
+			.vbi = VIDEO_NO_UNIT,
+			.radio = VIDEO_NO_UNIT,
+			.audio = VIDEO_NO_UNIT,
+			.teletext = VIDEO_NO_UNIT,
+		};
+
+		if (copy_to_user(arg, &unit, sizeof(unit)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGUNIT successfully called.")
+		return 0;
+	}
+
+	case VIDIOCKEY:
+		return 0;
+
+	case VIDIOCGFBUF:
+	{
+		struct video_buffer* buffer = (struct video_buffer*)arg;
+
+		memset(buffer, 0, sizeof(struct video_buffer));
+
+		DBG(5, "VIDIOCGFBUF successfully called.")
+		return 0;
+	}
+
+	case VIDIOCGTUNER:
+	{
+		struct video_tuner tuner;
+		if (copy_from_user(&tuner, arg, sizeof(tuner)))
+			return -EFAULT;
+
+		if (tuner.tuner != 0);
+			return -EINVAL;
+
+		strcpy(tuner.name, "no_tuner");
+		tuner.rangelow = 0;
+		tuner.rangehigh = 0;
+		tuner.flags = VIDEO_TUNER_NORM;
+		tuner.mode = VIDEO_MODE_AUTO;
+		tuner.signal = 0xffff;
+
+		if (copy_to_user(arg, &tuner, sizeof(tuner)))
+			return -EFAULT;
+
+		DBG(5, "VIDIOCGTUNER successfully called.")
+		return 0;
+	}
+
+	case VIDIOCSTUNER:
+	{
+		struct video_tuner tuner;
+		if (copy_from_user(&tuner, arg, sizeof(tuner)))
+			return -EFAULT;
+
+		if (tuner.tuner != 0)
+			return -EINVAL;
+
+		if (tuner.mode != VIDEO_MODE_AUTO)
+			return -EINVAL;
+
+		DBG(5, "VIDIOCSTUNER successfully called.")
+		return 0;
+	}
+
+	case VIDIOCSFBUF:
+	case VIDIOCCAPTURE:
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+	case VIDIOCSPLAYMODE:
+	case VIDIOCSWRITEMODE:
+	case VIDIOCGPLAYINFO:
+	case VIDIOCSMICROCODE:
+	case VIDIOCGVBIFMT:
+	case VIDIOCSVBIFMT:
+		DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s "
+		       "(type 0x%01X, "
+		       "n. 0x%01X, "
+		       "dir. 0x%01X, " 
+		       "size 0x%02X).",
+		    V4L1_IOCTL(cmd),
+		    _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd))
+
+		return -EINVAL;
+
+	default:
+		DBG(4, "Invalid V4L1 IOCtl: VIDIOC%s "
+		       "type 0x%01X, "
+		       "n. 0x%01X, "
+		       "dir. 0x%01X, "
+		       "size 0x%02X.",
+		    V4L1_IOCTL(cmd),
+		    _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd))
+
+		return -ENOIOCTLCMD;
+
+	} /* end of switch */
+
+ioctl_fail:
+	cam->misconfigured = 1;
+	DBG(1, "VIDIOC%s failed because of hardware problems. "
+	       "To use the camera, close and open it again.", V4L1_IOCTL(cmd))
+	return -EFAULT;
+}
+
+
+static struct file_operations w9968cf_fops = {
+	.owner =   THIS_MODULE,
+	.open =    w9968cf_open,
+	.release = w9968cf_release,
+	.read =    w9968cf_read,
+	.ioctl =   w9968cf_ioctl,
+	.mmap =    w9968cf_mmap,
+	.llseek =  no_llseek,
+};
+
+
+
+/****************************************************************************
+ * USB probe and V4L registration, disconnect and id_table[] definition     *
+ ****************************************************************************/
+
+static int
+w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct w9968cf_device* cam;
+	int err = 0;
+	enum w9968cf_model_id mod_id;
+	struct list_head* ptr;
+	u8 sc = 0; /* number of simultaneous cameras */
+	static unsigned short dev_nr = 0; /* we are handling device number n */
+
+	if (udev->descriptor.idVendor  == winbond_id_table[0].idVendor &&
+	    udev->descriptor.idProduct == winbond_id_table[0].idProduct)
+		mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */
+
+	else if (udev->descriptor.idVendor  == winbond_id_table[1].idVendor &&
+	         udev->descriptor.idProduct == winbond_id_table[1].idProduct)
+		mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */
+
+	else
+		return -ENODEV;
+
+	/* We don't handle multi-config cameras */
+	if (udev->descriptor.bNumConfigurations != 1)
+		return -ENODEV;
+
+	DBG(2, "%s detected.", symbolic(camlist, mod_id))
+
+	if (simcams > W9968CF_MAX_DEVICES)
+		simcams = W9968CF_SIMCAMS;
+
+	/* How many cameras are connected ? */
+	down(&w9968cf_devlist_sem);
+	list_for_each(ptr, &w9968cf_dev_list)
+		sc++;
+	up(&w9968cf_devlist_sem);
+
+	if (sc >= simcams) {
+		DBG(2, "Device rejected: too many connected cameras "
+		       "(max. %d)", simcams)
+		return -EPERM;
+	}
+
+	err = usb_set_configuration(udev, 1);
+	err += usb_set_interface(udev, 0, 0);
+
+	if (err) {
+		DBG(1, "Device configuration failed.")
+		return -EIO;
+	}
+
+	cam = (struct w9968cf_device*)
+	          kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
+
+	if (!cam) {
+		DBG(1, "Couldn't allocate %d bytes of kernel memory.",
+		    sizeof(struct w9968cf_device))
+		err = -ENOMEM;
+		goto fail;
+	}
+	memset(cam, 0, sizeof(*cam));
+
+	init_MUTEX(&cam->dev_sem);
+	down(&cam->dev_sem);
+
+	/* Allocate 2 bytes of memory for camera control USB transfers */
+	if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) {
+		DBG(1,"Couldn't allocate memory for camera control transfers.")
+		err = -ENOMEM;
+		goto fail;
+	}
+	memset(cam->control_buffer, 0, 2);
+
+	/* Allocate 8 bytes of memory for USB data transfers to the FSB */
+	if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) {
+		DBG(1, "Couldn't allocate memory for data "
+		       "transfers to the FSB.")
+		err = -ENOMEM;
+		goto fail;
+	}
+	memset(cam->data_buffer, 0, 8);
+
+	/* Set some basic constants */
+	w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
+
+	err = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER,
+	                            video_nr[dev_nr]);
+	if (err) {
+		DBG(1, "V4L device registration failed.")
+		if (err == -ENFILE && video_nr[dev_nr] == -1)
+			DBG(2, "Couldn't find a free /dev/videoX node.")
+		video_nr[dev_nr] = -1;
+		dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0;
+		goto fail;
+	}
+
+	DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev.minor)
+
+	/* Ok, add a new entry into the list of V4L registered devices */
+	down(&w9968cf_devlist_sem);
+	list_add(&cam->v4llist, &w9968cf_dev_list);
+	up(&w9968cf_devlist_sem);
+
+	dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+	w9968cf_turn_on_led(cam);
+
+	w9968cf_i2c_init(cam);
+
+	up(&cam->dev_sem);
+
+	dev_set_drvdata(&intf->dev, (void*)cam);
+
+	return 0;
+
+fail: /* Free unused memory */
+	if (cam) {
+		if (cam->control_buffer)
+			kfree(cam->control_buffer);
+		if (cam->data_buffer)
+			kfree(cam->data_buffer);
+		up(&cam->dev_sem);
+		kfree(cam);
+	}
+	return err;
+}
+
+
+static void w9968cf_usb_disconnect(struct usb_interface* intf)
+{
+	struct w9968cf_device* cam = 
+	   (struct w9968cf_device*)dev_get_drvdata(&intf->dev);
+
+	dev_set_drvdata(&intf->dev, NULL);
+
+	if (cam) {
+		/* Prevent concurrent accesses to data */
+		down(&cam->dev_sem); 
+
+		cam->streaming = 0;
+		cam->disconnected = 1;
+
+		DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id))
+
+		if (waitqueue_active(&cam->open))
+			wake_up_interruptible(&cam->open);
+
+		if (cam->users) {
+			DBG(2, "The device is open (/dev/video%d)! "
+			       "Process name: %s. Deregistration and memory "
+			       "deallocation are deferred on close.",
+			    cam->v4ldev.minor, cam->command)
+
+			cam->misconfigured = 1;
+
+			if (waitqueue_active(&cam->wait_queue))
+				wake_up_interruptible(&cam->wait_queue);
+		} else
+			w9968cf_release_resources(cam);
+
+		up(&cam->dev_sem);
+
+		if (!cam->users)
+			kfree(cam);
+	}
+}
+
+
+static struct usb_driver w9968cf_usb_driver = {
+	.owner =      THIS_MODULE,
+	.name =       "w9968cf",
+	.id_table =   winbond_id_table,
+	.probe =      w9968cf_usb_probe,
+	.disconnect = w9968cf_usb_disconnect,
+};
+
+
+
+/****************************************************************************
+ * Module init, exit and intermodule communication                          *
+ ****************************************************************************/
+
+static int w9968cf_vppmod_detect(void)
+{
+	w9968cf_vpp_init_decoder = inter_module_get("w9968cf_init_decoder");
+
+	if (!w9968cf_vpp_init_decoder) {
+		if (vppmod_load)
+			w9968cf_vpp_init_decoder = inter_module_get_request
+		                                  ( "w9968cf_init_decoder",
+			                            "w9968cf-vpp" );
+		if (!w9968cf_vpp_init_decoder) {
+			w9968cf_vppmod_present = 0;
+			DBG(4, "Video post-processing module not detected.")
+			return -ENODEV;
+		}
+	}
+
+	w9968cf_vpp_check_headers = inter_module_get("w9968cf_check_headers");
+	w9968cf_vpp_decode = inter_module_get("w9968cf_decode");
+	w9968cf_vpp_swap_yuvbytes = inter_module_get("w9968cf_swap_yuvbytes");
+	w9968cf_vpp_uyvy_to_rgbx = inter_module_get("w9968cf_uyvy_to_rgbx");
+	w9968cf_vpp_scale_up = inter_module_get("w9968cf_scale_up");
+
+	w9968cf_vppmod_present = 1;
+
+	/* Initialization */
+	(*w9968cf_vpp_init_decoder)();
+
+	DBG(2, "Video post-processing module detected.")
+	return 0;
+}
+
+
+static void w9968cf_vppmod_release(void)
+{
+	inter_module_put("w9968cf_init_decoder");
+	inter_module_put("w9968cf_check_headers");
+	inter_module_put("w9968cf_decode");
+	inter_module_put("w9968cf_swap_yuvbytes");
+	inter_module_put("w9968cf_uyvy_to_rgbx");
+	inter_module_put("w9968cf_scale_up");
+
+	DBG(2, "Video post-processing module released.")
+}
+
+
+static int __init w9968cf_module_init(void)
+{
+	int err;
+
+	DBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION)
+	DBG(3, W9968CF_MODULE_AUTHOR)
+
+	init_MUTEX(&w9968cf_devlist_sem);
+
+	w9968cf_vppmod_detect();
+
+	if ((err = usb_register(&w9968cf_usb_driver))) {
+		if (w9968cf_vppmod_present)
+			w9968cf_vppmod_release();
+		return err;
+	}
+
+	return 0;
+}
+
+
+static void __exit w9968cf_module_exit(void)
+{
+	/* w9968cf_usb_disconnect() will be called */
+	usb_deregister(&w9968cf_usb_driver);
+
+	if (w9968cf_vppmod_present)
+		w9968cf_vppmod_release();
+
+	DBG(2, W9968CF_MODULE_NAME" deregistered.")
+}
+
+
+module_init(w9968cf_module_init);
+module_exit(w9968cf_module_exit);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/w9968cf.h 001-linus.patch/drivers/usb/media/w9968cf.h
--- 000-virgin/drivers/usb/media/w9968cf.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/usb/media/w9968cf.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,312 @@
+/***************************************************************************
+ * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip.       *
+ *                                                                         *
+ * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _W9968CF_H_
+#define _W9968CF_H_
+
+#include <linux/videodev.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/config.h>
+#include <asm/semaphore.h>
+#include <asm/types.h>
+
+#include "w9968cf_externaldef.h"
+
+
+/****************************************************************************
+ * Default values                                                           *
+ ****************************************************************************/
+
+#define W9968CF_VPPMOD_LOAD     1  /* automatic 'w9968cf-vpp' module loading */
+
+/* Comment/uncomment the following line to enable/disable debugging messages */
+#define W9968CF_DEBUG
+
+/* These have effect only if W9968CF_DEBUG is defined */
+#define W9968CF_DEBUG_LEVEL    2 /* from 0 to 6. 0 for no debug informations */
+#define W9968CF_SPECIFIC_DEBUG 0 /* 0 or 1 */
+
+#define W9968CF_MAX_DEVICES    32
+#define W9968CF_SIMCAMS        W9968CF_MAX_DEVICES /* simultaneous cameras */
+
+#define W9968CF_MAX_BUFFERS   32
+#define W9968CF_BUFFERS       2 /* n. of frame buffers from 2 to MAX_BUFFERS */
+
+/* Maximum data payload sizes in bytes for alternate settings */
+static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575,
+                                      511, 447, 383, 319, 255, 191, 127,  63};
+#define W9968CF_PACKET_SIZE      1023 /* according to wMaxPacketSizes[] */
+#define W9968CF_MIN_PACKET_SIZE  63 /* minimum value */
+#define W9968CF_ISO_PACKETS      5 /* n.of packets for isochronous transfers */
+#define W9968CF_USB_CTRL_TIMEOUT HZ /* timeout for usb control commands */
+#define W9968CF_URBS             2 /* n. of scheduled URBs for ISO transfer */
+
+#define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
+#define W9968CF_I2C_RW_RETRIES   15 /* number of max I2C r/w retries */
+
+/* Available video formats */
+struct w9968cf_format {
+	const u16 palette;
+	const u16 depth;
+	const u8 compression;
+};
+
+static const struct w9968cf_format w9968cf_formatlist[] = {
+	{ VIDEO_PALETTE_UYVY,    16, 0 }, /* original video */
+	{ VIDEO_PALETTE_YUV422P, 16, 1 }, /* with JPEG compression */
+	{ VIDEO_PALETTE_YUV420P, 12, 1 }, /* with JPEG compression */
+	{ VIDEO_PALETTE_YUV420,  12, 1 }, /* same as YUV420P */
+	{ VIDEO_PALETTE_YUYV,    16, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_YUV422,  16, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_GREY,     8, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_RGB555,  16, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_RGB565,  16, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_RGB24,   24, 0 }, /* software conversion */
+	{ VIDEO_PALETTE_RGB32,   32, 0 }, /* software conversion */
+	{ 0,                      0, 0 }  /* 0 is a terminating entry */
+};
+
+#define W9968CF_DECOMPRESSION    2 /* decomp:0=disable,1=force,2=any formats */
+#define W9968CF_PALETTE_DECOMP_OFF   VIDEO_PALETTE_UYVY    /* when decomp=0 */
+#define W9968CF_PALETTE_DECOMP_FORCE VIDEO_PALETTE_YUV420P /* when decomp=1 */
+#define W9968CF_PALETTE_DECOMP_ON    VIDEO_PALETTE_UYVY    /* when decomp=2 */
+
+#define W9968CF_FORCE_RGB        0  /* read RGB instead of BGR, yes=1/no=0 */
+
+#define W9968CF_MAX_WIDTH      800 /* should be >= 640 */
+#define W9968CF_MAX_HEIGHT     600 /* should be >= 480 */
+#define W9968CF_WIDTH          320 /* from 128 to 352, multiple of 16 */
+#define W9968CF_HEIGHT         240 /* from  96 to 288, multiple of 16 */
+
+#define W9968CF_CLAMPING       0 /* 0 disable, 1 enable video data clamping */
+#define W9968CF_FILTER_TYPE    0 /* 0 disable  1 (1-2-1), 2 (2-3-6-3-2) */
+#define W9968CF_DOUBLE_BUFFER  1 /* 0 disable, 1 enable double buffer */
+#define W9968CF_LARGEVIEW      1 /* 0 disable, 1 enable */
+#define W9968CF_UPSCALING      0 /* 0 disable, 1 enable */
+
+#define W9968CF_SENSOR_MONO    0 /* 0 not monochrome, 1 monochrome sensor */
+#define W9968CF_BRIGHTNESS     31000 /* from 0 to 65535 */
+#define W9968CF_HUE            32768 /* from 0 to 65535 */
+#define W9968CF_COLOUR         32768 /* from 0 to 65535 */
+#define W9968CF_CONTRAST       50000 /* from 0 to 65535 */
+#define W9968CF_WHITENESS      32768 /* from 0 to 65535 */
+
+#define W9968CF_AUTOBRIGHT     0 /* 0 disable, 1 enable automatic brightness */
+#define W9968CF_AUTOEXP        1 /* 0 disable, 1 enable automatic exposure */
+#define W9968CF_LIGHTFREQ      50 /* light frequency. 50Hz (Europe) or 60Hz */
+#define W9968CF_BANDINGFILTER  0 /* 0 disable, 1 enable banding filter */
+#define W9968CF_BACKLIGHT      0 /* 0 or 1, 1=object is lit from behind */
+#define W9968CF_MIRROR         0 /* 0 or 1 [don't] reverse image horizontally*/
+
+#define W9968CF_CLOCKDIV         -1 /* -1 = automatic clock divisor */
+#define W9968CF_DEF_CLOCKDIVISOR  0 /* default sensor clock divisor value */
+
+
+/****************************************************************************
+ * Globals                                                                  *
+ ****************************************************************************/
+
+#define W9968CF_MODULE_NAME     "V4L driver for W996[87]CF JPEG USB " \
+                                "Dual Mode Camera Chip"
+#define W9968CF_MODULE_VERSION  "v1.22"
+#define W9968CF_MODULE_AUTHOR   "(C) 2002 2003 Luca Risolia"
+#define W9968CF_AUTHOR_EMAIL    "<luca_ing@libero.it>"
+
+static u8 w9968cf_vppmod_present; /* status flag: yes=1, no=0 */
+
+static const struct usb_device_id winbond_id_table[] = {
+	{
+		/* Creative Labs Video Blaster WebCam Go Plus */
+		USB_DEVICE(0x041e, 0x4003),
+		.driver_info = (unsigned long)"w9968cf",
+	},
+	{
+		/* Generic W996[87]CF JPEG USB Dual Mode Camera */
+		USB_DEVICE(0x1046, 0x9967),
+		.driver_info = (unsigned long)"w9968cf",
+	},
+	{ } /* terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, winbond_id_table);
+
+/* W996[87]CF camera models, internal ids: */
+enum w9968cf_model_id {
+	W9968CF_MOD_GENERIC = 1, /* Generic W996[87]CF based device */
+	W9968CF_MOD_CLVBWGP = 11,/*Creative Labs Video Blaster WebCam Go Plus*/
+	W9968CF_MOD_ADPA5R = 21, /* Aroma Digi Pen ADG-5000 Refurbished */
+	W9986CF_MOD_AU = 31,     /* AVerTV USB */
+	W9968CF_MOD_CLVBWG = 34, /* Creative Labs Video Blaster WebCam Go */
+	W9968CF_MOD_DLLDK = 37,  /* Die Lebon LDC-D35A Digital Kamera */
+	W9968CF_MOD_EEEMC = 40,   /* Ezonics EZ-802 EZMega Cam */
+	W9968CF_MOD_ODPVDMPC = 43,/* OPCOM Digi Pen VGA Dual Mode Pen Camera */
+};
+
+enum w9968cf_frame_status {
+	F_READY,            /* finished grabbing & ready to be read/synced */
+	F_GRABBING,         /* in the process of being grabbed into */
+	F_ERROR,            /* something bad happened while processing */
+	F_UNUSED            /* unused (no VIDIOCMCAPTURE) */
+};
+
+struct w9968cf_frame_t {
+	void* buffer;
+	u32 length;
+	enum w9968cf_frame_status status;
+	struct w9968cf_frame_t* next;
+	u8 queued;
+};
+
+enum w9968cf_vpp_flag {
+	VPP_NONE = 0x00,
+	VPP_UPSCALE = 0x01,
+	VPP_SWAP_YUV_BYTES = 0x02,
+	VPP_DECOMPRESSION = 0x04,
+	VPP_UYVY_TO_RGBX = 0x08,
+};
+
+struct list_head w9968cf_dev_list; /* head of V4L registered cameras list */
+LIST_HEAD(w9968cf_dev_list);
+struct semaphore w9968cf_devlist_sem; /* semaphore for list traversal */
+
+/* Main device driver structure */
+struct w9968cf_device {
+	enum w9968cf_model_id id;   /* private device identifier */
+
+	struct video_device v4ldev; /* V4L structure */
+	struct list_head v4llist;   /* entry of the list of V4L cameras */
+
+	struct usb_device* usbdev;           /* -> main USB structure */
+	struct urb* urb[W9968CF_URBS];       /* -> USB request block structs */
+	void* transfer_buffer[W9968CF_URBS]; /* -> ISO transfer buffers */
+	u16* control_buffer;                 /* -> buffer for control req.*/
+	u16* data_buffer;                    /* -> data to send to the FSB */
+
+	struct w9968cf_frame_t frame[W9968CF_MAX_BUFFERS];
+	struct w9968cf_frame_t frame_tmp;  /* temporary frame */
+	struct w9968cf_frame_t* frame_current; /* -> frame being grabbed */
+	struct w9968cf_frame_t* requested_frame[W9968CF_MAX_BUFFERS];
+	void* vpp_buffer; /* -> helper buffer for post-processing routines */
+
+	u8 max_buffers,   /* number of requested buffers */	   
+	   force_palette, /* yes=1/no=0 */
+	   force_rgb,     /* read RGB instead of BGR, yes=1, no=0 */
+	   double_buffer, /* hardware double buffering yes=1/no=0 */
+	   clamping,      /* video data clamping yes=1/no=0 */
+	   filter_type,   /* 0=disabled, 1=3 tap, 2=5 tap filter */
+	   capture,       /* 0=disabled, 1=enabled */
+	   largeview,     /* 0=disabled, 1=enabled */
+	   decompression, /* 0=disabled, 1=forced, 2=allowed */
+	   upscaling;     /* software image scaling, 0=enabled, 1=disabled */
+
+	struct video_picture picture; /* current window settings */
+	struct video_window window;   /* current picture settings */
+
+	u16 hw_depth,    /* depth (used by the chip) */
+	    hw_palette,  /* palette (used by the chip) */
+	    hw_width,    /* width (used by the chip) */
+	    hw_height,   /* height (used by the chip) */
+	    hs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */
+	    vs_polarity; /* 0=negative sync pulse, 1=positive sync pulse */
+
+	enum w9968cf_vpp_flag vpp_flag; /* post-processing routines in use */
+
+	u8 nbuffers,      /* number of allocated frame buffers */
+	   altsetting,    /* camera alternate setting */
+	   disconnected,  /* flag: yes=1, no=0 */
+	   misconfigured, /* flag: yes=1, no=0 */
+	   users,         /* flag: number of users holding the device */
+	   streaming;     /* flag: yes=1, no=0 */
+
+	int sensor; /* type of image CMOS sensor chip (CC_*) */
+
+	/* Determined by CMOS sensor type */
+	u16 maxwidth,
+	    maxheight,
+	    minwidth,
+	    minheight,
+	    start_cropx,
+	    start_cropy;
+
+	u8  auto_brt,     /* auto brightness enabled flag */
+	    auto_exp,     /* auto exposure enabled flag */
+	    backlight,    /* backlight exposure algorithm flag */
+	    mirror,       /* image is reversed horizontally */
+	    lightfreq,    /* power (lighting) frequency */
+	    bandfilt;     /* banding filter enabled flag */
+	s8  clockdiv;     /* clock divisor */
+	int sensor_mono;  /* CMOS sensor is (probably) monochrome */
+
+	/* I2C interface to kernel */
+	struct i2c_adapter i2c_adapter;
+	struct i2c_client* sensor_client;
+
+	/* Locks */
+	struct semaphore dev_sem,    /* for probe, disconnect,open and close */
+	                 fileop_sem; /* for read and ioctl */
+	spinlock_t urb_lock,   /* for submit_urb() and unlink_urb() */
+	           flist_lock; /* for requested frame list accesses */
+	char command[16]; /* name of the program holding the device */
+	wait_queue_head_t open, wait_queue;
+};
+
+#define W9968CF_HW_BUF_SIZE 640*480*2 /* buf. size for original video frames */
+
+#define SENSOR_FORMAT          VIDEO_PALETTE_UYVY
+#define SENSOR_FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
+
+
+/****************************************************************************
+ * Macros and other constants                                               *
+ ****************************************************************************/
+
+#undef DBG
+#ifdef W9968CF_DEBUG
+#	define DBG(level, fmt, args...) \
+{ \
+if ( ((specific_debug) && (debug == (level))) || \
+     ((!specific_debug) && (debug >= (level))) ) { \
+	if ((level) == 1) \
+		err(fmt, ## args); \
+	else if ((level) == 2 || (level) == 3) \
+		info(fmt, ## args); \
+	else if ((level) == 4) \
+		warn(fmt, ## args); \
+	else if ((level) >= 5) \
+		info("[%s,%d] " fmt, \
+		     __PRETTY_FUNCTION__, __LINE__ , ## args); \
+} \
+}
+#else
+	/* Not debugging: nothing */
+#	define DBG(level, fmt, args...) do {;} while(0);
+#endif
+
+#undef PDBG
+#undef PDBGG
+#define PDBG(fmt, args...) info("[%s, %d] "fmt, \
+	                        __PRETTY_FUNCTION__, __LINE__ , ## args);
+#define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
+
+#endif /* _W9968CF_H_ */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/w9968cf_decoder.h 001-linus.patch/drivers/usb/media/w9968cf_decoder.h
--- 000-virgin/drivers/usb/media/w9968cf_decoder.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/usb/media/w9968cf_decoder.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Video decoder for the W996[87]CF driver for Linux.                      *
+ *                                                                         *
+ * Copyright (C) 2003 by Luca Risolia <luca_ing@libero.it>                 *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _W9968CF_DECODER_H_
+#define _W9968CF_DECODER_H_
+
+/* Comment/uncomment this for high/low quality of compressed video */
+#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO
+
+#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO
+static const unsigned char Y_QUANTABLE[64] = {
+	16,  11,  10,  16,  24,  40,  51,  61,
+	12,  12,  14,  19,  26,  58,  60,  55,
+	14,  13,  16,  24,  40,  57,  69,  56,
+	14,  17,  22,  29,  51,  87,  80,  62,
+	18,  22,  37,  56,  68, 109, 103,  77,
+	24,  35,  55,  64,  81, 104, 113,  92,
+	49,  64,  78,  87, 103, 121, 120, 101,
+	72,  92,  95,  98, 112, 100, 103,  99
+};
+
+static const unsigned char UV_QUANTABLE[64] = {
+	17,  18,  24,  47,  99,  99,  99,  99,
+	18,  21,  26,  66,  99,  99,  99,  99,
+	24,  26,  56,  99,  99,  99,  99,  99,
+	47,  66,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99,
+	99,  99,  99,  99,  99,  99,  99,  99
+};
+#else
+static const unsigned char Y_QUANTABLE[64] = {
+	 8,   5,   5,   8,  12,  20,  25,  30,
+	 6,   6,   7,   9,  13,  29,  30,  27,
+	 7,   6,   8,  12,  20,  28,  34,  28,
+	 7,   8,  11,  14,  25,  43,  40,  31,
+	 9,  11,  18,  28,  34,  54,  51,  38,
+	12,  17,  27,  32,  40,  52,  56,  46,
+	24,  32,  39,  43,  51,  60,  60,  50,
+	36,  46,  47,  49,  56,  50,  51,  49
+};
+
+static const unsigned char UV_QUANTABLE[64] = {
+	 8,   9,  12,  23,  49,  49,  49,  49,
+	 9,  10,  13,  33,  49,  49,  49,  49,
+	12,  13,  28,  49,  49,  49,  49,  49,
+	23,  33,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49,
+	49,  49,  49,  49,  49,  49,  49,  49
+};
+#endif
+
+#define W9968CF_DEC_ERR_CORRUPTED_DATA  -1
+#define W9968CF_DEC_ERR_BUF_OVERFLOW    -2
+#define W9968CF_DEC_ERR_NO_SOI          -3
+#define W9968CF_DEC_ERR_NO_SOF0         -4
+#define W9968CF_DEC_ERR_NO_SOS          -5
+#define W9968CF_DEC_ERR_NO_EOI          -6
+
+extern void w9968cf_init_decoder(void);
+extern int w9968cf_check_headers(const unsigned char* Pin, 
+                                 const unsigned long BUF_SIZE);
+extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, 
+                          const unsigned W, const unsigned H, char* Pout);
+
+#endif /* _W9968CF_DECODER_H_ */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/media/w9968cf_externaldef.h 001-linus.patch/drivers/usb/media/w9968cf_externaldef.h
--- 000-virgin/drivers/usb/media/w9968cf_externaldef.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/usb/media/w9968cf_externaldef.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Various definitions for compatibility with external modules.            *
+ * This file is part of the W996[87]CF driver for Linux.                   *
+ *                                                                         *
+ * Copyright (C) 2002 2003 by Luca Risolia <luca_ing@libero.it>            *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#ifndef _W9968CF_EXTERNALDEF_H_
+#define _W9968CF_EXTERNALDEF_H_
+
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+/* The following values have been copied from the "ovcamchip" module. */
+
+#ifndef I2C_DRIVERID_OVCAMCHIP
+#	define I2C_DRIVERID_OVCAMCHIP   0xf00f
+#endif
+
+/* Controls */
+enum {
+	OVCAMCHIP_CID_CONT,       /* Contrast */
+	OVCAMCHIP_CID_BRIGHT,     /* Brightness */
+	OVCAMCHIP_CID_SAT,        /* Saturation */
+	OVCAMCHIP_CID_HUE,        /* Hue */
+	OVCAMCHIP_CID_EXP,        /* Exposure */
+	OVCAMCHIP_CID_FREQ,       /* Light frequency */
+	OVCAMCHIP_CID_BANDFILT,   /* Banding filter */
+	OVCAMCHIP_CID_AUTOBRIGHT, /* Auto brightness */
+	OVCAMCHIP_CID_AUTOEXP,    /* Auto exposure */
+	OVCAMCHIP_CID_BACKLIGHT,  /* Back light compensation */
+	OVCAMCHIP_CID_MIRROR,     /* Mirror horizontally */
+};
+
+/* I2C addresses */
+#define OV7xx0_SID   (0x42 >> 1)
+#define OV6xx0_SID   (0xC0 >> 1)
+
+/* Sensor types */
+enum {
+	CC_UNKNOWN,
+	CC_OV76BE,
+	CC_OV7610,
+	CC_OV7620,
+	CC_OV7620AE,
+	CC_OV6620,
+	CC_OV6630,
+	CC_OV6630AE,
+	CC_OV6630AF,
+};
+
+/* API */
+struct ovcamchip_control {
+	__u32 id;
+	__s32 value;
+};
+
+struct ovcamchip_window {
+	int x;
+	int y;
+	int width;
+	int height;
+	int format;
+	int quarter;   /* Scale width and height down 2x */
+
+	/* This stuff will be removed eventually */
+	int clockdiv;  /* Clock divisor setting */
+};
+
+/* Commands. 
+   You must call OVCAMCHIP_CMD_INITIALIZE before any of other commands */
+#define OVCAMCHIP_CMD_Q_SUBTYPE  _IOR  (0x88, 0x00, int)
+#define OVCAMCHIP_CMD_INITIALIZE _IOW  (0x88, 0x01, int)
+#define OVCAMCHIP_CMD_S_CTRL     _IOW  (0x88, 0x02, struct ovcamchip_control)
+#define OVCAMCHIP_CMD_G_CTRL     _IOWR (0x88, 0x03, struct ovcamchip_control)
+#define OVCAMCHIP_CMD_S_MODE     _IOW  (0x88, 0x04, struct ovcamchip_window)
+#define OVCAMCHIP_MAX_CMD        _IO   (0x88, 0x3f)
+
+#endif /* _W9968CF_EXTERNALDEF_H_ */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/misc/Kconfig 001-linus.patch/drivers/usb/misc/Kconfig
--- 000-virgin/drivers/usb/misc/Kconfig	Wed Dec 17 18:59:43 2003
+++ 001-linus.patch/drivers/usb/misc/Kconfig	Tue Dec 30 16:38:57 2003
@@ -58,6 +58,18 @@ config USB_RIO500
 	  To compile this driver as a module, choose M here: the
 	  module will be called rio500.
 
+config USB_LEGOTOWER
+	tristate "USB Lego Infrared Tower support (EXPERIMENTAL)"
+	depends on USB && EXPERIMENTAL
+	help
+	  Say Y here if you want to connect a USB Lego Infrared Tower to your
+	  computer's USB port.
+
+	  This code is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called legousbtower. If you want to compile it as
+	  a module, say M here and read <file:Documentation/modules.txt>.
+
 config USB_BRLVGER
 	tristate "Tieman Voyager USB Braille display support (EXPERIMENTAL)"
 	depends on USB && EXPERIMENTAL
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/misc/Makefile 001-linus.patch/drivers/usb/misc/Makefile
--- 000-virgin/drivers/usb/misc/Makefile	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/usb/misc/Makefile	Tue Dec 30 16:38:57 2003
@@ -12,3 +12,4 @@ obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_TIGL)		+= tiglusb.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
+obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/misc/legousbtower.c 001-linus.patch/drivers/usb/misc/legousbtower.c
--- 000-virgin/drivers/usb/misc/legousbtower.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/drivers/usb/misc/legousbtower.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,878 @@
+/*
+ * LEGO USB Tower driver
+ *
+ * Copyright (C) 2003 David Glance <davidgsf@sourceforge.net> 
+ *               2001 Juergen Stuber <stuber@loria.fr>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ *
+ * derived from USB Skeleton driver - 0.5
+ * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * History:
+ *
+ * 2001-10-13 - 0.1 js
+ *   - first version
+ * 2001-11-03 - 0.2 js
+ *   - simplified buffering, one-shot URBs for writing
+ * 2001-11-10 - 0.3 js
+ *   - removed IOCTL (setting power/mode is more complicated, postponed)
+ * 2001-11-28 - 0.4 js
+ *   - added vendor commands for mode of operation and power level in open
+ * 2001-12-04 - 0.5 js
+ *   - set IR mode by default (by oversight 0.4 set VLL mode)
+ * 2002-01-11 - 0.5? pcchan
+ *   - make read buffer reusable and work around bytes_to_write issue between
+ *     uhci and legusbtower
+ * 2002-09-23 - 0.52 david (david@csse.uwa.edu.au)
+ *   - imported into lejos project
+ *   - changed wake_up to wake_up_interruptible
+ *   - changed to use lego0 rather than tower0
+ *   - changed dbg() to use __func__ rather than deprecated __FUNCTION__
+ * 2003-01-12 - 0.53 david (david@csse.uwa.edu.au)
+ *   - changed read and write to write everything or timeout (from a patch by Chris Riesen and 
+ *     Brett Thaeler driver)
+ *   - added ioctl functionality to set timeouts
+ * 2003-07-18 - 0.54 davidgsf (david@csse.uwa.edu.au) 
+ *   - initial import into LegoUSB project
+ *   - merge of existing LegoUSB.c driver
+ * 2003-07-18 - 0.56 davidgsf (david@csse.uwa.edu.au) 
+ *   - port to 2.6 style driver
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
+
+#ifdef CONFIG_USB_DEBUG
+	static int debug = 4;
+#else
+	static int debug = 1;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(lvl, format, arg...) do { if (debug >= lvl) printk(KERN_DEBUG  __FILE__ " : " format " \n", ## arg); } while (0)
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.56"
+#define DRIVER_AUTHOR "David Glance, davidgsf@sourceforge.net"
+#define DRIVER_DESC "LEGO USB Tower Driver"
+
+/* Module paramaters */
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+
+/* Define these values to match your device */
+#define LEGO_USB_TOWER_VENDOR_ID	0x0694
+#define LEGO_USB_TOWER_PRODUCT_ID	0x0001
+
+/* table of devices that work with this driver */
+static struct usb_device_id tower_table [] = {
+	{ USB_DEVICE(LEGO_USB_TOWER_VENDOR_ID, LEGO_USB_TOWER_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, tower_table);
+
+#define LEGO_USB_TOWER_MINOR_BASE	160
+
+/* we can have up to this number of device plugged in at once */
+#define MAX_DEVICES		16
+
+#define COMMAND_TIMEOUT		(2*HZ)  /* 2 second timeout for a command */
+
+/* Structure to hold all of our device specific stuff */
+struct lego_usb_tower {
+	struct semaphore	sem;		/* locks this structure */
+	struct usb_device* 	udev;		/* save off the usb device pointer */
+	struct usb_interface*   interface;
+	unsigned char		minor;		/* the starting minor number for this device */
+
+	int			open_count;	/* number of times this port has been opened */
+
+	char*			read_buffer;
+	int			read_buffer_length;
+
+	wait_queue_head_t	read_wait;
+	wait_queue_head_t	write_wait;
+
+	char*			interrupt_in_buffer;
+	struct usb_endpoint_descriptor* interrupt_in_endpoint;
+	struct urb*		interrupt_in_urb;
+
+	char*			interrupt_out_buffer;
+	struct usb_endpoint_descriptor* interrupt_out_endpoint;
+	struct urb*		interrupt_out_urb;
+
+};
+
+/* Note that no locking is needed:
+ * read_buffer is arbitrated by read_buffer_length == 0
+ * interrupt_out_buffer is arbitrated by interrupt_out_urb->status == -EINPROGRESS
+ * interrupt_in_buffer belongs to urb alone and is overwritten on overflow
+ */
+
+/* local function prototypes */
+static ssize_t tower_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
+static ssize_t tower_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
+static inline void tower_delete (struct lego_usb_tower *dev);
+static int tower_open		(struct inode *inode, struct file *file);
+static int tower_release	(struct inode *inode, struct file *file);
+static int tower_release_internal (struct lego_usb_tower *dev);
+static void tower_abort_transfers (struct lego_usb_tower *dev);
+static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs);
+static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs);
+
+static int  tower_probe	(struct usb_interface *interface, const struct usb_device_id *id);
+static void tower_disconnect	(struct usb_interface *interface);
+
+
+/* prevent races between open() and disconnect */
+static DECLARE_MUTEX (disconnect_sem);
+
+/* file operations needed when we register this driver */
+static struct file_operations tower_fops = {
+	.owner = 	THIS_MODULE,
+	.read  = 	tower_read,
+	.write =	tower_write,
+	.open =		tower_open,
+	.release = 	tower_release,
+};
+
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver tower_class = {
+	.name =		"usb/legousbtower%d",
+	.fops =		&tower_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+	.minor_base =	LEGO_USB_TOWER_MINOR_BASE,
+};
+
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver tower_driver = {
+	.owner =        THIS_MODULE,
+	.name =	        "legousbtower",
+	.probe = 	tower_probe,
+	.disconnect = 	tower_disconnect,
+	.id_table = 	tower_table,
+};
+
+
+/**
+ *	lego_usb_tower_debug_data
+ */
+static inline void lego_usb_tower_debug_data (int level, const char *function, int size, const unsigned char *data)
+{
+	int i;
+
+	if (debug < level)
+		return; 
+	
+	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size);
+	for (i = 0; i < size; ++i) {
+		printk ("%.2x ", data[i]);
+	}
+	printk ("\n");
+}
+
+
+/**
+ *	tower_delete
+ */
+static inline void tower_delete (struct lego_usb_tower *dev)
+{
+	dbg(2, "%s enter", __func__);
+
+	tower_abort_transfers (dev);
+
+	/* free data structures */
+	if (dev->interrupt_in_urb != NULL) {
+		usb_free_urb (dev->interrupt_in_urb);
+	}
+	if (dev->interrupt_out_urb != NULL) {
+		usb_free_urb (dev->interrupt_out_urb);
+	}
+	kfree (dev->read_buffer);
+	kfree (dev->interrupt_in_buffer);
+	kfree (dev->interrupt_out_buffer);
+	kfree (dev);
+
+	dbg(2, "%s : leave", __func__);
+}
+
+
+/**
+ *	tower_open
+ */
+static int tower_open (struct inode *inode, struct file *file)
+{
+	struct lego_usb_tower *dev = NULL;
+	int subminor;
+	int retval = 0;
+	struct usb_interface *interface;
+
+	dbg(2,"%s : enter", __func__);
+
+	subminor = iminor(inode);
+
+	down (&disconnect_sem);
+
+	interface = usb_find_interface (&tower_driver, subminor);
+
+	if (!interface) {
+		err ("%s - error, can't find device for minor %d",
+		     __FUNCTION__, subminor);
+		retval = -ENODEV;
+		goto exit_no_device;
+	}
+
+	dev = usb_get_intfdata(interface);
+
+	if (!dev) {
+		retval = -ENODEV;
+		goto exit_no_device;
+	}
+
+	/* lock this device */
+	down (&dev->sem);
+
+	
+	/* increment our usage count for the device */
+	++dev->open_count;
+
+	/* save device in the file's private structure */
+	file->private_data = dev;
+
+
+	/* initialize in direction */
+	dev->read_buffer_length = 0;
+
+	up (&dev->sem);
+
+exit_no_device:
+
+	up (&disconnect_sem);
+
+	dbg(2,"%s : leave, return value %d ", __func__, retval);
+
+	return retval;
+}
+
+/**
+ *	tower_release
+ */
+static int tower_release (struct inode *inode, struct file *file)
+{
+	struct lego_usb_tower *dev;
+	int retval = 0;
+
+	dbg(2," %s : enter", __func__);
+
+	dev = (struct lego_usb_tower *)file->private_data;
+
+	if (dev == NULL) {
+		dbg(1," %s : object is NULL", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+
+	/* lock our device */
+	down (&dev->sem);
+
+ 	if (dev->open_count <= 0) {
+		dbg(1," %s : device not opened", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	/* do the work */
+	retval = tower_release_internal (dev);
+
+exit:
+	up (&dev->sem);
+	dbg(2," %s : leave, return value %d", __func__, retval);
+	return retval;
+}
+
+
+/**
+ *	tower_release_internal
+ */
+static int tower_release_internal (struct lego_usb_tower *dev)
+{
+	int retval = 0;
+
+	dbg(2," %s : enter", __func__);
+
+	if (dev->udev == NULL) {
+		/* the device was unplugged before the file was released */
+		tower_delete (dev);
+		goto exit;
+	}
+
+	/* decrement our usage count for the device */
+	--dev->open_count;
+	if (dev->open_count <= 0) {
+		tower_abort_transfers (dev);
+		dev->open_count = 0;
+	}
+
+exit:
+	dbg(2," %s : leave", __func__);
+	return retval;
+}
+
+
+/**
+ *	tower_abort_transfers
+ *      aborts transfers and frees associated data structures
+ */
+static void tower_abort_transfers (struct lego_usb_tower *dev)
+{
+	dbg(2," %s : enter", __func__);
+
+	if (dev == NULL) {
+		dbg(1," %s : dev is null", __func__);
+	        goto exit;
+	}
+
+	/* shutdown transfer */
+	if (dev->interrupt_in_urb != NULL) {
+		usb_unlink_urb (dev->interrupt_in_urb);
+	}
+	if (dev->interrupt_out_urb != NULL) {
+		usb_unlink_urb (dev->interrupt_out_urb);
+	}
+
+exit:
+	dbg(2," %s : leave", __func__);
+}
+
+
+/**
+ *	tower_read
+ */
+static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct lego_usb_tower *dev;
+	size_t bytes_read = 0;
+	size_t bytes_to_read;
+	int i;
+	int retval = 0;
+	int timeout = 0;
+
+	dbg(2," %s : enter, count = %Zd", __func__, count);
+
+	dev = (struct lego_usb_tower *)file->private_data;
+	
+	/* lock this object */
+	down (&dev->sem);
+
+	/* verify that the device wasn't unplugged */
+	if (dev->udev == NULL) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d", retval);
+		goto exit;
+	}
+
+	/* verify that we actually have some data to read */
+	if (count == 0) {
+		dbg(1," %s : read request of 0 bytes", __func__);
+		goto exit;
+	}
+
+
+	timeout = COMMAND_TIMEOUT;
+
+	while (1) {
+		if (dev->read_buffer_length == 0) {
+
+			/* start reading */
+			usb_fill_int_urb (dev->interrupt_in_urb,dev->udev,
+					  usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
+					  dev->interrupt_in_buffer,
+					  dev->interrupt_in_endpoint->wMaxPacketSize,
+					  tower_interrupt_in_callback,
+					  dev,
+					  dev->interrupt_in_endpoint->bInterval);
+			
+			retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL);
+			
+			if (retval < 0) {
+				err("Couldn't submit interrupt_in_urb");
+				goto exit;
+			}
+
+			if (timeout <= 0) {
+			        retval = -ETIMEDOUT;
+			        goto exit;
+			}
+
+			if (signal_pending(current)) {
+				retval = -EINTR;
+				goto exit;
+			}
+
+			up (&dev->sem);
+			timeout = interruptible_sleep_on_timeout (&dev->read_wait, timeout);
+			down (&dev->sem);
+
+		} else {
+			/* copy the data from read_buffer into userspace */
+			bytes_to_read = count > dev->read_buffer_length ? dev->read_buffer_length : count;
+			if (copy_to_user (buffer, dev->read_buffer, bytes_to_read) != 0) {
+				retval = -EFAULT;
+				goto exit;
+			}
+			dev->read_buffer_length -= bytes_to_read;
+			for (i=0; i<dev->read_buffer_length; i++) {
+				dev->read_buffer[i] = dev->read_buffer[i+bytes_to_read];
+			}
+
+			buffer += bytes_to_read;
+			count -= bytes_to_read;
+			bytes_read += bytes_to_read;
+			if (count == 0) {
+				break;
+			}
+		}
+	}
+
+	retval = bytes_read;
+
+exit:
+	/* unlock the device */
+	up (&dev->sem);
+
+	dbg(2," %s : leave, return value %d", __func__, retval);
+	return retval;
+}
+
+
+/**
+ *	tower_write
+ */
+static ssize_t tower_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct lego_usb_tower *dev;
+	size_t bytes_written = 0;
+	size_t bytes_to_write;
+	size_t buffer_size;
+	int retval = 0;
+	int timeout = 0;
+
+	dbg(2," %s : enter, count = %Zd", __func__, count);
+
+	dev = (struct lego_usb_tower *)file->private_data;
+
+	/* lock this object */
+	down (&dev->sem);
+
+	/* verify that the device wasn't unplugged */
+	if (dev->udev == NULL) {
+		retval = -ENODEV;
+		err("No device or device unplugged %d", retval);
+		goto exit;
+	}
+
+	/* verify that we actually have some data to write */
+	if (count == 0) {
+		dbg(1," %s : write request of 0 bytes", __func__);
+		goto exit;
+	}
+
+
+	while (count > 0) {
+		if (dev->interrupt_out_urb->status == -EINPROGRESS) {
+			timeout = COMMAND_TIMEOUT;
+
+			while (timeout > 0) {
+				if (signal_pending(current)) {
+					dbg(1," %s : interrupted", __func__);
+					retval = -EINTR;
+					goto exit;
+				}
+				up (&dev->sem);
+				timeout = interruptible_sleep_on_timeout (&dev->write_wait, timeout);
+				down (&dev->sem);
+				if (timeout > 0) {
+					break;
+				}
+				dbg(1," %s : interrupted timeout: %d", __func__, timeout);
+			}
+
+
+			dbg(1," %s : final timeout: %d", __func__, timeout);
+
+			if (timeout == 0) {
+				dbg(1, "%s - command timed out.", __func__);
+				retval = -ETIMEDOUT;
+				goto exit;
+			}
+
+			dbg(4," %s : in progress, count = %Zd", __func__, count);
+		} else {
+			dbg(4," %s : sending, count = %Zd", __func__, count);
+
+			/* write the data into interrupt_out_buffer from userspace */
+			buffer_size = dev->interrupt_out_endpoint->wMaxPacketSize;
+			bytes_to_write = count > buffer_size ? buffer_size : count;
+			dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", __func__, buffer_size, count, bytes_to_write);
+
+			if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+				retval = -EFAULT;
+				goto exit;
+			}
+
+			/* send off the urb */
+			usb_fill_int_urb(dev->interrupt_out_urb,
+					dev->udev, 
+					usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
+					dev->interrupt_out_buffer,
+					bytes_to_write,
+					tower_interrupt_out_callback,
+					dev,
+					dev->interrupt_in_endpoint->bInterval);
+
+			dev->interrupt_out_urb->actual_length = bytes_to_write;
+			retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL);
+
+			if (retval < 0) {
+				err("Couldn't submit interrupt_out_urb %d", retval);
+				goto exit;
+			}
+
+			buffer += bytes_to_write;
+			count -= bytes_to_write;
+
+			bytes_written += bytes_to_write;
+		}
+	}
+
+	retval = bytes_written;
+
+exit:
+	/* unlock the device */
+	up (&dev->sem);
+
+	dbg(2," %s : leave, return value %d", __func__, retval);
+
+	return retval;
+}
+
+
+/**
+ *	tower_interrupt_in_callback
+ */
+static void tower_interrupt_in_callback (struct urb *urb, struct pt_regs *regs)
+{
+	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+
+	dbg(4," %s : enter, status %d", __func__, urb->status);
+
+	lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+
+	if (urb->status != 0) {
+		if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
+			dbg(1," %s : nonzero status received: %d", __func__, urb->status);
+		}
+		goto exit;
+	}
+
+	down (&dev->sem);
+
+	if (urb->actual_length > 0) {
+		if (dev->read_buffer_length < (4 * dev->interrupt_in_endpoint->wMaxPacketSize) - (urb->actual_length)) {
+
+			memcpy (dev->read_buffer+dev->read_buffer_length, dev->interrupt_in_buffer, urb->actual_length);
+
+			dev->read_buffer_length += urb->actual_length;
+			dbg(1," %s reading  %d ", __func__, urb->actual_length);
+			wake_up_interruptible (&dev->read_wait);
+
+		} else {
+			dbg(1," %s : read_buffer overflow", __func__);
+		}
+	}
+
+	up (&dev->sem);
+
+exit:
+	lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+	dbg(4," %s : leave, status %d", __func__, urb->status);
+}
+
+
+/**
+ *	tower_interrupt_out_callback
+ */
+static void tower_interrupt_out_callback (struct urb *urb, struct pt_regs *regs)
+{
+	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+
+	dbg(4," %s : enter, status %d", __func__, urb->status);
+	lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+
+	if (urb->status != 0) {
+		if ((urb->status != -ENOENT) && 
+		    (urb->status != -ECONNRESET)) {
+			dbg(1, " %s :nonzero status received: %d", __func__, urb->status);
+		}
+		goto exit;
+	}                        
+
+	wake_up_interruptible(&dev->write_wait);
+exit:
+
+	lego_usb_tower_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+	dbg(4," %s : leave, status %d", __func__, urb->status);
+}
+
+
+/**
+ *	tower_probe
+ *
+ *	Called by the usb core when a new device is connected that it thinks
+ *	this driver might be interested in.
+ */
+static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct lego_usb_tower *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor* endpoint;
+	int i;
+	int retval = -ENOMEM;
+
+	dbg(2," %s : enter", __func__);
+
+	if (udev == NULL) {
+		info ("udev is NULL.");
+	}
+	
+	/* See if the device offered us matches what we can accept */
+	if ((udev->descriptor.idVendor != LEGO_USB_TOWER_VENDOR_ID) ||
+	    (udev->descriptor.idProduct != LEGO_USB_TOWER_PRODUCT_ID)) {
+		return -ENODEV;
+	}
+
+
+	/* allocate memory for our device state and intialize it */
+
+	dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
+
+	if (dev == NULL) {
+		err ("Out of memory");
+		goto exit;
+	}
+
+	init_MUTEX (&dev->sem);
+
+	dev->udev = udev;
+	dev->open_count = 0;
+
+	dev->read_buffer = NULL;
+	dev->read_buffer_length = 0;
+
+	init_waitqueue_head (&dev->read_wait);
+	init_waitqueue_head (&dev->write_wait);
+
+	dev->interrupt_in_buffer = NULL;
+	dev->interrupt_in_endpoint = NULL;
+	dev->interrupt_in_urb = NULL;
+
+	dev->interrupt_out_buffer = NULL;
+	dev->interrupt_out_endpoint = NULL;
+	dev->interrupt_out_urb = NULL;
+
+
+	iface_desc = &interface->altsetting[0];
+
+	/* set up the endpoint information */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			dev->interrupt_in_endpoint = endpoint;
+		}
+		
+		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			dev->interrupt_out_endpoint = endpoint;
+		}
+	}
+	if(dev->interrupt_in_endpoint == NULL) {
+		err("interrupt in endpoint not found");
+		goto error;
+	}
+	if (dev->interrupt_out_endpoint == NULL) {
+		err("interrupt out endpoint not found");
+		goto error;
+	}
+
+	dev->read_buffer = kmalloc ((4*dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL);
+	if (!dev->read_buffer) {
+		err("Couldn't allocate read_buffer");
+		goto error;
+	}
+	dev->interrupt_in_buffer = kmalloc (dev->interrupt_in_endpoint->wMaxPacketSize, GFP_KERNEL);
+	if (!dev->interrupt_in_buffer) {
+		err("Couldn't allocate interrupt_in_buffer");
+		goto error;
+	}
+	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_in_urb) {
+		err("Couldn't allocate interrupt_in_urb");
+		goto error;
+	}
+	dev->interrupt_out_buffer = kmalloc (dev->interrupt_out_endpoint->wMaxPacketSize, GFP_KERNEL);
+	if (!dev->interrupt_out_buffer) {
+		err("Couldn't allocate interrupt_out_buffer");
+		goto error;
+	}
+	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->interrupt_out_urb) {
+		err("Couldn't allocate interrupt_out_urb");
+		goto error;
+	}                
+
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata (interface, dev);
+
+	retval = usb_register_dev (interface, &tower_class);
+
+	if (retval) {
+		/* something prevented us from registering this driver */
+		err ("Not able to get a minor for this device.");
+		usb_set_intfdata (interface, NULL);
+		goto error;
+	}
+
+	dev->minor = interface->minor;
+
+	/* let the user know what node this device is now attached to */
+	info ("LEGO USB Tower device now attached to /dev/usb/lego%d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE));
+
+
+
+exit:
+	dbg(2," %s : leave, return value 0x%.8lx (dev)", __func__, (long) dev);
+
+	return retval;
+
+error:
+	tower_delete(dev);
+	return retval;
+}
+
+
+/**
+ *	tower_disconnect
+ *
+ *	Called by the usb core when the device is removed from the system.
+ */
+static void tower_disconnect (struct usb_interface *interface)
+{
+	struct lego_usb_tower *dev;
+	int minor;
+
+	dbg(2," %s : enter", __func__);
+
+	down (&disconnect_sem);
+
+	dev = usb_get_intfdata (interface);
+	usb_set_intfdata (interface, NULL);
+
+
+	down (&dev->sem);
+
+	minor = dev->minor;
+
+	/* give back our minor */
+	usb_deregister_dev (interface, &tower_class);
+
+	/* if the device is not opened, then we clean up right now */
+	if (!dev->open_count) {
+		up (&dev->sem);
+		tower_delete (dev);
+	} else {
+		dev->udev = NULL;
+		up (&dev->sem);
+	}
+
+	up (&disconnect_sem);
+
+	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+
+	dbg(2," %s : leave", __func__);
+}
+
+
+
+/**
+ *	lego_usb_tower_init
+ */
+static int __init lego_usb_tower_init(void)
+{
+	int result;
+	int retval = 0;
+
+	dbg(2," %s : enter", __func__);
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&tower_driver);
+	if (result < 0) {
+		err("usb_register failed for the "__FILE__" driver. Error number %d", result);
+		retval = -1;
+		goto exit;
+	}
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+exit:
+	dbg(2," %s : leave, return value %d", __func__, retval);
+
+	return retval;
+}
+
+
+/**
+ *	lego_usb_tower_exit
+ */
+static void __exit lego_usb_tower_exit(void)
+{
+	dbg(2," %s : enter", __func__);
+
+	/* deregister this driver with the USB subsystem */
+	usb_deregister (&tower_driver);
+
+	dbg(2," %s : leave", __func__);
+}
+
+module_init (lego_usb_tower_init);
+module_exit (lego_usb_tower_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/net/Kconfig 001-linus.patch/drivers/usb/net/Kconfig
--- 000-virgin/drivers/usb/net/Kconfig	Wed Dec 17 18:59:16 2003
+++ 001-linus.patch/drivers/usb/net/Kconfig	Tue Dec 30 16:38:57 2003
@@ -69,7 +69,7 @@ config USB_KAWETH
 
 config USB_PEGASUS
 	tristate "USB Pegasus/Pegasus-II based ethernet device support"
-	depends on USB && NET
+	depends on USB && NET_ETHERNET
 	select MII
 	---help---
 	  Say Y here if you know you have Pegasus or Pegasus-II based adapter.
@@ -96,8 +96,6 @@ config USB_RTL8150
 config USB_USBNET
 	tristate "Multi-purpose USB Networking Framework"
 	depends on USB && NET
-	select CRC32
-	select MII
 	---help---
 	  This driver supports several kinds of network links over USB,
 	  with "minidrivers" built around a common network driver core
@@ -206,6 +204,7 @@ config USB_EPSON2888
 config USB_ZAURUS
 	boolean "Sharp Zaurus (stock ROMs)"
 	depends on USB_USBNET
+	select CRC32
 	default y
 	help
 	  Choose this option to support the usb networking links used by
@@ -217,9 +216,7 @@ config USB_ZAURUS
 
 config USB_CDCETHER
 	boolean "CDC Ethernet support (smart devices such as cable modems)"
-	# experimental primarily because cdc-ether was.
-	# make it non-experimental after more interop testing
-	depends on USB_USBNET && EXPERIMENTAL
+	depends on USB_USBNET
 	default y
 	help
 	  This option supports devices conforming to the Communication Device
@@ -247,7 +244,9 @@ comment "USB Network Adapters"
 
 config USB_AX8817X
 	boolean "ASIX AX88172 Based USB 2.0 Ethernet Devices"
-	depends on USB_USBNET && EXPERIMENTAL
+	depends on USB_USBNET && NET_ETHERNET
+	select CRC32
+	select MII
 	default y
 	help
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/net/pegasus.h 001-linus.patch/drivers/usb/net/pegasus.h
--- 000-virgin/drivers/usb/net/pegasus.h	Wed Dec 17 18:59:53 2003
+++ 001-linus.patch/drivers/usb/net/pegasus.h	Tue Dec 30 16:38:57 2003
@@ -137,6 +137,7 @@ struct usb_eth_dev {
 #define	VENDOR_MELCO		0x0411
 #define	VENDOR_MOBILITY		0x1342
 #define	VENDOR_NETGEAR		0x0846
+#define	VENDOR_OCT		0x0b39
 #define	VENDOR_SMARTBRIDGES	0x08d1
 #define	VENDOR_SMC		0x0707
 #define	VENDOR_SOHOWARE		0x15e8
@@ -173,7 +174,7 @@ PEGASUS_DEV( "SpeedStream USB 10/100 Eth
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
 		VENDOR_ADMTEK, 0x8511,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
+		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
 PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
 		VENDOR_ADMTEK, 0x8513,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
@@ -260,6 +261,8 @@ PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VE
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/net/usbnet.c 001-linus.patch/drivers/usb/net/usbnet.c
--- 000-virgin/drivers/usb/net/usbnet.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/usb/net/usbnet.c	Tue Dec 30 16:38:57 2003
@@ -637,6 +637,27 @@ static void ax8817x_get_drvinfo (struct 
 	info->eedump_len = 0x3e;
 }
 
+static u32 ax8817x_get_link (struct net_device *net)
+{
+	struct usbnet *dev = (struct usbnet *)net->priv;
+
+	return (u32)mii_link_ok(&dev->mii);
+}
+
+static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+	struct usbnet *dev = (struct usbnet *)net->priv;
+
+	return mii_ethtool_gset(&dev->mii,cmd);
+}
+
+static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+	struct usbnet *dev = (struct usbnet *)net->priv;
+
+	return mii_ethtool_sset(&dev->mii,cmd);
+}
+
 static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
@@ -670,16 +691,6 @@ static int ax8817x_bind(struct usbnet *d
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-	/* Get IPG values */
-	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf)) < 0) {
-		dbg("Error reading IPG values: %d", ret);
-		return ret;
-	}
-
-	for(i = 0;i < 3;i++) {
-		ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0 + i, 0, 0, 1, &buf[i]);
-	}
-
 	/* Get the PHY id */
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
 		dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
@@ -735,9 +746,12 @@ static int ax8817x_bind(struct usbnet *d
 	dev->net->set_multicast_list = ax8817x_set_multicast;
 
 	usbnet_ethtool_ops.get_drvinfo = &ax8817x_get_drvinfo;
+	usbnet_ethtool_ops.get_link = &ax8817x_get_link;
 	usbnet_ethtool_ops.get_wol = &ax8817x_get_wol;
 	usbnet_ethtool_ops.set_wol = &ax8817x_set_wol;
 	usbnet_ethtool_ops.get_eeprom = &ax8817x_get_eeprom;
+	usbnet_ethtool_ops.get_settings = &ax8817x_get_settings;
+	usbnet_ethtool_ops.set_settings = &ax8817x_set_settings;
 
 	return 0;
 }
@@ -909,8 +923,7 @@ static int cdc_bind (struct usbnet *dev,
 	memset (info, 0, sizeof *info);
 	info->control = intf;
 	while (len > 3) {
-		/* ignore bDescriptorType != CS_INTERFACE */
-		if (buf [1] != 0x24)
+		if (buf [1] != USB_DT_CS_INTERFACE)
 			goto next_desc;
 
 		/* bDescriptorSubType identifies three "must have" descriptors;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/cyberjack.c 001-linus.patch/drivers/usb/serial/cyberjack.c
--- 000-virgin/drivers/usb/serial/cyberjack.c	Wed Dec 17 18:59:37 2003
+++ 001-linus.patch/drivers/usb/serial/cyberjack.c	Tue Dec 30 16:38:57 2003
@@ -295,7 +295,6 @@ static void cyberjack_read_int_callback(
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
 	struct usb_serial *serial;
 	unsigned char *data = urb->transfer_buffer;
 	int result;
@@ -323,13 +322,13 @@ static void cyberjack_read_int_callback(
 		/* This is a announcement of coming bulk_ins. */
 		unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
 
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock(&priv->lock);
 
 		old_rdtodo = priv->rdtodo;
 
 		if( (old_rdtodo+size)<(old_rdtodo) ) {
 			dbg( "To many bulk_in urbs to do." );
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_unlock(&priv->lock);
 			goto resubmit;
 		}
 
@@ -338,11 +337,11 @@ static void cyberjack_read_int_callback(
 
 		dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
 
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock(&priv->lock);
 
 		if( !old_rdtodo ) {
 			port->read_urb->dev = port->serial->dev;
-			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 			if( result )
 				err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 			dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
@@ -351,7 +350,7 @@ static void cyberjack_read_int_callback(
 
 resubmit:
 	port->interrupt_in_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 	if (result)
 		err(" usb_submit_urb(read int) failed");
 	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
@@ -361,7 +360,6 @@ static void cyberjack_read_bulk_callback
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
@@ -397,7 +395,7 @@ static void cyberjack_read_bulk_callback
 	  	tty_flip_buffer_push(tty);
 	}
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock(&priv->lock);
 
 	/* Reduce urbs to do by one. */
 	priv->rdtodo-=urb->actual_length;
@@ -405,14 +403,14 @@ static void cyberjack_read_bulk_callback
 	if ( priv->rdtodo<0 ) priv->rdtodo = 0;
 	todo = priv->rdtodo;
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->lock);
 
 	dbg("%s - rdtodo: %d", __FUNCTION__, todo);
 
 	/* Continue to read if we have still urbs to do. */
 	if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
 		port->read_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (result)
 			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
 		dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
@@ -423,7 +421,6 @@ static void cyberjack_write_bulk_callbac
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
-	unsigned long flags;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -438,7 +435,7 @@ static void cyberjack_write_bulk_callbac
 		return;
 	}
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock(&priv->lock);
 
 	/* only do something if we have more data to send */
 	if( priv->wrfilled ) {
@@ -446,7 +443,7 @@ static void cyberjack_write_bulk_callbac
 
 		if (port->write_urb->status == -EINPROGRESS) {
 			dbg("%s - already writing", __FUNCTION__);
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_unlock(&priv->lock);
 			return;
 		}
 
@@ -492,7 +489,7 @@ static void cyberjack_write_bulk_callbac
 	}
 
 exit:
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->lock);
 	schedule_work(&port->work);
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/ftdi_sio.c 001-linus.patch/drivers/usb/serial/ftdi_sio.c
--- 000-virgin/drivers/usb/serial/ftdi_sio.c	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/drivers/usb/serial/ftdi_sio.c	Tue Dec 30 16:38:57 2003
@@ -342,6 +342,10 @@ static struct usb_device_id id_table_8U2
 	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
 	{ }						/* Terminating entry */
 };
 
@@ -416,6 +420,10 @@ static struct usb_device_id id_table_FT2
 	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(IDTECH_VID, IDTECH_IDT1221U_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(OCT_VID, OCT_US101_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_1, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -505,6 +513,10 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
 	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
+	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) },
+	{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
+	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
+	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
 	{ }						/* Terminating entry */
 };
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/ftdi_sio.h 001-linus.patch/drivers/usb/serial/ftdi_sio.h
--- 000-virgin/drivers/usb/serial/ftdi_sio.h	Wed Dec 17 18:59:28 2003
+++ 001-linus.patch/drivers/usb/serial/ftdi_sio.h	Tue Dec 30 16:38:57 2003
@@ -145,6 +145,14 @@
 /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
 #define OCT_US101_PID		0x0421	/* OCT US101 USB to RS-232 */
 
+/*
+ * Protego product ids
+ */
+#define PROTEGO_SPECIAL_1	0xFC70	/* special/unknown device */
+#define PROTEGO_R2X0		0xFC71	/* R200-USB TRNG unit (R210, R220, and R230) */
+#define PROTEGO_SPECIAL_3	0xFC72	/* special/unknown device */
+#define PROTEGO_SPECIAL_4	0xFC73	/* special/unknown device */ 
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/io_edgeport.c 001-linus.patch/drivers/usb/serial/io_edgeport.c
--- 000-virgin/drivers/usb/serial/io_edgeport.c	Wed Dec 17 18:58:07 2003
+++ 001-linus.patch/drivers/usb/serial/io_edgeport.c	Tue Dec 30 16:38:57 2003
@@ -1488,16 +1488,20 @@ static void send_more_port_data(struct e
 		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
 		       buffer, count+2, edge_bulk_out_data_callback, edge_port);
 
+	/* decrement the number of credits we have by the number we just sent */
+	edge_port->txCredits -= count;
+	edge_port->icount.tx += count;
+
 	urb->dev = edge_serial->serial->dev;
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		/* something went wrong */
 		dbg("%s - usb_submit_urb(write bulk) failed", __FUNCTION__);
 		edge_port->write_in_progress = FALSE;
-	} else {
-		/* decrement the number of credits we have by the number we just sent */
-		edge_port->txCredits -= count;
-		edge_port->icount.tx += count;
+
+		/* revert the credits as something bad happened. */
+		edge_port->txCredits += count;
+		edge_port->icount.tx -= count;
 	}
 	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/io_fw_boot.h 001-linus.patch/drivers/usb/serial/io_fw_boot.h
--- 000-virgin/drivers/usb/serial/io_fw_boot.h	Wed Dec 17 18:59:55 2003
+++ 001-linus.patch/drivers/usb/serial/io_fw_boot.h	Tue Dec 30 16:38:57 2003
@@ -17,7 +17,7 @@
 		unsigned short Addr;
 		unsigned short Len;
 		unsigned char  Data[0];
-	};
+	} __attribute__ ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char	 MajorVersion;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/io_fw_boot2.h 001-linus.patch/drivers/usb/serial/io_fw_boot2.h
--- 000-virgin/drivers/usb/serial/io_fw_boot2.h	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/drivers/usb/serial/io_fw_boot2.h	Tue Dec 30 16:38:57 2003
@@ -17,7 +17,7 @@
 		unsigned short Addr;
 		unsigned short Len;
 		unsigned char  Data[0];
-	};
+	} __attribute__ ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char	 MajorVersion;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/io_fw_down.h 001-linus.patch/drivers/usb/serial/io_fw_down.h
--- 000-virgin/drivers/usb/serial/io_fw_down.h	Wed Dec 17 18:59:46 2003
+++ 001-linus.patch/drivers/usb/serial/io_fw_down.h	Tue Dec 30 16:38:57 2003
@@ -17,7 +17,7 @@
 		unsigned short	Addr;
 		unsigned short	Len;
 		unsigned char	Data[0];
-	};
+	} __attribute ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char	MajorVersion;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/io_fw_down2.h 001-linus.patch/drivers/usb/serial/io_fw_down2.h
--- 000-virgin/drivers/usb/serial/io_fw_down2.h	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/drivers/usb/serial/io_fw_down2.h	Tue Dec 30 16:38:57 2003
@@ -17,7 +17,7 @@
 		unsigned short Addr;
 		unsigned short Len;
 		unsigned char  Data[0];
-	};
+	} __attribute__ ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char  MajorVersion;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/mct_u232.c 001-linus.patch/drivers/usb/serial/mct_u232.c
--- 000-virgin/drivers/usb/serial/mct_u232.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/usb/serial/mct_u232.c	Tue Dec 30 16:38:57 2003
@@ -24,6 +24,11 @@
  *   Basic tests have been performed with minicom/zmodem transfers and
  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
  *
+ * 04-Nov-2003 Bill Marr <marr at flex dot com>
+ *   - Mimic Windows driver by sending 2 USB 'device request' messages
+ *     following normal 'baud rate change' message.  This allows data to be
+ *     transmitted to RS-232 devices which don't assert the 'CTS' signal.
+ *
  * 10-Nov-2001 Wolfgang Grandegger
  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
  *
@@ -85,7 +90,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1"
+#define DRIVER_VERSION "v1.2"
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
 
@@ -216,6 +221,7 @@ static int mct_u232_set_baud_rate(struct
 {
 	unsigned int divisor;
         int rc;
+        unsigned char zero_byte = 0;
 	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                              MCT_U232_SET_BAUD_RATE_REQUEST,
@@ -225,6 +231,35 @@ static int mct_u232_set_baud_rate(struct
 	if (rc < 0)
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
 	dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
+
+	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
+	   always sends two extra USB 'device request' messages after the
+	   'baud rate change' message.  The actual functionality of the
+	   request codes in these messages is not fully understood but these
+	   particular codes are never seen in any operation besides a baud
+	   rate change.  Both of these messages send a single byte of data
+	   whose value is always zero.  The second of these two extra messages
+	   is required in order for data to be properly written to an RS-232
+	   device which does not assert the 'CTS' signal. */
+
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     MCT_U232_SET_UNKNOWN1_REQUEST, 
+			     MCT_U232_SET_REQUEST_TYPE,
+			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, 
+			     WDR_TIMEOUT);
+	if (rc < 0)
+		err("Sending USB device request code %d failed (error = %d)", 
+		    MCT_U232_SET_UNKNOWN1_REQUEST, rc);
+
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     MCT_U232_SET_UNKNOWN2_REQUEST, 
+			     MCT_U232_SET_REQUEST_TYPE,
+			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE, 
+			     WDR_TIMEOUT);
+	if (rc < 0)
+		err("Sending USB device request code %d failed (error = %d)", 
+		    MCT_U232_SET_UNKNOWN2_REQUEST, rc);
+
         return rc;
 } /* mct_u232_set_baud_rate */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/mct_u232.h 001-linus.patch/drivers/usb/serial/mct_u232.h
--- 000-virgin/drivers/usb/serial/mct_u232.h	Wed Dec 17 18:59:41 2003
+++ 001-linus.patch/drivers/usb/serial/mct_u232.h	Tue Dec 30 16:38:57 2003
@@ -57,6 +57,21 @@
 #define MCT_U232_SET_MODEM_CTRL_REQUEST	10 /* Set Modem Control Register (MCR) */
 #define MCT_U232_SET_MODEM_CTRL_SIZE    1
 
+/* This USB device request code is not well understood.  It is transmitted by
+   the MCT-supplied Windows driver whenever the baud rate changes. 
+*/
+#define MCT_U232_SET_UNKNOWN1_REQUEST   11  /* Unknown functionality */
+#define MCT_U232_SET_UNKNOWN1_SIZE       1
+
+/* This USB device request code is not well understood.  It is transmitted by
+   the MCT-supplied Windows driver whenever the baud rate changes. 
+   
+   Without this USB device request, the USB/RS-232 adapter will not write to
+   RS-232 devices which do not assert the 'CTS' signal.
+*/
+#define MCT_U232_SET_UNKNOWN2_REQUEST   12  /* Unknown functionality */
+#define MCT_U232_SET_UNKNOWN2_SIZE       1
+
 /*
  * Baud rate (divisor)
  */
@@ -137,22 +152,31 @@
  * Baud rate (divisor)
  * -------------------
  *
- *   BmRequestType:  0x4 (0100 0000B)
- *   bRequest:       0x5
- *   wValue:         0x0
- *   wIndex:         0x0
- *   wLength:        0x4
+ *   BmRequestType:  0x40 (0100 0000B)
+ *   bRequest:       0x05
+ *   wValue:         0x0000
+ *   wIndex:         0x0000
+ *   wLength:        0x0004
  *   Data:           divisor = 115200 / baud_rate
  *
+ *   SniffUSB observations (Nov 2003): Contrary to the 'wLength' value of 4
+ *   shown above, observations with a Belkin F5U109 adapter, using the
+ *   MCT-supplied Windows98 driver (U2SPORT.VXD, "File version: 1.21P.0104 for
+ *   Win98/Me"), show this request has a length of 1 byte, presumably because
+ *   of the fact that the Belkin adapter and the 'Sitecom U232-P25' adapter
+ *   use a baud-rate code instead of a conventional RS-232 baud rate divisor.
+ *   The current source code for this driver does not reflect this fact, but
+ *   the driver works fine with this adapter/driver combination nonetheless.
+ *
  *
  * Line Control Register (LCR)
  * ---------------------------
  *
- *  BmRequestType:  0x4 (0100 0000B)    0xc (1100 0000B)
- *  bRequest:       0x7                 0x6
- *  wValue:         0x0
- *  wIndex:         0x0
- *  wLength:        0x1
+ *  BmRequestType:  0x40 (0100 0000B)    0xc0 (1100 0000B)
+ *  bRequest:       0x07                 0x06
+ *  wValue:         0x0000
+ *  wIndex:         0x0000
+ *  wLength:        0x0001
  *  Data:           LCR (see below)
  *
  *  Bit 7: Divisor Latch Access Bit (DLAB). When set, access to the data
@@ -186,18 +210,18 @@
  *
  *  SniffUSB observations: Bit 7 seems not to be used. There seem to be two bugs
  *  in the Win98 driver: the break does not work (bit 6 is not asserted) and the
- *  sticky parity bit is not cleared when set once. The LCR can also be read
+ *  stick parity bit is not cleared when set once. The LCR can also be read
  *  back with USB request 6 but this has never been observed with SniffUSB.
  *
  *
  * Modem Control Register (MCR)
  * ----------------------------
  *
- *  BmRequestType:  0x4  (0100 0000B)
- *  bRequest:       0xa
- *  wValue:         0x0
- *  wIndex:         0x0
- *  wLength:        0x1
+ *  BmRequestType:  0x40  (0100 0000B)
+ *  bRequest:       0x0a
+ *  wValue:         0x0000
+ *  wIndex:         0x0000
+ *  wLength:        0x0001
  *  Data:           MCR (Bit 4..7, see below)
  *
  *  Bit 7: Reserved, always 0.
@@ -226,11 +250,11 @@
  * Modem Status Register (MSR)
  * ---------------------------
  *
- *  BmRequestType:  0xc  (1100 0000B)
- *  bRequest:       0x2
- *  wValue:         0x0
- *  wIndex:         0x0
- *  wLength:        0x1
+ *  BmRequestType:  0xc0  (1100 0000B)
+ *  bRequest:       0x02
+ *  wValue:         0x0000
+ *  wIndex:         0x0000
+ *  wLength:        0x0001
  *  Data:           MSR (see below)
  *
  *  Bit 7: Data Carrier Detect (CD). Reflects the state of the DCD line on the
@@ -287,6 +311,41 @@
  *  minicom/zmodem transfers (CRC errors).
  *
  *
+ * Unknown #1
+ * -------------------
+ *
+ *   BmRequestType:  0x40 (0100 0000B)
+ *   bRequest:       0x0b
+ *   wValue:         0x0000
+ *   wIndex:         0x0000
+ *   wLength:        0x0001
+ *   Data:           0x00
+ *
+ *   SniffUSB observations (Nov 2003): With the MCT-supplied Windows98 driver
+ *   (U2SPORT.VXD, "File version: 1.21P.0104 for Win98/Me"), this request
+ *   occurs immediately after a "Baud rate (divisor)" message.  It was not
+ *   observed at any other time.  It is unclear what purpose this message
+ *   serves.
+ *
+ *
+ * Unknown #2
+ * -------------------
+ *
+ *   BmRequestType:  0x40 (0100 0000B)
+ *   bRequest:       0x0c
+ *   wValue:         0x0000
+ *   wIndex:         0x0000
+ *   wLength:        0x0001
+ *   Data:           0x00
+ *
+ *   SniffUSB observations (Nov 2003): With the MCT-supplied Windows98 driver
+ *   (U2SPORT.VXD, "File version: 1.21P.0104 for Win98/Me"), this request
+ *   occurs immediately after the 'Unknown #1' message (see above).  It was
+ *   not observed at any other time.  It is unclear what other purpose (if
+ *   any) this message might serve, but without it, the USB/RS-232 adapter
+ *   will not write to RS-232 devices which do not assert the 'CTS' signal.
+ *
+ *
  * Flow control
  * ------------
  *
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/pl2303.c 001-linus.patch/drivers/usb/serial/pl2303.c
--- 000-virgin/drivers/usb/serial/pl2303.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/usb/serial/pl2303.c	Tue Dec 30 16:38:57 2003
@@ -71,6 +71,7 @@ static struct usb_device_id id_table [] 
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+	{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
 	{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
 	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
@@ -169,6 +170,7 @@ static struct usb_serial_device_type pl2
 
 struct pl2303_private {
 	spinlock_t lock;
+	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
 	u8 termios_initialized;
@@ -186,6 +188,7 @@ static int pl2303_startup (struct usb_se
 			return -ENOMEM;
 		memset (priv, 0x00, sizeof (struct pl2303_private));
 		spin_lock_init(&priv->lock);
+		init_waitqueue_head(&priv->delta_msr_wait);
 		usb_set_serial_port_data(serial->port[i], priv);
 	}
 	return 0;
@@ -556,11 +559,51 @@ static int pl2303_tiocmget (struct usb_s
 	return result;
 }
 
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int prevstatus;
+	unsigned int status;
+	unsigned int changed;
+
+	spin_lock_irqsave (&priv->lock, flags);
+	prevstatus = priv->line_status;
+	spin_unlock_irqrestore (&priv->lock, flags);
+
+	while (1) {
+		interruptible_sleep_on(&priv->delta_msr_wait);
+		/* see if a signal did it */
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		
+		spin_lock_irqsave (&priv->lock, flags);
+		status = priv->line_status;
+		spin_unlock_irqrestore (&priv->lock, flags);
+		
+		changed=prevstatus^status;
+		
+		if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
+		    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
+		    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
+		    ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
+			return 0;
+		}
+		prevstatus = status;
+	}
+	/* NOTREACHED */
+	return 0;
+}
+
 static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
 
 	switch (cmd) {
+		case TIOCMIWAIT:
+			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+			return wait_modem_info(port, arg);
+
 		default:
 			dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
 			break;
@@ -703,6 +746,7 @@ static void pl2303_read_bulk_callback (s
 	spin_lock_irqsave(&priv->lock, flags);
 	status = priv->line_status;
 	spin_unlock_irqrestore(&priv->lock, flags);
+	wake_up_interruptible (&priv->delta_msr_wait);
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/pl2303.h 001-linus.patch/drivers/usb/serial/pl2303.h
--- 000-virgin/drivers/usb/serial/pl2303.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/drivers/usb/serial/pl2303.h	Tue Dec 30 16:38:57 2003
@@ -12,6 +12,7 @@
 #define PL2303_PRODUCT_ID_RSAQ2	0x04bb
 
 #define ATEN_VENDOR_ID		0x0557
+#define ATEN_VENDOR_ID2		0x0547
 #define ATEN_PRODUCT_ID		0x2008
 
 #define IODATA_VENDOR_ID	0x04bb
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/visor.c 001-linus.patch/drivers/usb/serial/visor.c
--- 000-virgin/drivers/usb/serial/visor.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/drivers/usb/serial/visor.c	Tue Dec 30 16:38:57 2003
@@ -231,6 +231,8 @@ static struct usb_device_id id_table [] 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), 
@@ -266,6 +268,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) },
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
 	{ },					/* optional parameter entry */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/serial/visor.h 001-linus.patch/drivers/usb/serial/visor.h
--- 000-virgin/drivers/usb/serial/visor.h	Wed Dec 17 18:59:26 2003
+++ 001-linus.patch/drivers/usb/serial/visor.h	Tue Dec 30 16:38:57 2003
@@ -41,6 +41,7 @@
 #define SONY_CLIE_4_1_ID		0x009A
 #define SONY_CLIE_NX60_ID		0x00DA
 #define SONY_CLIE_NZ90V_ID		0x00E9
+#define SONY_CLIE_UX50_ID		0x0144
 
 #define SAMSUNG_VENDOR_ID		0x04E8
 #define SAMSUNG_SCH_I330_ID		0x8001
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/Makefile 001-linus.patch/drivers/usb/storage/Makefile
--- 000-virgin/drivers/usb/storage/Makefile	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/drivers/usb/storage/Makefile	Tue Dec 30 16:38:57 2003
@@ -10,14 +10,14 @@ EXTRA_CFLAGS	:= -Idrivers/scsi
 obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
 usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e)	+= shuttle_usbat.o raw_bulk.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o raw_bulk.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o raw_bulk.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e)	+= shuttle_usbat.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM)	+= dpcm.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o raw_bulk.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o raw_bulk.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
 			initializers.o $(usb-storage-obj-y)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/datafab.c 001-linus.patch/drivers/usb/storage/datafab.c
--- 000-virgin/drivers/usb/storage/datafab.c	Wed Dec 17 18:59:54 2003
+++ 001-linus.patch/drivers/usb/storage/datafab.c	Tue Dec 30 16:38:57 2003
@@ -51,7 +51,6 @@
  */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -91,16 +90,14 @@ static int datafab_read_data(struct us_d
 			     struct datafab_info *info,
 			     u32 sector,
 			     u32 sectors, 
-			     unsigned char *dest, 
+			     unsigned char *buffer, 
 			     int use_sg)
 {
 	unsigned char *command = us->iobuf;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
 	unsigned char  thistime;
-	int totallen, len, result;
-	int sg_idx = 0, sg_offset = 0;
-	int rc;
+	unsigned int totallen, alloclen;
+	int len, result;
+	unsigned int sg_idx = 0, sg_offset = 0;
 
 	// we're working in LBA mode.  according to the ATA spec, 
 	// we can support up to 28-bit addressing.  I don't know if Datafab
@@ -111,23 +108,32 @@ static int datafab_read_data(struct us_d
 		return USB_STOR_TRANSPORT_ERROR;
 
 	if (info->lun == -1) {
-		rc = datafab_determine_lun(us, info);
-		if (rc != USB_STOR_TRANSPORT_GOOD)
-			return rc;
+		result = datafab_determine_lun(us, info);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			return result;
 	}
 
 	totallen = sectors * info->ssize;
 
+	// Since we don't read more than 64 KB at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	alloclen = min(totallen, 65536u);
+	if (use_sg) {
+		buffer = kmalloc(alloclen, GFP_NOIO);
+		if (buffer == NULL)
+			return USB_STOR_TRANSPORT_ERROR;
+	}
+
 	do {
 		// loop, never allocate or transfer more than 64k at once
 		// (min(128k, 255*info->ssize) is the real limit)
 
-		len = min_t(int, totallen, 65536);
-
-		ptr = buffer = (use_sg ? kmalloc(len, GFP_NOIO) : dest);
-		if (buffer == NULL)
-			return USB_STOR_TRANSPORT_ERROR;
-
+		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
 
 		command[0] = 0;
@@ -135,7 +141,7 @@ static int datafab_read_data(struct us_d
 		command[2] = sector & 0xFF;
 		command[3] = (sector >> 8) & 0xFF;
 		command[4] = (sector >> 16) & 0xFF;
-	
+
 		command[5] = 0xE0 + (info->lun << 4);
 		command[5] |= (sector >> 24) & 0x0F;
 		command[6] = 0x20;
@@ -147,24 +153,23 @@ static int datafab_read_data(struct us_d
 			goto leave;
 
 		// read the result
-		result = datafab_bulk_read(us, ptr, len);
+		result = datafab_bulk_read(us, buffer, len);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
-		sectors -= thistime;
-		sector  += thistime;
-
-		if (use_sg) {
-			us_copy_to_sgbuf(buffer, len, dest,
-					 &sg_idx, &sg_offset, use_sg);
-			kfree(buffer);
-		} else {
-			dest += len;
-		}
+		// Store the data (s-g) or update the pointer (!s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					 &sg_idx, &sg_offset, TO_XFER_BUF);
+		else
+			buffer += len;
 
+		sector += thistime;
 		totallen -= len;
 	} while (totallen > 0);
 
+	if (use_sg)
+		kfree(buffer);
 	return USB_STOR_TRANSPORT_GOOD;
 
  leave:
@@ -178,16 +183,15 @@ static int datafab_write_data(struct us_
 			      struct datafab_info *info,
 			      u32 sector,
 			      u32 sectors, 
-			      unsigned char *src, 
+			      unsigned char *buffer, 
 			      int use_sg)
 {
 	unsigned char *command = us->iobuf;
 	unsigned char *reply = us->iobuf;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
 	unsigned char thistime;
-	int totallen, len, result, rc;
-	int sg_idx = 0, sg_offset = 0;
+	unsigned int totallen, alloclen;
+	int len, result;
+	unsigned int sg_idx = 0, sg_offset = 0;
 
 	// we're working in LBA mode.  according to the ATA spec, 
 	// we can support up to 28-bit addressing.  I don't know if Datafab
@@ -198,38 +202,39 @@ static int datafab_write_data(struct us_
 		return USB_STOR_TRANSPORT_ERROR;
 
 	if (info->lun == -1) {
-		rc = datafab_determine_lun(us, info);
-		if (rc != USB_STOR_TRANSPORT_GOOD)
-			return rc;
+		result = datafab_determine_lun(us, info);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			return result;
 	}
 
-	// If we're using scatter-gather, we have to create a new
-	// buffer to read all of the data in first, since a
-	// scatter-gather buffer could in theory start in the middle
-	// of a page, which would be bad. A developer who wants a
-	// challenge might want to write a limited-buffer
-	// version of this code.
-
 	totallen = sectors * info->ssize;
 
-	do {
-		// loop, never allocate or transfer more than 64k at once
-		// (min(128k, 255*info->ssize) is the real limit)
-
-		len = min_t(int, totallen, 65536);
-
-		// if we are using scatter-gather,
-		// first copy all to one big buffer
-
-		buffer = us_copy_from_sgbuf(src, len, &sg_idx,
-					    &sg_offset, use_sg);
+	// Since we don't write more than 64 KB at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	alloclen = min(totallen, 65536u);
+	if (use_sg) {
+		buffer = kmalloc(alloclen, GFP_NOIO);
 		if (buffer == NULL)
 			return USB_STOR_TRANSPORT_ERROR;
+	}
 
-		ptr = buffer;
+	do {
+		// loop, never allocate or transfer more than 64k at once
+		// (min(128k, 255*info->ssize) is the real limit)
 
+		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
 
+		// Get the data from the transfer buffer (s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&sg_idx, &sg_offset, FROM_XFER_BUF);
+
 		command[0] = 0;
 		command[1] = thistime;
 		command[2] = sector & 0xFF;
@@ -247,7 +252,7 @@ static int datafab_write_data(struct us_
 			goto leave;
 
 		// send the data
-		result = datafab_bulk_write(us, ptr, len);
+		result = datafab_bulk_write(us, buffer, len);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
@@ -264,17 +269,16 @@ static int datafab_write_data(struct us_
 			goto leave;
 		}
 
-		sectors -= thistime;
-		sector  += thistime;
-
-		if (use_sg)
-			kfree(buffer);
-		else
-			src += len;
+		// Update the transfer buffer pointer (!s-g)
+		if (!use_sg)
+			buffer += len;
 
+		sector += thistime;
 		totallen -= len;
 	} while (totallen > 0);
 
+	if (use_sg)
+		kfree(buffer);
 	return USB_STOR_TRANSPORT_GOOD;
 
  leave:
@@ -435,7 +439,7 @@ static int datafab_handle_mode_sense(str
 	// datafab reader doesn't present a SCSI interface so we
 	// fudge the SCSI commands...
 	//
-	
+
 	if (sense_6)
 		param_len = srb->cmnd[4];
 	else
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/debug.c 001-linus.patch/drivers/usb/storage/debug.c
--- 000-virgin/drivers/usb/storage/debug.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/drivers/usb/storage/debug.c	Tue Dec 30 16:38:57 2003
@@ -150,65 +150,6 @@ void usb_stor_show_command(Scsi_Cmnd *sr
 	US_DEBUGPX("\n");
 }
 
-void usb_stor_print_Scsi_Cmnd(Scsi_Cmnd *cmd)
-{
-	int i=0, bufferSize = cmd->request_bufflen;
-	u8 *buffer = cmd->request_buffer;
-	struct scatterlist *sg = (struct scatterlist*)cmd->request_buffer;
-
-	US_DEBUGP("Dumping information about %p.\n", cmd);
-	US_DEBUGP("cmd->cmnd[0] value is %d.\n", cmd->cmnd[0]);
-	US_DEBUGP("(MODE_SENSE is %d and MODE_SENSE_10 is %d)\n",
-		  MODE_SENSE, MODE_SENSE_10);
-
-	US_DEBUGP("buffer is %p with length %d.\n", buffer, bufferSize);
-	for (i=0; i<bufferSize; i+=16) {
-		US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n"
-			  "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			  buffer[i],
-			  buffer[i+1],
-			  buffer[i+2],
-			  buffer[i+3],
-			  buffer[i+4],
-			  buffer[i+5],
-			  buffer[i+6],
-			  buffer[i+7],
-			  buffer[i+8],
-			  buffer[i+9],
-			  buffer[i+10],
-			  buffer[i+11],
-			  buffer[i+12],
-			  buffer[i+13],
-			  buffer[i+14],
-			  buffer[i+15] );
-	}
-
-	US_DEBUGP("Buffer has %d scatterlists.\n", cmd->use_sg );
-	for (i=0; i<cmd->use_sg; i++) {
-		char *adr = sg_address(sg[i]);
-		
-		US_DEBUGP("Length of scatterlist %d is %d.\n",i,sg[i].length);
-		US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n"
-			  "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			  adr[0],
-			  adr[1],
-			  adr[2],
-			  adr[3],
-			  adr[4],
-			  adr[5],
-			  adr[6],
-			  adr[7],
-			  adr[8],
-			  adr[9],
-			  adr[10],
-			  adr[11],
-			  adr[12],
-			  adr[13],
-			  adr[14],
-			  adr[15]);
-	}
-}
-
 void usb_stor_show_sense(
 		unsigned char key,
 		unsigned char asc,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/debug.h 001-linus.patch/drivers/usb/storage/debug.h
--- 000-virgin/drivers/usb/storage/debug.h	Wed Dec 17 19:00:02 2003
+++ 001-linus.patch/drivers/usb/storage/debug.h	Tue Dec 30 16:38:57 2003
@@ -53,7 +53,6 @@
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 void usb_stor_show_command(Scsi_Cmnd *srb);
-void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd );
 void usb_stor_show_sense( unsigned char key,
 		unsigned char asc, unsigned char ascq );
 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/isd200.c 001-linus.patch/drivers/usb/storage/isd200.c
--- 000-virgin/drivers/usb/storage/isd200.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/usb/storage/isd200.c	Tue Dec 30 16:38:57 2003
@@ -543,7 +543,6 @@ void isd200_invoke_transport( struct us_
 	int result;
 
 	/* send the command to the transport layer */
-	srb->resid = 0;
 	memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic));
 	srb->cmd_len = sizeof(ataCdb->generic);
 	transferStatus = usb_stor_Bulk_transport(srb, us);
@@ -1117,60 +1116,6 @@ int isd200_get_inquiry_data( struct us_d
 
 
 /**************************************************************************
- * isd200_data_copy
- *									 
- * Copy data into the srb request buffer.  Use scatter gather if required.
- *
- * RETURNS:
- *    void
- */
-void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length)
-{
-	unsigned int len = length;
-	struct scatterlist *sg;
-
-	if (srb->use_sg) {
-		int i;
-		unsigned int total = 0;
-
-		/* Add up the sizes of all the sg segments */
-		sg = (struct scatterlist *) srb->request_buffer;
-		for (i = 0; i < srb->use_sg; i++)
-			total += sg[i].length;
-
-		if (length > total)
-			len = total;
-
-		total = 0;
-
-		/* Copy data into sg buffer(s) */
-		for (i = 0; i < srb->use_sg; i++) {
-			if ((len > total) && (len > 0)) {
-				/* transfer the lesser of the next buffer or the
-				 * remaining data */
-				if (len - total >= sg[i].length) {
-					memcpy(sg_address(sg[i]), src + total, sg[i].length);
-					total += sg[i].length;
-				} else {
-					memcpy(sg_address(sg[i]), src + total, len - total);
-					total = len;
-				}
-			} 
-			else
-				break;
-		}
-	} else	{
-		/* Make sure length does not exceed buffer length */
-		if (length > srb->request_bufflen)
-			len = srb->request_bufflen;
-
-		if (len > 0)
-			memcpy(srb->request_buffer, src, len);
-	}
-}
-
-
-/**************************************************************************
  * isd200_scsi_to_ata
  *									 
  * Translate SCSI commands to ATA commands.
@@ -1198,11 +1143,9 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s
 	case INQUIRY:
 		US_DEBUGP("   ATA OUT - INQUIRY\n");
 
-		if (srb->request_bufflen > sizeof(struct inquiry_data))
-			srb->request_bufflen = sizeof(struct inquiry_data);
-
 		/* copy InquiryData */
-		isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);
+		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
+				sizeof(info->InquiryData), srb);
 		srb->result = SAM_STAT_GOOD;
 		sendToTransport = FALSE;
 		break;
@@ -1211,7 +1154,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s
 		US_DEBUGP("   ATA OUT - SCSIOP_MODE_SENSE\n");
 
 		/* Initialize the return buffer */
-		isd200_data_copy(srb, (char *) &senseData, 8);
+		usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb);
 
 		if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
 		{
@@ -1231,9 +1174,6 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s
 	case TEST_UNIT_READY:
 		US_DEBUGP("   ATA OUT - SCSIOP_TEST_UNIT_READY\n");
 
-		/* Initialize the return buffer */
-		isd200_data_copy(srb, (char *) &senseData, 8);
-
 		if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
 		{
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
@@ -1266,10 +1206,8 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s
 		readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity);
 		readCapacityData.BytesPerBlock = cpu_to_be32(0x200);
 
-		if (srb->request_bufflen > sizeof(struct read_capacity_data))
-			srb->request_bufflen = sizeof(struct read_capacity_data);
-
-		isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);
+		usb_stor_set_xfer_buf((unsigned char *) &readCapacityData,
+				sizeof(readCapacityData), srb);
 		srb->result = SAM_STAT_GOOD;
 		sendToTransport = FALSE;
 	}
@@ -1363,9 +1301,6 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, s
 		US_DEBUGP("   ATA OUT - SCSIOP_START_STOP_UNIT\n");
 		US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
 
-		/* Initialize the return buffer */
-		isd200_data_copy(srb, (char *) &senseData, 8);
-
 		if ((srb->cmnd[4] & 0x3) == 0x2) {
 			US_DEBUGP("   Media Eject\n");
 			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
@@ -1500,6 +1435,7 @@ void isd200_ata_command(Scsi_Cmnd *srb, 
 		US_DEBUGP("ERROR Driver not initialized\n");
 
 	/* Convert command */
+	srb->resid = 0;
 	sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb);
 
 	/* send the command to the transport layer */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/jumpshot.c 001-linus.patch/drivers/usb/storage/jumpshot.c
--- 000-virgin/drivers/usb/storage/jumpshot.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/drivers/usb/storage/jumpshot.c	Tue Dec 30 16:38:57 2003
@@ -48,7 +48,6 @@
   */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -111,15 +110,14 @@ static int jumpshot_read_data(struct us_
 			      struct jumpshot_info *info,
 			      u32 sector,
 			      u32 sectors, 
-			      unsigned char *dest, 
+			      unsigned char *buffer, 
 			      int use_sg)
 {
 	unsigned char *command = us->iobuf;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
 	unsigned char  thistime;
-	int totallen, len, result;
-	int sg_idx = 0, current_sg_offset = 0;
+	unsigned int totallen, alloclen;
+	int len, result;
+	unsigned int sg_idx = 0, sg_offset = 0;
 
 	// we're working in LBA mode.  according to the ATA spec, 
 	// we can support up to 28-bit addressing.  I don't know if Jumpshot
@@ -131,20 +129,24 @@ static int jumpshot_read_data(struct us_
 
 	totallen = sectors * info->ssize;
 
+	// Since we don't read more than 64 KB at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	alloclen = min(totallen, 65536u);
+	if (use_sg) {
+		buffer = kmalloc(alloclen, GFP_NOIO);
+		if (buffer == NULL)
+			return USB_STOR_TRANSPORT_ERROR;
+	}
+
 	do {
 		// loop, never allocate or transfer more than 64k at once
 		// (min(128k, 255*info->ssize) is the real limit)
-		len = min_t(int, totallen, 65536);
-
-		if (use_sg) {
-			buffer = kmalloc(len, GFP_NOIO);
-			if (buffer == NULL)
-				return USB_STOR_TRANSPORT_ERROR;
-			ptr = buffer;
-		} else {
-			ptr = dest;
-		}
-
+		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
 
 		command[0] = 0;
@@ -163,26 +165,25 @@ static int jumpshot_read_data(struct us_
 			goto leave;
 
 		// read the result
-		result = jumpshot_bulk_read(us, ptr, len);
+		result = jumpshot_bulk_read(us, buffer, len);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
 		US_DEBUGP("jumpshot_read_data:  %d bytes\n", len);
-	
-		sectors -= thistime;
-		sector  += thistime;
-
-		if (use_sg) {
-			us_copy_to_sgbuf(buffer, len, dest,
-					 &sg_idx, &current_sg_offset, use_sg);
-			kfree(buffer);
-		} else {
-			dest += len;
-		}
 
+		// Store the data (s-g) or update the pointer (!s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					 &sg_idx, &sg_offset, TO_XFER_BUF);
+		else
+			buffer += len;
+
+		sector += thistime;
 		totallen -= len;
 	} while (totallen > 0);
 
+	if (use_sg)
+		kfree(buffer);
 	return USB_STOR_TRANSPORT_GOOD;
 
  leave:
@@ -196,15 +197,14 @@ static int jumpshot_write_data(struct us
 			       struct jumpshot_info *info,
 			       u32 sector,
 			       u32 sectors, 
-			       unsigned char *src, 
+			       unsigned char *buffer, 
 			       int use_sg)
 {
 	unsigned char *command = us->iobuf;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
 	unsigned char  thistime;
-	int totallen, len, result, waitcount;
-	int sg_idx = 0, sg_offset = 0;
+	unsigned int totallen, alloclen;
+	int len, result, waitcount;
+	unsigned int sg_idx = 0, sg_offset = 0;
 
 	// we're working in LBA mode.  according to the ATA spec, 
 	// we can support up to 28-bit addressing.  I don't know if Jumpshot
@@ -216,24 +216,32 @@ static int jumpshot_write_data(struct us
 
 	totallen = sectors * info->ssize;
 
-	do {
-		// loop, never allocate or transfer more than 64k at once
-		// (min(128k, 255*info->ssize) is the real limit)
-
-		len = min_t(int, totallen, 65536);
-
-		// if we are using scatter-gather,
-		// first copy all to one big buffer
-
-		buffer = us_copy_from_sgbuf(src, len, &sg_idx,
-					    &sg_offset, use_sg);
+	// Since we don't write more than 64 KB at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	alloclen = min(totallen, 65536u);
+	if (use_sg) {
+		buffer = kmalloc(alloclen, GFP_NOIO);
 		if (buffer == NULL)
 			return USB_STOR_TRANSPORT_ERROR;
+	}
 
-		ptr = buffer;
+	do {
+		// loop, never allocate or transfer more than 64k at once
+		// (min(128k, 255*info->ssize) is the real limit)
 
+		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
 
+		// Get the data from the transfer buffer (s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&sg_idx, &sg_offset, FROM_XFER_BUF);
+
 		command[0] = 0;
 		command[1] = thistime;
 		command[2] = sector & 0xFF;
@@ -250,7 +258,7 @@ static int jumpshot_write_data(struct us
 			goto leave;
 
 		// send the data
-		result = jumpshot_bulk_write(us, ptr, len);
+		result = jumpshot_bulk_write(us, buffer, len);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
@@ -269,18 +277,17 @@ static int jumpshot_write_data(struct us
 
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			US_DEBUGP("jumpshot_write_data:  Gah!  Waitcount = 10.  Bad write!?\n");
-		
-		sectors -= thistime;
-		sector  += thistime;
 
-		if (use_sg)
-			kfree(buffer);
-		else
-			src += len;
+		// Update the transfer buffer pointer (!s-g)
+		if (!use_sg)
+			buffer += len;
 
+		sector += thistime;
 		totallen -= len;
 	} while (totallen > 0);
 
+	if (use_sg)
+		kfree(buffer);
 	return result;
 
  leave:
@@ -605,14 +612,14 @@ int jumpshot_transport(Scsi_Cmnd * srb, 
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n");
 		return jumpshot_handle_mode_sense(us, srb, ptr, FALSE);
 	}
-	
+
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
 		// sure.  whatever.  not like we can stop the user from popping
 		// the media out of the device (no locking doors, etc)
 		//
 		return USB_STOR_TRANSPORT_GOOD;
 	}
-	
+
 	if (srb->cmnd[0] == START_STOP) {
 		/* this is used by sd.c'check_scsidisk_media_change to detect
 		   media change */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/protocol.c 001-linus.patch/drivers/usb/storage/protocol.c
--- 000-virgin/drivers/usb/storage/protocol.c	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/drivers/usb/storage/protocol.c	Tue Dec 30 16:38:57 2003
@@ -44,6 +44,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/highmem.h>
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -54,48 +55,36 @@
  * Helper routines
  ***********************************************************************/
 
-static void *
-find_data_location(Scsi_Cmnd *srb) {
-	if (srb->use_sg) {
-		/*
-		 * This piece of code only works if the first page is
-		 * big enough to hold more than 3 bytes -- which is
-		 * _very_ likely.
-		 */
-		struct scatterlist *sg;
-
-		sg = (struct scatterlist *) srb->request_buffer;
-		return (void *) sg_address(sg[0]);
-	} else
-		return (void *) srb->request_buffer;
-}
-
 /*
  * Fix-up the return data from an INQUIRY command to show 
  * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
  */
 static void fix_inquiry_data(Scsi_Cmnd *srb)
 {
-	unsigned char *data_ptr;
+	unsigned char databuf[3];
+	unsigned int index, offset;
 
 	/* verify that it's an INQUIRY command */
 	if (srb->cmnd[0] != INQUIRY)
 		return;
 
-	/* oddly short buffer -- bail out */
-	if (srb->request_bufflen < 3)
+	index = offset = 0;
+	if (usb_stor_access_xfer_buf(databuf, sizeof(databuf), srb,
+			&index, &offset, FROM_XFER_BUF) != sizeof(databuf))
 		return;
 
-	data_ptr = find_data_location(srb);
-
-	if ((data_ptr[2] & 7) == 2)
+	if ((databuf[2] & 7) == 2)
 		return;
 
 	US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n",
-		  data_ptr[2] & 7);
+		  databuf[2] & 7);
 
 	/* Change the SCSI revision number */
-	data_ptr[2] = (data_ptr[2] & ~7) | 2;
+	databuf[2] = (databuf[2] & ~7) | 2;
+
+	index = offset = 0;
+	usb_stor_access_xfer_buf(databuf, sizeof(databuf), srb,
+			&index, &offset, TO_XFER_BUF);
 }
 
 /*
@@ -104,23 +93,27 @@ static void fix_inquiry_data(Scsi_Cmnd *
  */
 static void fix_read_capacity(Scsi_Cmnd *srb)
 {
-	unsigned char *dp;
+	unsigned int index, offset;
+	u32 c;
 	unsigned long capacity;
 
 	/* verify that it's a READ CAPACITY command */
 	if (srb->cmnd[0] != READ_CAPACITY)
 		return;
 
-	dp = find_data_location(srb);
+	index = offset = 0;
+	if (usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
+			&index, &offset, FROM_XFER_BUF) != 4)
+		return;
 
-	capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]);
+	capacity = be32_to_cpu(c);
 	US_DEBUGP("US: Fixing capacity: from %ld to %ld\n",
 	       capacity+1, capacity);
-	capacity--;
-	dp[0] = (capacity >> 24);
-	dp[1] = (capacity >> 16);
-	dp[2] = (capacity >> 8);
-	dp[3] = (capacity);
+	c = cpu_to_be32(capacity - 1);
+
+	index = offset = 0;
+	usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
+			&index, &offset, TO_XFER_BUF);
 }
 
 /***********************************************************************
@@ -234,3 +227,112 @@ void usb_stor_transparent_scsi_command(S
 			fix_read_capacity(srb);
 	}
 }
+
+/***********************************************************************
+ * Scatter-gather transfer buffer access routines
+ ***********************************************************************/
+
+/* Copy a buffer of length buflen to/from the srb's transfer buffer.
+ * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
+ * points to a list of s-g entries and we ignore srb->request_bufflen.
+ * For non-scatter-gather transfers, srb->request_buffer points to the
+ * transfer buffer itself and srb->request_bufflen is the buffer's length.)
+ * Update the *index and *offset variables so that the next copy will
+ * pick up from where this one left off. */
+
+unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int *offset, enum xfer_buf_dir dir)
+{
+	unsigned int cnt;
+
+	/* If not using scatter-gather, just transfer the data directly.
+	 * Make certain it will fit in the available buffer space. */
+	if (srb->use_sg == 0) {
+		if (*offset >= srb->request_bufflen)
+			return 0;
+		cnt = min(buflen, srb->request_bufflen - *offset);
+		if (dir == TO_XFER_BUF)
+			memcpy((unsigned char *) srb->request_buffer + *offset,
+					buffer, cnt);
+		else
+			memcpy(buffer, (unsigned char *) srb->request_buffer +
+					*offset, cnt);
+		*offset += cnt;
+
+	/* Using scatter-gather.  We have to go through the list one entry
+	 * at a time.  Each s-g entry contains some number of pages, and
+	 * each page has to be kmap()'ed separately.  If the page is already
+	 * in kernel-addressable memory then kmap() will return its address.
+	 * If the page is not directly accessible -- such as a user buffer
+	 * located in high memory -- then kmap() will map it to a temporary
+	 * position in the kernel's virtual address space. */
+	} else {
+		struct scatterlist *sg =
+				(struct scatterlist *) srb->request_buffer
+				+ *index;
+
+		/* This loop handles a single s-g list entry, which may
+		 * include multiple pages.  Find the initial page structure
+		 * and the starting offset within the page, and update
+		 * the *offset and *index values for the next loop. */
+		cnt = 0;
+		while (cnt < buflen && *index < srb->use_sg) {
+			struct page *page = sg->page +
+					((sg->offset + *offset) >> PAGE_SHIFT);
+			unsigned int poff =
+					(sg->offset + *offset) & (PAGE_SIZE-1);
+			unsigned int sglen = sg->length - *offset;
+
+			if (sglen > buflen - cnt) {
+
+				/* Transfer ends within this s-g entry */
+				sglen = buflen - cnt;
+				*offset += sglen;
+			} else {
+
+				/* Transfer continues to next s-g entry */
+				*offset = 0;
+				++*index;
+				++sg;
+			}
+
+			/* Transfer the data for all the pages in this
+			 * s-g entry.  For each page: call kmap(), do the
+			 * transfer, and call kunmap() immediately after. */
+			while (sglen > 0) {
+				unsigned int plen = min(sglen, (unsigned int)
+						PAGE_SIZE - poff);
+				unsigned char *ptr = kmap(page);
+
+				if (dir == TO_XFER_BUF)
+					memcpy(ptr + poff, buffer + cnt, plen);
+				else
+					memcpy(buffer + cnt, ptr + poff, plen);
+				kunmap(page);
+
+				/* Start at the beginning of the next page */
+				poff = 0;
+				++page;
+				cnt += plen;
+				sglen -= plen;
+			}
+		}
+	}
+
+	/* Return the amount actually transferred */
+	return cnt;
+}
+
+/* Store the contents of buffer into srb's transfer buffer and set the
+ * SCSI residue. */
+void usb_stor_set_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, Scsi_Cmnd *srb)
+{
+	unsigned int index = 0, offset = 0;
+
+	usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
+			TO_XFER_BUF);
+	if (buflen < srb->request_bufflen)
+		srb->resid = srb->request_bufflen - buflen;
+}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/protocol.h 001-linus.patch/drivers/usb/storage/protocol.h
--- 000-virgin/drivers/usb/storage/protocol.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/drivers/usb/storage/protocol.h	Tue Dec 30 16:38:57 2003
@@ -59,9 +59,19 @@
 
 #define US_SC_DEVICE	0xff		/* Use device's value */
 
+/* Protocol handling routines */
 extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
 extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
 extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
 extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
 
+/* Scsi_Cmnd transfer buffer access utilities */
+enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
+
+extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int *offset, enum xfer_buf_dir dir);
+
+extern void usb_stor_set_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, Scsi_Cmnd *srb);
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/raw_bulk.c 001-linus.patch/drivers/usb/storage/raw_bulk.c
--- 000-virgin/drivers/usb/storage/raw_bulk.c	Wed Dec 17 18:59:16 2003
+++ 001-linus.patch/drivers/usb/storage/raw_bulk.c	Wed Dec 31 16:00:00 1969
@@ -1,116 +0,0 @@
-/*
- * Common routines for a handful of drivers.
- * Unrelated to CF/SM - just scatter-gather stuff.
- */
-
-#include "usb.h"
-#include "raw_bulk.h"
-
-/*
- * The routines below convert scatter-gather to single buffer.
- * Some drivers claim this is necessary.
- * Nothing is done when use_sg is zero.
- */
-
-/*
- * Copy from scatter-gather buffer into a newly allocated single buffer,
- * starting at a given index and offset.
- * When done, update index and offset.
- * Return a pointer to the single buffer.
- */
-unsigned char *
-us_copy_from_sgbuf(unsigned char *content, int len,
-		   int *index, int *offset, int use_sg) {
-	struct scatterlist *sg;
-	unsigned char *buffer;
-	int transferred, i;
-
-	if (!use_sg)
-		return content;
-
-	sg = (struct scatterlist *)content;
-	buffer = kmalloc(len, GFP_NOIO);
-	if (buffer == NULL)
-		return NULL;
-
-	transferred = 0;
-	i = *index;
-	while (i < use_sg && transferred < len) {
-		unsigned char *ptr;
-		unsigned int length, room;
-
-		ptr = sg_address(sg[i]) + *offset;
-
-		room = sg[i].length - *offset;
-		length = len - transferred;
-		if (length > room)
-			length = room;
-
-		memcpy(buffer+transferred, ptr, length);
-		transferred += length;
-		*offset += length;
-		if (length == room) {
-			i++;
-			*offset = 0;
-		}
-	}
-	*index = i;
-
-	return buffer;
-}
-
-unsigned char *
-us_copy_from_sgbuf_all(unsigned char *content, int len, int use_sg) {
-	int index, offset;
-
-	index = offset = 0;
-	return us_copy_from_sgbuf(content, len, &index, &offset, use_sg);
-}
-
-/*
- * Copy from a single buffer into a scatter-gather buffer,
- * starting at a given index and offset.
- * When done, update index and offset.
- */
-void
-us_copy_to_sgbuf(unsigned char *buffer, int buflen,
-		 void *content, int *index, int *offset, int use_sg) {
-	struct scatterlist *sg;
-	int i, transferred;
-
-	if (!use_sg)
-		return;
-
-	transferred = 0;
-	sg = content;
-	i = *index;
-	while (i < use_sg && transferred < buflen) {
-		unsigned char *ptr;
-		unsigned int length, room;
-
-		ptr = sg_address(sg[i]) + *offset;
-
-		room = sg[i].length - *offset;
-		length = buflen - transferred;
-		if (length > room)
-			length = room;
-		
-		memcpy(ptr, buffer+transferred, length);
-		transferred += sg[i].length;
-		*offset += length;
-		if (length == room) {
-			i++;
-			*offset = 0;
-		}
-	}
-	*index = i;
-}
-
-void
-us_copy_to_sgbuf_all(unsigned char *buffer, int buflen,
-		     void *content, int use_sg) {
-	int index, offset;
-
-	index = offset = 0;
-	us_copy_to_sgbuf(buffer, buflen, content, &index, &offset, use_sg);
-}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/raw_bulk.h 001-linus.patch/drivers/usb/storage/raw_bulk.h
--- 000-virgin/drivers/usb/storage/raw_bulk.h	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/drivers/usb/storage/raw_bulk.h	Wed Dec 31 16:00:00 1969
@@ -1,20 +0,0 @@
-#ifndef _USB_STORAGE_RAW_BULK_H_
-#define _USB_STORAGE_RAW_BULK_H_
-
-/* scatter-gather */
-extern unsigned char *us_copy_from_sgbuf(
-	unsigned char *content, int buflen,
-	int *index, int *offset, int use_sg);
-
-extern unsigned char *us_copy_from_sgbuf_all(
-	unsigned char *content, int len, int use_sg);
-
-extern void us_copy_to_sgbuf(
-	unsigned char *buffer, int buflen,
-	void *content, int *index, int *offset, int use_sg);
-
-extern void us_copy_to_sgbuf_all(
-	unsigned char *buffer, int buflen,
-	void *content, int use_sg);
-
-#endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/scsiglue.c 001-linus.patch/drivers/usb/storage/scsiglue.c
--- 000-virgin/drivers/usb/storage/scsiglue.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/drivers/usb/storage/scsiglue.c	Tue Dec 30 16:38:57 2003
@@ -325,7 +325,8 @@ struct scsi_host_template usb_stor_host_
 	.emulated =			TRUE,
 
 	/* modify scsi_device bits on probe */
-	.flags = (BLIST_MS_SKIP_PAGE_08 | BLIST_USE_10_BYTE_MS),
+	.flags = (BLIST_MS_SKIP_PAGE_08 | BLIST_MS_SKIP_PAGE_3F |
+		  BLIST_USE_10_BYTE_MS),
 
 	/* module management */
 	.module =			THIS_MODULE
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/sddr09.c 001-linus.patch/drivers/usb/storage/sddr09.c
--- 000-virgin/drivers/usb/storage/sddr09.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/drivers/usb/storage/sddr09.c	Tue Dec 30 16:38:57 2003
@@ -28,7 +28,6 @@
  */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -66,7 +65,7 @@ struct nand_flash_dev {
  * NAND Flash Manufacturer ID Codes
  */
 #define NAND_MFR_AMD		0x01
-#define NAND_MFR_NS		0x8f
+#define NAND_MFR_NATSEMI	0x8f
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
 
@@ -74,8 +73,8 @@ static inline char *nand_flash_manufactu
 	switch(manuf_id) {
 	case NAND_MFR_AMD:
 		return "AMD";
-	case NAND_MFR_NS:
-		return "NS";
+	case NAND_MFR_NATSEMI:
+		return "NATSEMI";
 	case NAND_MFR_TOSHIBA:
 		return "Toshiba";
 	case NAND_MFR_SAMSUNG:
@@ -302,8 +301,7 @@ sddr09_request_sense(struct us_data *us,
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("request sense bulk in failed\n");
 		return USB_STOR_TRANSPORT_ERROR;
-	}
-	else {
+	} else {
 		US_DEBUGP("request sense worked\n");
 		return USB_STOR_TRANSPORT_GOOD;
 	}
@@ -469,6 +467,8 @@ sddr09_erase(struct us_data *us, unsigne
 	unsigned char *command = us->iobuf;
 	int result;
 
+	US_DEBUGP("sddr09_erase: erase address %lu\n", Eaddress);
+
 	memset(command, 0, 12);
 	command[0] = 0xEA;
 	command[1] = LUNBITS;
@@ -663,30 +663,31 @@ static int
 sddr09_read_data(struct us_data *us,
 		 unsigned long address,
 		 unsigned int sectors,
-		 unsigned char *content,
+		 unsigned char *buffer,
 		 int use_sg) {
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	unsigned int lba, maxlba, pba;
 	unsigned int page, pages;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
-	int result, len;
-
-	// If we're using scatter-gather, we have to create a new
-	// buffer to read all of the data in first, since a
-	// scatter-gather buffer could in theory start in the middle
-	// of a page, which would be bad. A developer who wants a
-	// challenge might want to write a limited-buffer
-	// version of this code.
-
-	len = sectors*info->pagesize;
-
-	buffer = (use_sg ? kmalloc(len, GFP_NOIO) : content);
-	if (buffer == NULL)
-		return USB_STOR_TRANSPORT_ERROR;
+	unsigned int len, index, offset;
+	int result;
 
-	ptr = buffer;
+	// Since we only read in one block at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	if (use_sg) {
+		len = min(sectors, (unsigned int) info->blocksize) *
+				info->pagesize;
+		buffer = kmalloc(len, GFP_NOIO);
+		if (buffer == NULL) {
+			printk("sddr09_read_data: Out of memory\n");
+			return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
 
 	// Figure out the initial LBA and page
 	lba = address >> info->blockshift;
@@ -697,13 +698,13 @@ sddr09_read_data(struct us_data *us,
 	// contiguous LBA's. Another exercise left to the student.
 
 	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
 
 	while (sectors > 0) {
 
 		/* Find number of pages we can read in this block */
-		pages = info->blocksize - page;
-		if (pages > sectors)
-			pages = sectors;
+		pages = min(sectors, info->blocksize - page);
+		len = pages << info->pageshift;
 
 		/* Not overflowing capacity? */
 		if (lba >= maxlba) {
@@ -726,7 +727,7 @@ sddr09_read_data(struct us_data *us,
 			   Instead of returning USB_STOR_TRANSPORT_ERROR
 			   it is better to return all zero data. */
 
-			memset(ptr, 0, pages << info->pageshift);
+			memset(buffer, 0, len);
 
 		} else {
 			US_DEBUGP("Read %d pages, from PBA %d"
@@ -737,37 +738,50 @@ sddr09_read_data(struct us_data *us,
 				info->pageshift;
 
 			result = sddr09_read20(us, address>>1,
-					       pages, info->pageshift, ptr, 0);
+					pages, info->pageshift, buffer, 0);
 			if (result != USB_STOR_TRANSPORT_GOOD)
 				break;
 		}
 
+		// Store the data (s-g) or update the pointer (!s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&index, &offset, TO_XFER_BUF);
+		else
+			buffer += len;
+
 		page = 0;
 		lba++;
 		sectors -= pages;
-		ptr += (pages << info->pageshift);
 	}
 
-	if (use_sg && result == USB_STOR_TRANSPORT_GOOD)
-		us_copy_to_sgbuf_all(buffer, len, content, use_sg);
-
 	if (use_sg)
 		kfree(buffer);
 
 	return result;
 }
 
-/* we never free blocks, so lastpba can only increase */
 static unsigned int
-sddr09_find_unused_pba(struct sddr09_card_info *info) {
+sddr09_find_unused_pba(struct sddr09_card_info *info, unsigned int lba) {
 	static unsigned int lastpba = 1;
-	int numblocks = info->capacity >> (info->blockshift + info->pageshift);
-	int i;
+	int zonestart, end, i;
 
-	for (i = lastpba+1; i < numblocks; i++) {
-		if (info->pba_to_lba[i] == UNDEF) {
+	zonestart = (lba/1000) << 10;
+	end = info->capacity >> (info->blockshift + info->pageshift);
+	end -= zonestart;
+	if (end > 1024)
+		end = 1024;
+
+	for (i = lastpba+1; i < end; i++) {
+		if (info->pba_to_lba[zonestart+i] == UNDEF) {
+			lastpba = i;
+			return zonestart+i;
+		}
+	}
+	for (i = 0; i <= lastpba; i++) {
+		if (info->pba_to_lba[zonestart+i] == UNDEF) {
 			lastpba = i;
-			return i;
+			return zonestart+i;
 		}
 	}
 	return 0;
@@ -776,29 +790,31 @@ sddr09_find_unused_pba(struct sddr09_car
 static int
 sddr09_write_lba(struct us_data *us, unsigned int lba,
 		 unsigned int page, unsigned int pages,
-		 unsigned char *ptr) {
+		 unsigned char *ptr, unsigned char *blockbuffer) {
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	unsigned long address;
 	unsigned int pba, lbap;
-	unsigned int pagelen, blocklen;
-	unsigned char *blockbuffer, *bptr, *cptr, *xptr;
+	unsigned int pagelen;
+	unsigned char *bptr, *cptr, *xptr;
 	unsigned char ecc[3];
-	int i, result;
+	int i, result, isnew;
 
-	lbap = ((lba & 0x3ff) << 1) | 0x1000;
+	lbap = ((lba % 1000) << 1) | 0x1000;
 	if (parity[MSB_of(lbap) ^ LSB_of(lbap)])
 		lbap ^= 1;
 	pba = info->lba_to_pba[lba];
+	isnew = 0;
 
 	if (pba == UNDEF) {
-		pba = sddr09_find_unused_pba(info);
+		pba = sddr09_find_unused_pba(info, lba);
 		if (!pba) {
 			printk("sddr09_write_lba: Out of unused blocks\n");
 			return USB_STOR_TRANSPORT_ERROR;
 		}
 		info->pba_to_lba[pba] = lba;
 		info->lba_to_pba[lba] = pba;
+		isnew = 1;
 	}
 
 	if (pba == 1) {
@@ -809,22 +825,16 @@ sddr09_write_lba(struct us_data *us, uns
 	}
 
 	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
-	blocklen = (pagelen << info->blockshift);
-	blockbuffer = kmalloc(blocklen, GFP_NOIO);
-	if (!blockbuffer) {
-		printk("sddr09_write_lba: Out of memory\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
 
 	/* read old contents */
 	address = (pba << (info->pageshift + info->blockshift));
 	result = sddr09_read22(us, address>>1, info->blocksize,
 			       info->pageshift, blockbuffer, 0);
 	if (result != USB_STOR_TRANSPORT_GOOD)
-		goto err;
+		return result;
 
-	/* check old contents */
-	for (i = 0; i < info->blockshift; i++) {
+	/* check old contents and fill lba */
+	for (i = 0; i < info->blocksize; i++) {
 		bptr = blockbuffer + i*pagelen;
 		cptr = bptr + info->pagesize;
 		nand_compute_ecc(bptr, ecc);
@@ -839,6 +849,8 @@ sddr09_write_lba(struct us_data *us, uns
 				  i, pba);
 			nand_store_ecc(cptr+8, ecc);
 		}
+		cptr[6] = cptr[11] = MSB_of(lbap);
+		cptr[7] = cptr[12] = LSB_of(lbap);
 	}
 
 	/* copy in new stuff and compute ECC */
@@ -852,8 +864,6 @@ sddr09_write_lba(struct us_data *us, uns
 		nand_store_ecc(cptr+13, ecc);
 		nand_compute_ecc(bptr+(info->pagesize / 2), ecc);
 		nand_store_ecc(cptr+8, ecc);
-		cptr[6] = cptr[11] = MSB_of(lbap);
-		cptr[7] = cptr[12] = LSB_of(lbap);
 	}
 
 	US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba);
@@ -880,11 +890,6 @@ sddr09_write_lba(struct us_data *us, uns
 		int result2 = sddr09_test_unit_ready(us);
 	}
 #endif
- err:
-	kfree(blockbuffer);
-
-	/* TODO: instead of doing kmalloc/kfree for each block,
-	   add a bufferpointer to the info structure */
 
 	return result;
 }
@@ -893,49 +898,84 @@ static int
 sddr09_write_data(struct us_data *us,
 		  unsigned long address,
 		  unsigned int sectors,
-		  unsigned char *content,
+		  unsigned char *buffer,
 		  int use_sg) {
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	unsigned int lba, page, pages;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
-	int result, len;
+	unsigned int pagelen, blocklen;
+	unsigned char *blockbuffer;
+	unsigned int len, index, offset;
+	int result;
 
-	len = sectors*info->pagesize;
+	// blockbuffer is used for reading in the old data, overwriting
+	// with the new data, and performing ECC calculations
 
-	buffer = us_copy_from_sgbuf_all(content, len, use_sg);
-	if (buffer == NULL)
+	/* TODO: instead of doing kmalloc/kfree for each write,
+	   add a bufferpointer to the info structure */
+
+	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
+	blocklen = (pagelen << info->blockshift);
+	blockbuffer = kmalloc(blocklen, GFP_NOIO);
+	if (!blockbuffer) {
+		printk("sddr09_write_data: Out of memory\n");
 		return USB_STOR_TRANSPORT_ERROR;
+	}
 
-	ptr = buffer;
+	// Since we don't write the user data directly to the device,
+	// we have to create a bounce buffer if the transfer uses
+	// scatter-gather.  We will move the data a piece at a time
+	// between the bounce buffer and the actual transfer buffer.
+	// If we're not using scatter-gather, we can simply update
+	// the transfer buffer pointer to get the same effect.
+
+	if (use_sg) {
+		len = min(sectors, (unsigned int) info->blocksize) *
+				info->pagesize;
+		buffer = kmalloc(len, GFP_NOIO);
+		if (buffer == NULL) {
+			printk("sddr09_write_data: Out of memory\n");
+			kfree(blockbuffer);
+			return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
 
 	// Figure out the initial LBA and page
 	lba = address >> info->blockshift;
 	page = (address & info->blockmask);
 
 	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
 
 	while (sectors > 0) {
 
 		// Write as many sectors as possible in this block
 
-		pages = info->blocksize - page;
-		if (pages > sectors)
-			pages = sectors;
+		pages = min(sectors, info->blocksize - page);
+		len = (pages << info->pageshift);
+
+		// Get the data from the transfer buffer (s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&index, &offset, FROM_XFER_BUF);
 
-		result = sddr09_write_lba(us, lba, page, pages, ptr);
+		result = sddr09_write_lba(us, lba, page, pages,
+				buffer, blockbuffer);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			break;
 
+		// Update the transfer buffer pointer (!s-g)
+		if (!use_sg)
+			buffer += len;
+
 		page = 0;
 		lba++;
 		sectors -= pages;
-		ptr += (pages << info->pageshift);
 	}
 
 	if (use_sg)
 		kfree(buffer);
+	kfree(blockbuffer);
 
 	return result;
 }
@@ -947,10 +987,11 @@ sddr09_read_control(struct us_data *us,
 		unsigned char *content,
 		int use_sg) {
 
-	US_DEBUGP("Read control address %08lX blocks %04X\n",
+	US_DEBUGP("Read control address %lu, blocks %d\n",
 		address, blocks);
 
-	return sddr09_read21(us, address, blocks, CONTROL_SHIFT, content, use_sg);
+	return sddr09_read21(us, address, blocks,
+			     CONTROL_SHIFT, content, use_sg);
 }
 
 /*
@@ -997,7 +1038,7 @@ sddr09_get_wp(struct us_data *us, struct
 		US_DEBUGP("sddr09_get_wp: read_status fails\n");
 		return result;
 	}
-	US_DEBUGP("sddr09_get_wp: status %02X", status);
+	US_DEBUGP("sddr09_get_wp: status 0x%02X", status);
 	if ((status & 0x80) == 0) {
 		info->flags |= SDDR09_WP;	/* write protected */
 		US_DEBUGP(" WP");
@@ -1092,69 +1133,36 @@ sddr09_get_cardinfo(struct us_data *us, 
 static int
 sddr09_read_map(struct us_data *us) {
 
-	struct scatterlist *sg;
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	int numblocks, alloc_len, alloc_blocks;
 	int i, j, result;
-	unsigned char *ptr;
+	unsigned char *buffer, *buffer_end, *ptr;
 	unsigned int lba, lbact;
 
 	if (!info->capacity)
 		return -1;
 
-	// read 64 (1<<6) bytes for every block 
-	// ( 1 << ( blockshift + pageshift ) bytes)
-	//	 of capacity:
-	// (1<<6)*capacity/(1<<(b+p)) =
-	// ((1<<6)*capacity)>>(b+p) =
-	// capacity>>(b+p-6)
-
-	alloc_len = info->capacity >> 
-		(info->blockshift + info->pageshift - CONTROL_SHIFT);
-
-	// Allocate a number of scatterlist structures according to
-	// the number of 128k blocks in the alloc_len. Adding 128k-1
-	// and then dividing by 128k gives the correct number of blocks.
-	// 128k = 1<<17
-
-	alloc_blocks = (alloc_len + (1<<17) - 1) >> 17;
-	sg = kmalloc(alloc_blocks*sizeof(struct scatterlist),
-		     GFP_NOIO);
-	if (sg == NULL)
-		return 0;
-
-	for (i=0; i<alloc_blocks; i++) {
-		int alloc_req = (i < alloc_blocks-1 ? 1 << 17 : alloc_len);
-		char *vaddr = kmalloc(alloc_req, GFP_NOIO);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
-		sg[i].page = virt_to_page(vaddr);
-		sg[i].offset = offset_in_page(vaddr);
-#else
-		sg[i].address = vaddr;
-#endif
-		sg[i].length = alloc_req;
-		alloc_len -= alloc_req;
-	}
-
-	for (i=0; i<alloc_blocks; i++)
-		if (sg[i].page == NULL) {
-			for (i=0; i<alloc_blocks; i++)
-				if (sg[i].page != NULL)
-					kfree(sg_address(sg[i]));
-			kfree(sg);
-			return 0;
-		}
+	// size of a block is 1 << (blockshift + pageshift) bytes
+	// divide into the total capacity to get the number of blocks
 
 	numblocks = info->capacity >> (info->blockshift + info->pageshift);
 
-	result = sddr09_read_control(us, 0, numblocks,
-				     (unsigned char *)sg, alloc_blocks);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
-		for (i=0; i<alloc_blocks; i++)
-			kfree(sg_address(sg[i]));
-		kfree(sg);
-		return -1;
+	// read 64 bytes for every block (actually 1 << CONTROL_SHIFT)
+	// but only use a 64 KB buffer
+	// buffer size used must be a multiple of (1 << CONTROL_SHIFT)
+#define SDDR09_READ_MAP_BUFSZ 65536
+
+	alloc_blocks = min(numblocks, SDDR09_READ_MAP_BUFSZ >> CONTROL_SHIFT);
+	alloc_len = (alloc_blocks << CONTROL_SHIFT);
+	buffer = kmalloc(alloc_len, GFP_NOIO);
+	if (buffer == NULL) {
+		printk("sddr09_read_map: out of memory\n");
+		result = -1;
+		goto done;
 	}
+	buffer_end = buffer + alloc_len;
+
+#undef SDDR09_READ_MAP_BUFSZ
 
 	kfree(info->lba_to_pba);
 	kfree(info->pba_to_lba);
@@ -1162,29 +1170,35 @@ sddr09_read_map(struct us_data *us) {
 	info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
 
 	if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
-		kfree(info->lba_to_pba);
-		kfree(info->pba_to_lba);
-		info->lba_to_pba = NULL;
-		info->pba_to_lba = NULL;
-		for (i=0; i<alloc_blocks; i++)
-			kfree(sg_address(sg[i]));
-		kfree(sg);
-		return 0;
+		printk("sddr09_read_map: out of memory\n");
+		result = -1;
+		goto done;
 	}
 
 	for (i = 0; i < numblocks; i++)
 		info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;
 
-	ptr = sg_address(sg[0]);
-
 	/*
 	 * Define lba-pba translation table
 	 */
-	// Each block is 64 bytes of control data, so block i is located in
-	// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
 
-	for (i=0; i<numblocks; i++) {
-		ptr = sg_address(sg[i>>11]) + ((i&0x7ff)<<6);
+	ptr = buffer_end;
+	for (i = 0; i < numblocks; i++) {
+		ptr += (1 << CONTROL_SHIFT);
+		if (ptr >= buffer_end) {
+			unsigned long address;
+
+			address = i << (info->pageshift + info->blockshift);
+			result = sddr09_read_control(
+				us, address>>1,
+				min(alloc_blocks, numblocks - i),
+				buffer, 0);
+			if (result != USB_STOR_TRANSPORT_GOOD) {
+				result = -1;
+				goto done;
+			}
+			ptr = buffer;
+		}
 
 		if (i == 0 || i == 1) {
 			info->pba_to_lba[i] = UNUSABLE;
@@ -1196,7 +1210,7 @@ sddr09_read_map(struct us_data *us) {
 			if (ptr[j] != 0)
 				goto nonz;
 		info->pba_to_lba[i] = UNUSABLE;
-		printk("sddr09: PBA %04X has no logical mapping\n", i);
+		printk("sddr09: PBA %d has no logical mapping\n", i);
 		continue;
 
 	nonz:
@@ -1209,7 +1223,7 @@ sddr09_read_map(struct us_data *us) {
 	nonff:
 		/* normal PBAs start with six FFs */
 		if (j < 6) {
-			printk("sddr09: PBA %04X has no logical mapping: "
+			printk("sddr09: PBA %d has no logical mapping: "
 			       "reserved area = %02X%02X%02X%02X "
 			       "data status %02X block status %02X\n",
 			       i, ptr[0], ptr[1], ptr[2], ptr[3],
@@ -1219,7 +1233,7 @@ sddr09_read_map(struct us_data *us) {
 		}
 
 		if ((ptr[6] >> 4) != 0x01) {
-			printk("sddr09: PBA %04X has invalid address field "
+			printk("sddr09: PBA %d has invalid address field "
 			       "%02X%02X/%02X%02X\n",
 			       i, ptr[6], ptr[7], ptr[11], ptr[12]);
 			info->pba_to_lba[i] = UNUSABLE;
@@ -1228,7 +1242,7 @@ sddr09_read_map(struct us_data *us) {
 
 		/* check even parity */
 		if (parity[ptr[6] ^ ptr[7]]) {
-			printk("sddr09: Bad parity in LBA for block %04X"
+			printk("sddr09: Bad parity in LBA for block %d"
 			       " (%02X %02X)\n", i, ptr[6], ptr[7]);
 			info->pba_to_lba[i] = UNUSABLE;
 			continue;
@@ -1247,27 +1261,32 @@ sddr09_read_map(struct us_data *us) {
 		 */
 
 		if (lba >= 1000) {
-			unsigned long address;
-
-			printk("sddr09: Bad LBA %04X for block %04X\n",
+			printk("sddr09: Bad low LBA %d for block %d\n",
 			       lba, i);
-			info->pba_to_lba[i] = UNDEF /* UNUSABLE */;
-			if (erase_bad_lba_entries) {
-				/* some cameras cannot erase a card if it has
-				   bad entries, so we supply this function */
-				address = (i << (info->pageshift + info->blockshift));
-				sddr09_erase(us, address>>1);
-			}
-			continue;
+			goto possibly_erase;
 		}
 
 		lba += 1000*(i/0x400);
 
-		if (lba<0x10 || (lba >= 0x3E0 && lba < 0x3EF))
-			US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
+		if (info->lba_to_pba[lba] != UNDEF) {
+			printk("sddr09: LBA %d seen for PBA %d and %d\n",
+			       lba, info->lba_to_pba[lba], i);
+			goto possibly_erase;
+		}
 
 		info->pba_to_lba[i] = lba;
 		info->lba_to_pba[lba] = i;
+		continue;
+
+	possibly_erase:
+		if (erase_bad_lba_entries) {
+			unsigned long address;
+
+			address = (i << (info->pageshift + info->blockshift));
+			sddr09_erase(us, address>>1);
+			info->pba_to_lba[i] = UNDEF;
+		} else
+			info->pba_to_lba[i] = UNUSABLE;
 	}
 
 	/*
@@ -1292,11 +1311,17 @@ sddr09_read_map(struct us_data *us) {
 	}
 	info->lbact = lbact;
 	US_DEBUGP("Found %d LBA's\n", lbact);
+	result = 0;
 
-	for (i=0; i<alloc_blocks; i++)
-		kfree(sg_address(sg[i]));
-	kfree(sg);
-	return 0;
+ done:
+	if (result != 0) {
+		kfree(info->lba_to_pba);
+		kfree(info->pba_to_lba);
+		info->lba_to_pba = NULL;
+		info->pba_to_lba = NULL;
+	}
+	kfree(buffer);
+	return result;
 }
 
 static void
@@ -1438,6 +1463,7 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 		cardinfo = sddr09_get_cardinfo(us, info->flags);
 		if (!cardinfo) {
 			/* probably no media */
+		init_error:
 			sensekey = 0x02;	/* not ready */
 			sensecode = 0x3a;	/* medium not present */
 			return USB_STOR_TRANSPORT_FAILED;
@@ -1451,7 +1477,10 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 		info->blockmask = info->blocksize - 1;
 
 		// map initialization, must follow get_cardinfo()
-		sddr09_read_map(us);
+		if (sddr09_read_map(us)) {
+			/* probably out of memory */
+			goto init_error;
+		}
 
 		// Report capacity
 
@@ -1472,12 +1501,13 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 		return USB_STOR_TRANSPORT_GOOD;
 	}
 
-	if (srb->cmnd[0] == MODE_SENSE) {
+	if (srb->cmnd[0] == MODE_SENSE || srb->cmnd[0] == MODE_SENSE_10) {
 		int modepage = (srb->cmnd[2] & 0x3F);
 		int len;
 
 		/* They ask for the Read/Write error recovery page,
 		   or for all pages. Give as much as they have room for. */
+		/* %% We should check DBD %% */
 		if (modepage == 0x01 || modepage == 0x3F) {
 
 			US_DEBUGP("SDDR09: Dummy up request for "
@@ -1496,20 +1526,14 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 			return USB_STOR_TRANSPORT_GOOD;
 		}
 
-		return USB_STOR_TRANSPORT_ERROR;
+		sensekey = 0x05;	/* illegal request */
+		sensecode = 0x24;	/* invalid field in CDB */
+		return USB_STOR_TRANSPORT_FAILED;
 	}
 
-	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
-
-		US_DEBUGP(
-			"SDDR09: %s medium removal. Not that I can do"
-			" anything about it...\n",
-			(srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
-
+	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL)
 		return USB_STOR_TRANSPORT_GOOD;
 
-	}
-
 	havefakesense = 0;
 
 	if (srb->cmnd[0] == READ_10) {
@@ -1542,8 +1566,10 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 
 	if (srb->cmnd[0] != TEST_UNIT_READY &&
 	    srb->cmnd[0] != REQUEST_SENSE) {
+		sensekey = 0x05;	/* illegal request */
+		sensecode = 0x20;	/* invalid command */
 		havefakesense = 1;
-		return USB_STOR_TRANSPORT_ERROR;
+		return USB_STOR_TRANSPORT_FAILED;
 	}
 
 	for (; srb->cmd_len<12; srb->cmd_len++)
@@ -1555,8 +1581,7 @@ int sddr09_transport(Scsi_Cmnd *srb, str
 	for (i=0; i<12; i++)
 		sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);
 
-	US_DEBUGP("SDDR09: Send control for command %s\n",
-		  string);
+	US_DEBUGP("SDDR09: Send control for command %s\n", string);
 
 	result = sddr09_send_scsi_command(us, srb->cmnd, 12);
 	if (result != USB_STOR_TRANSPORT_GOOD) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/sddr55.c 001-linus.patch/drivers/usb/storage/sddr55.c
--- 000-virgin/drivers/usb/storage/sddr55.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/drivers/usb/storage/sddr55.c	Tue Dec 30 16:38:57 2003
@@ -25,7 +25,6 @@
  */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -155,7 +154,7 @@ static int sddr55_read_data(struct us_da
 		unsigned int lba,
 		unsigned int page,
 		unsigned short sectors,
-		unsigned char *content,
+		unsigned char *buffer,
 		int use_sg) {
 
 	int result = USB_STOR_TRANSPORT_GOOD;
@@ -167,17 +166,24 @@ static int sddr55_read_data(struct us_da
 	unsigned long address;
 
 	unsigned short pages;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
-	int len;
+	unsigned int len, index, offset;
 
-	len = sectors * PAGESIZE;
-
-	buffer = (use_sg ? kmalloc(len, GFP_NOIO) : content);
-	if (buffer == NULL)
-		return USB_STOR_TRANSPORT_ERROR; /* out of memory */
-
-	ptr = buffer;
+	// Since we only read in one block at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	if (use_sg) {
+		len = min((unsigned int) sectors,
+				(unsigned int) info->blocksize >>
+					info->smallpageshift) * PAGESIZE;
+		buffer = kmalloc(len, GFP_NOIO);
+		if (buffer == NULL)
+			return USB_STOR_TRANSPORT_ERROR; /* out of memory */
+	}
+	index = offset = 0;
 
 	while (sectors>0) {
 
@@ -189,9 +195,9 @@ static int sddr55_read_data(struct us_da
 
 		// Read as many sectors as possible in this block
 
-		pages = info->blocksize - page;
-		if (pages > (sectors << info->smallpageshift))
-			pages = (sectors << info->smallpageshift);
+		pages = min((unsigned int) sectors << info->smallpageshift,
+				info->blocksize - page);
+		len = pages << info->pageshift;
 
 		US_DEBUGP("Read %02X pages, from PBA %04X"
 			" (LBA %04X) page %02X\n",
@@ -199,7 +205,7 @@ static int sddr55_read_data(struct us_da
 
 		if (pba == NOT_ALLOCATED) {
 			/* no pba for this lba, fill with zeroes */
-			memset (ptr, 0, pages << info->pageshift);
+			memset (buffer, 0, len);
 		} else {
 
 			address = (pba << info->blockshift) + page;
@@ -228,8 +234,7 @@ static int sddr55_read_data(struct us_da
 
 			/* read data */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, ptr,
-				pages<<info->pageshift);
+				SCSI_DATA_READ, buffer, len);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -253,13 +258,18 @@ static int sddr55_read_data(struct us_da
 			}
 		}
 
+		// Store the data (s-g) or update the pointer (!s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&index, &offset, TO_XFER_BUF);
+		else
+			buffer += len;
+
 		page = 0;
 		lba++;
 		sectors -= pages >> info->smallpageshift;
-		ptr += (pages << info->pageshift);
 	}
 
-	us_copy_to_sgbuf_all(buffer, len, content, use_sg);
 	result = USB_STOR_TRANSPORT_GOOD;
 
 leave:
@@ -273,7 +283,7 @@ static int sddr55_write_data(struct us_d
 		unsigned int lba,
 		unsigned int page,
 		unsigned short sectors,
-		unsigned char *content,
+		unsigned char *buffer,
 		int use_sg) {
 
 	int result = USB_STOR_TRANSPORT_GOOD;
@@ -286,9 +296,8 @@ static int sddr55_write_data(struct us_d
 	unsigned long address;
 
 	unsigned short pages;
-	unsigned char *buffer = NULL;
-	unsigned char *ptr;
-	int i, len;
+	int i;
+	unsigned int len, index, offset;
 
 	/* check if we are allowed to write */
 	if (info->read_only || info->force_read_only) {
@@ -296,13 +305,22 @@ static int sddr55_write_data(struct us_d
 		return USB_STOR_TRANSPORT_FAILED;
 	}
 
-	len = sectors * PAGESIZE;
-
-	buffer = us_copy_from_sgbuf_all(content, len, use_sg);
-	if (buffer == NULL)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	ptr = buffer;
+	// Since we only write one block at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
+	if (use_sg) {
+		len = min((unsigned int) sectors,
+				(unsigned int) info->blocksize >>
+					info->smallpageshift) * PAGESIZE;
+		buffer = kmalloc(len, GFP_NOIO);
+		if (buffer == NULL)
+			return USB_STOR_TRANSPORT_ERROR;
+	}
+	index = offset = 0;
 
 	while (sectors > 0) {
 
@@ -314,9 +332,14 @@ static int sddr55_write_data(struct us_d
 
 		// Write as many sectors as possible in this block
 
-		pages = info->blocksize - page;
-		if (pages > (sectors << info->smallpageshift))
-			pages = (sectors << info->smallpageshift);
+		pages = min((unsigned int) sectors << info->smallpageshift,
+				info->blocksize - page);
+		len = pages << info->pageshift;
+
+		// Get the data from the transfer buffer (s-g)
+		if (use_sg)
+			usb_stor_access_xfer_buf(buffer, len, us->srb,
+					&index, &offset, FROM_XFER_BUF);
 
 		US_DEBUGP("Write %02X pages, to PBA %04X"
 			" (LBA %04X) page %02X\n",
@@ -400,8 +423,7 @@ static int sddr55_write_data(struct us_d
 
 		/* send the data */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, ptr,
-			pages<<info->pageshift);
+			SCSI_DATA_WRITE, buffer, len);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_data in write_data %d\n",
@@ -458,10 +480,12 @@ static int sddr55_write_data(struct us_d
 		/* update the pba<->lba maps for new_pba */
 		info->pba_to_lba[new_pba] = lba % 1000;
 
+		// Update the transfer buffer pointer (!s-g)
+		if (!use_sg)
+			buffer += len;
 		page = 0;
 		lba++;
 		sectors -= pages >> info->smallpageshift;
-		ptr += (pages << info->pageshift);
 	}
 	result = USB_STOR_TRANSPORT_GOOD;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/shuttle_usbat.c 001-linus.patch/drivers/usb/storage/shuttle_usbat.c
--- 000-virgin/drivers/usb/storage/shuttle_usbat.c	Wed Dec 17 18:57:59 2003
+++ 001-linus.patch/drivers/usb/storage/shuttle_usbat.c	Tue Dec 30 16:38:57 2003
@@ -40,7 +40,6 @@
  */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -529,9 +528,8 @@ int usbat_handle_read10(struct us_data *
 	unsigned char *buffer;
 	unsigned int len;
 	unsigned int sector;
-	struct scatterlist *sg = NULL;
-	int sg_segment = 0;
-	int sg_offset = 0;
+	unsigned int sg_segment = 0;
+	unsigned int sg_offset = 0;
 
 	US_DEBUGP("handle_read10: transfersize %d\n",
 		srb->transfersize);
@@ -570,21 +568,29 @@ int usbat_handle_read10(struct us_data *
 			srb->transfersize);
 	}
 
+	// Since we only read in one block at a time, we have to create
+	// a bounce buffer if the transfer uses scatter-gather.  We will
+	// move the data a piece at a time between the bounce buffer and
+	// the actual transfer buffer.  If we're not using scatter-gather,
+	// we can simply update the transfer buffer pointer to get the
+	// same effect.
+
 	len = (65535/srb->transfersize) * srb->transfersize;
 	US_DEBUGP("Max read is %d bytes\n", len);
-	buffer = kmalloc(len, GFP_NOIO);
-	if (buffer == NULL) // bloody hell!
-		return USB_STOR_TRANSPORT_FAILED;
+	len = min(len, srb->request_bufflen);
+	if (srb->use_sg) {
+		buffer = kmalloc(len, GFP_NOIO);
+		if (buffer == NULL) // bloody hell!
+			return USB_STOR_TRANSPORT_FAILED;
+	} else
+		buffer = srb->request_buffer;
 	sector = short_pack(data[7+3], data[7+2]);
 	sector <<= 16;
 	sector |= short_pack(data[7+5], data[7+4]);
 	transferred = 0;
 
-	if (srb->use_sg) {
-		sg = (struct scatterlist *)srb->request_buffer;
-		sg_segment = 0; // for keeping track of where we are in
-		sg_offset = 0;  // the scatter/gather list
-	}
+	sg_segment = 0; // for keeping track of where we are in
+	sg_offset = 0;  // the scatter/gather list
 
 	while (transferred != srb->request_bufflen) {
 
@@ -615,13 +621,12 @@ int usbat_handle_read10(struct us_data *
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			break;
 
-		// Transfer the received data into the srb buffer
-
+		// Store the data (s-g) or update the pointer (!s-g)
 		if (srb->use_sg)
-			us_copy_to_sgbuf(buffer, len, sg,
-					 &sg_segment, &sg_offset, srb->use_sg);
+			usb_stor_access_xfer_buf(buffer, len, srb,
+					 &sg_segment, &sg_offset, TO_XFER_BUF);
 		else
-			memcpy(srb->request_buffer+transferred, buffer, len);
+			buffer += len;
 
 		// Update the amount transferred and the sector number
 
@@ -630,7 +635,8 @@ int usbat_handle_read10(struct us_data *
 
 	} // while transferred != srb->request_bufflen
 
-	kfree(buffer);
+	if (srb->use_sg)
+		kfree(buffer);
 	return result;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/transport.c 001-linus.patch/drivers/usb/storage/transport.c
--- 000-virgin/drivers/usb/storage/transport.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/drivers/usb/storage/transport.c	Tue Dec 30 16:38:57 2003
@@ -760,6 +760,7 @@ void usb_stor_stop_transport(struct us_d
 int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
+	unsigned int pipe = 0;
 	int result;
 
 	/* COMMAND STAGE */
@@ -785,7 +786,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -813,12 +814,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr
 		if (srb->cmnd[0] == REQUEST_SENSE ||
 		    srb->cmnd[0] == INQUIRY)
 			return USB_STOR_TRANSPORT_GOOD;
-		else {
-			if (us->iobuf[0])
-				return USB_STOR_TRANSPORT_FAILED;
-			else
-				return USB_STOR_TRANSPORT_GOOD;
-		}
+		if (us->iobuf[0])
+			goto Failed;
+		return USB_STOR_TRANSPORT_GOOD;
 	}
 
 	/* If not UFI, we interpret the data as a result code 
@@ -835,13 +833,17 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr
 		case 0x00: 
 			return USB_STOR_TRANSPORT_GOOD;
 		case 0x01: 
-			return USB_STOR_TRANSPORT_FAILED;
-		default: 
-			return USB_STOR_TRANSPORT_ERROR;
+			goto Failed;
 	}
-
-	/* we should never get here, but if we do, we're in trouble */
 	return USB_STOR_TRANSPORT_ERROR;
+
+	/* the CBI spec requires that the bulk pipe must be cleared
+	 * following any data-in/out command failure (section 2.4.3.1.3)
+	 */
+  Failed:
+	if (pipe)
+		usb_stor_clear_halt(us, pipe);
+	return USB_STOR_TRANSPORT_FAILED;
 }
 
 /*
@@ -924,6 +926,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
 	unsigned int transfer_length = srb->request_bufflen;
+	unsigned int residue;
 	int result;
 	int fake_sense = 0;
 
@@ -999,9 +1002,10 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s
 		return USB_STOR_TRANSPORT_ERROR;
 
 	/* check bulk status */
-	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %d Stat 0x%x\n",
+	residue = le32_to_cpu(bcs->Residue);
+	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
 			le32_to_cpu(bcs->Signature), bcs->Tag, 
-			bcs->Residue, bcs->Status);
+			residue, bcs->Status);
 	if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
 		    bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
 			bcs->Tag != srb->serial_number || 
@@ -1010,6 +1014,11 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *s
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
+	/* try to compute the actual residue, based on how much data
+	 * was really transferred and what the device tells us */
+	residue = min(residue, transfer_length);
+	srb->resid = max(srb->resid, (int) residue);
+
 	/* based on the status code, we report good or bad */
 	switch (bcs->Status) {
 		case US_BULK_STAT_OK:
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/unusual_devs.h 001-linus.patch/drivers/usb/storage/unusual_devs.h
--- 000-virgin/drivers/usb/storage/unusual_devs.h	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/drivers/usb/storage/unusual_devs.h	Tue Dec 30 16:38:57 2003
@@ -45,6 +45,13 @@
  *
  */
 
+/* Patch submitted by Martin Berentsen <berentsen at sent5 dot uni-duisburg dot de> */
+#define US_FL_START_STOP  0x00000004   /* ignore START_STOP commands     */
+UNUSUAL_DEV(  0x0686, 0x4014, 0x0001, 0x0001, 
+		"Minolta",
+		"Dimage S414",
+		US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP), 
+
 UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x0245, 
 		"Mitsumi",
 		"CD-R/RW Drive",
@@ -53,7 +60,7 @@ UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
 		"Mitsumi",
 		"USB FDD",
-		US_SC_UFI, US_PR_CBI, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200, 
@@ -102,6 +109,12 @@ UNUSUAL_DEV(  0x0482, 0x0101, 0x0100, 0x
 		"Finecam S4",
 		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
+/* Patch submitted by Stephane Galles <stephane.galles@free.fr> */
+UNUSUAL_DEV(  0x0482, 0x0103, 0x0100, 0x0100,
+		"Kyocera",
+		"Finecam S5",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+
 /* Reported by Paul Stewart <stewart@wetlogic.net>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
@@ -257,7 +270,7 @@ UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x
 UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
 		"Sony",
 		"Memorystick MSAC-US1",
-		US_SC_UFI, US_PR_CB, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Klaus Mueller <k.mueller@intershop.de> */
@@ -298,6 +311,12 @@ UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Fabrizio Fellini <fello@libero.it> */
+UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
+		"Fujifilm",
+		"Digital Camera EX-20 DSC",
+		US_SC_8070, US_PR_CBI, NULL, 0 ),
+
 UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200, 
 		"LaCie",
 		"USB Hard Disk",
@@ -354,6 +373,13 @@ UNUSUAL_DEV(  0x05e3, 0x0700, 0x0000, 0x
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Submitted Alexander Oltu <alexander@all-2.com> */
+UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff, 
+		"", 
+		"USB TO IDE",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE ), 
+
 /* Reported by Peter Marks <peter.marks@turner.com>
  * Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly
  * 36 bytes of data.  No more, no less. That is the only reason this entry
@@ -400,6 +426,28 @@ UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x
                 "DIMAGE E223",
                 US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
 
+/* Following three Minolta cameras reported by Martin Pool
+ * <mbp@sourcefrog.net>.  Originally discovered by Kedar Petankar,
+ * Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
+ */
+UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
+             "Minolta",
+             "DiMAGE 7",
+             US_SC_SCSI, US_PR_DEVICE, NULL,
+             0 ),
+
+UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001,
+             "Minolta",
+             "DiMAGE 7i",
+             US_SC_SCSI, US_PR_DEVICE, NULL,
+             0 ),
+
+UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
+             "Minolta",
+             "DiMAGE 7Hi",
+             US_SC_SCSI, US_PR_DEVICE, NULL,
+             0 ),
+
 UNUSUAL_DEV(  0x0693, 0x0002, 0x0100, 0x0100, 
 		"Hagiwara",
 		"FlashGate SmartMedia",
@@ -441,6 +489,11 @@ UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x
 		"Freecom",
 		"USB-IDE",
 		US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
+
+UNUSUAL_DEV(  0x07ab, 0xfc84, 0x0000, 0x9999,
+		"Freecom",
+		"FX-5/FX-50",
+		US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
 #endif
 
 UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133, 
@@ -528,6 +581,14 @@ UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0x
 		US_SC_SCSI, US_PR_DATAFAB, NULL,
 		US_FL_MODE_XLATE ),
 #endif
+#ifdef CONFIG_USB_STORAGE_SDDR55
+/* SM part - aeb <Andries.Brouwer@cwi.nl> */
+UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
+		"Datafab Systems, Inc.",
+		"USB to CF + SM Combo (LC1)",
+		US_SC_SCSI, US_PR_SDDR55, NULL,
+		US_FL_SINGLE_LUN ),
+#endif
 
 /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
  * Only revision 1.13 tested (same for all of the above devices,
@@ -570,6 +631,14 @@ UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ),
 
+/*Medion 6047 Digital Camera
+Davide Andrian <_nessuno_@katamail.com>
+*/
+UNUSUAL_DEV( 0x08ca, 0x2011, 0x0001, 0x0001,
+		"3MegaCam",
+		"3MegaCam",
+		US_SC_DEVICE, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE ),
 /* aeb */
 UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
 		"Feiya",
@@ -605,8 +674,8 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1
 /* Submitted by Per Winkvist <per.winkvist@uk.com> */
 UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
                 "Pentax",
-                "Optio S",
-                US_SC_8070, US_PR_CBI, NULL,
+                "Optio S/S4",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_FIX_INQUIRY ),
 		
 #ifdef CONFIG_USB_STORAGE_ISD200
@@ -617,13 +686,6 @@ UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x
 		0 ),
 #endif
 
-/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
-UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
-		"USB",
-		"Solid state disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_INQUIRY ),
-
 /* Submitted by Joris Struyve <joris@struyve.be> */
 UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
 		"Medion",
@@ -640,6 +702,13 @@ UNUSUAL_DEV(  0x0d96, 0x5200, 0x0001, 0x
 		"Jenoptik",
 		"JD 5200 z3",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+
+/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
+UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
+		"USB",
+		"Solid state disk",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
 		
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/usb/storage/usb.c 001-linus.patch/drivers/usb/storage/usb.c
--- 000-virgin/drivers/usb/storage/usb.c	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/drivers/usb/storage/usb.c	Tue Dec 30 16:38:57 2003
@@ -234,16 +234,8 @@ struct usb_driver usb_storage_driver = {
  */
 
 void fill_inquiry_response(struct us_data *us, unsigned char *data,
-		unsigned int data_len) {
-
-	int i;
-	struct scatterlist *sg;
-	int len =
-		us->srb->request_bufflen > data_len ? data_len :
-		us->srb->request_bufflen;
-	int transferred;
-	int amt;
-
+		unsigned int data_len)
+{
 	if (data_len<36) // You lose.
 		return;
 
@@ -270,22 +262,7 @@ void fill_inquiry_response(struct us_dat
 		data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
 	}
 
-	if (us->srb->use_sg) {
-		sg = (struct scatterlist *)us->srb->request_buffer;
-		for (i=0; i<us->srb->use_sg; i++)
-			memset(sg_address(sg[i]), 0, sg[i].length);
-		for (i=0, transferred=0; 
-				i<us->srb->use_sg && transferred < len;
-				i++) {
-			amt = sg[i].length > len-transferred ? 
-					len-transferred : sg[i].length;
-			memcpy(sg_address(sg[i]), data+transferred, amt);
-			transferred -= amt;
-		}
-	} else {
-		memset(us->srb->request_buffer, 0, us->srb->request_bufflen);
-		memcpy(us->srb->request_buffer, data, len);
-	}
+	usb_stor_set_xfer_buf(data, data_len, us->srb);
 }
 
 static int usb_stor_control_thread(void * __us)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/video/fbmon.c 001-linus.patch/drivers/video/fbmon.c
--- 000-virgin/drivers/video/fbmon.c	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/drivers/video/fbmon.c	Tue Dec 30 16:38:57 2003
@@ -890,30 +890,6 @@ struct __fb_timings {
 	u32 vtotal;
 };
 
-/*
- * a simple function to get the square root of integers 
- */
-static u32 fb_sqrt(int x)
-{
-	register int op, res, one;
-
-	op = x;
-	res = 0;
-
-	one = 1 << 30;
-	while (one > op) one >>= 2;
-
-	while (one != 0) {
-		if (op >= res + one) {
-			op = op - (res + one);
-			res = res +  2 * one;
-		}
-		res /= 2;
-		one /= 4;
-	}
-	return((u32) res);
-}
-
 /**
  * fb_get_vblank - get vertical blank time
  * @hfreq: horizontal freq
@@ -1002,7 +978,7 @@ static u32 fb_get_hblank_by_dclk(u32 dcl
 	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
 	h_period *=10000; 
 
-	h_period = fb_sqrt((int) h_period);
+	h_period = int_sqrt(h_period);
 	h_period -= (100 - C_VAL) * 100;
 	h_period *= 1000; 
 	h_period /= 2 * M_VAL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/drivers/video/sis/init301.c 001-linus.patch/drivers/video/sis/init301.c
--- 000-virgin/drivers/video/sis/init301.c	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/drivers/video/sis/init301.c	Tue Dec 30 16:38:57 2003
@@ -11712,7 +11712,7 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_
   }
 
   temp = GetOEMLCDPtr(SiS_Pr,HwDeviceExtension, ROMAddr, 1);
-  if(temp = 0xFFFF) return;
+  if(temp == 0xFFFF) return;
 
   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
   for(i=0x14, j=0; i<=0x17; i++, j++) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/Kconfig 001-linus.patch/fs/Kconfig
--- 000-virgin/fs/Kconfig	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/fs/Kconfig	Tue Dec 30 16:38:57 2003
@@ -246,6 +246,7 @@ config REISERFS_PROC_INFO
 
 config JFS_FS
 	tristate "JFS filesystem support"
+	select NLS
 	help
 	  This is a port of IBM's Journaled Filesystem .  More information is
 	  available in the file Documentation/filesystems/jfs.txt.
@@ -485,6 +486,7 @@ config ISO9660_FS
 config JOLIET
 	bool "Microsoft Joliet CDROM extensions"
 	depends on ISO9660_FS
+	select NLS
 	help
 	  Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system
 	  which allows for long filenames in unicode format (unicode is the
@@ -530,6 +532,7 @@ menu "DOS/FAT/NT Filesystems"
 
 config FAT_FS
 	tristate "DOS FAT fs support"
+	select NLS
 	help
 	  If you want to use one of the FAT-based file systems (the MS-DOS,
 	  VFAT (Windows 95) and UMSDOS (used to run Linux on top of an
@@ -651,6 +654,7 @@ config UMSDOS_FS
 
 config NTFS_FS
 	tristate "NTFS file system support"
+	select NLS
 	help
 	  NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003.
 
@@ -962,6 +966,7 @@ config HFS_FS
 config BEFS_FS
 	tristate "BeOS file systemv(BeFS) support (read only) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	select NLS
 	help
 	  The BeOS File System (BeFS) is the native file system of Be, Inc's
 	  BeOS. Notable features include support for arbitrary attributes
@@ -1440,6 +1445,7 @@ config RPCSEC_GSS_KRB5
 config SMB_FS
 	tristate "SMB file system support (to mount Windows shares etc.)"
 	depends on INET
+	select NLS
 	help
 	  SMB (Server Message Block) is the protocol Windows for Workgroups
 	  (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
@@ -1495,6 +1501,7 @@ config SMB_NLS_REMOTE
 config CIFS
 	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)(EXPERIMENTAL)"
 	depends on INET
+	select NLS
 	help
 	  This is the client VFS module for the Common Internet File System
 	  (CIFS) protocol which is the successor to the Server Message Block 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/Kconfig.binfmt 001-linus.patch/fs/Kconfig.binfmt
--- 000-virgin/fs/Kconfig.binfmt	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/fs/Kconfig.binfmt	Tue Dec 30 16:38:57 2003
@@ -23,10 +23,6 @@ config BINFMT_ELF
 	  ld.so (check the file <file:Documentation/Changes> for location and
 	  latest version).
 
-	  To compile this as a module, choose M here: the module will be called
-	  binfmt_elf. Saying M or N here is dangerous because some crucial
-	  programs on your system might be in ELF format.
-
 config BINFMT_FLAT
 	tristate "Kernel support for flat binaries"
 	depends on !MMU || SUPERH
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/binfmt_elf.c 001-linus.patch/fs/binfmt_elf.c
--- 000-virgin/fs/binfmt_elf.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/fs/binfmt_elf.c	Tue Dec 30 16:38:57 2003
@@ -82,13 +82,17 @@ static struct linux_binfmt elf_format = 
 
 #define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)
 
-static void set_brk(unsigned long start, unsigned long end)
+static int set_brk(unsigned long start, unsigned long end)
 {
 	start = ELF_PAGEALIGN(start);
 	end = ELF_PAGEALIGN(end);
-	if (end > start)
-		do_brk(start, end - start);
+	if (end > start) {
+		unsigned long addr = do_brk(start, end - start);
+		if (BAD_ADDR(addr))
+			return addr;
+	}
 	current->mm->start_brk = current->mm->brk = end;
+	return 0;
 }
 
 
@@ -381,8 +385,11 @@ static unsigned long load_elf_interp(str
 	elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);	/* What we have mapped so far */
 
 	/* Map the last of the bss segment */
-	if (last_bss > elf_bss)
-		do_brk(elf_bss, last_bss - elf_bss);
+	if (last_bss > elf_bss) {
+		error = do_brk(elf_bss, last_bss - elf_bss);
+		if (BAD_ADDR(error))
+			goto out_close;
+	}
 
 	*interp_load_addr = load_addr;
 	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
@@ -466,6 +473,7 @@ static int load_elf_binary(struct linux_
 	struct elfhdr interp_elf_ex;
   	struct exec interp_ex;
 	char passed_fileno[6];
+	struct files_struct *files;
 	
 	/* Get the exec-header */
 	elf_ex = *((struct elfhdr *) bprm->buf);
@@ -498,9 +506,20 @@ static int load_elf_binary(struct linux_
 	if (retval < 0)
 		goto out_free_ph;
 
+	files = current->files;		/* Refcounted so ok */
+	if(unshare_files() < 0)
+		goto out_free_ph;
+	if (files == current->files) {
+		put_files_struct(files);
+		files = NULL;
+	}
+
+	/* exec will make our files private anyway, but for the a.out
+	   loader stuff we need to do it earlier */
+
 	retval = get_unused_fd();
 	if (retval < 0)
-		goto out_free_ph;
+		goto out_free_fh;
 	get_file(bprm->file);
 	fd_install(elf_exec_fileno = retval, bprm->file);
 
@@ -631,6 +650,13 @@ static int load_elf_binary(struct linux_
 	if (retval)
 		goto out_free_dentry;
 
+	/* Discard our unneeded old files struct */
+	if (files) {
+		steal_locks(files);
+		put_files_struct(files);
+		files = NULL;
+	}
+
 	/* OK, This is the point of no return */
 	current->mm->start_data = 0;
 	current->mm->end_data = 0;
@@ -672,7 +698,12 @@ static int load_elf_binary(struct linux_
 			/* There was a PT_LOAD segment with p_memsz > p_filesz
 			   before this one. Map anonymous pages, if needed,
 			   and clear the area.  */
-			set_brk (elf_bss + load_bias, elf_brk + load_bias);
+			retval = set_brk (elf_bss + load_bias,
+					  elf_brk + load_bias);
+			if (retval) {
+				send_sig(SIGKILL, current, 0);
+				goto out_free_dentry;
+			}
 			nbyte = ELF_PAGEOFFSET(elf_bss);
 			if (nbyte) {
 				nbyte = ELF_MIN_ALIGN - nbyte;
@@ -737,6 +768,18 @@ static int load_elf_binary(struct linux_
 	start_data += load_bias;
 	end_data += load_bias;
 
+	/* Calling set_brk effectively mmaps the pages that we need
+	 * for the bss and break sections.  We must do this before
+	 * mapping in the interpreter, to make sure it doesn't wind
+	 * up getting placed where the bss needs to go.
+	 */
+	retval = set_brk(elf_bss, elf_brk);
+	if (retval) {
+		send_sig(SIGKILL, current, 0);
+		goto out_free_dentry;
+	}
+	padzero(elf_bss);
+
 	if (elf_interpreter) {
 		if (interpreter_type == INTERPRETER_AOUT)
 			elf_entry = load_aout_interp(&interp_ex,
@@ -745,19 +788,17 @@ static int load_elf_binary(struct linux_
 			elf_entry = load_elf_interp(&interp_elf_ex,
 						    interpreter,
 						    &interp_load_addr);
-
-		allow_write_access(interpreter);
-		fput(interpreter);
-		kfree(elf_interpreter);
-
 		if (BAD_ADDR(elf_entry)) {
 			printk(KERN_ERR "Unable to load interpreter\n");
-			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
 			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
-			goto out;
+			goto out_free_dentry;
 		}
 		reloc_func_desc = interp_load_addr;
+
+		allow_write_access(interpreter);
+		fput(interpreter);
+		kfree(elf_interpreter);
 	} else {
 		elf_entry = elf_ex.e_entry;
 	}
@@ -782,13 +823,6 @@ static int load_elf_binary(struct linux_
 	current->mm->end_data = end_data;
 	current->mm->start_stack = bprm->p;
 
-	/* Calling set_brk effectively mmaps the pages that we need
-	 * for the bss and break sections
-	 */
-	set_brk(elf_bss, elf_brk);
-
-	padzero(elf_bss);
-
 	if (current->personality & MMAP_PAGE_ZERO) {
 		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 		   and some applications "depend" upon this behavior.
@@ -835,6 +869,11 @@ out_free_interp:
 		kfree(elf_interpreter);
 out_free_file:
 	sys_close(elf_exec_fileno);
+out_free_fh:
+	if (files) {
+		put_files_struct(current->files);
+		current->files = files;
+	}
 out_free_ph:
 	kfree(elf_phdata);
 	goto out;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/binfmt_som.c 001-linus.patch/fs/binfmt_som.c
--- 000-virgin/fs/binfmt_som.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/fs/binfmt_som.c	Tue Dec 30 16:38:57 2003
@@ -217,7 +217,7 @@ load_som_binary(struct linux_binprm * bp
 			(char *) hpuxhdr, size);
 	if (retval < 0)
 		goto out_free;
-
+#error "Fix security hole before enabling me"
 	retval = get_unused_fd();
 	if (retval < 0)
 		goto out_free;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/compat.c 001-linus.patch/fs/compat.c
--- 000-virgin/fs/compat.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/fs/compat.c	Tue Dec 30 16:38:57 2003
@@ -559,3 +559,96 @@ asmlinkage long compat_sys_fcntl(unsigne
 	return compat_sys_fcntl64(fd, cmd, arg);
 }
 
+extern asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
+
+asmlinkage long
+compat_sys_io_setup(unsigned nr_reqs, u32 *ctx32p)
+{
+	long ret;
+	aio_context_t ctx64;
+
+	mm_segment_t oldfs = get_fs();
+	if (unlikely(get_user(ctx64, ctx32p)))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_io_setup(nr_reqs, &ctx64);
+	set_fs(oldfs);
+	/* truncating is ok because it's a user address */
+	if (!ret)
+		ret = put_user((u32) ctx64, ctx32p);
+	return ret;
+}
+
+extern asmlinkage long sys_io_getevents(aio_context_t ctx_id,
+					  long min_nr,
+					  long nr,
+					  struct io_event *events,
+					  struct timespec *timeout);
+
+asmlinkage long
+compat_sys_io_getevents(aio_context_t ctx_id,
+				 unsigned long min_nr,
+				 unsigned long nr,
+				 struct io_event *events,
+				 struct compat_timespec *timeout)
+{
+	long ret;
+	struct timespec t;
+	struct timespec *ut = NULL;
+
+	ret = -EFAULT;
+	if (unlikely(!access_ok(VERIFY_WRITE, events, 
+				nr * sizeof(struct io_event))))
+		goto out;
+	if (timeout) {
+		if (get_compat_timespec(&t, timeout))
+			goto out;
+
+		ut = compat_alloc_user_space(sizeof(*ut));
+		if (copy_to_user(ut, &t, sizeof(t)) )
+			goto out;
+	} 
+	ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut);
+out:
+	return ret;
+}
+
+extern asmlinkage long sys_io_submit(aio_context_t, long, 
+				struct iocb __user **);
+
+static inline long
+copy_iocb(long nr, u32 *ptr32, u64 *ptr64)
+{
+	compat_uptr_t uptr;
+	int i;
+
+	for (i = 0; i < nr; ++i) {
+		if (get_user(uptr, ptr32 + i))
+			return -EFAULT;
+		if (put_user((u64)compat_ptr(uptr), ptr64 + i))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+#define MAX_AIO_SUBMITS 	(PAGE_SIZE/sizeof(struct iocb *))
+
+asmlinkage long
+compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 *iocb)
+{
+	struct iocb **iocb64; 
+	long ret;
+
+	if (unlikely(nr < 0))
+		return -EINVAL;
+
+	if (nr > MAX_AIO_SUBMITS)
+		nr = MAX_AIO_SUBMITS;
+	
+	iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64));
+	ret = copy_iocb(nr, iocb, (u64 *) iocb64);
+	if (!ret)
+		ret = sys_io_submit(ctx_id, nr, iocb64);
+	return ret;
+}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/compat_ioctl.c 001-linus.patch/fs/compat_ioctl.c
--- 000-virgin/fs/compat_ioctl.c	Wed Dec 17 18:59:41 2003
+++ 001-linus.patch/fs/compat_ioctl.c	Tue Dec 30 16:38:57 2003
@@ -63,6 +63,8 @@
 #include <linux/ctype.h>
 #include <linux/ioctl32.h>
 #include <linux/ncp_fs.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
 
 #include <net/sock.h>          /* siocdevprivate_ioctl */
 #include <net/bluetooth/bluetooth.h>
@@ -128,7 +130,7 @@ static int w_long(unsigned int fd, unsig
 	set_fs (KERNEL_DS);
 	err = sys_ioctl(fd, cmd, (unsigned long)&val);
 	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)arg))
+	if (!err && put_user(val, (u32 *)compat_ptr(arg)))
 		return -EFAULT;
 	return err;
 }
@@ -136,15 +138,16 @@ static int w_long(unsigned int fd, unsig
 static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
+	u32 *argptr = compat_ptr(arg);
 	int err;
 	unsigned long val;
 	
-	if(get_user(val, (u32 *)arg))
+	if(get_user(val, argptr))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	err = sys_ioctl(fd, cmd, (unsigned long)&val);
 	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)arg))
+	if (!err && put_user(val, argptr))
 		return -EFAULT;
 	return err;
 }
@@ -1701,7 +1704,7 @@ static int do_smb_getmountuid(unsigned i
 	set_fs(old_fs);
 
 	if (err >= 0)
-		err = put_user(kuid, (compat_pid_t *)arg);
+		err = put_user(kuid, (compat_uid_t *)arg);
 
 	return err;
 }
@@ -2869,6 +2872,105 @@ static int do_usbdevfs_discsignal(unsign
 
         return err;
 }
+
+/*
+ * I2C layer ioctls
+ */
+
+struct i2c_msg32 {
+	u16 addr;
+	u16 flags;
+	u16 len;
+	compat_caddr_t buf;
+};
+
+struct i2c_rdwr_ioctl_data32 {
+	compat_caddr_t msgs; /* struct i2c_msg __user *msgs */
+	u32 nmsgs;
+};
+
+struct i2c_smbus_ioctl_data32 {
+	u8 read_write;
+	u8 command;
+	u32 size;
+	compat_caddr_t data; /* union i2c_smbus_data *data */
+};
+
+static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_rdwr_ioctl_data	*tdata;
+	struct i2c_rdwr_ioctl_data32	*udata;
+	struct i2c_msg			*tmsgs;
+	struct i2c_msg32		*umsgs;
+	compat_caddr_t			datap;
+	int				nmsgs, i;
+
+	tdata = compat_alloc_user_space(sizeof(*tdata));
+	if (tdata == NULL)
+		return -ENOMEM;
+	if (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata)))
+		return -EFAULT;
+
+	udata = (struct i2c_rdwr_ioctl_data32 *)compat_ptr(arg);
+	if (verify_area(VERIFY_READ, udata, sizeof(*udata)))
+		return -EFAULT;
+	if (__get_user(nmsgs, &udata->nmsgs) || __put_user(nmsgs, &tdata->nmsgs))
+		return -EFAULT;
+	if (nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+		return -EINVAL;
+	if (__get_user(datap, &udata->msgs))
+		return -EFAULT;
+	umsgs = (struct i2c_msg32 *)compat_ptr(datap);
+	if (verify_area(VERIFY_READ, umsgs, sizeof(struct i2c_msg) * nmsgs))
+		return -EFAULT;
+
+	tmsgs = compat_alloc_user_space(sizeof(struct i2c_msg) * nmsgs);
+	if (tmsgs == NULL)
+		return -ENOMEM;
+	if (verify_area(VERIFY_WRITE, tmsgs, sizeof(struct i2c_msg) * nmsgs))
+		return -EFAULT;
+	if (__put_user(tmsgs, &tdata->msgs))
+		return -ENOMEM;
+	for (i = 0; i < nmsgs; i++) {
+		if (__copy_in_user(&tmsgs[i].addr,
+				   &umsgs[i].addr,
+				   3 * sizeof(u16)))
+			return -EFAULT;
+		if (__get_user(datap, &umsgs[i].buf) ||
+		    __put_user(compat_ptr(datap), &tmsgs[i].buf))
+			return -EFAULT;
+	}
+	return sys_ioctl(fd, cmd, (unsigned long)tdata);
+}
+
+static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct i2c_smbus_ioctl_data	*tdata;
+	struct i2c_smbus_ioctl_data32	*udata;
+	compat_caddr_t			datap;
+
+	tdata = compat_alloc_user_space(sizeof(*tdata));
+	if (tdata == NULL)
+		return -ENOMEM;
+	if (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata)))
+		return -EFAULT;
+
+	udata = (struct i2c_smbus_ioctl_data32 *)compat_ptr(arg);
+	if (verify_area(VERIFY_READ, udata, sizeof(*udata)))
+		return -EFAULT;
+
+	if (__copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
+		return -EFAULT;
+	if (__copy_in_user(&tdata->size, &udata->size, 2 * sizeof(u32)))
+		return -EFAULT;
+	if (__get_user(datap, &udata->data) ||
+	    __put_user(compat_ptr(datap), &tdata->data))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long)tdata);
+}
+
+
 #undef CODE
 #endif
 
@@ -2979,7 +3081,7 @@ HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioc
 HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl)
 HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
 /* One SMB ioctl needs translations. */
-#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_pid_t)
+#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
 HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
 HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
@@ -3027,5 +3129,10 @@ HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevf
 HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
 HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
 HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+/* i2c */
+HANDLE_IOCTL(I2C_FUNCS, w_long)
+HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
+HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl)
+
 #undef DECLARES
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/dcache.c 001-linus.patch/fs/dcache.c
--- 000-virgin/fs/dcache.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/fs/dcache.c	Tue Dec 30 16:38:57 2003
@@ -639,24 +639,9 @@ void shrink_dcache_anon(struct hlist_hea
 
 /*
  * This is called from kswapd when we think we need some more memory.
- *
- * We don't want the VM to steal _all_ unused dcache.  Because that leads to
- * the VM stealing all unused inodes, which shoots down recently-used
- * pagecache.  So what we do is to tell fibs to the VM about how many reapable
- * objects there are in this cache.   If the number of unused dentries is
- * less than half of the total dentry count then return zero.  The net effect
- * is that the number of unused dentries will be, at a minimum, equal to the
- * number of used ones.
- *
- * If unused_ratio is set to 5, the number of unused dentries will not fall
- * below 5* the number of used ones.
  */
 static int shrink_dcache_memory(int nr, unsigned int gfp_mask)
 {
-	int nr_used;
-	int nr_unused;
-	const int unused_ratio = 1;
-
 	if (nr) {
 		/*
 		 * Nasty deadlock avoidance.
@@ -672,11 +657,7 @@ static int shrink_dcache_memory(int nr, 
 		if (gfp_mask & __GFP_FS)
 			prune_dcache(nr);
 	}
-	nr_unused = dentry_stat.nr_unused;
-	nr_used = dentry_stat.nr_dentry - nr_unused;
-	if (nr_unused < nr_used * unused_ratio)
-		return 0;
-	return nr_unused - nr_used * unused_ratio;
+	return dentry_stat.nr_unused;
 }
 
 #define NAME_ALLOC_LEN(len)	((len+16) & ~15)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/direct-io.c 001-linus.patch/fs/direct-io.c
--- 000-virgin/fs/direct-io.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/fs/direct-io.c	Tue Dec 30 16:38:57 2003
@@ -947,6 +947,12 @@ direct_io_worker(int rw, struct kiocb *i
 		dio_bio_submit(dio);
 
 	/*
+	 * It is possible that, we return short IO due to end of file.
+	 * In that case, we need to release all the pages we got hold on.
+	 */
+	dio_cleanup(dio);
+
+	/*
 	 * OK, all BIOs are submitted, so we can decrement bio_count to truly
 	 * reflect the number of to-be-processed BIOs.
 	 */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/dquot.c 001-linus.patch/fs/dquot.c
--- 000-virgin/fs/dquot.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/fs/dquot.c	Tue Dec 30 16:38:57 2003
@@ -192,6 +192,8 @@ static struct list_head dquot_hash[NR_DQ
 
 struct dqstats dqstats;
 
+static void dqput(struct dquot *dquot);
+
 static inline int const hashfn(struct super_block *sb, unsigned int id, int type)
 {
 	return((((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
@@ -339,8 +341,11 @@ restart:
 			continue;
 		if (!dquot_dirty(dquot))
 			continue;
+		atomic_inc(&dquot->dq_count);
+		dqstats.lookups++;
 		spin_unlock(&dq_list_lock);
-		sb->dq_op->sync_dquot(dquot);
+		sb->dq_op->write_dquot(dquot);
+		dqput(dquot);
 		goto restart;
 	}
 	spin_unlock(&dq_list_lock);
@@ -427,7 +432,7 @@ we_slept:
 	}
 	if (dquot_dirty(dquot)) {
 		spin_unlock(&dq_list_lock);
-		commit_dqblk(dquot);
+		dquot->dq_sb->dq_op->write_dquot(dquot);
 		goto we_slept;
 	}
 	atomic_dec(&dquot->dq_count);
@@ -1083,7 +1088,7 @@ struct dquot_operations dquot_operations
 	.free_space	= dquot_free_space,
 	.free_inode	= dquot_free_inode,
 	.transfer	= dquot_transfer,
-	.sync_dquot	= commit_dqblk
+	.write_dquot	= commit_dqblk
 };
 
 /* Function used by filesystems for initializing the dquot_operations structure */
@@ -1207,9 +1212,9 @@ int vfs_quota_on(struct super_block *sb,
 	error = -EINVAL;
 	if (!fmt->qf_ops->check_quota_file(sb, type))
 		goto out_file_init;
-	/* We don't want quota on quota files */
+	/* We don't want quota and atime on quota files (deadlocks possible) */
 	dquot_drop_nolock(inode);
-	inode->i_flags |= S_NOQUOTA;
+	inode->i_flags |= S_NOQUOTA | S_NOATIME;
 
 	dqopt->ops[type] = fmt->qf_ops;
 	dqopt->info[type].dqi_format = fmt;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/exec.c 001-linus.patch/fs/exec.c
--- 000-virgin/fs/exec.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/fs/exec.c	Tue Dec 30 16:38:57 2003
@@ -779,6 +779,7 @@ int flush_old_exec(struct linux_binprm *
 {
 	char * name;
 	int i, ch, retval;
+	struct files_struct *files;
 
 	/*
 	 * Make sure we have a private signal table and that
@@ -789,15 +790,26 @@ int flush_old_exec(struct linux_binprm *
 		goto out;
 
 	/*
+	 * Make sure we have private file handles. Ask the
+	 * fork helper to do the work for us and the exit
+	 * helper to do the cleanup of the old one.
+	 */
+	files = current->files;		/* refcounted so safe to hold */
+	retval = unshare_files();
+	if (retval)
+		goto out;
+	/*
 	 * Release all of the old mmap stuff
 	 */
 	retval = exec_mmap(bprm->mm);
 	if (retval)
-		goto out;
+		goto mmap_failed;
 
 	bprm->mm = NULL;		/* We're using it now */
 
 	/* This is the point of no return */
+	steal_locks(files);
+	put_files_struct(files);
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
@@ -830,6 +842,9 @@ int flush_old_exec(struct linux_binprm *
 
 	return 0;
 
+mmap_failed:
+	put_files_struct(current->files);
+	current->files = files;
 out:
 	return retval;
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/ext3/super.c 001-linus.patch/fs/ext3/super.c
--- 000-virgin/fs/ext3/super.c	Wed Dec 17 18:59:36 2003
+++ 001-linus.patch/fs/ext3/super.c	Tue Dec 30 16:38:57 2003
@@ -340,6 +340,7 @@ fail:
  */
 static int ext3_blkdev_put(struct block_device *bdev)
 {
+	bd_release(bdev);
 	return blkdev_put(bdev, BDEV_FS);
 }
 
@@ -1480,6 +1481,13 @@ static journal_t *ext3_get_dev_journal(s
 	if (bdev == NULL)
 		return NULL;
 
+	if (bd_claim(bdev, sb)) {
+		printk(KERN_ERR
+		        "EXT3: failed to claim external journal device.\n");
+		blkdev_put(bdev, BDEV_FS);
+		return NULL;
+	}
+
 	blocksize = sb->s_blocksize;
 	hblock = bdev_hardsect_size(bdev);
 	if (blocksize < hblock) {
@@ -1944,9 +1952,9 @@ int ext3_statfs (struct super_block * sb
 /* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
 #define EXT3_V0_QFMT_BLOCKS 27
 
-static int (*old_sync_dquot)(struct dquot *dquot);
+static int (*old_write_dquot)(struct dquot *dquot);
 
-static int ext3_sync_dquot(struct dquot *dquot)
+static int ext3_write_dquot(struct dquot *dquot)
 {
 	int nblocks;
 	int ret;
@@ -1971,7 +1979,7 @@ static int ext3_sync_dquot(struct dquot 
 		ret = PTR_ERR(handle);
 		goto out;
 	}
-	ret = old_sync_dquot(dquot);
+	ret = old_write_dquot(dquot);
 	err = ext3_journal_stop(handle);
 	if (ret == 0)
 		ret = err;
@@ -2004,8 +2012,8 @@ static int __init init_ext3_fs(void)
 		goto out1;
 #ifdef CONFIG_QUOTA
 	init_dquot_operations(&ext3_qops);
-	old_sync_dquot = ext3_qops.sync_dquot;
-	ext3_qops.sync_dquot = ext3_sync_dquot;
+	old_write_dquot = ext3_qops.write_dquot;
+	ext3_qops.write_dquot = ext3_write_dquot;
 #endif
         err = register_filesystem(&ext3_fs_type);
 	if (err)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/file_table.c 001-linus.patch/fs/file_table.c
--- 000-virgin/fs/file_table.c	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/fs/file_table.c	Tue Dec 30 16:38:57 2003
@@ -183,9 +183,9 @@ void __fput(struct file *file)
 	fops_put(file->f_op);
 	if (file->f_mode & FMODE_WRITE)
 		put_write_access(inode);
+	file_kill(file);
 	file->f_dentry = NULL;
 	file->f_vfsmnt = NULL;
-	file_kill(file);
 	file_free(file);
 	dput(dentry);
 	mntput(mnt);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/isofs/inode.c 001-linus.patch/fs/isofs/inode.c
--- 000-virgin/fs/isofs/inode.c	Wed Dec 17 18:59:43 2003
+++ 001-linus.patch/fs/isofs/inode.c	Tue Dec 30 16:38:57 2003
@@ -1463,4 +1463,5 @@ static void __exit exit_iso9660_fs(void)
 module_init(init_iso9660_fs)
 module_exit(exit_iso9660_fs)
 MODULE_LICENSE("GPL");
-
+/* Actual filesystem name is iso9660, as requested in filesystems.c */
+MODULE_ALIAS("iso9660");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/jbd/commit.c 001-linus.patch/fs/jbd/commit.c
--- 000-virgin/fs/jbd/commit.c	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/fs/jbd/commit.c	Tue Dec 30 16:38:57 2003
@@ -177,8 +177,14 @@ void journal_commit_transaction(journal_
 		 * leave undo-committed data.
 		 */
 		if (jh->b_committed_data) {
-			kfree(jh->b_committed_data);
-			jh->b_committed_data = NULL;
+			struct buffer_head *bh = jh2bh(jh);
+
+			jbd_lock_bh_state(bh);
+			if (jh->b_committed_data) {
+				kfree(jh->b_committed_data);
+				jh->b_committed_data = NULL;
+			}
+			jbd_unlock_bh_state(bh);
 		}
 		journal_refile_buffer(journal, jh);
 	}
@@ -264,6 +270,16 @@ write_out_data_locked:
 				jbd_unlock_bh_state(bh);
 				journal_remove_journal_head(bh);
 				__brelse(bh);
+				if (need_resched() && commit_transaction->
+							t_sync_datalist) {
+					commit_transaction->t_sync_datalist =
+								next_jh;
+					if (bufs)
+						break;
+					spin_unlock(&journal->j_list_lock);
+					cond_resched();
+					goto write_out_data;
+				}
 			}
 		}
 		if (bufs == ARRAY_SIZE(wbuf)) {
@@ -284,8 +300,7 @@ write_out_data_locked:
 		cond_resched();
 		journal_brelse_array(wbuf, bufs);
 		spin_lock(&journal->j_list_lock);
-		if (bufs)
-			goto write_out_data_locked;
+		goto write_out_data_locked;
 	}
 
 	/*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/locks.c 001-linus.patch/fs/locks.c
--- 000-virgin/fs/locks.c	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/fs/locks.c	Tue Dec 30 16:38:57 2003
@@ -1983,6 +1983,24 @@ int lock_may_write(struct inode *inode, 
 
 EXPORT_SYMBOL(lock_may_write);
 
+void steal_locks(fl_owner_t from)
+{
+	struct list_head *tmp;
+
+	if (from == current->files)
+		return;
+
+	lock_kernel();
+	list_for_each(tmp, &file_lock_list) {
+		struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
+		if (fl->fl_owner == from)
+			fl->fl_owner = current->files;
+	}
+	unlock_kernel();
+}
+
+EXPORT_SYMBOL(steal_locks);
+
 static int __init filelock_init(void)
 {
 	filelock_cache = kmem_cache_create("file_lock_cache",
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/ncpfs/Kconfig 001-linus.patch/fs/ncpfs/Kconfig
--- 000-virgin/fs/ncpfs/Kconfig	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/fs/ncpfs/Kconfig	Tue Dec 30 16:38:57 2003
@@ -65,6 +65,7 @@ config NCPFS_SMALLDOS
 config NCPFS_NLS
 	bool "Use Native Language Support"
 	depends on NCP_FS
+	select NLS
 	help
 	  Allows you to use codepages and I/O charsets for file name
 	  translation between the server file system and input/output. This
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/ncpfs/mmap.c 001-linus.patch/fs/ncpfs/mmap.c
--- 000-virgin/fs/ncpfs/mmap.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/fs/ncpfs/mmap.c	Tue Dec 30 16:38:57 2003
@@ -26,7 +26,7 @@
  * Fill in the supplied page for mmap
  */
 static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
-				     unsigned long address, int write_access)
+				     unsigned long address, int *type)
 {
 	struct file *file = area->vm_file;
 	struct dentry *dentry = file->f_dentry;
@@ -85,6 +85,15 @@ static struct page* ncp_file_mmap_nopage
 		memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
 	flush_dcache_page(page);
 	kunmap(page);
+
+	/*
+	 * If I understand ncp_read_kernel() properly, the above always
+	 * fetches from the network, here the analogue of disk.
+	 * -- wli
+	 */
+	if (type)
+		*type = VM_FAULT_MAJOR;
+	inc_page_state(pgmajfault);
 	return page;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/nls/Kconfig 001-linus.patch/fs/nls/Kconfig
--- 000-virgin/fs/nls/Kconfig	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/fs/nls/Kconfig	Tue Dec 30 16:38:57 2003
@@ -1,24 +1,25 @@
 #
 # Native language support configuration
 #
-# smb wants NLS
-config SMB_NLS
-	bool
-	depends on SMB_FS
-	default y
 
-# msdos and Joliet want NLS
+menu "Native Language Support"
+
 config NLS
-	bool
-	depends on JOLIET || FAT_FS || NTFS_FS || NCPFS_NLS || SMB_NLS || JFS_FS || CIFS || BEFS_FS
-	default y
+	tristate "Base native language support"
+	---help---
+	  The base Native Language Support. A number of filesystems
+	  depend on it (e.g. FAT, JOLIET, NT, BEOS filesystems), as well
+	  as the ability of some filesystems to use native languages
+	  (NCP, SMB).
 
+	  If unsure, say Y.
 
-menu "Native Language Support"
-	depends on NLS
+	  To compile this code as a module, choose M here: the module
+	  will be called nls_base.
 
 config NLS_DEFAULT
 	string "Default NLS Option"
+	depends on NLS
 	default "iso8859-1"
 	---help---
 	  The default NLS used when mounting file system. Note, that this is
@@ -38,6 +39,7 @@ config NLS_DEFAULT
 
 config NLS_CODEPAGE_437
 	tristate "Codepage 437 (United States, Canada)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored
@@ -50,6 +52,7 @@ config NLS_CODEPAGE_437
 
 config NLS_CODEPAGE_737
 	tristate "Codepage 737 (Greek)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored
@@ -62,6 +65,7 @@ config NLS_CODEPAGE_737
 
 config NLS_CODEPAGE_775
 	tristate "Codepage 775 (Baltic Rim)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored
@@ -75,6 +79,7 @@ config NLS_CODEPAGE_775
 
 config NLS_CODEPAGE_850
 	tristate "Codepage 850 (Europe)"
+	depends on NLS
 	---help---
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -91,6 +96,7 @@ config NLS_CODEPAGE_850
 
 config NLS_CODEPAGE_852
 	tristate "Codepage 852 (Central/Eastern Europe)"
+	depends on NLS
 	---help---
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -106,6 +112,7 @@ config NLS_CODEPAGE_852
 
 config NLS_CODEPAGE_855
 	tristate "Codepage 855 (Cyrillic)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -117,6 +124,7 @@ config NLS_CODEPAGE_855
 
 config NLS_CODEPAGE_857
 	tristate "Codepage 857 (Turkish)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -128,6 +136,7 @@ config NLS_CODEPAGE_857
 
 config NLS_CODEPAGE_860
 	tristate "Codepage 860 (Portuguese)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -139,6 +148,7 @@ config NLS_CODEPAGE_860
 
 config NLS_CODEPAGE_861
 	tristate "Codepage 861 (Icelandic)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -150,6 +160,7 @@ config NLS_CODEPAGE_861
 
 config NLS_CODEPAGE_862
 	tristate "Codepage 862 (Hebrew)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -161,6 +172,7 @@ config NLS_CODEPAGE_862
 
 config NLS_CODEPAGE_863
 	tristate "Codepage 863 (Canadian French)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -173,6 +185,7 @@ config NLS_CODEPAGE_863
 
 config NLS_CODEPAGE_864
 	tristate "Codepage 864 (Arabic)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -184,6 +197,7 @@ config NLS_CODEPAGE_864
 
 config NLS_CODEPAGE_865
 	tristate "Codepage 865 (Norwegian, Danish)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -196,6 +210,7 @@ config NLS_CODEPAGE_865
 
 config NLS_CODEPAGE_866
 	tristate "Codepage 866 (Cyrillic/Russian)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -208,6 +223,7 @@ config NLS_CODEPAGE_866
 
 config NLS_CODEPAGE_869
 	tristate "Codepage 869 (Greek)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -219,6 +235,7 @@ config NLS_CODEPAGE_869
 
 config NLS_CODEPAGE_936
 	tristate "Simplified Chinese charset (CP936, GB2312)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -231,6 +248,7 @@ config NLS_CODEPAGE_936
 
 config NLS_CODEPAGE_950
 	tristate "Traditional Chinese charset (Big5)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -243,6 +261,7 @@ config NLS_CODEPAGE_950
 
 config NLS_CODEPAGE_932
 	tristate "Japanese charsets (Shift-JIS, EUC-JP)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -256,6 +275,7 @@ config NLS_CODEPAGE_932
 
 config NLS_CODEPAGE_949
 	tristate "Korean charset (CP949, EUC-KR)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -267,6 +287,7 @@ config NLS_CODEPAGE_949
 
 config NLS_CODEPAGE_874
 	tristate "Thai charset (CP874, TIS-620)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -278,6 +299,7 @@ config NLS_CODEPAGE_874
 
 config NLS_ISO8859_8
 	tristate "Hebrew charsets (ISO-8859-8, CP1255)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -287,6 +309,7 @@ config NLS_ISO8859_8
 
 config NLS_CODEPAGE_1250
 	tristate "Windows CP1250 (Slavic/Central European Languages)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CDROMs
@@ -298,6 +321,7 @@ config NLS_CODEPAGE_1250
 
 config NLS_CODEPAGE_1251
 	tristate "Windows CP1251 (Bulgarian, Belarusian)"
+	depends on NLS
 	help
 	  The Microsoft FAT file system family can deal with filenames in
 	  native language character sets. These character sets are stored in
@@ -310,6 +334,7 @@ config NLS_CODEPAGE_1251
 
 config NLS_ISO8859_1
 	tristate "NLS ISO 8859-1  (Latin 1; Western European Languages)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -322,6 +347,7 @@ config NLS_ISO8859_1
 
 config NLS_ISO8859_2
 	tristate "NLS ISO 8859-2  (Latin 2; Slavic/Central European Languages)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -333,6 +359,7 @@ config NLS_ISO8859_2
 
 config NLS_ISO8859_3
 	tristate "NLS ISO 8859-3  (Latin 3; Esperanto, Galician, Maltese, Turkish)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -343,6 +370,7 @@ config NLS_ISO8859_3
 
 config NLS_ISO8859_4
 	tristate "NLS ISO 8859-4  (Latin 4; old Baltic charset)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -353,6 +381,7 @@ config NLS_ISO8859_4
 
 config NLS_ISO8859_5
 	tristate "NLS ISO 8859-5  (Cyrillic)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -364,6 +393,7 @@ config NLS_ISO8859_5
 
 config NLS_ISO8859_6
 	tristate "NLS ISO 8859-6  (Arabic)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -373,6 +403,7 @@ config NLS_ISO8859_6
 
 config NLS_ISO8859_7
 	tristate "NLS ISO 8859-7  (Modern Greek)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -382,6 +413,7 @@ config NLS_ISO8859_7
 
 config NLS_ISO8859_9
 	tristate "NLS ISO 8859-9  (Latin 5; Turkish)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -392,6 +424,7 @@ config NLS_ISO8859_9
 
 config NLS_ISO8859_13
 	tristate "NLS ISO 8859-13 (Latin 7; Baltic)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -402,6 +435,7 @@ config NLS_ISO8859_13
 
 config NLS_ISO8859_14
 	tristate "NLS ISO 8859-14 (Latin 8; Celtic)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -413,6 +447,7 @@ config NLS_ISO8859_14
 
 config NLS_ISO8859_15
 	tristate "NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)"
+	depends on NLS
 	---help---
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -429,6 +464,7 @@ config NLS_ISO8859_15
 
 config NLS_KOI8_R
 	tristate "NLS KOI8-R (Russian)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -438,6 +474,7 @@ config NLS_KOI8_R
 
 config NLS_KOI8_U
 	tristate "NLS KOI8-U/RU (Ukrainian, Belarusian)"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
@@ -447,6 +484,7 @@ config NLS_KOI8_U
 
 config NLS_UTF8
 	tristate "NLS UTF8"
+	depends on NLS
 	help
 	  If you want to display filenames with native language characters
 	  from the Microsoft FAT file system family or from JOLIET CD-ROMs
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/nls/nls_base.c 001-linus.patch/fs/nls/nls_base.c
--- 000-virgin/fs/nls/nls_base.c	Wed Dec 17 18:59:04 2003
+++ 001-linus.patch/fs/nls/nls_base.c	Tue Dec 30 16:38:57 2003
@@ -480,7 +480,7 @@ struct nls_table *load_nls_default(void)
 	if (default_nls != NULL)
 		return default_nls;
 	else
-               return &default_table;
+		return &default_table;
 }
 
 EXPORT_SYMBOL(register_nls);
@@ -492,3 +492,5 @@ EXPORT_SYMBOL(utf8_mbtowc);
 EXPORT_SYMBOL(utf8_mbstowcs);
 EXPORT_SYMBOL(utf8_wctomb);
 EXPORT_SYMBOL(utf8_wcstombs);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/pipe.c 001-linus.patch/fs/pipe.c
--- 000-virgin/fs/pipe.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/fs/pipe.c	Tue Dec 30 16:38:57 2003
@@ -13,6 +13,7 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
@@ -43,19 +44,63 @@ void pipe_wait(struct inode * inode)
 	down(PIPE_SEM(*inode));
 }
 
+static inline int
+pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
+{
+	unsigned long copy;
+
+	while (len > 0) {
+		while (!iov->iov_len)
+			iov++;
+		copy = min_t(unsigned long, len, iov->iov_len);
+
+		if (copy_from_user(to, iov->iov_base, copy))
+			return -EFAULT;
+		to += copy;
+		len -= copy;
+		iov->iov_base += copy;
+		iov->iov_len -= copy;
+	}
+	return 0;
+}
+
+static inline int
+pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
+{
+	unsigned long copy;
+
+	while (len > 0) {
+		while (!iov->iov_len)
+			iov++;
+		copy = min_t(unsigned long, len, iov->iov_len);
+
+		if (copy_to_user(iov->iov_base, from, copy))
+			return -EFAULT;
+		from += copy;
+		len -= copy;
+		iov->iov_base += copy;
+		iov->iov_len -= copy;
+	}
+	return 0;
+}
+
 static ssize_t
-pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+pipe_readv(struct file *filp, const struct iovec *_iov,
+	   unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	int do_wakeup;
 	ssize_t ret;
+	struct iovec *iov = (struct iovec *)_iov;
+	size_t total_len;
 
 	/* pread is not allowed on pipes. */
 	if (unlikely(ppos != &filp->f_pos))
 		return -ESPIPE;
-	
+
+	total_len = iov_length(iov, nr_segs);
 	/* Null read succeeds. */
-	if (unlikely(count == 0))
+	if (unlikely(total_len == 0))
 		return 0;
 
 	do_wakeup = 0;
@@ -67,12 +112,12 @@ pipe_read(struct file *filp, char __user
 			char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
 			ssize_t chars = PIPE_MAX_RCHUNK(*inode);
 
-			if (chars > count)
-				chars = count;
+			if (chars > total_len)
+				chars = total_len;
 			if (chars > size)
 				chars = size;
 
-			if (copy_to_user(buf, pipebuf, chars)) {
+			if (pipe_iov_copy_to_user(iov, pipebuf, chars)) {
 				if (!ret) ret = -EFAULT;
 				break;
 			}
@@ -81,12 +126,11 @@ pipe_read(struct file *filp, char __user
 			PIPE_START(*inode) += chars;
 			PIPE_START(*inode) &= (PIPE_SIZE - 1);
 			PIPE_LEN(*inode) -= chars;
-			count -= chars;
-			buf += chars;
+			total_len -= chars;
 			do_wakeup = 1;
+			if (!total_len)
+				break;	/* common path: read succeeded */
 		}
-		if (!count)
-			break;	/* common path: read succeeded */
 		if (PIPE_LEN(*inode)) /* test for cyclic buffers */
 			continue;
 		if (!PIPE_WRITERS(*inode))
@@ -126,24 +170,35 @@ pipe_read(struct file *filp, char __user
 }
 
 static ssize_t
-pipe_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
+pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct iovec iov = { .iov_base = buf, .iov_len = count };
+	return pipe_readv(filp, &iov, 1, ppos);
+}
+
+static ssize_t
+pipe_writev(struct file *filp, const struct iovec *_iov,
+	    unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	ssize_t ret;
 	size_t min;
 	int do_wakeup;
+	struct iovec *iov = (struct iovec *)_iov;
+	size_t total_len;
 
 	/* pwrite is not allowed on pipes. */
 	if (unlikely(ppos != &filp->f_pos))
 		return -ESPIPE;
-	
+
+	total_len = iov_length(iov, nr_segs);
 	/* Null write succeeds. */
-	if (unlikely(count == 0))
+	if (unlikely(total_len == 0))
 		return 0;
 
 	do_wakeup = 0;
 	ret = 0;
-	min = count;
+	min = total_len;
 	if (min > PIPE_BUF)
 		min = 1;
 	down(PIPE_SEM(*inode));
@@ -164,23 +219,22 @@ pipe_write(struct file *filp, const char
 			 * syscall merging.
 			 */
 			do_wakeup = 1;
-			if (chars > count)
-				chars = count;
+			if (chars > total_len)
+				chars = total_len;
 			if (chars > free)
 				chars = free;
 
-			if (copy_from_user(pipebuf, buf, chars)) {
+			if (pipe_iov_copy_from_user(pipebuf, iov, chars)) {
 				if (!ret) ret = -EFAULT;
 				break;
 			}
-
 			ret += chars;
+
 			PIPE_LEN(*inode) += chars;
-			count -= chars;
-			buf += chars;
+			total_len -= chars;
+			if (!total_len)
+				break;
 		}
-		if (!count)
-			break;
 		if (PIPE_FREE(*inode) && ret) {
 			/* handle cyclic data buffers */
 			min = 1;
@@ -214,6 +268,14 @@ pipe_write(struct file *filp, const char
 }
 
 static ssize_t
+pipe_write(struct file *filp, const char __user *buf,
+	   size_t count, loff_t *ppos)
+{
+	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+	return pipe_writev(filp, &iov, 1, ppos);
+}
+
+static ssize_t
 bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
 {
 	return -EBADF;
@@ -405,6 +467,7 @@ pipe_rdwr_open(struct inode *inode, stru
 struct file_operations read_fifo_fops = {
 	.llseek		= no_llseek,
 	.read		= pipe_read,
+	.readv		= pipe_readv,
 	.write		= bad_pipe_w,
 	.poll		= fifo_poll,
 	.ioctl		= pipe_ioctl,
@@ -417,6 +480,7 @@ struct file_operations write_fifo_fops =
 	.llseek		= no_llseek,
 	.read		= bad_pipe_r,
 	.write		= pipe_write,
+	.writev		= pipe_writev,
 	.poll		= fifo_poll,
 	.ioctl		= pipe_ioctl,
 	.open		= pipe_write_open,
@@ -427,7 +491,9 @@ struct file_operations write_fifo_fops =
 struct file_operations rdwr_fifo_fops = {
 	.llseek		= no_llseek,
 	.read		= pipe_read,
+	.readv		= pipe_readv,
 	.write		= pipe_write,
+	.writev		= pipe_writev,
 	.poll		= fifo_poll,
 	.ioctl		= pipe_ioctl,
 	.open		= pipe_rdwr_open,
@@ -438,6 +504,7 @@ struct file_operations rdwr_fifo_fops = 
 struct file_operations read_pipe_fops = {
 	.llseek		= no_llseek,
 	.read		= pipe_read,
+	.readv		= pipe_readv,
 	.write		= bad_pipe_w,
 	.poll		= pipe_poll,
 	.ioctl		= pipe_ioctl,
@@ -450,6 +517,7 @@ struct file_operations write_pipe_fops =
 	.llseek		= no_llseek,
 	.read		= bad_pipe_r,
 	.write		= pipe_write,
+	.writev		= pipe_writev,
 	.poll		= pipe_poll,
 	.ioctl		= pipe_ioctl,
 	.open		= pipe_write_open,
@@ -460,7 +528,9 @@ struct file_operations write_pipe_fops =
 struct file_operations rdwr_pipe_fops = {
 	.llseek		= no_llseek,
 	.read		= pipe_read,
+	.readv		= pipe_readv,
 	.write		= pipe_write,
+	.writev		= pipe_writev,
 	.poll		= pipe_poll,
 	.ioctl		= pipe_ioctl,
 	.open		= pipe_rdwr_open,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/proc/base.c 001-linus.patch/fs/proc/base.c
--- 000-virgin/fs/proc/base.c	Wed Dec 17 18:58:58 2003
+++ 001-linus.patch/fs/proc/base.c	Tue Dec 30 16:38:57 2003
@@ -277,15 +277,50 @@ static int proc_root_link(struct inode *
 	return result;
 }
 
+#define MAY_PTRACE(task) \
+	(task == current || \
+	(task->parent == current && \
+	(task->ptrace & PT_PTRACED) &&  task->state == TASK_STOPPED && \
+	 security_ptrace(current,task) == 0))
+
+static int may_ptrace_attach(struct task_struct *task)
+{
+	int retval = 0;
+
+	task_lock(task);
+
+	if (!task->mm)
+		goto out;
+	if (((current->uid != task->euid) ||
+	     (current->uid != task->suid) ||
+	     (current->uid != task->uid) ||
+	     (current->gid != task->egid) ||
+	     (current->gid != task->sgid) ||
+	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+		goto out;
+	rmb();
+	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+		goto out;
+	if (security_ptrace(current, task))
+		goto out;
+
+	retval = 1;
+out:
+	task_unlock(task);
+	return retval;
+}
+
 static int proc_pid_environ(struct task_struct *task, char * buffer)
 {
 	int res = 0;
 	struct mm_struct *mm = get_task_mm(task);
 	if (mm) {
-		int len = mm->env_end - mm->env_start;
+		unsigned int len = mm->env_end - mm->env_start;
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
+		if (!may_ptrace_attach(task))
+			res = -ESRCH;
 		mmput(mm);
 	}
 	return res;
@@ -294,7 +329,7 @@ static int proc_pid_environ(struct task_
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 {
 	int res = 0;
-	int len;
+	unsigned int len;
 	struct mm_struct *mm = get_task_mm(task);
 	if (!mm)
 		goto out;
@@ -521,10 +556,6 @@ static struct file_operations proc_info_
 	.read		= proc_info_read,
 };
 
-#define MAY_PTRACE(p) \
-(p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ptrace(current,p)==0))
-
-
 static int mem_open(struct inode* inode, struct file* file)
 {
 	file->private_data = (void*)((long)current->self_exec_id);
@@ -540,7 +571,7 @@ static ssize_t mem_read(struct file * fi
 	int ret = -ESRCH;
 	struct mm_struct *mm;
 
-	if (!MAY_PTRACE(task))
+	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
 		goto out;
 
 	ret = -ENOMEM;
@@ -566,7 +597,7 @@ static ssize_t mem_read(struct file * fi
 
 		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
 		retval = access_process_vm(task, src, page, this_len, 0);
-		if (!retval) {
+		if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) {
 			if (!ret)
 				ret = -EIO;
 			break;
@@ -604,7 +635,7 @@ static ssize_t mem_write(struct file * f
 	struct task_struct *task = proc_task(file->f_dentry->d_inode);
 	unsigned long dst = *ppos;
 
-	if (!MAY_PTRACE(task))
+	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
 		return -ESRCH;
 
 	page = (char *)__get_free_page(GFP_USER);
@@ -1524,6 +1555,7 @@ struct dentry *proc_pid_lookup(struct in
 	struct inode *inode;
 	struct proc_inode *ei;
 	unsigned tgid;
+	int died;
 
 	if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
 		inode = new_inode(dir->i_sb);
@@ -1567,12 +1599,21 @@ struct dentry *proc_pid_lookup(struct in
 
 	dentry->d_op = &pid_base_dentry_operations;
 
+	died = 0;
+	d_add(dentry, inode);
 	spin_lock(&task->proc_lock);
 	task->proc_dentry = dentry;
-	d_add(dentry, inode);
+	if (!pid_alive(task)) {
+		dentry = proc_pid_unhash(task);
+		died = 1;
+	}
 	spin_unlock(&task->proc_lock);
 
 	put_task_struct(task);
+	if (died) {
+		proc_pid_flush(dentry);
+		goto out;
+	}
 	return NULL;
 out:
 	return ERR_PTR(-ENOENT);
@@ -1612,10 +1653,7 @@ static struct dentry *proc_task_lookup(s
 
 	dentry->d_op = &pid_base_dentry_operations;
 
-	spin_lock(&task->proc_lock);
-	task->proc_dentry = dentry;
 	d_add(dentry, inode);
-	spin_unlock(&task->proc_lock);
 
 	put_task_struct(task);
 	return NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/proc/generic.c 001-linus.patch/fs/proc/generic.c
--- 000-virgin/fs/proc/generic.c	Wed Dec 17 18:59:57 2003
+++ 001-linus.patch/fs/proc/generic.c	Tue Dec 30 16:38:57 2003
@@ -567,12 +567,12 @@ struct proc_dir_entry *proc_symlink(cons
 	return ent;
 }
 
-struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
+struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
+		struct proc_dir_entry *parent)
 {
 	struct proc_dir_entry *ent;
 
-	ent = proc_create(&parent,name,
-			  (S_IFDIR | S_IRUGO | S_IXUGO),2);
+	ent = proc_create(&parent, name, S_IFDIR | mode, 2);
 	if (ent) {
 		ent->proc_fops = &proc_dir_operations;
 		ent->proc_iops = &proc_dir_inode_operations;
@@ -585,6 +585,12 @@ struct proc_dir_entry *proc_mkdir(const 
 	return ent;
 }
 
+struct proc_dir_entry *proc_mkdir(const char *name,
+		struct proc_dir_entry *parent)
+{
+	return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
+}
+
 struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 					 struct proc_dir_entry *parent)
 {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/proc/proc_misc.c 001-linus.patch/fs/proc/proc_misc.c
--- 000-virgin/fs/proc/proc_misc.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/fs/proc/proc_misc.c	Tue Dec 30 16:38:57 2003
@@ -473,30 +473,46 @@ static int devices_read_proc(char *page,
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-extern int show_interrupts(struct seq_file *p, void *v);
-static int interrupts_open(struct inode *inode, struct file *file)
+/*
+ * /proc/interrupts
+ */
+static void *int_seq_start(struct seq_file *f, loff_t *pos)
 {
-	unsigned size = 4096 * (1 + num_online_cpus() / 8);
-	char *buf = kmalloc(size, GFP_KERNEL);
-	struct seq_file *m;
-	int res;
-
-	if (!buf)
-		return -ENOMEM;
-	res = single_open(file, show_interrupts, NULL);
-	if (!res) {
-		m = file->private_data;
-		m->buf = buf;
-		m->size = size;
-	} else
-		kfree(buf);
-	return res;
+	return (*pos <= NR_IRQS) ? pos : NULL;
 }
+
+static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
+{
+	(*pos)++;
+	if (*pos > NR_IRQS)
+		return NULL;
+	return pos;
+}
+
+static void int_seq_stop(struct seq_file *f, void *v)
+{
+	/* Nothing to do */
+}
+
+
+extern int show_interrupts(struct seq_file *f, void *v); /* In arch code */
+static struct seq_operations int_seq_ops = {
+	.start = int_seq_start,
+	.next  = int_seq_next,
+	.stop  = int_seq_stop,
+	.show  = show_interrupts
+};
+
+int interrupts_open(struct inode *inode, struct file *filp)
+{
+	return seq_open(filp, &int_seq_ops);
+}
+
 static struct file_operations proc_interrupts_operations = {
 	.open		= interrupts_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= seq_release,
 };
 
 static int filesystems_read_proc(char *page, char **start, off_t off,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/proc/proc_tty.c 001-linus.patch/fs/proc/proc_tty.c
--- 000-virgin/fs/proc/proc_tty.c	Wed Dec 17 18:58:41 2003
+++ 001-linus.patch/fs/proc/proc_tty.c	Tue Dec 30 16:38:57 2003
@@ -229,7 +229,13 @@ void __init proc_tty_init(void)
 	if (!proc_mkdir("tty", 0))
 		return;
 	proc_tty_ldisc = proc_mkdir("tty/ldisc", 0);
-	proc_tty_driver = proc_mkdir("tty/driver", 0);
+	/*
+	 * /proc/tty/driver/serial reveals the exact character counts for
+	 * serial links which is just too easy to abuse for inferring
+	 * password lengths and inter-keystroke timings during password
+	 * entry.
+	 */
+	proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, 0);
 
 	create_proc_read_entry("tty/ldiscs", 0, 0, tty_ldiscs_read_proc,NULL);
 	entry = create_proc_entry("tty/drivers", 0, NULL);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/proc/task_mmu.c 001-linus.patch/fs/proc/task_mmu.c
--- 000-virgin/fs/proc/task_mmu.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/fs/proc/task_mmu.c	Tue Dec 30 16:38:57 2003
@@ -105,7 +105,7 @@ static int show_map(struct seq_file *m, 
 		if (len < 1)
 			len = 1;
 		seq_printf(m, "%*c", len, ' ');
-		seq_path(m, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+		seq_path(m, file->f_vfsmnt, file->f_dentry, "");
 	}
 	seq_putc(m, '\n');
 	return 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/stat.c 001-linus.patch/fs/stat.c
--- 000-virgin/fs/stat.c	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/fs/stat.c	Tue Dec 30 16:38:57 2003
@@ -106,7 +106,7 @@ int vfs_fstat(unsigned int fd, struct ks
 EXPORT_SYMBOL(vfs_fstat);
 
 #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \
-  && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
+  && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) \
   && !defined(__arm__) && !defined(CONFIG_V850) && !defined(__powerpc64__)
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/fs/udf/super.c 001-linus.patch/fs/udf/super.c
--- 000-virgin/fs/udf/super.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/fs/udf/super.c	Tue Dec 30 16:38:57 2003
@@ -414,7 +414,7 @@ udf_parse_options(char *options, struct 
 		case Opt_utf8:
 			uopt->flags |= (1 << UDF_FLAG_UTF8);
 			break;
-#ifdef CONFIG_NLS
+#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
 		case Opt_iocharset:
 			uopt->nls_map = load_nls(args[0].from);
 			uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
@@ -1510,7 +1510,7 @@ static int udf_fill_super(struct super_b
 			"utf8 cannot be combined with iocharset\n");
 		goto error_out;
 	}
-#ifdef CONFIG_NLS
+#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
 	if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map)
 	{
 		uopt.nls_map = load_nls_default();
@@ -1674,7 +1674,7 @@ error_out:
 				udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
 		}
 	}
-#ifdef CONFIG_NLS
+#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
 		unload_nls(UDF_SB(sb)->s_nls_map);
 #endif
@@ -1766,7 +1766,7 @@ udf_put_super(struct super_block *sb)
 				udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
 		}
 	}
-#ifdef CONFIG_NLS
+#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
 		unload_nls(UDF_SB(sb)->s_nls_map);
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-alpha/cpumask.h 001-linus.patch/include/asm-alpha/cpumask.h
--- 000-virgin/include/asm-alpha/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-alpha/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_ALPHA_CPUMASK_H
+#define _ASM_ALPHA_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_ALPHA_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/arch-ebsa285/time.h 001-linus.patch/include/asm-arm/arch-ebsa285/time.h
--- 000-virgin/include/asm-arm/arch-ebsa285/time.h	Wed Dec 17 19:00:02 2003
+++ 001-linus.patch/include/asm-arm/arch-ebsa285/time.h	Tue Dec 30 16:38:57 2003
@@ -243,6 +243,7 @@ void __init time_init(void)
 
 		if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
 		    CMOS_READ(RTC_REG_B) == reg_b) {
+			struct timespec tv;
 
 			/*
 			 * We have a RTC.  Check the battery
@@ -250,7 +251,9 @@ void __init time_init(void)
 			if ((reg_d & 0x80) == 0)
 				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
 
-			xtime.tv_sec = get_isa_cmos_time();
+			tv.tv_nsec = 0;
+			tv.tv_sec = get_isa_cmos_time();
+			do_settimeofday(&tv);
 			set_rtc = set_isa_cmos_time;
 		} else
 			rtc_base = 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/arch-pxa/time.h 001-linus.patch/include/asm-arm/arch-pxa/time.h
--- 000-virgin/include/asm-arm/arch-pxa/time.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/asm-arm/arch-pxa/time.h	Tue Dec 30 16:38:57 2003
@@ -33,7 +33,7 @@ static int pxa_set_rtc(void)
 /* IRQs are disabled before entering here from do_gettimeofday() */
 static unsigned long pxa_gettimeoffset (void)
 {
-	unsigned long ticks_to_match, elapsed, usec;
+	long ticks_to_match, elapsed, usec;
 
 	/* Get ticks before next timer match */
 	ticks_to_match = OSMR0 - OSCR;
@@ -41,6 +41,10 @@ static unsigned long pxa_gettimeoffset (
 	/* We need elapsed ticks since last match */
 	elapsed = LATCH - ticks_to_match;
 
+	/* don't get fooled by the workaround in pxa_timer_interrupt() */
+	if (elapsed <= 0)
+		return 0;
+
 	/* Now convert them to usec */
 	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
 
@@ -59,6 +63,15 @@ pxa_timer_interrupt(int irq, void *dev_i
 	 * IRQs are disabled inside the loop to ensure coherence between
 	 * lost_ticks (updated in do_timer()) and the match reg value, so we
 	 * can use do_gettimeofday() from interrupt handlers.
+	 *
+	 * HACK ALERT: it seems that the PXA timer regs aren't updated right
+	 * away in all cases when a write occurs.  We therefore compare with
+	 * 8 instead of 0 in the while() condition below to avoid missing a
+	 * match if OSCR has already reached the next OSMR value.
+	 * Experience has shown that up to 6 ticks are needed to work around
+	 * this problem, but let's use 8 to be conservative.  Note that this
+	 * affect things only when the timer IRQ has been delayed by nearly
+	 * exactly one tick period which should be a pretty rare event.
 	 */
 	do {
 		do_leds();
@@ -66,16 +79,22 @@ pxa_timer_interrupt(int irq, void *dev_i
 		do_timer(regs);
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
 		next_match = (OSMR0 += LATCH);
-	} while( (signed long)(next_match - OSCR) <= 0 );
+	} while( (signed long)(next_match - OSCR) <= 8 );
 
 	return IRQ_HANDLED;
 }
 
 void __init time_init(void)
 {
+	struct timespec tv;
+
 	gettimeoffset = pxa_gettimeoffset;
 	set_rtc = pxa_set_rtc;
-	xtime.tv_sec = pxa_get_rtc_time();
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = pxa_get_rtc_time();
+	do_settimeofday(&tv);
+
 	timer_irq.handler = pxa_timer_interrupt;
 	OSMR0 = 0;		/* set initial match at 0 */
 	OSSR = 0xf;		/* clear status on all timers */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/arch-sa1100/time.h 001-linus.patch/include/asm-arm/arch-sa1100/time.h
--- 000-virgin/include/asm-arm/arch-sa1100/time.h	Wed Dec 17 19:00:00 2003
+++ 001-linus.patch/include/asm-arm/arch-sa1100/time.h	Tue Dec 30 16:38:57 2003
@@ -92,9 +92,15 @@ sa1100_timer_interrupt(int irq, void *de
 
 void __init time_init(void)
 {
+	struct timespec tv;
+
 	gettimeoffset = sa1100_gettimeoffset;
 	set_rtc = sa1100_set_rtc;
-	xtime.tv_sec = sa1100_get_rtc_time();
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = sa1100_get_rtc_time();
+	do_settimeofday(&tv);
+
 	timer_irq.handler = sa1100_timer_interrupt;
 	OSMR0 = 0;		/* set initial match at 0 */
 	OSSR = 0xf;		/* clear status on all timers */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/arch-shark/time.h 001-linus.patch/include/asm-arm/arch-shark/time.h
--- 000-virgin/include/asm-arm/arch-shark/time.h	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/include/asm-arm/arch-shark/time.h	Tue Dec 30 16:38:57 2003
@@ -34,8 +34,6 @@ void __init time_init(void)
 	outb(HZ_TIME & 0xff, 0x40);     /* LSB of count */
 	outb(HZ_TIME >> 8, 0x40);
 
-	xtime.tv_sec = 0;
-
 	timer_irq.handler = timer_interrupt;
 	setup_irq(IRQ_TIMER, &timer_irq);
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/cpumask.h 001-linus.patch/include/asm-arm/cpumask.h
--- 000-virgin/include/asm-arm/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-arm/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_ARM_CPUMASK_H
+#define _ASM_ARM_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_ARM_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/div64.h 001-linus.patch/include/asm-arm/div64.h
--- 000-virgin/include/asm-arm/div64.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/asm-arm/div64.h	Tue Dec 30 16:38:57 2003
@@ -1,18 +1,42 @@
 #ifndef __ASM_ARM_DIV64
 #define __ASM_ARM_DIV64
 
-/* We're not 64-bit, but... */
+/*
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * 	uint32_t remainder = *n % base;
+ * 	*n = *n / base;
+ * 	return remainder;
+ * }
+ *
+ * In other words, a 64-bit dividend with a 32-bit divisor producing
+ * a 64-bit result and a 32-bit remainder.  To accomplish this optimally
+ * we call a special __do_div64 helper with completely non standard
+ * calling convention for arguments and results (beware).
+ */
+
+#ifdef __ARMEB__
+#define __xh "r0"
+#define __xl "r1"
+#else
+#define __xl "r0"
+#define __xh "r1"
+#endif
+
 #define do_div(n,base)						\
 ({								\
-	register int __res asm("r2") = base;			\
-	register unsigned long long __n asm("r0") = n;		\
-	asm("bl do_div64"					\
-		: "=r" (__n), "=r" (__res)			\
-		: "0" (__n), "1" (__res)			\
-		: "r3", "ip", "lr", "cc");			\
-	n = __n;						\
-	__res;							\
+	register unsigned int __base      asm("r4") = base;	\
+	register unsigned long long __n   asm("r0") = n;	\
+	register unsigned long long __res asm("r2");		\
+	register unsigned int __rem       asm(__xh);		\
+	asm("bl	__do_div64"					\
+		: "=r" (__rem), "=r" (__res)			\
+		: "r" (__n), "r" (__base)			\
+		: "ip", "lr", "cc");				\
+	n = __res;						\
+	__rem;							\
 })
 
 #endif
-
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/kmap_types.h 001-linus.patch/include/asm-arm/kmap_types.h
--- 000-virgin/include/asm-arm/kmap_types.h	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/include/asm-arm/kmap_types.h	Tue Dec 30 16:38:57 2003
@@ -5,8 +5,21 @@
  * This is the "bare minimum".  AIO seems to require this.
  */
 enum km_type {
+	KM_BOUNCE_READ,
+	KM_SKB_SUNRPC_DATA,
+	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
+	KM_BIO_SRC_IRQ,
+	KM_BIO_DST_IRQ,
+	KM_PTE0,
+	KM_PTE1,
+	KM_PTE2,
 	KM_IRQ0,
-	KM_USER1
+	KM_IRQ1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	KM_TYPE_NR
 };
 
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/unaligned.h 001-linus.patch/include/asm-arm/unaligned.h
--- 000-virgin/include/asm-arm/unaligned.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/include/asm-arm/unaligned.h	Tue Dec 30 16:38:57 2003
@@ -159,7 +159,7 @@ static inline void __put_unaligned_8_be(
 		(void) 0;					\
 	})
 
-#define put_unaligned_be(val,ptr)					\
+#define __put_unaligned_be(val,ptr)					\
 	({							\
 		switch (sizeof(*(ptr))) {			\
 		case 1:						\
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm/unistd.h 001-linus.patch/include/asm-arm/unistd.h
--- 000-virgin/include/asm-arm/unistd.h	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/include/asm-arm/unistd.h	Tue Dec 30 16:38:57 2003
@@ -282,6 +282,20 @@
 					/* 254 for set_thread_area */
 					/* 255 for get_thread_area */
 					/* 256 for set_tid_address */
+#define __NR_timer_create		(__NR_SYSCALL_BASE+257)
+#define __NR_timer_settime		(__NR_SYSCALL_BASE+258)
+#define __NR_timer_gettime		(__NR_SYSCALL_BASE+259)
+#define __NR_timer_getoverrun		(__NR_SYSCALL_BASE+260)
+#define __NR_timer_delete		(__NR_SYSCALL_BASE+261)
+#define __NR_clock_settime		(__NR_SYSCALL_BASE+262)
+#define __NR_clock_gettime		(__NR_SYSCALL_BASE+263)
+#define __NR_clock_getres		(__NR_SYSCALL_BASE+264)
+#define __NR_clock_nanosleep		(__NR_SYSCALL_BASE+265)
+#define __NR_statfs64			(__NR_SYSCALL_BASE+266)
+#define __NR_fstatfs64			(__NR_SYSCALL_BASE+267)
+#define __NR_tgkill			(__NR_SYSCALL_BASE+268)
+#define __NR_utimes			(__NR_SYSCALL_BASE+269)
+#define __NR_fadvise64_64		(__NR_SYSCALL_BASE+270)
 
 /*
  * The following SWIs are ARM private.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-arm26/cpumask.h 001-linus.patch/include/asm-arm26/cpumask.h
--- 000-virgin/include/asm-arm26/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-arm26/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_ARM26_CPUMASK_H
+#define _ASM_ARM26_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_ARM26_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-cris/cpumask.h 001-linus.patch/include/asm-cris/cpumask.h
--- 000-virgin/include/asm-cris/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-cris/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_CRIS_CPUMASK_H
+#define _ASM_CRIS_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_CRIS_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/cpumask.h 001-linus.patch/include/asm-generic/cpumask.h
--- 000-virgin/include/asm-generic/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-generic/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,40 @@
+#ifndef __ASM_GENERIC_CPUMASK_H
+#define __ASM_GENERIC_CPUMASK_H
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/types.h>
+#include <linux/bitmap.h>
+
+#if NR_CPUS > BITS_PER_LONG && NR_CPUS != 1
+#define CPU_ARRAY_SIZE		BITS_TO_LONGS(NR_CPUS)
+
+struct cpumask
+{
+	unsigned long mask[CPU_ARRAY_SIZE];
+};
+
+typedef struct cpumask cpumask_t;
+
+#else
+typedef unsigned long cpumask_t;
+#endif
+
+#ifdef CONFIG_SMP
+#if NR_CPUS > BITS_PER_LONG
+#include <asm-generic/cpumask_array.h>
+#else
+#include <asm-generic/cpumask_arith.h>
+#endif
+#else
+#include <asm-generic/cpumask_up.h>
+#endif
+
+#if NR_CPUS <= 4*BITS_PER_LONG
+#include <asm-generic/cpumask_const_value.h>
+#else
+#include <asm-generic/cpumask_const_reference.h>
+#endif
+
+#endif /* __ASM_GENERIC_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/cpumask_arith.h 001-linus.patch/include/asm-generic/cpumask_arith.h
--- 000-virgin/include/asm-generic/cpumask_arith.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-generic/cpumask_arith.h	Tue Dec 30 16:38:57 2003
@@ -17,6 +17,7 @@
 #define cpus_complement(map)		do { map = ~(map); } while (0)
 #define cpus_equal(map1, map2)		((map1) == (map2))
 #define cpus_empty(map)			((map) == 0)
+#define cpus_addr(map)			(&(map))
 
 #if BITS_PER_LONG == 32
 #define cpus_weight(map)		hweight32(map)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/cpumask_array.h 001-linus.patch/include/asm-generic/cpumask_array.h
--- 000-virgin/include/asm-generic/cpumask_array.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/include/asm-generic/cpumask_array.h	Tue Dec 30 16:38:57 2003
@@ -20,6 +20,7 @@
 #define cpus_complement(map)	bitmap_complement((map).mask, NR_CPUS)
 #define cpus_equal(map1, map2)	bitmap_equal((map1).mask, (map2).mask, NR_CPUS)
 #define cpus_empty(map)		bitmap_empty(map.mask, NR_CPUS)
+#define cpus_addr(map)		((map).mask)
 #define cpus_weight(map)		bitmap_weight((map).mask, NR_CPUS)
 #define cpus_shift_right(d, s, n)	bitmap_shift_right((d).mask, (s).mask, n, NR_CPUS)
 #define cpus_shift_left(d, s, n)	bitmap_shift_left((d).mask, (s).mask, n, NR_CPUS)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/cpumask_const_value.h 001-linus.patch/include/asm-generic/cpumask_const_value.h
--- 000-virgin/include/asm-generic/cpumask_const_value.h	Wed Dec 17 18:57:59 2003
+++ 001-linus.patch/include/asm-generic/cpumask_const_value.h	Tue Dec 30 16:38:57 2003
@@ -3,7 +3,7 @@
 
 typedef const cpumask_t cpumask_const_t;
 
-#define mk_cpumask_const(map)		((cpumask_const_t)(map))
+#define mk_cpumask_const(map)		(map)
 #define cpu_isset_const(cpu, map)	cpu_isset(cpu, map)
 #define cpus_and_const(dst,src1,src2)	cpus_and(dst, src1, src2)
 #define cpus_or_const(dst,src1,src2)	cpus_or(dst, src1, src2)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/cpumask_up.h 001-linus.patch/include/asm-generic/cpumask_up.h
--- 000-virgin/include/asm-generic/cpumask_up.h	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/include/asm-generic/cpumask_up.h	Tue Dec 30 16:38:57 2003
@@ -33,6 +33,7 @@
 
 #define cpus_equal(map1, map2)		(cpus_coerce(map1) == cpus_coerce(map2))
 #define cpus_empty(map)			(cpus_coerce(map) == 0UL)
+#define cpus_addr(map)			(&(map))
 #define cpus_weight(map)		(cpus_coerce(map) ? 1UL : 0UL)
 #define cpus_shift_right(d, s, n)	do { cpus_coerce(d) = 0UL; } while (0)
 #define cpus_shift_left(d, s, n)	do { cpus_coerce(d) = 0UL; } while (0)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-generic/statfs.h 001-linus.patch/include/asm-generic/statfs.h
--- 000-virgin/include/asm-generic/statfs.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/include/asm-generic/statfs.h	Tue Dec 30 16:38:57 2003
@@ -34,4 +34,18 @@ struct statfs64 {
 	__u32 f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-h8300/cpumask.h 001-linus.patch/include/asm-h8300/cpumask.h
--- 000-virgin/include/asm-h8300/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-h8300/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_H8300_CPUMASK_H
+#define _ASM_H8300_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_H8300_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/cpumask.h 001-linus.patch/include/asm-i386/cpumask.h
--- 000-virgin/include/asm-i386/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-i386/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_I386_CPUMASK_H
+#define _ASM_I386_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_I386_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/hw_irq.h 001-linus.patch/include/asm-i386/hw_irq.h
--- 000-virgin/include/asm-i386/hw_irq.h	Wed Dec 17 18:59:55 2003
+++ 001-linus.patch/include/asm-i386/hw_irq.h	Tue Dec 30 16:38:57 2003
@@ -41,6 +41,7 @@ asmlinkage void apic_timer_interrupt(voi
 asmlinkage void error_interrupt(void);
 asmlinkage void spurious_interrupt(void);
 asmlinkage void thermal_interrupt(struct pt_regs);
+#define platform_legacy_irq(irq)	((irq) < 16)
 #endif
 
 void mask_irq(unsigned int irq);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/io_apic.h 001-linus.patch/include/asm-i386/io_apic.h
--- 000-virgin/include/asm-i386/io_apic.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-i386/io_apic.h	Tue Dec 30 16:38:57 2003
@@ -13,6 +13,46 @@
 
 #ifdef CONFIG_X86_IO_APIC
 
+#ifdef CONFIG_PCI_USE_VECTOR
+static inline int use_pci_vector(void)	{return 1;}
+static inline void disable_edge_ioapic_vector(unsigned int vector) { }
+static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
+static inline void end_edge_ioapic_vector (unsigned int vector) { }
+#define startup_level_ioapic	startup_level_ioapic_vector
+#define shutdown_level_ioapic	mask_IO_APIC_vector
+#define enable_level_ioapic	unmask_IO_APIC_vector
+#define disable_level_ioapic	mask_IO_APIC_vector
+#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector
+#define end_level_ioapic	end_level_ioapic_vector
+#define set_ioapic_affinity	set_ioapic_affinity_vector
+
+#define startup_edge_ioapic 	startup_edge_ioapic_vector
+#define shutdown_edge_ioapic 	disable_edge_ioapic_vector
+#define enable_edge_ioapic 	unmask_IO_APIC_vector
+#define disable_edge_ioapic 	disable_edge_ioapic_vector
+#define ack_edge_ioapic 	ack_edge_ioapic_vector
+#define end_edge_ioapic 	end_edge_ioapic_vector
+#else
+static inline int use_pci_vector(void)	{return 0;}
+static inline void disable_edge_ioapic_irq(unsigned int irq) { }
+static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
+static inline void end_edge_ioapic_irq (unsigned int irq) { }
+#define startup_level_ioapic	startup_level_ioapic_irq
+#define shutdown_level_ioapic	mask_IO_APIC_irq
+#define enable_level_ioapic	unmask_IO_APIC_irq
+#define disable_level_ioapic	mask_IO_APIC_irq
+#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
+#define end_level_ioapic	end_level_ioapic_irq
+#define set_ioapic_affinity	set_ioapic_affinity_irq
+
+#define startup_edge_ioapic 	startup_edge_ioapic_irq
+#define shutdown_edge_ioapic 	disable_edge_ioapic_irq
+#define enable_edge_ioapic 	unmask_IO_APIC_irq
+#define disable_edge_ioapic 	disable_edge_ioapic_irq
+#define ack_edge_ioapic 	ack_edge_ioapic_irq
+#define end_edge_ioapic 	end_edge_ioapic_irq
+#endif
+
 #define APIC_MISMATCH_DEBUG
 
 #define IO_APIC_BASE(idx) \
@@ -177,4 +217,6 @@ extern int io_apic_set_pci_routing (int 
 #define io_apic_assign_pci_irqs 0
 #endif
 
+extern int assign_irq_vector(int irq);
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/ioctl.h 001-linus.patch/include/asm-i386/ioctl.h
--- 000-virgin/include/asm-i386/ioctl.h	Wed Dec 17 18:58:07 2003
+++ 001-linus.patch/include/asm-i386/ioctl.h	Tue Dec 30 16:38:57 2003
@@ -53,7 +53,7 @@
 	 ((size) << _IOC_SIZESHIFT))
 
 /* provoke compile error for invalid uses of size argument */
-extern int __invalid_size_argument_for_IOC;
+extern unsigned int __invalid_size_argument_for_IOC;
 #define _IOC_TYPECHECK(t) \
 	((sizeof(t) == sizeof(t[1]) && \
 	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/irq.h 001-linus.patch/include/asm-i386/irq.h
--- 000-virgin/include/asm-i386/irq.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-i386/irq.h	Tue Dec 30 16:38:57 2003
@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
 extern void release_x86_irqs(struct task_struct *);
+extern int can_request_irq(unsigned int, unsigned long flags);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #define ARCH_HAS_NMI_WATCHDOG		/* See include/linux/nmi.h */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/mach-default/irq_vectors.h 001-linus.patch/include/asm-i386/mach-default/irq_vectors.h
--- 000-virgin/include/asm-i386/mach-default/irq_vectors.h	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/include/asm-i386/mach-default/irq_vectors.h	Tue Dec 30 16:38:57 2003
@@ -76,6 +76,18 @@
  * Since vectors 0x00-0x1f are used/reserved for the CPU,
  * the usable vector space is 0x20-0xff (224 vectors)
  */
+
+/*
+ * The maximum number of vectors supported by i386 processors
+ * is limited to 256. For processors other than i386, NR_VECTORS
+ * should be changed accordingly.
+ */
+#define NR_VECTORS 256
+
+#ifdef CONFIG_PCI_USE_VECTOR
+#define NR_IRQS FIRST_SYSTEM_VECTOR
+#define NR_IRQ_VECTORS NR_IRQS
+#else
 #ifdef CONFIG_X86_IO_APIC
 #define NR_IRQS 224
 # if (224 >= 32 * NR_CPUS)
@@ -87,6 +99,7 @@
 #define NR_IRQS 16
 #define NR_IRQ_VECTORS NR_IRQS
 #endif
+#endif
 
 #define FPU_IRQ			13
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/mach-default/mach_apic.h 001-linus.patch/include/asm-i386/mach-default/mach_apic.h
--- 000-virgin/include/asm-i386/mach-default/mach_apic.h	Wed Dec 17 18:59:59 2003
+++ 001-linus.patch/include/asm-i386/mach-default/mach_apic.h	Tue Dec 30 16:38:57 2003
@@ -5,12 +5,12 @@
 
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
-static inline cpumask_t target_cpus(void)
+static inline cpumask_const_t target_cpus(void)
 { 
 #ifdef CONFIG_SMP
-	return cpu_online_map;
+	return mk_cpumask_const(cpu_online_map);
 #else
-	return cpumask_of_cpu(0);
+	return mk_cpumask_const(cpumask_of_cpu(0));
 #endif
 } 
 #define TARGET_CPUS (target_cpus())
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/processor.h 001-linus.patch/include/asm-i386/processor.h
--- 000-virgin/include/asm-i386/processor.h	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/include/asm-i386/processor.h	Tue Dec 30 16:38:57 2003
@@ -407,6 +407,7 @@ struct thread_struct {
 /* cached TLS descriptors. */
 	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
 	unsigned long	esp0;
+	unsigned long	sysenter_cs;
 	unsigned long	eip;
 	unsigned long	esp;
 	unsigned long	fs;
@@ -428,6 +429,7 @@ struct thread_struct {
 
 #define INIT_THREAD  {							\
 	.vm86_info = NULL,						\
+	.sysenter_cs = __KERNEL_CS,					\
 	.io_bitmap_ptr = NULL,						\
 }
 
@@ -447,21 +449,13 @@ struct thread_struct {
 	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
 }
 
-static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
+static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
 {
-	tss->esp0 = esp0;
+	tss->esp0 = thread->esp0;
 	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
-	if ((unlikely(tss->ss1 != __KERNEL_CS))) {
-		tss->ss1 = __KERNEL_CS;
-		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-	}
-}
-
-static inline void disable_sysenter(struct tss_struct *tss)
-{
-	if (cpu_has_sep)  {
-		tss->ss1 = 0;
-		wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+		tss->ss1 = thread->sysenter_cs;
+		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/setup.h 001-linus.patch/include/asm-i386/setup.h
--- 000-virgin/include/asm-i386/setup.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-i386/setup.h	Tue Dec 30 16:38:57 2003
@@ -29,6 +29,11 @@
 #define IST_INFO   (*(struct ist_info *) (PARAM+0x60))
 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
+#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
+#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
+#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
+#define EFI_MEMMAP ((efi_memory_desc_t *) *((unsigned long *)(PARAM+0x1d0)))
+#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
 #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
 #define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/string.h 001-linus.patch/include/asm-i386/string.h
--- 000-virgin/include/asm-i386/string.h	Wed Dec 17 18:59:58 2003
+++ 001-linus.patch/include/asm-i386/string.h	Tue Dec 30 16:38:57 2003
@@ -291,7 +291,7 @@ extern void __struct_cpy_bug (void);
 #define struct_cpy(x,y) 			\
 ({						\
 	if (sizeof(*(x)) != sizeof(*(y))) 	\
-		__struct_cpy_bug;		\
+		__struct_cpy_bug();		\
 	memcpy(x, y, sizeof(*(x)));		\
 })
 
@@ -299,14 +299,9 @@ extern void __struct_cpy_bug (void);
 static inline void * memmove(void * dest,const void * src, size_t n)
 {
 int d0, d1, d2;
-if (dest<src)
-__asm__ __volatile__(
-	"rep\n\t"
-	"movsb"
-	: "=&c" (d0), "=&S" (d1), "=&D" (d2)
-	:"0" (n),"1" (src),"2" (dest)
-	: "memory");
-else
+if (dest<src) {
+	memcpy(dest,src,n);
+} else
 __asm__ __volatile__(
 	"std\n\t"
 	"rep\n\t"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-i386/timer.h 001-linus.patch/include/asm-i386/timer.h
--- 000-virgin/include/asm-i386/timer.h	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/include/asm-i386/timer.h	Tue Dec 30 16:38:57 2003
@@ -11,6 +11,7 @@
  *	last timer intruupt.
  */
 struct timer_opts{
+	char* name;
 	int (*init)(char *override);
 	void (*mark_offset)(void);
 	unsigned long (*get_offset)(void);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/acpi.h 001-linus.patch/include/asm-ia64/acpi.h
--- 000-virgin/include/asm-ia64/acpi.h	Wed Dec 17 18:59:30 2003
+++ 001-linus.patch/include/asm-ia64/acpi.h	Tue Dec 30 16:38:57 2003
@@ -88,11 +88,8 @@ ia64_acpi_release_global_lock (unsigned 
 
 const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
-int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
-int acpi_get_interrupt_model (int *type);
 int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger);
 int acpi_irq_to_vector (u32 irq);
-int acpi_get_addr_space (void *obj, u8 type, u64 *base, u64 *length,u64 *tra);
 
 #ifdef CONFIG_ACPI_NUMA
 #include <asm/numa.h>
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/cpumask.h 001-linus.patch/include/asm-ia64/cpumask.h
--- 000-virgin/include/asm-ia64/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-ia64/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_CPUMASK_H
+#define _ASM_IA64_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_IA64_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/intrinsics.h 001-linus.patch/include/asm-ia64/intrinsics.h
--- 000-virgin/include/asm-ia64/intrinsics.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/include/asm-ia64/intrinsics.h	Tue Dec 30 16:38:57 2003
@@ -167,7 +167,7 @@ extern long ia64_cmpxchg_called_with_bad
 	if (_cmpxchg_bugcheck_count-- <= 0) {					\
 		void *ip;							\
 		extern int printk(const char *fmt, ...);			\
-		ip = ia64_getreg(_IA64_REG_IP);					\
+		ip = (void *) ia64_getreg(_IA64_REG_IP);			\
 		printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));	\
 		break;								\
 	}									\
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/mca.h 001-linus.patch/include/asm-ia64/mca.h
--- 000-virgin/include/asm-ia64/mca.h	Wed Dec 17 18:58:18 2003
+++ 001-linus.patch/include/asm-ia64/mca.h	Tue Dec 30 16:38:57 2003
@@ -18,6 +18,7 @@
 #include <asm/param.h>
 #include <asm/sal.h>
 #include <asm/processor.h>
+#include <asm/mca_asm.h>
 
 /* These are the return codes from all the IA64_MCA specific interfaces */
 typedef	int ia64_mca_return_code_t;
@@ -61,6 +62,17 @@ enum {
 	IA64_MCA_RENDEZ_CHECKIN_DONE	=	0x1
 };
 
+/* the following data structure is used for TLB error recovery purposes */
+extern struct ia64_mca_tlb_info {
+	u64	cr_lid;
+	u64	percpu_paddr;
+	u64	ptce_base;
+	u32	ptce_count[2];
+	u32	ptce_stride[2];
+	u64	pal_paddr;
+	u64	pal_base;
+} ia64_mca_tlb_list[NR_CPUS];
+
 /* Information maintained by the MC infrastructure */
 typedef struct ia64_mc_info_s {
 	u64		imi_mca_handler;
@@ -141,7 +153,6 @@ extern irqreturn_t ia64_mca_cpe_int_call
 extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_mca_check_errors(void);
-extern u64  ia64_log_get(int, prfunc_t);
 
 #define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/mmu_context.h 001-linus.patch/include/asm-ia64/mmu_context.h
--- 000-virgin/include/asm-ia64/mmu_context.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/include/asm-ia64/mmu_context.h	Tue Dec 30 16:38:57 2003
@@ -95,12 +95,13 @@ delayed_tlb_flush (void)
 static inline mm_context_t
 get_mmu_context (struct mm_struct *mm)
 {
+	unsigned long flags;
 	mm_context_t context = mm->context;
 
 	if (context)
 		return context;
 
-	spin_lock(&ia64_ctx.lock);
+	spin_lock_irqsave(&ia64_ctx.lock, flags);
 	{
 		/* re-check, now that we've got the lock: */
 		context = mm->context;
@@ -110,7 +111,7 @@ get_mmu_context (struct mm_struct *mm)
 			mm->context = context = ia64_ctx.next++;
 		}
 	}
-	spin_unlock(&ia64_ctx.lock);
+	spin_unlock_irqrestore(&ia64_ctx.lock, flags);
 	return context;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/numa.h 001-linus.patch/include/asm-ia64/numa.h
--- 000-virgin/include/asm-ia64/numa.h	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/include/asm-ia64/numa.h	Tue Dec 30 16:38:57 2003
@@ -24,7 +24,7 @@
 
 #include <asm/mmzone.h>
 
-extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+extern volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
 extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
 
 /* Stuff below this line could be architecture independent */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/numnodes.h 001-linus.patch/include/asm-ia64/numnodes.h
--- 000-virgin/include/asm-ia64/numnodes.h	Wed Dec 17 19:00:00 2003
+++ 001-linus.patch/include/asm-ia64/numnodes.h	Tue Dec 30 16:38:57 2003
@@ -5,8 +5,8 @@
 /* Max 8 Nodes */
 #define NODES_SHIFT	3
 #elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
-/* Max 128 Nodes */
-#define NODES_SHIFT	7
+/* Max 256 Nodes */
+#define NODES_SHIFT	8
 #endif
 
 #endif /* _ASM_MAX_NUMNODES_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/page.h 001-linus.patch/include/asm-ia64/page.h
--- 000-virgin/include/asm-ia64/page.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/include/asm-ia64/page.h	Tue Dec 30 16:38:57 2003
@@ -63,7 +63,7 @@
 # define HPAGE_SIZE	(__IA64_UL_CONST(1) << HPAGE_SHIFT)
 # define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-# define ARCH_HAS_VALID_HUGEPAGE_RANGE
+# define ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #ifdef __ASSEMBLY__
@@ -137,7 +137,9 @@ typedef union ia64_va {
 # define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
 				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
 # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
-extern int  check_valid_hugepage_range(unsigned long addr, unsigned long len);
+# define is_hugepage_only_range(addr, len)		\
+	 (REGION_NUMBER(addr) == REGION_HPAGE &&	\
+	  REGION_NUMBER((addr)+(len)) == REGION_HPAGE)
 #endif
 
 static __inline__ int
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/pal.h 001-linus.patch/include/asm-ia64/pal.h
--- 000-virgin/include/asm-ia64/pal.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-ia64/pal.h	Tue Dec 30 16:38:57 2003
@@ -461,23 +461,13 @@ typedef struct pal_process_state_info_s 
 } pal_processor_state_info_t;
 
 typedef struct pal_cache_check_info_s {
-	u64		reserved1	: 16,
-			way		: 5,	/* Way in which the
-						 * error occurred
-						 */
-			reserved2	: 1,
-			mc		: 1,	/* Machine check corrected */
-			tv		: 1,	/* Target address
-						 * structure is valid
-						 */
-
-			wv		: 1,	/* Way field valid */
-			op		: 3,	/* Type of cache
+	u64		op		: 4,	/* Type of cache
 						 * operation that
 						 * caused the machine
 						 * check.
 						 */
-
+			level		: 2,	/* Cache level */
+			reserved1	: 2,
 			dl		: 1,	/* Failure in data part
 						 * of cache line
 						 */
@@ -486,11 +476,34 @@ typedef struct pal_cache_check_info_s {
 						 */
 			dc		: 1,	/* Failure in dcache */
 			ic		: 1,	/* Failure in icache */
-			index		: 24,	/* Cache line index */
-			mv		: 1,	/* mesi valid */
 			mesi		: 3,	/* Cache line state */
-			level		: 4;	/* Cache level */
+			mv		: 1,	/* mesi valid */
+			way		: 5,	/* Way in which the
+						 * error occurred
+						 */
+			wiv		: 1,	/* Way field valid */
+			reserved2	: 10,
+
+			index		: 20,	/* Cache line index */
+			reserved3	: 2,
 
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_cache_check_info_t;
 
 typedef struct pal_tlb_check_info_s {
@@ -498,18 +511,38 @@ typedef struct pal_tlb_check_info_s {
 	u64		tr_slot		: 8,	/* Slot# of TR where
 						 * error occurred
 						 */
-			reserved2	: 8,
+			trv		: 1,	/* tr_slot field is valid */
+			reserved1	: 1,
+			level		: 2,	/* TLB level where failure occurred */
+			reserved2	: 4,
 			dtr		: 1,	/* Fail in data TR */
 			itr		: 1,	/* Fail in inst TR */
 			dtc		: 1,	/* Fail in data TC */
 			itc		: 1,	/* Fail in inst. TC */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 43;
+			op		: 4,	/* Cache operation */
+			reserved3	: 30,
 
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_tlb_check_info_t;
 
 typedef struct pal_bus_check_info_s {
-	u64		size		: 5,	/* Xaction size*/
+	u64		size		: 5,	/* Xaction size */
 			ib		: 1,	/* Internal bus error */
 			eb		: 1,	/* External bus error */
 			cc		: 1,	/* Error occurred
@@ -518,22 +551,99 @@ typedef struct pal_bus_check_info_s {
 						 */
 			type		: 8,	/* Bus xaction type*/
 			sev		: 5,	/* Bus error severity*/
-			tv		: 1,	/* Targ addr valid */
-			rp		: 1,	/* Resp addr valid */
-			rq		: 1,	/* Req addr valid */
+			hier		: 2,	/* Bus hierarchy level */
+			reserved1	: 1,
 			bsi		: 8,	/* Bus error status
 						 * info
 						 */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 31;
+			reserved2	: 22,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_bus_check_info_t;
 
+typedef struct pal_reg_file_check_info_s {
+	u64		id		: 4,	/* Register file identifier */
+			op		: 4,	/* Type of register
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			reg_num		: 7,	/* Register number */
+			rnv		: 1,	/* reg_num valid */
+			reserved2	: 38,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			reserved3	: 3,
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_reg_file_check_info_t;
+
+typedef struct pal_uarch_check_info_s {
+	u64		sid		: 5,	/* Structure identification */
+			level		: 3,	/* Level of failure */
+			array_id	: 4,	/* Array identification */
+			op		: 4,	/* Type of
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			way		: 6,	/* Way of structure */
+			wv		: 1,	/* way valid */
+			xv		: 1,	/* index valid */
+			reserved1	: 8,
+			index		: 8,	/* Index or set of the uarch
+						 * structure that failed.
+						 */
+			reserved2	: 24,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_uarch_check_info_t;
+
 typedef union pal_mc_error_info_u {
 	u64				pmei_data;
 	pal_processor_state_info_t	pme_processor;
 	pal_cache_check_info_t		pme_cache;
 	pal_tlb_check_info_t		pme_tlb;
 	pal_bus_check_info_t		pme_bus;
+	pal_reg_file_check_info_t	pme_reg_file;
+	pal_uarch_check_info_t		pme_uarch;
 } pal_mc_error_info_t;
 
 #define pmci_proc_unknown_check			pme_processor.uc
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/pgtable.h 001-linus.patch/include/asm-ia64/pgtable.h
--- 000-virgin/include/asm-ia64/pgtable.h	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/include/asm-ia64/pgtable.h	Tue Dec 30 16:38:57 2003
@@ -230,6 +230,10 @@ ia64_phys_addr_valid (unsigned long addr
 
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
+/* This takes a physical page address that is used by the remapping functions */
+#define mk_pte_phys(physpage, pgprot) \
+({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
+
 #define pte_modify(_pte, newprot) \
 	(__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK)))
 
@@ -455,6 +459,15 @@ extern struct page *zero_page_memmap_ptr
 /* We provide our own get_unmapped_area to cope with VA holes for userland */
 #define HAVE_ARCH_UNMAPPED_AREA
 
+#ifdef CONFIG_HUGETLB_PAGE
+#define HUGETLB_PGDIR_SHIFT	(HPAGE_SHIFT + 2*(PAGE_SHIFT-3))
+#define HUGETLB_PGDIR_SIZE	(__IA64_UL(1) << HUGETLB_PGDIR_SHIFT)
+#define HUGETLB_PGDIR_MASK	(~(HUGETLB_PGDIR_SIZE-1))
+struct mmu_gather;
+extern void hugetlb_free_pgtables(struct mmu_gather *tlb,
+	struct vm_area_struct * prev, unsigned long start, unsigned long end);
+#endif
+
 typedef pte_t *pte_addr_t;
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/sal.h 001-linus.patch/include/asm-ia64/sal.h
--- 000-virgin/include/asm-ia64/sal.h	Wed Dec 17 18:59:42 2003
+++ 001-linus.patch/include/asm-ia64/sal.h	Tue Dec 30 16:38:57 2003
@@ -71,7 +71,9 @@ extern spinlock_t sal_lock;
 # define SAL_CALL_REENTRANT(result,args...) do {	\
 	struct ia64_fpreg __ia64_scs_fr[6];		\
 	ia64_save_scratch_fpregs(__ia64_scs_fr);	\
+	preempt_disable();				\
 	__SAL_CALL(result, args);			\
+	preempt_enable();				\
 	ia64_load_scratch_fpregs(__ia64_scs_fr);	\
 } while (0)
 
@@ -725,14 +727,16 @@ ia64_sal_mc_rendez (void)
  * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
  * the machine check rendezvous sequence as well as the mechanism to wake up the
  * non-monarch processor at the end of machine check processing.
+ * Returns the complete ia64_sal_retval because some calls return more than just a status
+ * value.
  */
-static inline s64
+static inline struct ia64_sal_retval
 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always)
 {
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val,
 		 timeout, rz_always, 0, 0);
-	return isrv.status;
+	return isrv;
 }
 
 /* Read from PCI configuration space */
@@ -804,10 +808,12 @@ ia64_sal_update_pal (u64 param_buf, u64 
 
 extern unsigned long sal_platform_features;
 
+extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
+
 struct sal_ret_values {
 	long r8; long r9; long r10; long r11;
 };
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* _ASM_IA64_PAL_H */
+#endif /* _ASM_IA64_SAL_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/spinlock.h 001-linus.patch/include/asm-ia64/spinlock.h
--- 000-virgin/include/asm-ia64/spinlock.h	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/include/asm-ia64/spinlock.h	Tue Dec 30 16:38:57 2003
@@ -39,7 +39,7 @@ _raw_spin_lock (spinlock_t *lock)
 {
 	register volatile unsigned int *ptr asm ("r31") = &lock->lock;
 
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 # ifdef CONFIG_ITANIUM
 	/* don't use brl on Itanium... */
 	asm volatile ("{\n\t"
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/statfs.h 001-linus.patch/include/asm-ia64/statfs.h
--- 000-virgin/include/asm-ia64/statfs.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/include/asm-ia64/statfs.h	Tue Dec 30 16:38:57 2003
@@ -43,5 +43,18 @@ struct statfs64 {
 	long f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+} __attribute__((packed));
 
 #endif /* _ASM_IA64_STATFS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/system.h 001-linus.patch/include/asm-ia64/system.h
--- 000-virgin/include/asm-ia64/system.h	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/include/asm-ia64/system.h	Tue Dec 30 16:38:57 2003
@@ -19,8 +19,11 @@
 #include <asm/pal.h>
 #include <asm/percpu.h>
 
-/* 0xa000000000000000 - 0xa000000000000000+PERCPU_PAGE_SIZE remain unmapped */
-#define GATE_ADDR		(0xa000000000000000 + PERCPU_PAGE_SIZE)
+#define GATE_ADDR		(0xa000000000000000)
+/*
+ * 0xa000000000000000+2*PERCPU_PAGE_SIZE
+ * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
+ */
 #define KERNEL_START		 0xa000000100000000
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ia64/uaccess.h 001-linus.patch/include/asm-ia64/uaccess.h
--- 000-virgin/include/asm-ia64/uaccess.h	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/include/asm-ia64/uaccess.h	Tue Dec 30 16:38:57 2003
@@ -50,7 +50,7 @@
 #define get_fs()  (current_thread_info()->addr_limit)
 #define set_fs(x) (current_thread_info()->addr_limit = (x))
 
-#define segment_eq(a,b)	((a).seg == (b).seg)
+#define segment_eq(a, b)	((a).seg == (b).seg)
 
 /*
  * When accessing user memory, we need to make sure the entire area really is in
@@ -58,16 +58,16 @@
  * address TASK_SIZE is never valid.  We also need to make sure that the address doesn't
  * point inside the virtually mapped linear page table.
  */
-#define __access_ok(addr,size,segment)						\
-	likely(((unsigned long) (addr)) <= (segment).seg			\
-	       && ((segment).seg == KERNEL_DS.seg				\
-		   || REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))
-#define access_ok(type,addr,size)	__access_ok((addr),(size),get_fs())
+#define __access_ok(addr, size, segment)					\
+	(likely((unsigned long) (addr) <= (segment).seg)			\
+	 && ((segment).seg == KERNEL_DS.seg					\
+	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)))
+#define access_ok(type, addr, size)	__access_ok((addr), (size), get_fs())
 
 static inline int
 verify_area (int type, const void *addr, unsigned long size)
 {
-	return access_ok(type,addr,size) ? 0 : -EFAULT;
+	return access_ok(type, addr, size) ? 0 : -EFAULT;
 }
 
 /*
@@ -78,292 +78,173 @@ verify_area (int type, const void *addr,
  * (a) re-use the arguments for side effects (sizeof/typeof is ok)
  * (b) require any knowledge of processes at this stage
  */
-#define put_user(x,ptr)	__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs())
-#define get_user(x,ptr)	__get_user_check((x),(ptr),sizeof(*(ptr)),get_fs())
+#define put_user(x, ptr)	__put_user_check((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)), get_fs())
+#define get_user(x, ptr)	__get_user_check((x), (ptr), sizeof(*(ptr)), get_fs())
 
 /*
  * The "__xxx" versions do not do address space checking, useful when
  * doing multiple accesses to the same area (the programmer has to do the
  * checks by hand with "access_ok()")
  */
-#define __put_user(x,ptr)	__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr)	__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x, ptr)	__put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
+#define __get_user(x, ptr)	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
 
 #ifdef ASM_SUPPORTED
-
-extern void __get_user_unknown (void);
-
-#define __get_user_nocheck(x,ptr,size)		\
-({						\
-	register long __gu_err asm ("r8") = 0;	\
-	register long __gu_val asm ("r9") = 0;	\
-	switch (size) {				\
-	  case 1: __get_user_8(ptr); break;	\
-	  case 2: __get_user_16(ptr); break;	\
-	  case 4: __get_user_32(ptr); break;	\
-	  case 8: __get_user_64(ptr); break;	\
-	  default: __get_user_unknown(); break;	\
-	}					\
-	(x) = (__typeof__(*(ptr))) __gu_val;	\
-	__gu_err;				\
-})
-
-#define __get_user_check(x,ptr,size,segment)			\
-({								\
-	register long __gu_err asm ("r8") = -EFAULT;		\
-	register long __gu_val asm ("r9") = 0;			\
-	const __typeof__(*(ptr)) *__gu_addr = (ptr);		\
-	if (__access_ok((long)__gu_addr,size,segment)) {	\
-		__gu_err = 0;					\
-		switch (size) {					\
-		  case 1: __get_user_8(__gu_addr); break;	\
-		  case 2: __get_user_16(__gu_addr); break;	\
-		  case 4: __get_user_32(__gu_addr); break;	\
-		  case 8: __get_user_64(__gu_addr); break;	\
-		  default: __get_user_unknown(); break;		\
-		}						\
-	}							\
-	(x) = (__typeof__(*(ptr))) __gu_val;			\
-	__gu_err;						\
-})
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+  struct __large_struct { unsigned long buf[100]; };
+# define __m(x) (*(struct __large_struct *)(x))
 
 /* We need to declare the __ex_table section before we can use it in .xdata.  */
 asm (".section \"__ex_table\", \"a\"\n\t.previous");
 
-#define __get_user_64(addr)									\
-	asm ("\n[1:]\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"	\
-	     "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n"						\
-	     "[1:]"										\
-	     : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
-
-#define __get_user_32(addr)									\
-	asm ("\n[1:]\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"	\
+# define __get_user_size(val, addr, n, err)							\
+do {												\
+	register long __gu_r8 asm ("r8") = 0;							\
+	register long __gu_r9 asm ("r9");							\
+	asm ("\n[1:]\tld"#n" %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"	\
 	     "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n"						\
 	     "[1:]"										\
-	     : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
-
-#define __get_user_16(addr)									\
-	asm ("\n[1:]\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"	\
-	     "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n"						\
-	     "[1:]"										\
-	     : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
-
-#define __get_user_8(addr)									\
-	asm ("\n[1:]\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n"	\
-	     "\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n"						\
-	     "[1:]"										\
-	     : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
-
-extern void __put_user_unknown (void);
-
-#define __put_user_nocheck(x,ptr,size)		\
-({						\
-	register long __pu_err asm ("r8") = 0;	\
-	switch (size) {				\
-	  case 1: __put_user_8(x,ptr); break;	\
-	  case 2: __put_user_16(x,ptr); break;	\
-	  case 4: __put_user_32(x,ptr); break;	\
-	  case 8: __put_user_64(x,ptr); break;	\
-	  default: __put_user_unknown(); break;	\
-	}					\
-	__pu_err;				\
-})
-
-#define __put_user_check(x,ptr,size,segment)			\
-({								\
-	register long __pu_err asm ("r8") = -EFAULT;		\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
-	if (__access_ok((long)__pu_addr,size,segment)) {	\
-		__pu_err = 0;					\
-		switch (size) {					\
-		  case 1: __put_user_8(x,__pu_addr); break;	\
-		  case 2: __put_user_16(x,__pu_addr); break;	\
-		  case 4: __put_user_32(x,__pu_addr); break;	\
-		  case 8: __put_user_64(x,__pu_addr); break;	\
-		  default: __put_user_unknown(); break;		\
-		}						\
-	}							\
-	__pu_err;						\
-})
+	     : "=r"(__gu_r9), "=r"(__gu_r8) : "m"(__m(addr)), "1"(__gu_r8));			\
+	(err) = __gu_r8;									\
+	(val) = __gu_r9;									\
+} while (0)
 
 /*
- * The "__put_user_xx()" macros tell gcc they read from memory
- * instead of writing: this is because they do not write to
- * any memory gcc knows about, so there are no aliasing issues
+ * The "__put_user_size()" macro tells gcc it reads from memory instead of writing it.  This
+ * is because they do not write to any memory gcc knows about, so there are no aliasing
+ * issues.
  */
-#define __put_user_64(x,addr)								\
-	asm volatile (									\
-		"\n[1:]\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"	\
-		"\t.xdata4 \"__ex_table\", 1b-., 1f-.\n"				\
-		"[1:]"									\
-		: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
-
-#define __put_user_32(x,addr)								\
-	asm volatile (									\
-		"\n[1:]\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"	\
-		"\t.xdata4 \"__ex_table\", 1b-., 1f-.\n"				\
-		"[1:]"									\
-		: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
-
-#define __put_user_16(x,addr)								\
-	asm volatile (									\
-		"\n[1:]\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"	\
-		"\t.xdata4 \"__ex_table\", 1b-., 1f-.\n"				\
-		"[1:]"									\
-		: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
-
-#define __put_user_8(x,addr)								\
-	asm volatile (									\
-		"\n[1:]\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n"	\
-		"\t.xdata4 \"__ex_table\", 1b-., 1f-.\n"				\
-		"[1:]"									\
-		: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+# define __put_user_size(val, addr, n, err)							\
+do {												\
+	register long __pu_r8 asm ("r8") = 0;							\
+	asm volatile ("\n[1:]\tst"#n" %1=%r2%P1\t// %0 gets overwritten by exception handler\n"	\
+		      "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n"					\
+		      "[1:]"									\
+		      : "=r"(__pu_r8) : "m"(__m(addr)), "rO"(val), "0"(__pu_r8));		\
+	(err) = __pu_r8;									\
+} while (0)
 
 #else /* !ASM_SUPPORTED */
-
-#define RELOC_TYPE	2	/* ip-rel */
-
-#define __put_user_xx(val, addr, size, err)							\
-	__st_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE, (unsigned long) (val));	\
-	(err) = ia64_getreg(_IA64_REG_R8);
-
-#define __get_user_xx(val, addr, size, err)					\
-	__ld_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE);	\
-	(err) = ia64_getreg(_IA64_REG_R8);					\
-	(val) = ia64_getreg(_IA64_REG_R9);
+# define RELOC_TYPE	2	/* ip-rel */
+# define __get_user_size(val, addr, n, err)				\
+do {									\
+	__ld_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE);	\
+	(err) = ia64_getreg(_IA64_REG_R8);				\
+	(val) = ia64_getreg(_IA64_REG_R9);				\
+} while (0)
+# define __put_user_size(val, addr, n, err)							\
+do {												\
+	__st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, (unsigned long) (val));	\
+	(err) = ia64_getreg(_IA64_REG_R8);							\
+} while (0)
+#endif /* !ASM_SUPPORTED */
 
 extern void __get_user_unknown (void);
 
-#define __get_user_nocheck(x, ptr, size)				\
-({									\
-	register long __gu_err = 0;					\
-	register long __gu_val = 0;					\
-	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
-	switch (size) {							\
-	      case 1: case 2: case 4: case 8:				\
-		__get_user_xx(__gu_val, __gu_addr, size, __gu_err);	\
-		break;							\
-	      default:							\
-		__get_user_unknown();					\
-		break;							\
-        }								\
-        (x) = (__typeof__(*(ptr))) __gu_val;				\
-        __gu_err;							\
+/*
+ * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which
+ * could clobber r8 and r9 (among others).  Thus, be careful not to evaluate it while
+ * using r8/r9.
+ */
+#define __do_get_user(check, x, ptr, size, segment)					\
+({											\
+	const __typeof__(*(ptr)) *__gu_ptr = (ptr);					\
+	__typeof__ (size) __gu_size = (size);						\
+	long __gu_err = -EFAULT, __gu_val = 0;						\
+											\
+	if (!check || __access_ok((long) __gu_ptr, size, segment))			\
+		switch (__gu_size) {							\
+		      case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break;	\
+		      case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break;	\
+		      case 4: __get_user_size(__gu_val, __gu_ptr, 4, __gu_err); break;	\
+		      case 8: __get_user_size(__gu_val, __gu_ptr, 8, __gu_err); break;	\
+		      default: __get_user_unknown(); break;				\
+		}									\
+	(x) = (__typeof__(*(__gu_ptr))) __gu_val;					\
+	__gu_err;									\
 })
 
-#define __get_user_check(x,ptr,size,segment)					\
-({										\
-	register long __gu_err = -EFAULT;					\
-	register long __gu_val  = 0;						\
-	const __typeof__(*(ptr)) *__gu_addr = (ptr);				\
-	if (__access_ok((long) __gu_addr, size, segment)) {			\
-		switch (size) {							\
-		      case 1: case 2: case 4: case 8:				\
-			__get_user_xx(__gu_val, __gu_addr, size, __gu_err);	\
-			break;							\
-		      default:							\
-			__get_user_unknown(); break;				\
-		}								\
-	}									\
-	(x) = (__typeof__(*(ptr))) __gu_val;					\
-	__gu_err;								\
-})
+#define __get_user_nocheck(x, ptr, size)	__do_get_user(0, x, ptr, size, KERNEL_DS)
+#define __get_user_check(x, ptr, size, segment)	__do_get_user(1, x, ptr, size, segment)
 
 extern void __put_user_unknown (void);
 
-#define __put_user_nocheck(x, ptr, size)			\
-({								\
-	int __pu_err = 0;					\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
-	switch (size) {						\
-	      case 1: case 2: case 4: case 8:			\
-	  	__put_user_xx(x, __pu_addr, size, __pu_err);	\
-		break;						\
-	      default:						\
-	  	__put_user_unknown(); break;			\
-	}							\
-	__pu_err;						\
-})
-
-#define __put_user_check(x,ptr,size,segment)				\
-({									\
-	register long __pu_err = -EFAULT;				\
-	__typeof__(*(ptr)) *__pu_addr = (ptr);				\
-	if (__access_ok((long)__pu_addr,size,segment)) {		\
-		switch (size) {						\
-		      case 1: case 2: case 4: case 8:			\
-			__put_user_xx(x,__pu_addr, size, __pu_err);	\
-			break;						\
-		      default:						\
-			__put_user_unknown(); break;			\
-		}							\
-	}								\
-	__pu_err;							\
+/*
+ * Evaluating arguments X, PTR, SIZE, and SEGMENT may involve subroutine-calls, which
+ * could clobber r8 (among others).  Thus, be careful not to evaluate them while using r8.
+ */
+#define __do_put_user(check, x, ptr, size, segment)					\
+({											\
+	__typeof__ (x) __pu_x = (x);							\
+	__typeof__ (*(ptr)) *__pu_ptr = (ptr);						\
+	__typeof__ (size) __pu_size = (size);						\
+	long __pu_err = -EFAULT;							\
+											\
+	if (!check || __access_ok((long) __pu_ptr, __pu_size, segment))			\
+		switch (__pu_size) {							\
+		      case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break;	\
+		      case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break;	\
+		      case 4: __put_user_size(__pu_x, __pu_ptr, 4, __pu_err); break;	\
+		      case 8: __put_user_size(__pu_x, __pu_ptr, 8, __pu_err); break;	\
+		      default: __put_user_unknown(); break;				\
+		}									\
+	__pu_err;									\
 })
 
-#endif /* !ASM_SUPPORTED */
+#define __put_user_nocheck(x, ptr, size)	__do_put_user(0, x, ptr, size, KERNEL_DS)
+#define __put_user_check(x, ptr, size, segment)	__do_put_user(1, x, ptr, size, segment)
 
 /*
  * Complex access routines
  */
 extern unsigned long __copy_user (void *to, const void *from, unsigned long count);
 
-#define __copy_to_user(to,from,n)	__copy_user((to), (from), (n))
-#define __copy_from_user(to,from,n)	__copy_user((to), (from), (n))
+#define __copy_to_user(to, from, n)	__copy_user((to), (from), (n))
+#define __copy_from_user(to, from, n)	__copy_user((to), (from), (n))
 
-#define copy_to_user(to,from,n)   __copy_tofrom_user((to), (from), (n), 1)
-#define copy_from_user(to,from,n) __copy_tofrom_user((to), (from), (n), 0)
+#define copy_to_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 1)
+#define copy_from_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 0)
 
-#define __copy_tofrom_user(to,from,n,check_to)							\
-({												\
-	void *__cu_to = (to);									\
-	const void *__cu_from = (from);								\
-	long __cu_len = (n);									\
-												\
-	if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) {	\
-		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len);				\
-	}											\
-	__cu_len;										\
+#define __copy_tofrom_user(to, from, n, check_to)					\
+({											\
+	void *__cu_to = (to);								\
+	const void *__cu_from = (from);							\
+	long __cu_len = (n);								\
+											\
+	if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs()))	\
+		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len);			\
+	__cu_len;									\
 })
 
-#define __copy_in_user(to, from, size)          \
-        __copy_user((to), (from), (size))
+#define __copy_in_user(to, from, size)	__copy_user((to), (from), (size))
 
 static inline unsigned long
 copy_in_user (void *to, const void *from, unsigned long n)
 {
-	if (likely(access_ok(VERIFY_READ, from, n) &&
-	    access_ok(VERIFY_WRITE, to, n)))
+	if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)))
 		n = __copy_user(to, from, n);
 	return n;
 }
 
 extern unsigned long __do_clear_user (void *, unsigned long);
 
-#define __clear_user(to,n)			\
-({						\
-	__do_clear_user(to,n);			\
-})
+#define __clear_user(to, n)		__do_clear_user(to, n)
 
-#define clear_user(to,n)					\
+#define clear_user(to, n)					\
 ({								\
 	unsigned long __cu_len = (n);				\
-	if (__access_ok((long) to, __cu_len, get_fs())) {	\
+	if (__access_ok((long) to, __cu_len, get_fs()))		\
 		__cu_len = __do_clear_user(to, __cu_len);	\
-	}							\
 	__cu_len;						\
 })
 
 
-/* Returns: -EFAULT if exception before terminator, N if the entire
-   buffer filled, else strlen.  */
-
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else
+ * strlen.
+ */
 extern long __strncpy_from_user (char *to, const char *from, long to_len);
 
-#define strncpy_from_user(to,from,n)					\
+#define strncpy_from_user(to, from, n)					\
 ({									\
 	const char * __sfu_from = (from);				\
 	long __sfu_ret = -EFAULT;					\
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-m68k/cpumask.h 001-linus.patch/include/asm-m68k/cpumask.h
--- 000-virgin/include/asm-m68k/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-m68k/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_M68K_CPUMASK_H
+#define _ASM_M68K_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_M68K_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-m68knommu/cpumask.h 001-linus.patch/include/asm-m68knommu/cpumask.h
--- 000-virgin/include/asm-m68knommu/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-m68knommu/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_M68KNOMMU_CPUMASK_H
+#define _ASM_M68KNOMMU_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_M68KNOMMU_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-mips/cpumask.h 001-linus.patch/include/asm-mips/cpumask.h
--- 000-virgin/include/asm-mips/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-mips/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_MIPS_CPUMASK_H
+#define _ASM_MIPS_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_MIPS_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-mips/statfs.h 001-linus.patch/include/asm-mips/statfs.h
--- 000-virgin/include/asm-mips/statfs.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-mips/statfs.h	Tue Dec 30 16:38:57 2003
@@ -75,6 +75,20 @@ struct statfs64 {			/* Same as struct st
 	long		f_spare[6];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #endif /* _ASM_STATFS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/cpumask.h 001-linus.patch/include/asm-parisc/cpumask.h
--- 000-virgin/include/asm-parisc/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-parisc/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_PARISC_CPUMASK_H
+#define _ASM_PARISC_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_PARISC_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/dma-mapping.h 001-linus.patch/include/asm-parisc/dma-mapping.h
--- 000-virgin/include/asm-parisc/dma-mapping.h	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/include/asm-parisc/dma-mapping.h	Tue Dec 30 16:38:57 2003
@@ -5,9 +5,7 @@
 #include <linux/config.h>
 #include <asm/cacheflush.h>
 
-/*
-** See Documentation/DMA-mapping.txt
-*/
+/* See Documentation/DMA-mapping.txt */
 struct hppa_dma_ops {
 	int  (*dma_supported)(struct device *dev, u64 mask);
 	void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, int flag);
@@ -208,15 +206,13 @@ int ccio_request_resource(const struct p
 		struct resource *res);
 int ccio_allocate_resource(const struct parisc_device *dev,
 		struct resource *res, unsigned long size,
-		unsigned long min, unsigned long max, unsigned long align,
-		void (*alignf)(void *, struct resource *, unsigned long, unsigned long),
-		void *alignf_data);
+		unsigned long min, unsigned long max, unsigned long align);
 #else /* !CONFIG_IOMMU_CCIO */
 #define ccio_get_iommu(dev) NULL
 #define ccio_request_resource(dev, res) request_resource(&iomem_resource, res)
-#define ccio_allocate_resource(dev, res, size, min, max, align, alignf, data) \
+#define ccio_allocate_resource(dev, res, size, min, max, align) \
 		allocate_resource(&iomem_resource, res, size, min, max, \
-				align, alignf, data)
+				align, NULL, NULL)
 #endif /* !CONFIG_IOMMU_CCIO */
 
 #ifdef CONFIG_IOMMU_SBA
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/ioctl.h 001-linus.patch/include/asm-parisc/ioctl.h
--- 000-virgin/include/asm-parisc/ioctl.h	Wed Dec 17 18:57:57 2003
+++ 001-linus.patch/include/asm-parisc/ioctl.h	Tue Dec 30 16:38:57 2003
@@ -45,7 +45,7 @@
 	 ((size) << _IOC_SIZESHIFT))
 
 /* provoke compile error for invalid uses of size argument */
-extern int __invalid_size_argument_for_IOC;
+extern unsigned int __invalid_size_argument_for_IOC;
 #define _IOC_TYPECHECK(t) \
 	((sizeof(t) == sizeof(t[1]) && \
 	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/statfs.h 001-linus.patch/include/asm-parisc/statfs.h
--- 000-virgin/include/asm-parisc/statfs.h	Wed Dec 17 18:59:17 2003
+++ 001-linus.patch/include/asm-parisc/statfs.h	Tue Dec 30 16:38:57 2003
@@ -41,4 +41,18 @@ struct statfs64 {
 	long f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/uaccess.h 001-linus.patch/include/asm-parisc/uaccess.h
--- 000-virgin/include/asm-parisc/uaccess.h	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/include/asm-parisc/uaccess.h	Tue Dec 30 16:38:57 2003
@@ -40,10 +40,10 @@ extern int __put_user_bad(void);
 #define get_user __get_user
 
 #if BITS_PER_LONG == 32
-#define LDD_KERNEL(ptr) __get_kernel_bad();
-#define LDD_USER(ptr) __get_user_bad();
-#define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr)
-#define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr)
+#define LDD_KERNEL(ptr)		__get_kernel_bad();
+#define LDD_USER(ptr)		__get_user_bad();
+#define STD_KERNEL(x, ptr)	__put_kernel_asm64(x,ptr)
+#define STD_USER(x, ptr)	__put_user_asm64(x,ptr)
 #else
 #define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr)
 #define LDD_USER(ptr) __get_user_asm("ldd",ptr)
@@ -256,11 +256,12 @@ static inline void __put_user_asm64(u64 
  * Complex access routines -- external declarations
  */
 
-extern unsigned long lcopy_to_user(void *, const void *, unsigned long);
-extern unsigned long lcopy_from_user(void *, const void *, unsigned long);
-extern long lstrncpy_from_user(char *, const char *, long);
-extern unsigned lclear_user(void *,unsigned long);
-extern long lstrnlen_user(const char *,long);
+extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long);
+extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long);
+extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long);
+extern long lstrncpy_from_user(char *, const char __user *, long);
+extern unsigned lclear_user(void __user *,unsigned long);
+extern long lstrnlen_user(const char __user *,long);
 
 /*
  * Complex access routines -- macros
@@ -276,5 +277,7 @@ extern long lstrnlen_user(const char *,l
 #define __copy_from_user lcopy_from_user
 #define copy_to_user lcopy_to_user
 #define __copy_to_user lcopy_to_user
+#define copy_in_user lcopy_in_user
+#define __copy_in_user lcopy_in_user
 
 #endif /* __PARISC_UACCESS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/ucontext.h 001-linus.patch/include/asm-parisc/ucontext.h
--- 000-virgin/include/asm-parisc/ucontext.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/include/asm-parisc/ucontext.h	Tue Dec 30 16:38:57 2003
@@ -1,12 +1,12 @@
-#ifndef _ASMPARISC_UCONTEXT_H
-#define _ASMPARISC_UCONTEXT_H
+#ifndef _ASM_PARISC_UCONTEXT_H
+#define _ASM_PARISC_UCONTEXT_H
 
 struct ucontext {
-	unsigned long	  uc_flags;
+	unsigned int	  uc_flags;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
 	struct sigcontext uc_mcontext;
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
 };
 
-#endif /* !_ASMPARISC_UCONTEXT_H */
+#endif /* !_ASM_PARISC_UCONTEXT_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-parisc/unistd.h 001-linus.patch/include/asm-parisc/unistd.h
--- 000-virgin/include/asm-parisc/unistd.h	Wed Dec 17 18:57:59 2003
+++ 001-linus.patch/include/asm-parisc/unistd.h	Tue Dec 30 16:38:57 2003
@@ -490,7 +490,7 @@
  */
 
 #define __NR_Linux                0
-#define __NR_syscall              (__NR_Linux + 0)
+#define __NR_restart_syscall      (__NR_Linux + 0)
 #define __NR_exit                 (__NR_Linux + 1)
 #define __NR_fork                 (__NR_Linux + 2)
 #define __NR_read                 (__NR_Linux + 3)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ppc/cpumask.h 001-linus.patch/include/asm-ppc/cpumask.h
--- 000-virgin/include/asm-ppc/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-ppc/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_PPC_CPUMASK_H
+#define _ASM_PPC_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_PPC_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ppc/ioctl.h 001-linus.patch/include/asm-ppc/ioctl.h
--- 000-virgin/include/asm-ppc/ioctl.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/asm-ppc/ioctl.h	Tue Dec 30 16:38:57 2003
@@ -38,7 +38,7 @@
 	 ((size) << _IOC_SIZESHIFT))
 
 /* provoke compile error for invalid uses of size argument */
-extern int __invalid_size_argument_for_IOC;
+extern unsigned int __invalid_size_argument_for_IOC;
 #define _IOC_TYPECHECK(t) \
 	((sizeof(t) == sizeof(t[1]) && \
 	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ppc64/cpumask.h 001-linus.patch/include/asm-ppc64/cpumask.h
--- 000-virgin/include/asm-ppc64/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-ppc64/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_PPC64_CPUMASK_H
+#define _ASM_PPC64_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_PPC64_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ppc64/ioctl.h 001-linus.patch/include/asm-ppc64/ioctl.h
--- 000-virgin/include/asm-ppc64/ioctl.h	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/include/asm-ppc64/ioctl.h	Tue Dec 30 16:38:57 2003
@@ -43,7 +43,7 @@
 	 ((size) << _IOC_SIZESHIFT))
 
 /* provoke compile error for invalid uses of size argument */
-extern int __invalid_size_argument_for_IOC;
+extern unsigned int __invalid_size_argument_for_IOC;
 #define _IOC_TYPECHECK(t) \
        ((sizeof(t) == sizeof(t[1]) && \
          sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-ppc64/statfs.h 001-linus.patch/include/asm-ppc64/statfs.h
--- 000-virgin/include/asm-ppc64/statfs.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-ppc64/statfs.h	Tue Dec 30 16:38:57 2003
@@ -44,4 +44,18 @@ struct statfs64 {
 	long f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif  /* _PPC64_STATFS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-s390/cpumask.h 001-linus.patch/include/asm-s390/cpumask.h
--- 000-virgin/include/asm-s390/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-s390/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_S390_CPUMASK_H
+#define _ASM_S390_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_S390_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-s390/statfs.h 001-linus.patch/include/asm-s390/statfs.h
--- 000-virgin/include/asm-s390/statfs.h	Wed Dec 17 18:59:54 2003
+++ 001-linus.patch/include/asm-s390/statfs.h	Tue Dec 30 16:38:57 2003
@@ -53,5 +53,19 @@ struct statfs64 {
 	int  f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif /* __s390x__ */
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sh/cpumask.h 001-linus.patch/include/asm-sh/cpumask.h
--- 000-virgin/include/asm-sh/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-sh/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_SH_CPUMASK_H
+#define _ASM_SH_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_SH_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc/cpumask.h 001-linus.patch/include/asm-sparc/cpumask.h
--- 000-virgin/include/asm-sparc/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-sparc/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_SPARC_CPUMASK_H
+#define _ASM_SPARC_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_SPARC_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc/processor.h 001-linus.patch/include/asm-sparc/processor.h
--- 000-virgin/include/asm-sparc/processor.h	Wed Dec 17 18:59:56 2003
+++ 001-linus.patch/include/asm-sparc/processor.h	Tue Dec 30 16:38:57 2003
@@ -56,19 +56,12 @@ typedef struct {
 /* The Sparc processor specific thread struct. */
 struct thread_struct {
 	struct pt_regs *kregs;
+	unsigned int _pad1;
 
 	/* Special child fork kpsr/kwim values. */
 	unsigned long fork_kpsr __attribute__ ((aligned (8)));
 	unsigned long fork_kwim;
 
-	/* A place to store user windows and stack pointers
-	 * when the stack needs inspection.
-	 */
-#define NSWINS 8
-	struct reg_window reg_window[NSWINS] __attribute__ ((aligned (8)));
-	unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
-	unsigned long w_saved;
-
 	/* Floating point regs */
 	unsigned long   float_regs[32] __attribute__ ((aligned (8)));
 	unsigned long   fsr;
@@ -78,23 +71,16 @@ struct thread_struct {
 	mm_segment_t current_ds;
 	struct exec core_exec;     /* just what it says. */
 	int new_signal;
-	atomic_t refcount;	/* used for sun4c only */
 };
 
 #define SPARC_FLAG_KTHREAD      0x1    /* task is a kernel thread */
 #define SPARC_FLAG_UNALIGNED    0x2    /* is allowed to do unaligned accesses */
 
 #define INIT_THREAD  { \
-/* kregs, */ \
-   0,  \
+/* kregs, _pad1, */ \
+   0, 0,  \
 /* fork_kpsr, fork_kwim */ \
    0,         0, \
-/* reg_window */  \
-{ { { 0, }, { 0, } }, }, \
-/* rwbuf_stkptrs */  \
-{ 0, 0, 0, 0, 0, 0, 0, 0, }, \
-/* w_saved */ \
-   0, \
 /* FPU regs */   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
 /* FPU status, FPU qdepth, FPU queue */ \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc/thread_info.h 001-linus.patch/include/asm-sparc/thread_info.h
--- 000-virgin/include/asm-sparc/thread_info.h	Wed Dec 17 18:59:42 2003
+++ 001-linus.patch/include/asm-sparc/thread_info.h	Tue Dec 30 16:38:57 2003
@@ -16,16 +16,14 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/btfixup.h>
+#include <asm/ptrace.h>
 
 /*
  * Low level task data.
  *
- * If you change this, change the TI_* offsets below to match. XXX check_asm.
- *
- * The uwinmask is a first class citizen among w_saved and friends.
- * XXX Is this a good idea? wof.S/wuf.S have to use w_saved anyway,
- *     so they waste a register on current, and an ld on fetching it.
+ * If you change this, change the TI_* offsets below to match.
  */
+#define NSWINS 8
 struct thread_info {
 	unsigned long		uwinmask;
 	struct task_struct	*task;		/* main task structure */
@@ -43,6 +41,13 @@ struct thread_info {
 	unsigned long kpsr;
 	unsigned long kwim;
 
+	/* A place to store user windows and stack pointers
+	 * when the stack needs inspection.
+	 */
+	struct reg_window	reg_window[NSWINS];	/* align for ldd! */
+	unsigned long		rwbuf_stkptrs[NSWINS];
+	unsigned long		w_saved;
+
 	struct restart_block	restart_block;
 };
 
@@ -100,6 +105,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 
 /*
  * Offsets in thread_info structure, used in assembly code
+ * The "#define REGWIN_SZ 0x40" was abolished, so no multiplications.
  */
 #define TI_UWINMASK	0x00	/* uwinmask */
 #define TI_TASK		0x04
@@ -113,7 +119,10 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TI_KPC		0x24	/* kpc (ldd'ed with kpc) */
 #define TI_KPSR		0x28	/* kpsr */
 #define TI_KWIM		0x2c	/* kwim (ldd'ed with kpsr) */
-#define TI_RESTART_BLOCK 0x30
+#define TI_REG_WINDOW	0x30
+#define TI_RWIN_SPTRS	0x230
+#define TI_W_SAVED	0x250
+/* #define TI_RESTART_BLOCK 0x25n */ /* Nobody cares */
 
 #define PREEMPT_ACTIVE		0x4000000
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc/winmacro.h 001-linus.patch/include/asm-sparc/winmacro.h
--- 000-virgin/include/asm-sparc/winmacro.h	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/include/asm-sparc/winmacro.h	Tue Dec 30 16:38:57 2003
@@ -9,7 +9,6 @@
 
 #include <linux/config.h>
 #include <asm/ptrace.h>
-#include <asm/psr.h>
 
 /* Store the register window onto the 8-byte aligned area starting
  * at %reg.  It might be %sp, it might not, we don't care.
@@ -91,18 +90,18 @@
         STORE_PT_INS(base_reg)
 
 #define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \
-        ld       [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved], %scratch; \
+        ld       [%cur_reg + TI_W_SAVED], %scratch; \
         sll      %scratch, 2, %scratch; \
         add      %scratch, %cur_reg, %scratch; \
-        st       %sp, [%scratch + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]; \
+        st       %sp, [%scratch + TI_RWIN_SPTRS]; \
         sub      %scratch, %cur_reg, %scratch; \
         sll      %scratch, 4, %scratch; \
         add      %scratch, %cur_reg, %scratch; \
-        STORE_WINDOW(scratch + AOFF_task_thread + AOFF_thread_reg_window); \
+        STORE_WINDOW(scratch + TI_REG_WINDOW); \
         sub      %scratch, %cur_reg, %scratch; \
         srl      %scratch, 6, %scratch; \
         add      %scratch, 1, %scratch; \
-        st       %scratch, [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved];
+        st       %scratch, [%cur_reg + TI_W_SAVED];
 
 #ifdef CONFIG_SMP
 #define LOAD_CURRENT4M(dest_reg, idreg) \
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc64/cpumask.h 001-linus.patch/include/asm-sparc64/cpumask.h
--- 000-virgin/include/asm-sparc64/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-sparc64/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_SPARC64_CPUMASK_H
+#define _ASM_SPARC64_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_SPARC64_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-sparc64/statfs.h 001-linus.patch/include/asm-sparc64/statfs.h
--- 000-virgin/include/asm-sparc64/statfs.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/include/asm-sparc64/statfs.h	Tue Dec 30 16:38:57 2003
@@ -38,4 +38,18 @@ struct statfs64 {
 	long f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-um/cpumask.h 001-linus.patch/include/asm-um/cpumask.h
--- 000-virgin/include/asm-um/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-um/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_CPUMASK_H
+#define _ASM_UM_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_UM_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-v850/cpumask.h 001-linus.patch/include/asm-v850/cpumask.h
--- 000-virgin/include/asm-v850/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-v850/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_V850_CPUMASK_H
+#define _ASM_V850_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_V850_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/a.out.h 001-linus.patch/include/asm-x86_64/a.out.h
--- 000-virgin/include/asm-x86_64/a.out.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/asm-x86_64/a.out.h	Tue Dec 30 16:38:57 2003
@@ -1,13 +1,11 @@
 #ifndef __X8664_A_OUT_H__
 #define __X8664_A_OUT_H__
 
-
-/* Note: a.out is not supported in 64bit mode. This is just here to 
-   still let some old things compile. */ 
+/* 32bit a.out */
 
 struct exec
 {
-  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned int a_info;		/* Use macros N_MAGIC, etc for access */
   unsigned a_text;		/* length of text, in bytes */
   unsigned a_data;		/* length of data, in bytes */
   unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
@@ -23,7 +21,7 @@ struct exec
 
 #ifdef __KERNEL__
 
-#define STACK_TOP	TASK_SIZE
+#define STACK_TOP	0xc0000000
 
 #endif
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/cpumask.h 001-linus.patch/include/asm-x86_64/cpumask.h
--- 000-virgin/include/asm-x86_64/cpumask.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/asm-x86_64/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_64_CPUMASK_H
+#define _ASM_X86_64_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_X86_64_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/hw_irq.h 001-linus.patch/include/asm-x86_64/hw_irq.h
--- 000-virgin/include/asm-x86_64/hw_irq.h	Wed Dec 17 18:59:45 2003
+++ 001-linus.patch/include/asm-x86_64/hw_irq.h	Tue Dec 30 16:38:57 2003
@@ -173,6 +173,8 @@ static inline void hw_resend_irq(struct 
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
 #endif
 
+#define platform_legacy_irq(irq)	((irq) < 16)
+
 #endif
 
 #endif /* _ASM_HW_IRQ_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/io.h 001-linus.patch/include/asm-x86_64/io.h
--- 000-virgin/include/asm-x86_64/io.h	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/include/asm-x86_64/io.h	Tue Dec 30 16:38:57 2003
@@ -304,8 +304,8 @@ out:
 /* Disable vmerge for now. Need to fix the block layer code
    to check for non iommu addresses first.
    When the IOMMU is force it is safe to enable. */
-extern int force_iommu; 
-#define BIO_VERMGE_BOUNDARY (force_iommu ? 4096 : 0)
+extern int iommu_merge;
+#define BIO_VMERGE_BOUNDARY (iommu_merge ? 4096 : 0)
 
 #endif /* __KERNEL__ */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/io_apic.h 001-linus.patch/include/asm-x86_64/io_apic.h
--- 000-virgin/include/asm-x86_64/io_apic.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/include/asm-x86_64/io_apic.h	Tue Dec 30 16:38:57 2003
@@ -174,6 +174,25 @@ extern int sis_apic_bug; /* dummy */ 
 #define io_apic_assign_pci_irqs 0
 #endif
 
+static inline int use_pci_vector(void)	{return 0;}
+static inline void disable_edge_ioapic_irq(unsigned int irq) { }
+static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
+static inline void end_edge_ioapic_irq (unsigned int irq) { }
+#define startup_level_ioapic	startup_level_ioapic_irq
+#define shutdown_level_ioapic	mask_IO_APIC_irq
+#define enable_level_ioapic	unmask_IO_APIC_irq
+#define disable_level_ioapic	mask_IO_APIC_irq
+#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
+#define end_level_ioapic	end_level_ioapic_irq
+#define set_ioapic_affinity	set_ioapic_affinity_irq
+
+#define startup_edge_ioapic 	startup_edge_ioapic_irq
+#define shutdown_edge_ioapic 	disable_edge_ioapic_irq
+#define enable_edge_ioapic 	unmask_IO_APIC_irq
+#define disable_edge_ioapic 	disable_edge_ioapic_irq
+#define ack_edge_ioapic 	ack_edge_ioapic_irq
+#define end_edge_ioapic 	end_edge_ioapic_irq
+
 void enable_NMI_through_LVT0 (void * dummy);
 
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/stat.h 001-linus.patch/include/asm-x86_64/stat.h
--- 000-virgin/include/asm-x86_64/stat.h	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/include/asm-x86_64/stat.h	Tue Dec 30 16:38:57 2003
@@ -26,4 +26,19 @@ struct stat {
   	long		__unused[3];
 };
 
+/* For 32bit emulation */
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned int  st_size;
+	unsigned int  st_atime;
+	unsigned int  st_mtime;
+	unsigned int  st_ctime;
+};
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/asm-x86_64/statfs.h 001-linus.patch/include/asm-x86_64/statfs.h
--- 000-virgin/include/asm-x86_64/statfs.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/asm-x86_64/statfs.h	Tue Dec 30 16:38:57 2003
@@ -41,4 +41,18 @@ struct statfs64 {
 	long f_spare[5];
 };
 
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+} __attribute__((packed));
+
 #endif
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/compat.h 001-linus.patch/include/linux/compat.h
--- 000-virgin/include/linux/compat.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/include/linux/compat.h	Tue Dec 30 16:38:57 2003
@@ -44,8 +44,8 @@ typedef struct {
 } compat_sigset_t;
 
 extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
-extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
+extern int get_compat_timespec(struct timespec *, const struct compat_timespec *);
+extern int put_compat_timespec(struct timespec *, const struct compat_timespec *);
 
 struct compat_iovec {
 	compat_uptr_t	iov_base;
@@ -76,20 +76,6 @@ struct compat_rusage {
 	compat_long_t	ru_nivcsw;
 };
 
-struct compat_statfs64 {
-	__u32 f_type;
-	__u32 f_bsize;
-	__u64 f_blocks;
-	__u64 f_bfree;
-	__u64 f_bavail;
-	__u64 f_files;
-	__u64 f_ffree;
-	__kernel_fsid_t f_fsid;
-	__u32 f_namelen;
-	__u32 f_frsize;
-	__u32 f_spare[5];
-};
-
 struct compat_dirent {
 	u32		d_ino;
 	compat_off_t	d_off;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/compat_ioctl.h 001-linus.patch/include/linux/compat_ioctl.h
--- 000-virgin/include/linux/compat_ioctl.h	Wed Dec 17 18:59:43 2003
+++ 001-linus.patch/include/linux/compat_ioctl.h	Tue Dec 30 16:38:57 2003
@@ -678,3 +678,10 @@ COMPATIBLE_IOCTL(NBD_CLEAR_QUE)
 COMPATIBLE_IOCTL(NBD_PRINT_DEBUG)
 COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS)
 COMPATIBLE_IOCTL(NBD_DISCONNECT)
+/* i2c */
+COMPATIBLE_IOCTL(I2C_SLAVE)
+COMPATIBLE_IOCTL(I2C_SLAVE_FORCE)
+COMPATIBLE_IOCTL(I2C_TENBIT)
+COMPATIBLE_IOCTL(I2C_PEC)
+COMPATIBLE_IOCTL(I2C_RETRIES)
+COMPATIBLE_IOCTL(I2C_TIMEOUT)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/console.h 001-linus.patch/include/linux/console.h
--- 000-virgin/include/linux/console.h	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/include/linux/console.h	Tue Dec 30 16:38:57 2003
@@ -71,18 +71,6 @@ void give_up_console(const struct consw 
 #define CM_MOVE     (3)
 
 /*
- *	Array of consoles built from command line options (console=)
- */
-struct console_cmdline
-{
-	char	name[8];			/* Name of the driver	    */
-	int	index;				/* Minor dev. to use	    */
-	char	*options;			/* Options for the driver   */
-};
-#define MAX_CMDLINECONSOLES 8
-extern struct console_cmdline console_list[MAX_CMDLINECONSOLES];
-
-/*
  *	The interface for a console, or any other device that
  *	wants to capture console messages (printer driver?)
  */
@@ -106,6 +94,7 @@ struct console
 	struct	 console *next;
 };
 
+extern int add_preferred_console(char *name, int idx, char *options);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
 extern struct console *console_drivers;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/cpumask.h 001-linus.patch/include/linux/cpumask.h
--- 000-virgin/include/linux/cpumask.h	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/include/linux/cpumask.h	Tue Dec 30 16:38:57 2003
@@ -1,42 +1,9 @@
 #ifndef __LINUX_CPUMASK_H
 #define __LINUX_CPUMASK_H
 
-#include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/threads.h>
-#include <linux/types.h>
-#include <linux/bitmap.h>
-
-#if NR_CPUS > BITS_PER_LONG && NR_CPUS != 1
-#define CPU_ARRAY_SIZE		BITS_TO_LONGS(NR_CPUS)
-
-struct cpumask
-{
-	unsigned long mask[CPU_ARRAY_SIZE];
-};
-
-typedef struct cpumask cpumask_t;
-
-#else
-typedef unsigned long cpumask_t;
-#endif
-
-#ifdef CONFIG_SMP
-#if NR_CPUS > BITS_PER_LONG
-#include <asm-generic/cpumask_array.h>
-#else
-#include <asm-generic/cpumask_arith.h>
-#endif
-#else
-#include <asm-generic/cpumask_up.h>
-#endif
-
-#if NR_CPUS <= 4*BITS_PER_LONG
-#include <asm-generic/cpumask_const_value.h>
-#else
-#include <asm-generic/cpumask_const_reference.h>
-#endif
-
+#include <asm/cpumask.h>
+#include <asm/bug.h>
 
 #ifdef CONFIG_SMP
 
@@ -53,19 +20,31 @@ extern cpumask_t cpu_online_map;
 static inline int next_online_cpu(int cpu, cpumask_t map)
 {
 	do
-		cpu = next_cpu_const(cpu, map);
+		cpu = next_cpu_const(cpu, mk_cpumask_const(map));
 	while (cpu < NR_CPUS && !cpu_online(cpu));
 	return cpu;
 }
 
 #define for_each_cpu(cpu, map)						\
-	for (cpu = first_cpu_const(map);				\
+	for (cpu = first_cpu_const(mk_cpumask_const(map));		\
 		cpu < NR_CPUS;						\
-		cpu = next_cpu_const(cpu,map))
+		cpu = next_cpu_const(cpu,mk_cpumask_const(map)))
 
 #define for_each_online_cpu(cpu, map)					\
-	for (cpu = first_cpu_const(map);				\
+	for (cpu = first_cpu_const(mk_cpumask_const(map));		\
 		cpu < NR_CPUS;						\
 		cpu = next_online_cpu(cpu,map))
 
+extern int __mask_snprintf_len(char *buf, unsigned int buflen,
+		const unsigned long *maskp, unsigned int maskbytes);
+
+#define cpumask_snprintf(buf, buflen, map)				\
+	__mask_snprintf_len(buf, buflen, cpus_addr(map), sizeof(map))
+
+extern int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen,
+	unsigned long *maskp, unsigned int maskbytes);
+
+#define cpumask_parse(buf, buflen, map)					\
+	__mask_parse_len(buf, buflen, cpus_addr(map), sizeof(map))
+
 #endif /* __LINUX_CPUMASK_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/device.h 001-linus.patch/include/linux/device.h
--- 000-virgin/include/linux/device.h	Wed Dec 17 18:59:37 2003
+++ 001-linus.patch/include/linux/device.h	Tue Dec 30 16:38:57 2003
@@ -372,7 +372,7 @@ extern int platform_device_register(stru
 extern void platform_device_unregister(struct platform_device *);
 
 extern struct bus_type platform_bus_type;
-extern struct device legacy_bus;
+extern struct device platform_bus;
 
 /* drivers/base/power.c */
 extern void device_shutdown(void);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/efi.h 001-linus.patch/include/linux/efi.h
--- 000-virgin/include/linux/efi.h	Wed Dec 17 18:59:40 2003
+++ 001-linus.patch/include/linux/efi.h	Tue Dec 30 16:38:57 2003
@@ -16,6 +16,8 @@
 #include <linux/time.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/rtc.h>
+#include <linux/ioport.h>
 
 #include <asm/page.h>
 #include <asm/system.h>
@@ -77,18 +79,23 @@ typedef	struct {
 #define EFI_MAX_MEMORY_TYPE		14
 
 /* Attribute values: */
-#define EFI_MEMORY_UC		0x0000000000000001	/* uncached */
-#define EFI_MEMORY_WC		0x0000000000000002	/* write-coalescing */
-#define EFI_MEMORY_WT		0x0000000000000004	/* write-through */
-#define EFI_MEMORY_WB		0x0000000000000008	/* write-back */
-#define EFI_MEMORY_WP		0x0000000000001000	/* write-protect */
-#define EFI_MEMORY_RP		0x0000000000002000	/* read-protect */
-#define EFI_MEMORY_XP		0x0000000000004000	/* execute-protect */
-#define EFI_MEMORY_RUNTIME	0x8000000000000000	/* range requires runtime mapping */
+#define EFI_MEMORY_UC		((u64)0x0000000000000001ULL)	/* uncached */
+#define EFI_MEMORY_WC		((u64)0x0000000000000002ULL)	/* write-coalescing */
+#define EFI_MEMORY_WT		((u64)0x0000000000000004ULL)	/* write-through */
+#define EFI_MEMORY_WB		((u64)0x0000000000000008ULL)	/* write-back */
+#define EFI_MEMORY_WP		((u64)0x0000000000001000ULL)	/* write-protect */
+#define EFI_MEMORY_RP		((u64)0x0000000000002000ULL)	/* read-protect */
+#define EFI_MEMORY_XP		((u64)0x0000000000004000ULL)	/* execute-protect */
+#define EFI_MEMORY_RUNTIME	((u64)0x8000000000000000ULL)	/* range requires runtime mapping */
 #define EFI_MEMORY_DESCRIPTOR_VERSION	1
 
 #define EFI_PAGE_SHIFT		12
 
+/*
+ * For current x86 implementations of EFI, there is
+ * additional padding in the mem descriptors.  This is not
+ * the case in ia64.  Need to have this fixed in the f/w.
+ */
 typedef struct {
 	u32 type;
 	u32 pad;
@@ -96,6 +103,9 @@ typedef struct {
 	u64 virt_addr;
 	u64 num_pages;
 	u64 attribute;
+#if defined (__i386__)
+	u64 pad1;
+#endif
 } efi_memory_desc_t;
 
 typedef int efi_freemem_callback_t (unsigned long start, unsigned long end, void *arg);
@@ -132,11 +142,12 @@ typedef struct {
  */
 #define EFI_RESET_COLD 0
 #define EFI_RESET_WARM 1
+#define EFI_RESET_SHUTDOWN 2
 
 /*
  * EFI Runtime Services table
  */
-#define EFI_RUNTIME_SERVICES_SIGNATURE 0x5652453544e5552
+#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
 #define EFI_RUNTIME_SERVICES_REVISION  0x00010000
 
 typedef struct {
@@ -169,6 +180,10 @@ typedef efi_status_t efi_set_variable_t 
 typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
 typedef void efi_reset_system_t (int reset_type, efi_status_t status,
 				 unsigned long data_size, efi_char16_t *data);
+typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
+						unsigned long descriptor_size,
+						u32 descriptor_version,
+						efi_memory_desc_t *virtual_map);
 
 /*
  *  EFI Configuration Table and GUID definitions
@@ -194,12 +209,15 @@ typedef void efi_reset_system_t (int res
 #define HCDP_TABLE_GUID	\
     EFI_GUID(  0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
 
+#define UGA_IO_PROTOCOL_GUID \
+    EFI_GUID(  0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
+
 typedef struct {
 	efi_guid_t guid;
 	unsigned long table;
 } efi_config_table_t;
 
-#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
+#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 #define EFI_SYSTEM_TABLE_REVISION  ((1 << 16) | 00)
 
 typedef struct {
@@ -218,6 +236,13 @@ typedef struct {
 	unsigned long tables;
 } efi_system_table_t;
 
+struct efi_memory_map {
+	efi_memory_desc_t *phys_map;
+	efi_memory_desc_t *map;
+	int nr_map;
+	unsigned long desc_version;
+};
+
 /*
  * All runtime access to EFI goes through this structure:
  */
@@ -230,6 +255,7 @@ extern struct efi {
 	void *sal_systab;		/* SAL system table */
 	void *boot_info;		/* boot info table */
 	void *hcdp;			/* HCDP table */
+	void *uga;			/* UGA table */
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
 	efi_get_wakeup_time_t *get_wakeup_time;
@@ -239,6 +265,7 @@ extern struct efi {
 	efi_set_variable_t *set_variable;
 	efi_get_next_high_mono_count_t *get_next_high_mono_count;
 	efi_reset_system_t *reset_system;
+	efi_set_virtual_address_map_t *set_virtual_address_map;
 } efi;
 
 static inline int
@@ -260,12 +287,25 @@ efi_guid_unparse(efi_guid_t *guid, char 
 
 extern void efi_init (void);
 extern void efi_map_pal_code (void);
+extern void efi_map_memmap(void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
+extern void efi_initialize_iomem_resources(struct resource *code_resource,
+					struct resource *data_resource);
+extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc);
+extern unsigned long inline __init efi_get_time(void);
+extern int inline __init efi_set_rtc_mmss(unsigned long nowtime);
+extern struct efi_memory_map memmap;
+
+#ifdef CONFIG_EFI
+extern int efi_enabled;
+#else
+#define efi_enabled 0
+#endif
 
 /*
  * Variable Attributes
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/fs.h 001-linus.patch/include/linux/fs.h
--- 000-virgin/include/linux/fs.h	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/include/linux/fs.h	Tue Dec 30 16:38:57 2003
@@ -630,6 +630,7 @@ extern int __break_lease(struct inode *i
 extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void steal_locks(fl_owner_t from);
 
 struct fasync_struct {
 	int	magic;
@@ -1408,5 +1409,8 @@ static inline ino_t parent_ino(struct de
 	return res;
 }
 
+/* kernel/fork.c */
+extern int unshare_files(void);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_FS_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/i2c-dev.h 001-linus.patch/include/linux/i2c-dev.h
--- 000-virgin/include/linux/i2c-dev.h	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/include/linux/i2c-dev.h	Tue Dec 30 16:38:57 2003
@@ -43,4 +43,6 @@ struct i2c_rdwr_ioctl_data {
 	__u32 nmsgs;			/* number of i2c_msgs */
 };
 
+#define  I2C_RDRW_IOCTL_MAX_MSGS	42
+
 #endif /* _LINUX_I2C_DEV_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/i2c-id.h 001-linus.patch/include/linux/i2c-id.h
--- 000-virgin/include/linux/i2c-id.h	Wed Dec 17 18:58:07 2003
+++ 001-linus.patch/include/linux/i2c-id.h	Tue Dec 30 16:38:57 2003
@@ -258,6 +258,7 @@
 #define I2C_HW_SMBUS_AMD8111	0x0a
 #define I2C_HW_SMBUS_SCX200	0x0b
 #define I2C_HW_SMBUS_NFORCE2	0x0c
+#define I2C_HW_SMBUS_W9968CF	0x0d
 
 /* --- ISA pseudo-adapter						*/
 #define I2C_HW_ISA 0x00
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/ide.h 001-linus.patch/include/linux/ide.h
--- 000-virgin/include/linux/ide.h	Wed Dec 17 18:58:44 2003
+++ 001-linus.patch/include/linux/ide.h	Tue Dec 30 16:38:57 2003
@@ -1693,6 +1693,8 @@ extern void ide_setup_pci_devices(struct
 #define GOOD_DMA_DRIVE		1
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+extern int ide_build_sglist(ide_drive_t *, struct request *);
+extern int ide_raw_build_sglist(ide_drive_t *, struct request *);
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
 extern void ide_destroy_dmatable(ide_drive_t *);
 extern ide_startstop_t ide_dma_intr(ide_drive_t *);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/input.h 001-linus.patch/include/linux/input.h
--- 000-virgin/include/linux/input.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/linux/input.h	Tue Dec 30 16:38:57 2003
@@ -870,6 +870,7 @@ struct input_handler {
 	char *name;
 
 	struct input_device_id *id_table;
+	struct input_device_id *blacklist;
 
 	struct list_head	h_list;
 	struct list_head	node;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/jiffies.h 001-linus.patch/include/linux/jiffies.h
--- 000-virgin/include/linux/jiffies.h	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/include/linux/jiffies.h	Tue Dec 30 16:38:57 2003
@@ -10,7 +10,7 @@
 
 /*
  * The 64-bit value is not volatile - you MUST NOT read it
- * without holding read_lock_irq(&xtime_lock).
+ * without sampling the sequence number in xtime_lock.
  * get_jiffies_64() will do this for you as appropriate.
  */
 extern u64 jiffies_64;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/kernel.h 001-linus.patch/include/linux/kernel.h
--- 000-virgin/include/linux/kernel.h	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/include/linux/kernel.h	Tue Dec 30 16:38:57 2003
@@ -87,6 +87,8 @@ extern int session_of_pgrp(int pgrp);
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
 
+unsigned long int_sqrt(unsigned long);
+
 static inline void console_silent(void)
 {
 	console_loglevel = 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/keyboard.h 001-linus.patch/include/linux/keyboard.h
--- 000-virgin/include/linux/keyboard.h	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/include/linux/keyboard.h	Tue Dec 30 16:38:57 2003
@@ -2,7 +2,6 @@
 #define __LINUX_KEYBOARD_H
 
 #include <linux/wait.h>
-#include <linux/input.h>
 
 #define KG_SHIFT	0
 #define KG_CTRL		2
@@ -17,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		(KEY_MAX+1)
+#define NR_KEYS		255
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/libata.h 001-linus.patch/include/linux/libata.h
--- 000-virgin/include/linux/libata.h	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/include/linux/libata.h	Tue Dec 30 16:38:57 2003
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <linux/ata.h>
 
+
 /*
  * compile-time options
  */
@@ -66,8 +67,6 @@
 
 /* defines only for the constants which don't work well as enums */
 #define ATA_TAG_POISON		0xfafbfcfdU
-#define ATA_DMA_BOUNDARY	0xffffUL
-#define ATA_DMA_MASK		0xffffffffULL
 
 enum {
 	/* various global constants */
@@ -171,6 +170,7 @@ enum {
 };
 
 /* forward declarations */
+struct scsi_device;
 struct ata_port_operations;
 struct ata_port;
 struct ata_queued_cmd;
@@ -247,8 +247,8 @@ struct ata_queued_cmd {
 	struct ata_port		*ap;
 	struct ata_device	*dev;
 
-	Scsi_Cmnd		*scsicmd;
-	void			(*scsidone)(Scsi_Cmnd *);
+	struct scsi_cmnd		*scsicmd;
+	void			(*scsidone)(struct scsi_cmnd *);
 
 	struct list_head	node;
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
@@ -403,7 +403,7 @@ extern int ata_pci_init_one (struct pci_
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 extern int ata_device_add(struct ata_probe_ent *ent);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
-extern int ata_scsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
+extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
@@ -427,6 +427,9 @@ extern void ata_bmdma_start_pio (struct 
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat, unsigned int done_late);
 extern void ata_eng_timeout(struct ata_port *ap);
+extern int ata_std_bios_param(struct scsi_device *sdev,
+			      struct block_device *bdev,
+			      sector_t capacity, int geom[]);
 
 
 static inline unsigned long msecs_to_jiffies(unsigned long msecs)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/list.h 001-linus.patch/include/linux/list.h
--- 000-virgin/include/linux/list.h	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/include/linux/list.h	Tue Dec 30 16:38:57 2003
@@ -212,6 +212,12 @@ static inline int list_empty(const struc
  * list_empty_careful - tests whether a list is
  * empty _and_ checks that no other CPU might be
  * in the process of still modifying either member
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ *
  * @head: the list to test.
  */
 static inline int list_empty_careful(const struct list_head *head)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/mm.h 001-linus.patch/include/linux/mm.h
--- 000-virgin/include/linux/mm.h	Wed Dec 17 18:58:05 2003
+++ 001-linus.patch/include/linux/mm.h	Tue Dec 30 16:38:57 2003
@@ -143,7 +143,7 @@ extern pgprot_t protection_map[16];
 struct vm_operations_struct {
 	void (*open)(struct vm_area_struct * area);
 	void (*close)(struct vm_area_struct * area);
-	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int unused);
+	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
 	int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
 };
 
@@ -322,8 +322,10 @@ static inline void put_page(struct page 
 /*
  * The zone field is never updated after free_area_init_core()
  * sets it, so none of the operations on it need to be atomic.
+ * We'll have up to log2(MAX_NUMNODES * MAX_NR_ZONES) zones
+ * total, so we use NODES_SHIFT here to get enough bits.
  */
-#define ZONE_SHIFT (BITS_PER_LONG - 8)
+#define ZONE_SHIFT (BITS_PER_LONG - NODES_SHIFT - MAX_NR_ZONES_SHIFT)
 
 struct zone;
 extern struct zone *zone_table[];
@@ -405,7 +407,7 @@ static inline int page_mapped(struct pag
 extern void show_free_areas(void);
 
 struct page *shmem_nopage(struct vm_area_struct * vma,
-			unsigned long address, int unused);
+			unsigned long address, int *type);
 struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
 void shmem_lock(struct file * file, int lock);
 int shmem_zero_setup(struct vm_area_struct *);
@@ -563,7 +565,7 @@ extern unsigned long page_unuse(struct p
 extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
-extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);
+struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
 
 /* mm/page-writeback.c */
 int write_one_page(struct page *page, int wait);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/mmzone.h 001-linus.patch/include/linux/mmzone.h
--- 000-virgin/include/linux/mmzone.h	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/include/linux/mmzone.h	Tue Dec 30 16:38:57 2003
@@ -159,7 +159,10 @@ struct zone {
 #define ZONE_DMA		0
 #define ZONE_NORMAL		1
 #define ZONE_HIGHMEM		2
-#define MAX_NR_ZONES		3
+
+#define MAX_NR_ZONES		3	/* Sync this with MAX_NR_ZONES_SHIFT */
+#define MAX_NR_ZONES_SHIFT	2	/* ceil(log2(MAX_NR_ZONES)) */
+
 #define GFP_ZONEMASK	0x03
 
 /*
@@ -284,8 +287,6 @@ struct ctl_table;
 struct file;
 int min_free_kbytes_sysctl_handler(struct ctl_table *, int, struct file *, 
 					  void *, size_t *);
-extern void setup_per_zone_pages_min(void);
-
 
 #ifdef CONFIG_NUMA
 #define MAX_NR_MEMBLKS	BITS_PER_LONG /* Max number of Memory Blocks */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/nbd.h 001-linus.patch/include/linux/nbd.h
--- 000-virgin/include/linux/nbd.h	Wed Dec 17 18:59:39 2003
+++ 001-linus.patch/include/linux/nbd.h	Tue Dec 30 16:38:57 2003
@@ -35,6 +35,9 @@ enum {
 /* Define PARANOIA to include extra sanity checking code in here & driver */
 #define PARANOIA
 
+/* userspace doesn't need the nbd_device structure */
+#ifdef __KERNEL__
+
 struct nbd_device {
 	int flags;
 	int harderror;		/* Code of hard error			*/
@@ -53,6 +56,8 @@ struct nbd_device {
 	u64 bytesize;
 };
 
+#endif
+
 /* This now IS in some kind of include file...	*/
 
 /* These are send over network in request/reply magic field */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/page-flags.h 001-linus.patch/include/linux/page-flags.h
--- 000-virgin/include/linux/page-flags.h	Wed Dec 17 18:59:06 2003
+++ 001-linus.patch/include/linux/page-flags.h	Tue Dec 30 16:38:57 2003
@@ -133,6 +133,7 @@ extern void get_full_page_state(struct p
 
 #define inc_page_state(member)	mod_page_state(member, 1UL)
 #define dec_page_state(member)	mod_page_state(member, 0UL - 1)
+#define add_page_state(member,delta) mod_page_state(member, (delta))
 #define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta))
 
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/pagemap.h 001-linus.patch/include/linux/pagemap.h
--- 000-virgin/include/linux/pagemap.h	Wed Dec 17 18:58:04 2003
+++ 001-linus.patch/include/linux/pagemap.h	Tue Dec 30 16:38:57 2003
@@ -8,7 +8,6 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/highmem.h>
-#include <linux/pagemap.h>
 #include <asm/uaccess.h>
 #include <linux/gfp.h>
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/parser.h 001-linus.patch/include/linux/parser.h
--- 000-virgin/include/linux/parser.h	Wed Dec 17 19:00:01 2003
+++ 001-linus.patch/include/linux/parser.h	Tue Dec 30 16:38:57 2003
@@ -1,3 +1,14 @@
+/*
+ * linux/include/linux/parser.h
+ *
+ * Header for lib/parser.c
+ * Intended use of these functions is parsing filesystem argument lists,
+ * but could potentially be used anywhere else that simple option=arg
+ * parsing is required.
+ */
+
+
+/* associates an integer enumerator with a pattern string. */
 struct match_token {
 	int token;
 	char *pattern;
@@ -5,15 +16,16 @@ struct match_token {
 
 typedef struct match_token match_table_t[];
 
+/* Maximum number of arguments that match_token will find in a pattern */
 enum {MAX_OPT_ARGS = 3};
 
+/* Describe the location within a string of a substring */
 typedef struct {
 	char *from;
 	char *to;
 } substring_t;
 
-int match_token(char *s, match_table_t table, substring_t args[]);
-
+int match_token(char *, match_table_t table, substring_t args[]);
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/pci.h 001-linus.patch/include/linux/pci.h
--- 000-virgin/include/linux/pci.h	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/include/linux/pci.h	Tue Dec 30 16:38:57 2003
@@ -36,6 +36,7 @@
 #define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
 #define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
 #define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 
 #define PCI_STATUS		0x06	/* 16 bits */
 #define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
@@ -198,6 +199,8 @@
 #define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
 #define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
 #define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
+#define  PCI_CAP_ID_EXP 	0x10	/* PCI Express */
+#define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
 #define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
 #define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
 #define PCI_CAP_SIZEOF		4
@@ -275,11 +278,13 @@
 #define  PCI_MSI_FLAGS_QSIZE	0x70	/* Message queue size configured */
 #define  PCI_MSI_FLAGS_QMASK	0x0e	/* Maximum queue size available */
 #define  PCI_MSI_FLAGS_ENABLE	0x01	/* MSI feature enabled */
+#define  PCI_MSI_FLAGS_MASKBIT	0x100	/* 64-bit mask bits allowed */
 #define PCI_MSI_RFU		3	/* Rest of capability flags */
 #define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
 #define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
 #define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
 #define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
+#define PCI_MSI_MASK_BIT	16	/* Mask bits register */
 
 /* CompactPCI Hotswap Register */
 
@@ -695,6 +700,18 @@ void pci_pool_free (struct pci_pool *poo
 extern struct pci_dev *isa_bridge;
 #endif
 
+#ifndef CONFIG_PCI_USE_VECTOR
+static inline void pci_scan_msi_device(struct pci_dev *dev) {}
+static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
+static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+#else
+extern void pci_scan_msi_device(struct pci_dev *dev);
+extern int pci_enable_msi(struct pci_dev *dev);
+extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+extern int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec);
+extern int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec);
+#endif
+
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/pci_ids.h 001-linus.patch/include/linux/pci_ids.h
--- 000-virgin/include/linux/pci_ids.h	Wed Dec 17 18:58:47 2003
+++ 001-linus.patch/include/linux/pci_ids.h	Tue Dec 30 16:38:57 2003
@@ -900,6 +900,7 @@
 
 #define PCI_VENDOR_ID_SGI		0x10a9
 #define PCI_DEVICE_ID_SGI_IOC3		0x0003
+#define PCI_DEVICE_ID_SGI_IOC4		0x100a
 #define PCI_VENDOR_ID_SGI_LITHIUM	0x1002
 
 #define PCI_VENDOR_ID_ACC		0x10aa
@@ -2052,6 +2053,7 @@
 #define PCI_DEVICE_ID_INTEL_82443MX_3	0x719b
 #define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
 #define PCI_DEVICE_ID_INTEL_82443GX_1	0x71a1
+#define PCI_DEVICE_ID_INTEL_82443GX_2	0x71a2
 #define PCI_DEVICE_ID_INTEL_82372FB_0	0x7600
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
 #define PCI_DEVICE_ID_INTEL_82372FB_2	0x7602
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/pci_msi.h 001-linus.patch/include/linux/pci_msi.h
--- 000-virgin/include/linux/pci_msi.h	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/include/linux/pci_msi.h	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,193 @@
+/*
+ *	../include/linux/pci_msi.h
+ *
+ */
+
+#ifndef _ASM_PCI_MSI_H
+#define _ASM_PCI_MSI_H
+
+#include <linux/pci.h>
+
+#define MSI_AUTO -1
+#define NR_REPEATS	23
+#define NR_RESERVED_VECTORS 3 /*FIRST_DEVICE_VECTOR,FIRST_SYSTEM_VECTOR,0x80 */
+
+/*
+ * Assume the maximum number of hot plug slots supported by the system is about
+ * ten. The worstcase is that each of these slots is hot-added with a device,
+ * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which
+ * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined
+ * as below to ensure at least one message is assigned to each detected MSI/
+ * MSI-X device function.
+ */
+#define NR_HP_RESERVED_VECTORS 	20
+
+extern int vector_irq[NR_IRQS];
+extern cpumask_t pending_irq_balance_cpumask[NR_IRQS];
+extern void (*interrupt[NR_IRQS])(void);
+
+#ifdef CONFIG_SMP
+#define set_msi_irq_affinity	set_msi_affinity
+#else
+#define set_msi_irq_affinity	NULL
+static inline void move_msi(int vector) {}
+#endif
+
+#ifndef CONFIG_X86_IO_APIC
+static inline int get_ioapic_vector(struct pci_dev *dev) { return -1;}
+static inline void restore_ioapic_irq_handler(int irq) {}
+#else
+extern void restore_ioapic_irq_handler(int irq);
+#endif
+
+/*
+ * MSI-X Address Register
+ */
+#define PCI_MSIX_FLAGS_QSIZE		0x7FF
+#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
+#define PCI_MSIX_FLAGS_BIRMASK		(7 << 0)
+#define PCI_MSIX_FLAGS_BITMASK		(1 << 0)
+
+#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET	0
+#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET	4
+#define PCI_MSIX_ENTRY_DATA_OFFSET		8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET	12
+#define PCI_MSIX_ENTRY_SIZE			16
+
+#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
+#define msi_lower_address_reg(base)	(base + PCI_MSI_ADDRESS_LO)
+#define msi_upper_address_reg(base)	(base + PCI_MSI_ADDRESS_HI)
+#define msi_data_reg(base, is64bit)	\
+	( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
+#define msi_mask_bits_reg(base, is64bit) \
+	( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
+#define msi_disable(control)		control &= ~PCI_MSI_FLAGS_ENABLE
+#define multi_msi_capable(control) \
+	(1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1))
+#define multi_msi_enable(control, num) \
+	control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE);
+#define is_64bit_address(control)	(control & PCI_MSI_FLAGS_64BIT)
+#define is_mask_bit_support(control)	(control & PCI_MSI_FLAGS_MASKBIT)
+#define msi_enable(control, num) multi_msi_enable(control, num); \
+	control |= PCI_MSI_FLAGS_ENABLE
+
+#define msix_control_reg		msi_control_reg
+#define msix_table_offset_reg(base)	(base + 0x04)
+#define msix_pba_offset_reg(base)	(base + 0x08)
+#define msix_enable(control)	 	control |= PCI_MSIX_FLAGS_ENABLE
+#define msix_disable(control)	 	control &= ~PCI_MSIX_FLAGS_ENABLE
+#define msix_table_size(control) 	((control & PCI_MSIX_FLAGS_QSIZE)+1)
+#define multi_msix_capable		msix_table_size
+#define msix_unmask(address)	 	(address & ~PCI_MSIX_FLAGS_BITMASK)
+#define msix_mask(address)		(address | PCI_MSIX_FLAGS_BITMASK)
+#define msix_is_pending(address) 	(address & PCI_MSIX_FLAGS_PENDMASK)
+
+extern char __dbg_str_buf[256];
+#define _DEFINE_DBG_BUFFER	char __dbg_str_buf[256];
+#define _DBG_K_TRACE_ENTRY	((unsigned int)0x00000001)
+#define _DBG_K_TRACE_EXIT	((unsigned int)0x00000002)
+#define _DBG_K_INFO		((unsigned int)0x00000004)
+#define _DBG_K_ERROR		((unsigned int)0x00000008)
+#define _DBG_K_TRACE	(_DBG_K_TRACE_ENTRY | _DBG_K_TRACE_EXIT)
+
+#define _DEBUG_LEVEL	(_DBG_K_INFO | _DBG_K_ERROR | _DBG_K_TRACE)
+#define _DBG_PRINT( dbg_flags, args... )		\
+if ( _DEBUG_LEVEL & (dbg_flags) )			\
+{							\
+	int len;					\
+	len = sprintf(__dbg_str_buf, "%s:%d: %s ", 	\
+		__FILE__, __LINE__, __FUNCTION__ ); 	\
+	sprintf(__dbg_str_buf + len, args);		\
+	printk(KERN_INFO "%s\n", __dbg_str_buf);	\
+}
+
+#define MSI_FUNCTION_TRACE_ENTER	\
+	_DBG_PRINT (_DBG_K_TRACE_ENTRY, "%s", "[Entry]");
+#define MSI_FUNCTION_TRACE_EXIT		\
+	_DBG_PRINT (_DBG_K_TRACE_EXIT, "%s", "[Entry]");
+
+/*
+ * MSI Defined Data Structures
+ */
+#define MSI_ADDRESS_HEADER		0xfee
+#define MSI_ADDRESS_HEADER_SHIFT	12
+#define MSI_ADDRESS_HEADER_MASK		0xfff000
+#define MSI_TARGET_CPU_SHIFT		4
+#define MSI_TARGET_CPU_MASK		0xff
+#define MSI_DELIVERY_MODE		0
+#define MSI_LEVEL_MODE			1	/* Edge always assert */
+#define MSI_TRIGGER_MODE		0	/* MSI is edge sensitive */
+#define MSI_LOGICAL_MODE		1
+#define MSI_REDIRECTION_HINT_MODE	0
+#ifdef CONFIG_SMP
+#define MSI_TARGET_CPU			logical_smp_processor_id()
+#else
+#define MSI_TARGET_CPU			TARGET_CPUS
+#endif
+
+struct msg_data {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u32	vector		:  8;
+	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
+	__u32	reserved_1	:  3;
+	__u32	level		:  1;	/* 0: deassert | 1: assert */
+	__u32	trigger		:  1;	/* 0: edge | 1: level */
+	__u32	reserved_2	: 16;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	__u32	reserved_2	: 16;
+	__u32	trigger		:  1;	/* 0: edge | 1: level */
+	__u32	level		:  1;	/* 0: deassert | 1: assert */
+	__u32	reserved_1	:  3;
+	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
+	__u32	vector		:  8;
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
+} __attribute__ ((packed));
+
+struct msg_address {
+	union {
+		struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+			__u32	reserved_1	:  2;
+			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
+			__u32	redirection_hint:  1;  	/*0: dedicated CPU
+							  1: lowest priority */
+			__u32	reserved_2	:  4;
+ 			__u32	dest_id		: 24;	/* Destination ID */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ 			__u32	dest_id		: 24;	/* Destination ID */
+			__u32	reserved_2	:  4;
+			__u32	redirection_hint:  1;  	/*0: dedicated CPU
+							  1: lowest priority */
+			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
+			__u32	reserved_1	:  2;
+#else
+#error "Bitfield endianness not defined! Check your byteorder.h"
+#endif
+      		}u;
+       		__u32  value;
+	}lo_address;
+	__u32 	hi_address;
+} __attribute__ ((packed));
+
+struct msi_desc {
+	struct {
+		__u8	type	: 5; 	/* {0: unused, 5h:MSI, 11h:MSI-X} */
+		__u8	maskbit	: 1; 	/* mask-pending bit supported ?   */
+		__u8	reserved: 2; 	/* reserved			  */
+		__u8	entry_nr;    	/* specific enabled entry 	  */
+		__u8	default_vector; /* default pre-assigned vector    */
+		__u8	current_cpu; 	/* current destination cpu	  */
+	}msi_attrib;
+
+	struct {
+		__u16	head;
+		__u16	tail;
+	}link;
+
+	unsigned long mask_base;
+	struct pci_dev *dev;
+};
+
+#endif /* _ASM_PCI_MSI_H */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/percpu_counter.h 001-linus.patch/include/linux/percpu_counter.h
--- 000-virgin/include/linux/percpu_counter.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/include/linux/percpu_counter.h	Tue Dec 30 16:38:57 2003
@@ -8,17 +8,14 @@
 #include <linux/spinlock.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
+#include <linux/percpu.h>
 
 #ifdef CONFIG_SMP
 
-struct __percpu_counter {
-	long count;
-} ____cacheline_aligned;
-
 struct percpu_counter {
 	spinlock_t lock;
 	long count;
-	struct __percpu_counter counters[NR_CPUS];
+	long *counters;
 };
 
 #if NR_CPUS >= 16
@@ -29,12 +26,14 @@ struct percpu_counter {
 
 static inline void percpu_counter_init(struct percpu_counter *fbc)
 {
-	int i;
-
 	spin_lock_init(&fbc->lock);
 	fbc->count = 0;
-	for (i = 0; i < NR_CPUS; i++)
-		fbc->counters[i].count = 0;
+	fbc->counters = alloc_percpu(long);
+}
+
+static inline void percpu_counter_destroy(struct percpu_counter *fbc)
+{
+	free_percpu(fbc->counters);
 }
 
 void percpu_counter_mod(struct percpu_counter *fbc, long amount);
@@ -69,6 +68,10 @@ static inline void percpu_counter_init(s
 	fbc->count = 0;
 }
 
+static inline void percpu_counter_destroy(struct percpu_counter *fbc)
+{
+}
+
 static inline void
 percpu_counter_mod(struct percpu_counter *fbc, long amount)
 {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/proc_fs.h 001-linus.patch/include/linux/proc_fs.h
--- 000-virgin/include/linux/proc_fs.h	Wed Dec 17 18:57:58 2003
+++ 001-linus.patch/include/linux/proc_fs.h	Tue Dec 30 16:38:57 2003
@@ -141,6 +141,8 @@ extern void proc_rtas_init(void);
 extern struct proc_dir_entry *proc_symlink(const char *,
 		struct proc_dir_entry *, const char *);
 extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
+extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
+			struct proc_dir_entry *parent);
 
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *base, 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/quota.h 001-linus.patch/include/linux/quota.h
--- 000-virgin/include/linux/quota.h	Wed Dec 17 18:59:15 2003
+++ 001-linus.patch/include/linux/quota.h	Tue Dec 30 16:38:57 2003
@@ -250,7 +250,7 @@ struct dquot_operations {
 	void (*free_space) (struct inode *, qsize_t);
 	void (*free_inode) (const struct inode *, unsigned long);
 	int (*transfer) (struct inode *, struct iattr *);
-	int (*sync_dquot) (struct dquot *);
+	int (*write_dquot) (struct dquot *);
 };
 
 /* Operations handling requests from userspace */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/sched.h 001-linus.patch/include/linux/sched.h
--- 000-virgin/include/linux/sched.h	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/include/linux/sched.h	Tue Dec 30 16:38:57 2003
@@ -205,7 +205,6 @@ struct mm_struct {
 	unsigned long rss, total_vm, locked_vm;
 	unsigned long def_flags;
 	cpumask_t cpu_vm_mask;
-	unsigned long swap_address;
 
 	unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/serio.h 001-linus.patch/include/linux/serio.h
--- 000-virgin/include/linux/serio.h	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/include/linux/serio.h	Tue Dec 30 16:38:57 2003
@@ -49,6 +49,7 @@ struct serio_dev {
 	irqreturn_t (*interrupt)(struct serio *, unsigned char,
 			unsigned int, struct pt_regs *);
 	void (*connect)(struct serio *, struct serio_dev *dev);
+	int  (*reconnect)(struct serio *);
 	void (*disconnect)(struct serio *);
 	void (*cleanup)(struct serio *);
 
@@ -58,12 +59,15 @@ struct serio_dev {
 int serio_open(struct serio *serio, struct serio_dev *dev);
 void serio_close(struct serio *serio);
 void serio_rescan(struct serio *serio);
+void serio_reconnect(struct serio *serio);
 irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
 
 void serio_register_port(struct serio *serio);
-void serio_register_slave_port(struct serio *serio);
+void serio_register_port_delayed(struct serio *serio);
+void __serio_register_port(struct serio *serio);
 void serio_unregister_port(struct serio *serio);
-void serio_unregister_slave_port(struct serio *serio);
+void serio_unregister_port_delayed(struct serio *serio);
+void __serio_unregister_port(struct serio *serio);
 void serio_register_device(struct serio_dev *dev);
 void serio_unregister_device(struct serio_dev *dev);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/sysctl.h 001-linus.patch/include/linux/sysctl.h
--- 000-virgin/include/linux/sysctl.h	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/include/linux/sysctl.h	Tue Dec 30 16:38:57 2003
@@ -579,6 +579,14 @@ enum {
 	NET_SCTP_MAX_BURST               = 12,
 };
 
+/* /proc/sys/net/bridge */
+enum {
+	NET_BRIDGE_NF_CALL_ARPTABLES = 1,
+	NET_BRIDGE_NF_CALL_IPTABLES = 2,
+	NET_BRIDGE_NF_CALL_IP6TABLES = 3,
+	NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4,
+};
+
 /* CTL_PROC names: */
 
 /* CTL_FS names: */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/usb.h 001-linus.patch/include/linux/usb.h
--- 000-virgin/include/linux/usb.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/linux/usb.h	Tue Dec 30 16:38:57 2003
@@ -414,9 +414,6 @@ static inline int usb_make_path (struct 
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
  *	or your driver's probe function will never get called.
  * @driver: the driver model core driver structure.
- * @serialize: a semaphore used to serialize access to this driver.  Used
- * 	in the probe and disconnect functions.  Only the USB core should use
- * 	this lock.
  *
  * USB drivers must provide a name, probe() and disconnect() methods,
  * and an id_table.  Other driver fields are optional.
@@ -451,8 +448,6 @@ struct usb_driver {
 	const struct usb_device_id *id_table;
 
 	struct device_driver driver;
-
-	struct semaphore serialize;
 };
 #define	to_usb_driver(d) container_of(d, struct usb_driver, driver)
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/usb_ch9.h 001-linus.patch/include/linux/usb_ch9.h
--- 000-virgin/include/linux/usb_ch9.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/linux/usb_ch9.h	Tue Dec 30 16:38:57 2003
@@ -116,6 +116,17 @@ struct usb_ctrlrequest {
 #define USB_DT_DEVICE_QUALIFIER		0x06
 #define USB_DT_OTHER_SPEED_CONFIG	0x07
 #define USB_DT_INTERFACE_POWER		0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG			0x09
+#define USB_DT_DEBUG			0x0a
+#define USB_DT_INTERFACE_ASSOCIATION	0x0b
+
+/* conventional codes for class-specific descriptors */
+#define USB_DT_CS_DEVICE		0x21
+#define USB_DT_CS_CONFIG		0x22
+#define USB_DT_CS_STRING		0x23
+#define USB_DT_CS_INTERFACE		0x24
+#define USB_DT_CS_ENDPOINT		0x25
 
 /* All standard descriptors have these 2 fields at the beginning */
 struct usb_descriptor_header {
@@ -165,6 +176,7 @@ struct usb_device_descriptor {
 #define USB_CLASS_CDC_DATA		0x0a
 #define USB_CLASS_CSCID			0x0b	/* chip+ smart card */
 #define USB_CLASS_CONTENT_SEC		0x0d	/* content security */
+#define USB_CLASS_VIDEO			0x0e
 #define USB_CLASS_APP_SPEC		0xfe
 #define USB_CLASS_VENDOR_SPEC		0xff
 
@@ -281,6 +293,36 @@ struct usb_qualifier_descriptor {
 } __attribute__ ((packed));
 
 
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_OTG (from OTG 1.0a supplement) */
+struct usb_otg_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+
+	__u8  bmAttributes;	/* support for HNP, SRP, etc */
+} __attribute__ ((packed));
+
+/* from usb_otg_descriptor.bmAttributes */
+#define USB_OTG_SRP		(1 << 0)
+#define USB_OTG_HNP		(1 << 1)	/* swap host/device roles */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+
+	__u8  bFirstInterface;
+	__u8  bInterfaceCount;
+	__u8  bFunctionClass;
+	__u8  bFunctionSubClass;
+	__u8  bFunctionProtocol;
+	__u8  iFunction;
+} __attribute__ ((packed));
+
+
 /*-------------------------------------------------------------------------*/
 
 /* USB 2.0 defines three speeds, here's how Linux identifies them */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/usb_gadget.h 001-linus.patch/include/linux/usb_gadget.h
--- 000-virgin/include/linux/usb_gadget.h	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/include/linux/usb_gadget.h	Tue Dec 30 16:38:57 2003
@@ -28,12 +28,20 @@ struct usb_ep;
  * 	for mapping and unmapping the buffer.
  * @length: Length of that data
  * @no_interrupt: If true, hints that no completion irq is needed.
- *	Helpful sometimes with deep request queues.
+ *	Helpful sometimes with deep request queues that are handled
+ *	directly by DMA controllers.
  * @zero: If true, when writing data, makes the last packet be "short"
  *     by adding a zero length packet as needed;
  * @short_not_ok: When reading data, makes short packets be
  *     treated as errors (queue stops advancing till cleanup).
- * @complete: Function called when request completes
+ * @complete: Function called when request completes, so this request and
+ *	its buffer may be re-used.
+ *	Reads terminate with a short packet, or when the buffer fills,
+ *	whichever comes first.  When writes terminate, some data bytes
+ *	will usually still be in flight (often in a hardware fifo).
+ *	Errors (for reads or writes) stop the queue from advancing
+ *	until the completion function returns, so that any transfers
+ *	invalidated by the error may first be dequeued.
  * @context: For use by the completion callback
  * @list: For use by the gadget driver.
  * @status: Reports completion code, zero or a negative errno.
@@ -41,12 +49,13 @@ struct usb_ep;
  * 	the completion callback returns.
  * 	Code "-ESHUTDOWN" indicates completion caused by device disconnect,
  * 	or when the driver disabled the endpoint.
- * @actual: Reports actual bytes transferred.  For reads (OUT
+ * @actual: Reports bytes transferred to/from the buffer.  For reads (OUT
  * 	transfers) this may be less than the requested length.  If the
  * 	short_not_ok flag is set, short reads are treated as errors
  * 	even when status otherwise indicates successful completion.
- * 	Note that for writes (IN transfers) the data bytes may still
- * 	reside in a device-side FIFO.
+ * 	Note that for writes (IN transfers) some data bytes may still
+ * 	reside in a device-side FIFO when the request is reported as
+ *	complete.
  *
  * These are allocated/freed through the endpoint they're used with.  The
  * hardware's driver can add extra per-request data to the memory it returns,
@@ -287,6 +296,9 @@ usb_ep_free_buffer (struct usb_ep *ep, v
  * Each request is turned into one or more packets.  The controller driver
  * never merges adjacent requests into the same packet.  OUT transfers
  * will sometimes use data that's already buffered in the hardware.
+ * Drivers can rely on the fact that the first byte of the request's buffer
+ * always corresponds to the first byte of some USB packet, for both
+ * IN and OUT transfers.
  *
  * Bulk endpoints can queue any amount of data; the transfer is packetized
  * automatically.  The last packet will be short if the request doesn't fill it
@@ -361,6 +373,9 @@ static inline int usb_ep_dequeue (struct
  *
  * Returns zero, or a negative error code.  On success, this call sets
  * underlying hardware state that blocks data transfers.
+ * Attempts to halt IN endpoints will fail (returning -EAGAIN) if any
+ * transfer requests are still queued, or if the controller hardware
+ * (usually a FIFO) still holds bytes that the host hasn't collected.
  */
 static inline int
 usb_ep_set_halt (struct usb_ep *ep)
@@ -393,8 +408,8 @@ usb_ep_clear_halt (struct usb_ep *ep)
  *
  * FIFO endpoints may have "unclaimed data" in them in certain cases,
  * such as after aborted transfers.  Hosts may not have collected all
- * the IN data written by the gadget driver, as reported by a request
- * completion.  The gadget driver may not have collected all the data
+ * the IN data written by the gadget driver (and reported by a request
+ * completion).  The gadget driver may not have collected all the data
  * written OUT to it by the host.  Drivers that need precise handling for
  * fault reporting or recovery may need to use this call.
  *
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/linux/videodev.h 001-linus.patch/include/linux/videodev.h
--- 000-virgin/include/linux/videodev.h	Wed Dec 17 19:00:03 2003
+++ 001-linus.patch/include/linux/videodev.h	Tue Dec 30 16:38:57 2003
@@ -429,6 +429,7 @@ struct video_code
 #define VID_HARDWARE_CPIA2	33
 #define VID_HARDWARE_VICAM      34
 #define VID_HARDWARE_SF16FMR2	35
+#define VID_HARDWARE_W9968CF	36	/* W996[87]CF JPEG USB Dual Mode Cam */
 #endif /* __LINUX_VIDEODEV_H */
 
 /*
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/net/ax25.h 001-linus.patch/include/net/ax25.h
--- 000-virgin/include/net/ax25.h	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/include/net/ax25.h	Tue Dec 30 16:38:57 2003
@@ -227,8 +227,7 @@ extern void ax25_cb_add(ax25_cb *);
 struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
 struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
 extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
-extern struct sock *ax25_addr_match(ax25_address *);
-extern void ax25_send_to_raw(struct sock *, struct sk_buff *, int);
+extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
 extern void ax25_destroy_socket(ax25_cb *);
 extern ax25_cb *ax25_create_cb(void);
 extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/include/net/pkt_cls.h 001-linus.patch/include/net/pkt_cls.h
--- 000-virgin/include/net/pkt_cls.h	Wed Dec 17 18:59:15 2003
+++ 001-linus.patch/include/net/pkt_cls.h	Tue Dec 30 16:38:57 2003
@@ -81,7 +81,12 @@ static inline int tc_classify(struct sk_
 	return -1;
 }
 
-
+static inline void tcf_destroy(struct tcf_proto *tp)
+{
+	tp->ops->destroy(tp);
+	module_put(tp->ops->owner);
+	kfree(tp);
+}
 
 extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
 extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/init/Kconfig 001-linus.patch/init/Kconfig
--- 000-virgin/init/Kconfig	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/init/Kconfig	Tue Dec 30 16:38:57 2003
@@ -196,6 +196,19 @@ config EPOLL
 
 source "drivers/block/Kconfig.iosched"
 
+config CC_OPTIMIZE_FOR_SIZE
+	bool "Optimize for size" if EMBEDDED
+	default y if ARM || H8300
+	default n
+	help
+	  Enabling this option will pass "-Os" instead of "-O2" to gcc
+	  resulting in a smaller kernel.
+
+	  WARNING: some versions of gcc may generate incorrect code with this
+	  option.  If problems are observed, a gcc upgrade may be needed.
+
+	  If unsure, say N.
+
 endmenu		# General setup
 
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/init/do_mounts.c 001-linus.patch/init/do_mounts.c
--- 000-virgin/init/do_mounts.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/init/do_mounts.c	Tue Dec 30 16:38:57 2003
@@ -130,11 +130,11 @@ fail:
  *	Driverfs is used to check if something is a disk name - it has
  *	all known disks under bus/block/devices.  If the disk name
  *	contains slashes, name of driverfs node has them replaced with
- *	dots.  try_name() does the actual checks, assuming that driverfs
+ *	bangs.  try_name() does the actual checks, assuming that driverfs
  *	is mounted on rootfs /sys.
  */
 
-dev_t name_to_dev_t(char *name)
+dev_t __init name_to_dev_t(char *name)
 {
 	char s[32];
 	char *p;
@@ -169,7 +169,7 @@ dev_t name_to_dev_t(char *name)
 	strcpy(s, name);
 	for (p = s; *p; p++)
 		if (*p == '/')
-			*p = '.';
+			*p = '!';
 	res = try_name(s, 0);
 	if (res)
 		goto done;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/init/main.c 001-linus.patch/init/main.c
--- 000-virgin/init/main.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/init/main.c	Tue Dec 30 16:38:57 2003
@@ -38,6 +38,7 @@
 #include <linux/moduleparam.h>
 #include <linux/writeback.h>
 #include <linux/cpu.h>
+#include <linux/efi.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -374,7 +375,7 @@ static void __init smp_init(void)
 
 static void rest_init(void)
 {
-	kernel_thread(init, NULL, CLONE_KERNEL);
+	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
 	unlock_kernel();
  	cpu_idle();
 } 
@@ -395,7 +396,6 @@ asmlinkage void __init start_kernel(void
 	lock_kernel();
 	printk(linux_banner);
 	setup_arch(&command_line);
-	setup_per_zone_pages_min();
 	setup_per_cpu_areas();
 
 	/*
@@ -443,6 +443,10 @@ asmlinkage void __init start_kernel(void
 	pidmap_init();
 	pgtable_cache_init();
 	pte_chain_init();
+#ifdef CONFIG_X86
+	if (efi_enabled)
+		efi_enter_virtual_mode();
+#endif
 	fork_init(num_physpages);
 	proc_caches_init();
 	buffer_init();
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/ipc/sem.c 001-linus.patch/ipc/sem.c
--- 000-virgin/ipc/sem.c	Wed Dec 17 18:58:41 2003
+++ 001-linus.patch/ipc/sem.c	Tue Dec 30 16:38:57 2003
@@ -59,6 +59,8 @@
  * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  * Enforced range limit on SEM_UNDO
  * (c) 2001 Red Hat Inc <alan@redhat.com>
+ * Lockless wakeup
+ * (c) 2003 Manfred Spraul <manfred@colorfullife.com>
  */
 
 #include <linux/config.h>
@@ -118,6 +120,40 @@ void __init sem_init (void)
 #endif
 }
 
+/*
+ * Lockless wakeup algorithm:
+ * Without the check/retry algorithm a lockless wakeup is possible:
+ * - queue.status is initialized to -EINTR before blocking.
+ * - wakeup is performed by
+ *	* unlinking the queue entry from sma->sem_pending
+ *	* setting queue.status to IN_WAKEUP
+ *	  This is the notification for the blocked thread that a
+ *	  result value is imminent.
+ *	* call wake_up_process
+ *	* set queue.status to the final value.
+ * - the previously blocked thread checks queue.status:
+ *   	* if it's IN_WAKEUP, then it must wait until the value changes
+ *   	* if it's not -EINTR, then the operation was completed by
+ *   	  update_queue. semtimedop can return queue.status without
+ *   	  performing any operation on the semaphore array.
+ *   	* otherwise it must acquire the spinlock and check what's up.
+ *
+ * The two-stage algorithm is necessary to protect against the following
+ * races:
+ * - if queue.status is set after wake_up_process, then the woken up idle
+ *   thread could race forward and try (and fail) to acquire sma->lock
+ *   before update_queue had a chance to set queue.status
+ * - if queue.status is written before wake_up_process and if the
+ *   blocked process is woken up by a signal between writing
+ *   queue.status and the wake_up_process, then the woken up
+ *   process could return from semtimedop and die by calling
+ *   sys_exit before wake_up_process is called. Then wake_up_process
+ *   will oops, because the task structure is already invalid.
+ *   (yes, this happened on s390 with sysv msg).
+ *
+ */
+#define IN_WAKEUP	1
+
 static int newary (key_t key, int nsems, int semflg)
 {
 	int id;
@@ -331,16 +367,25 @@ static void update_queue (struct sem_arr
 	int error;
 	struct sem_queue * q;
 
-	for (q = sma->sem_pending; q; q = q->next) {
-			
+	q = sma->sem_pending;
+	while(q) {
 		error = try_atomic_semop(sma, q->sops, q->nsops,
 					 q->undo, q->pid);
 
 		/* Does q->sleeper still need to sleep? */
 		if (error <= 0) {
-			q->status = error;
+			struct sem_queue *n;
 			remove_from_queue(sma,q);
+			n = q->next;
+			q->status = IN_WAKEUP;
 			wake_up_process(q->sleeper);
+			/* hands-off: q will disappear immediately after
+			 * writing q->status.
+			 */
+			q->status = error;
+			q = n;
+		} else {
+			q = q->next;
 		}
 	}
 }
@@ -409,10 +454,16 @@ static void freeary (struct sem_array *s
 		un->semid = -1;
 
 	/* Wake up all pending processes and let them fail with EIDRM. */
-	for (q = sma->sem_pending; q; q = q->next) {
-		q->status = -EIDRM;
+	q = sma->sem_pending;
+	while(q) {
+		struct sem_queue *n;
+		/* lazy remove_from_queue: we are killing the whole queue */
 		q->prev = NULL;
+		n = q->next;
+		q->status = IN_WAKEUP;
 		wake_up_process(q->sleeper); /* doesn't sleep */
+		q->status = -EIDRM;	/* hands-off q */
+		q = n;
 	}
 
 	/* Remove the semaphore set from the ID array*/
@@ -1083,6 +1134,18 @@ retry_undos:
 	else
 		schedule();
 
+	error = queue.status;
+	while(unlikely(error == IN_WAKEUP)) {
+		cpu_relax();
+		error = queue.status;
+	}
+
+	if (error != -EINTR) {
+		/* fast path: update_queue already obtained all requested
+		 * resources */
+		goto out_free;
+	}
+
 	sma = sem_lock(semid);
 	if(sma==NULL) {
 		if(queue.prev != NULL)
@@ -1095,7 +1158,7 @@ retry_undos:
 	 * If queue.status != -EINTR we are woken up by another process
 	 */
 	error = queue.status;
-	if (queue.status != -EINTR) {
+	if (error != -EINTR) {
 		goto out_unlock_free;
 	}
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/compat.c 001-linus.patch/kernel/compat.c
--- 000-virgin/kernel/compat.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/kernel/compat.c	Tue Dec 30 16:38:57 2003
@@ -22,14 +22,14 @@
 
 #include <asm/uaccess.h>
 
-int get_compat_timespec(struct timespec *ts, struct compat_timespec *cts)
+int get_compat_timespec(struct timespec *ts, const struct compat_timespec *cts)
 {
 	return (verify_area(VERIFY_READ, cts, sizeof(*cts)) ||
 			__get_user(ts->tv_sec, &cts->tv_sec) ||
 			__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
 
-int put_compat_timespec(struct timespec *ts, struct compat_timespec *cts)
+int put_compat_timespec(struct timespec *ts, const struct compat_timespec *cts)
 {
 	return (verify_area(VERIFY_WRITE, cts, sizeof(*cts)) ||
 			__put_user(ts->tv_sec, &cts->tv_sec) ||
@@ -204,7 +204,8 @@ asmlinkage long compat_sys_sigprocmask(i
 	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
 	set_fs(old_fs);
 	if (ret == 0)
-		ret = put_user(s, oset);
+		if (oset)
+			ret = put_user(s, oset);
 	return ret;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/exit.c 001-linus.patch/kernel/exit.c
--- 000-virgin/kernel/exit.c	Wed Dec 17 18:59:29 2003
+++ 001-linus.patch/kernel/exit.c	Tue Dec 30 16:38:57 2003
@@ -472,21 +472,29 @@ static inline void __exit_mm(struct task
 	if (!mm)
 		return;
 	/*
-	 * Serialize with any possible pending coredump:
+	 * Serialize with any possible pending coredump.
+	 * We must hold mmap_sem around checking core_waiters
+	 * and clearing tsk->mm.  The core-inducing thread
+	 * will increment core_waiters for each thread in the
+	 * group with ->mm != NULL.
 	 */
+	down_read(&mm->mmap_sem);
 	if (mm->core_waiters) {
+		up_read(&mm->mmap_sem);
 		down_write(&mm->mmap_sem);
 		if (!--mm->core_waiters)
 			complete(mm->core_startup_done);
 		up_write(&mm->mmap_sem);
 
 		wait_for_completion(&mm->core_done);
+		down_read(&mm->mmap_sem);
 	}
 	atomic_inc(&mm->mm_count);
 	if (mm != tsk->active_mm) BUG();
 	/* more a memory barrier than a real lock */
 	task_lock(tsk);
 	tsk->mm = NULL;
+	up_read(&mm->mmap_sem);
 	enter_lazy_tlb(mm, current);
 	task_unlock(tsk);
 	mmput(mm);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/fork.c 001-linus.patch/kernel/fork.c
--- 000-virgin/kernel/fork.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/kernel/fork.c	Tue Dec 30 16:38:57 2003
@@ -642,6 +642,11 @@ static int copy_files(unsigned long clon
 		goto out;
 	}
 
+	/*
+	 * Note: we may be using current for both targets (See exec.c)
+	 * This works because we cache current->files (old) as oldf. Don't
+	 * break this.
+	 */
 	tsk->files = NULL;
 	error = -ENOMEM;
 	newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
@@ -731,6 +736,35 @@ out_release:
 	goto out;
 }
 
+/*
+ *	Helper to unshare the files of the current task.
+ *	We don't want to expose copy_files internals to
+ *	the exec layer of the kernel.
+ */
+
+int unshare_files(void)
+{
+	struct files_struct *files  = current->files;
+	int rc;
+
+	if(!files)
+		BUG();
+
+	/* This can race but the race causes us to copy when we don't
+	   need to and drop the copy */
+	if(atomic_read(&files->count) == 1)
+	{
+		atomic_inc(&files->count);
+		return 0;
+	}
+	rc = copy_files(0, current);
+	if(rc)
+		current->files = files;
+	return rc;
+}
+
+EXPORT_SYMBOL(unshare_files);
+
 static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
 {
 	struct sighand_struct *sig;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/futex.c 001-linus.patch/kernel/futex.c
--- 000-virgin/kernel/futex.c	Wed Dec 17 18:58:29 2003
+++ 001-linus.patch/kernel/futex.c	Tue Dec 30 16:38:57 2003
@@ -246,7 +246,7 @@ static inline void get_key_refs(union fu
  * Drop a reference to the resource addressed by a key.
  * The hash bucket spinlock must not be held.
  */
-static inline void drop_key_refs(union futex_key *key)
+static void drop_key_refs(union futex_key *key)
 {
 	if (key->both.ptr != 0) {
 		if (key->both.offset & 1)
@@ -260,7 +260,7 @@ static inline void drop_key_refs(union f
  * The hash bucket lock must be held when this is called.
  * Afterwards, the futex_q must not be accessed.
  */
-static inline void wake_futex(struct futex_q *q)
+static void wake_futex(struct futex_q *q)
 {
 	list_del_init(&q->list);
 	if (q->filp)
@@ -384,7 +384,7 @@ out:
  */
 
 /* The key must be already stored in q->key. */
-static inline void queue_me(struct futex_q *q, int fd, struct file *filp)
+static void queue_me(struct futex_q *q, int fd, struct file *filp)
 {
 	struct futex_hash_bucket *bh;
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/printk.c 001-linus.patch/kernel/printk.c
--- 000-virgin/kernel/printk.c	Wed Dec 17 18:59:58 2003
+++ 001-linus.patch/kernel/printk.c	Tue Dec 30 16:38:57 2003
@@ -86,7 +86,19 @@ static unsigned long con_start;	/* Index
 static unsigned long log_end;	/* Index into log_buf: most-recently-written-char + 1 */
 static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
 
-struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
+/*
+ *	Array of consoles built from command line options (console=)
+ */
+struct console_cmdline
+{
+	char	name[8];			/* Name of the driver	    */
+	int	index;				/* Minor dev. to use	    */
+	char	*options;			/* Options for the driver   */
+};
+
+#define MAX_CMDLINECONSOLES 8
+
+static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
 static int preferred_console = -1;
 
 /* Flag: console code may call schedule() */
@@ -97,10 +109,9 @@ static int console_may_schedule;
  */
 static int __init console_setup(char *str)
 {
-	struct console_cmdline *c;
-	char name[sizeof(c->name)];
+	char name[sizeof(console_cmdline[0].name)];
 	char *s, *options;
-	int i, idx;
+	int idx;
 
 	/*
 	 *	Decode str into name, index, options.
@@ -125,6 +136,27 @@ static int __init console_setup(char *st
 	idx = simple_strtoul(s, NULL, 10);
 	*s = 0;
 
+	add_preferred_console(name, idx, options);
+	return 1;
+}
+
+__setup("console=", console_setup);
+
+/**
+ * add_preferred_console - add a device to the list of preferred consoles.
+ *
+ * The last preferred console added will be used for kernel messages
+ * and stdin/out/err for init.  Normally this is used by console_setup
+ * above to handle user-supplied console arguments; however it can also
+ * be used by arch-specific code either to override the user or more
+ * commonly to provide a default console (ie from PROM variables) when
+ * the user has not supplied one.
+ */
+int __init add_preferred_console(char *name, int idx, char *options)
+{
+	struct console_cmdline *c;
+	int i;
+
 	/*
 	 *	See if this tty is not yet registered, and
 	 *	if we have a slot free.
@@ -133,20 +165,19 @@ static int __init console_setup(char *st
 		if (strcmp(console_cmdline[i].name, name) == 0 &&
 			  console_cmdline[i].index == idx) {
 				preferred_console = i;
-				return 1;
+				return 0;
 		}
 	if (i == MAX_CMDLINECONSOLES)
-		return 1;
+		return -E2BIG;
 	preferred_console = i;
 	c = &console_cmdline[i];
 	memcpy(c->name, name, sizeof(c->name));
+	c->name[sizeof(c->name) - 1] = 0;
 	c->options = options;
 	c->index = idx;
-	return 1;
+	return 0;
 }
 
-__setup("console=", console_setup);
-
 static int __init log_buf_len_setup(char *str)
 {
 	unsigned long size = memparse(str, &str);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/sched.c 001-linus.patch/kernel/sched.c
--- 000-virgin/kernel/sched.c	Wed Dec 17 18:59:19 2003
+++ 001-linus.patch/kernel/sched.c	Tue Dec 30 16:38:57 2003
@@ -1061,10 +1061,11 @@ static inline runqueue_t *find_busiest_q
 	 * the lock held.
 	 *
 	 * We fend off statistical fluctuations in runqueue lengths by
-	 * saving the runqueue length during the previous load-balancing
-	 * operation and using the smaller one the current and saved lengths.
-	 * If a runqueue is long enough for a longer amount of time then
-	 * we recognize it and pull tasks from it.
+	 * saving the runqueue length (as seen by the balancing CPU) during
+	 * the previous load-balancing operation and using the smaller one
+	 * of the current and saved lengths. If a runqueue is long enough
+	 * for a longer amount of time then we recognize it and pull tasks
+	 * from it.
 	 *
 	 * The 'current runqueue length' is a statistical maximum variable,
 	 * for that one we take the longer one - to avoid fluctuations in
@@ -1470,6 +1471,7 @@ void scheduling_functions_start_here(voi
  */
 asmlinkage void schedule(void)
 {
+	long *switch_count;
 	task_t *prev, *next;
 	runqueue_t *rq;
 	prio_array_t *array;
@@ -1516,32 +1518,25 @@ need_resched:
 	 * if entering off of a kernel preemption go straight
 	 * to picking the next task.
 	 */
-	if (unlikely(preempt_count() & PREEMPT_ACTIVE))
-		goto pick_next_task;
-
-	switch (prev->state) {
-	case TASK_INTERRUPTIBLE:
-		if (unlikely(signal_pending(prev))) {
+	switch_count = &prev->nivcsw;
+	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
+		switch_count = &prev->nvcsw;
+		if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
+				unlikely(signal_pending(prev))))
 			prev->state = TASK_RUNNING;
-			break;
-		}
-	default:
-		deactivate_task(prev, rq);
-		prev->nvcsw++;
-		break;
-	case TASK_RUNNING:
-		prev->nivcsw++;
+		else
+			deactivate_task(prev, rq);
 	}
-pick_next_task:
+
 	if (unlikely(!rq->nr_running)) {
 #ifdef CONFIG_SMP
 		load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
-		if (rq->nr_running)
-			goto pick_next_task;
 #endif
-		next = rq->idle;
-		rq->expired_timestamp = 0;
-		goto switch_tasks;
+		if (!rq->nr_running) {
+			next = rq->idle;
+			rq->expired_timestamp = 0;
+			goto switch_tasks;
+		}
 	}
 
 	array = rq->active;
@@ -1588,6 +1583,7 @@ switch_tasks:
 		next->timestamp = now;
 		rq->nr_switches++;
 		rq->curr = next;
+		++*switch_count;
 
 		prepare_arch_switch(rq, next);
 		prev = context_switch(rq, prev, next);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/kernel/sys.c 001-linus.patch/kernel/sys.c
--- 000-virgin/kernel/sys.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/kernel/sys.c	Tue Dec 30 16:38:57 2003
@@ -1323,8 +1323,6 @@ asmlinkage long sys_setrlimit(unsigned i
  * either stopped or zombied.  In the zombied case the task won't get
  * reaped till shortly after the call to getrusage(), in both cases the
  * task being examined is in a frozen state so the counters won't change.
- *
- * FIXME! Get the fault counts properly!
  */
 int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
 {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/lib/Makefile 001-linus.patch/lib/Makefile
--- 000-virgin/lib/Makefile	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/lib/Makefile	Tue Dec 30 16:38:57 2003
@@ -5,7 +5,7 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o idr.o div64.o parser.o
+	 kobject.o idr.o div64.o parser.o int_sqrt.o mask.o
 
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/lib/int_sqrt.c 001-linus.patch/lib/int_sqrt.c
--- 000-virgin/lib/int_sqrt.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/lib/int_sqrt.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,32 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/**
+ * int_sqrt - rough approximation to sqrt
+ * @x: integer of which to calculate the sqrt
+ *
+ * A very rough approximation to the sqrt() function.
+ */
+unsigned long int_sqrt(unsigned long x)
+{
+	unsigned long op, res, one;
+
+	op = x;
+	res = 0;
+
+	one = 1 << 30;
+	while (one > op)
+		one >>= 2;
+
+	while (one != 0) {
+		if (op >= res + one) {
+			op = op - (res + one);
+			res = res +  2 * one;
+		}
+		res /= 2;
+		one /= 4;
+	}
+	return res;
+}
+EXPORT_SYMBOL(int_sqrt);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/lib/mask.c 001-linus.patch/lib/mask.c
--- 000-virgin/lib/mask.c	Wed Dec 31 16:00:00 1969
+++ 001-linus.patch/lib/mask.c	Tue Dec 30 16:38:57 2003
@@ -0,0 +1,178 @@
+/*
+ * lib/mask.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * Routines to manipulate multi-word bit masks, such as cpumasks.
+ *
+ * The ascii representation of multi-word bit masks displays each
+ * 32bit word in hex (not zero filled), and for masks longer than
+ * one word, uses a comma separator between words.  Words are
+ * displayed in big-endian order most significant first.  And hex
+ * digits within a word are also in big-endian order, of course.
+ *
+ * Examples:
+ *   A mask with just bit 0 set displays as "1".
+ *   A mask with just bit 127 set displays as "80000000,0,0,0".
+ *   A mask with just bit 64 set displays as "1,0,0".
+ *   A mask with bits 0, 1, 2, 4, 8, 16, 32 and 64 set displays
+ *     as "1,1,10117".  The first "1" is for bit 64, the second
+ *     for bit 32, the third for bit 16, and so forth, to the
+ *     "7", which is for bits 2, 1 and 0.
+ *   A mask with bits 32 through 39 set displays as "ff,0".
+ *
+ * The internal binary representation of masks is as one or
+ * an array of unsigned longs, perhaps wrapped in a struct for
+ * convenient use as an lvalue.  The following code doesn't know
+ * about any such struct details, relying on inline macros in
+ * files such as cpumask.h to pass in an unsigned long pointer
+ * and a length (in bytes), describing the mask contents.
+ * The 32bit words in the array are in little-endian order,
+ * low order word first.  Beware that this is the reverse order
+ * of the ascii representation.
+ *
+ * Even though the size of the input mask is provided in bytes,
+ * the following code may assume that the mask is a multiple of
+ * 32 or 64 bit words long, and ignore any fractional portion
+ * of a word at the end.  The main reason the size is passed in
+ * bytes is because it is so easy to write 'sizeof(somemask_t)'
+ * in the macros.
+ *
+ * Masks are not a single,simple type, like classic 'C'
+ * nul-term strings.  Rather they are a family of types, one
+ * for each different length.  Inline macros are used to pick
+ * up the actual length, where it is known to the compiler, and
+ * pass it down to these routines, which work on any specified
+ * length array of unsigned longs.  Poor man's templates.
+ *
+ * Many of the inline macros don't call into the following
+ * routines.  Some of them call into other kernel routines,
+ * such as memset(), set_bit() or ffs().  Some of them can
+ * accomplish their task right inline, such as returning the
+ * size or address of the unsigned long array, or optimized
+ * versions of the macros for the most common case of an array
+ * of a single unsigned long.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <asm/uaccess.h>
+
+#define MAX_HEX_PER_BYTE 4	/* dont need > 4 hex chars to encode byte */
+#define BASE 16			/* masks are input in hex (base 16) */
+#define NUL ((char)'\0')	/* nul-terminator */
+
+/**
+ * __mask_snprintf_len - represent multi-word bit mask as string.
+ * @buf: The buffer to place the result into
+ * @buflen: The size of the buffer, including the trailing null space
+ * @maskp: Points to beginning of multi-word bit mask.
+ * @maskbytes: Number of bytes in bit mask at maskp.
+ *
+ * This routine is expected to be called from a macro such as:
+ *
+ * #define cpumask_snprintf(buf, buflen, mask) \
+ *   __mask_snprintf_len(buf, buflen, cpus_addr(mask), sizeof(mask))
+ */
+
+int __mask_snprintf_len(char *buf, unsigned int buflen,
+	const unsigned long *maskp, unsigned int maskbytes)
+{
+	u32 *wordp = (u32 *)maskp;
+	int i = maskbytes/sizeof(u32) - 1;
+	int len = 0;
+	char *sep = "";
+
+	while (i >= 1 && wordp[i] == 0)
+		i--;
+	while (i >= 0) {
+		len += snprintf(buf+len, buflen-len, "%s%x", sep, wordp[i]);
+		sep = ",";
+		i--;
+	}
+	return len;
+}
+
+/**
+ * __mask_parse_len - parse user string into maskbytes mask at maskp
+ * @ubuf: The user buffer from which to take the string
+ * @ubuflen: The size of this buffer, including the terminating char
+ * @maskp: Place resulting mask (array of unsigned longs) here
+ * @masklen: Construct mask at @maskp to have exactly @masklen bytes
+ *
+ * @masklen is a multiple of sizeof(unsigned long).  A mask of
+ * @masklen bytes is constructed starting at location @maskp.
+ * The value of this mask is specified by the user provided
+ * string starting at address @ubuf.  Only bytes in the range
+ * [@ubuf, @ubuf+@ubuflen) can be read from user space, and
+ * reading will stop after the first byte that is not a comma
+ * or valid hex digit in the characters [,0-9a-fA-F], or at
+ * the point @ubuf+@ubuflen, whichever comes first.
+ *
+ * Since the user only needs about 2.25 chars per byte to encode
+ * a mask (one char per nibble plus one comma separator or nul
+ * terminator per byte), we blow them off with -EINVAL if they
+ * claim a @ubuflen more than 4 (MAX_HEX_PER_BYTE) times maskbytes.
+ * An empty word (delimited by two consecutive commas, for example)
+ * is taken as zero.  If @buflen is zero, the entire @maskp is set
+ * to zero.
+ *
+ * If the user provides fewer comma-separated ascii words
+ * than there are 32 bit words in maskbytes, we zero fill the
+ * remaining high order words.  If they provide more, they fail
+ * with -EINVAL.  Each comma-separate ascii word is taken as
+ * a hex representation; leading zeros are ignored, and do not
+ * imply octal.  '00e1', 'e1', '00E1', 'E1' are all the same.
+ * If user passes a word that is larger than fits in a u32,
+ * they fail with -EOVERFLOW.
+ */
+
+int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen,
+	unsigned long *maskp, unsigned int maskbytes)
+{
+	char buf[maskbytes * MAX_HEX_PER_BYTE + sizeof(NUL)];
+	char *bp = buf;
+	u32 *wordp = (u32 *)maskp;
+	char *p;
+	int i, j;
+
+	if (ubuflen > maskbytes * MAX_HEX_PER_BYTE)
+		return -EINVAL;
+	if (copy_from_user(buf, ubuf, ubuflen))
+		return -EFAULT;
+	buf[ubuflen] = NUL;
+
+	/*
+	 * Put the words into wordp[] in big-endian order,
+	 * then go back and reverse them.
+	 */
+	memset(wordp, 0, maskbytes);
+	i = j = 0;
+	while ((p = strsep(&bp, ",")) != NULL) {
+		unsigned long long t;
+		if (j == maskbytes/sizeof(u32))
+			return -EINVAL;
+		t = simple_strtoull(p, 0, BASE);
+		if (t != (u32)t)
+			return -EOVERFLOW;
+		wordp[j++] = t;
+	}
+	--j;
+	while (i < j) {
+		u32 t = wordp[i];
+		wordp[i] = wordp[j];
+		wordp[j] = t;
+		i++, --j;
+	}
+	return 0;
+}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/lib/parser.c 001-linus.patch/lib/parser.c
--- 000-virgin/lib/parser.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/lib/parser.c	Tue Dec 30 16:38:57 2003
@@ -11,6 +11,17 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
+/**
+ * match_one: - Determines if a string matches a simple pattern
+ * @s: the string to examine for presense of the pattern
+ * @p: the string containing the pattern
+ * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
+ * locations.
+ *
+ * Description: Determines if the pattern @p is present in string @s. Can only
+ * match extremely simple token=arg style patterns. If the pattern is found,
+ * the location(s) of the arguments will be returned in the @args array.
+ */
 static int match_one(char *s, char *p, substring_t args[])
 {
 	char *meta;
@@ -74,6 +85,20 @@ static int match_one(char *s, char *p, s
 	}
 }
 
+/**
+ * match_token: - Find a token (and optional args) in a string
+ * @s: the string to examine for token/argument pairs
+ * @table: match_table_t describing the set of allowed option tokens and the
+ * arguments that may be associated with them. Must be terminated with a
+ * &struct match_token whose pattern is set to the NULL pointer.
+ * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
+ * locations.
+ *
+ * Description: Detects which if any of a set of token strings has been passed
+ * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
+ * format identifiers which will be taken into account when matching the
+ * tokens, and whose locations will be returned in the @args array.
+ */
 int match_token(char *s, match_table_t table, substring_t args[])
 {
 	struct match_token *p;
@@ -84,6 +109,16 @@ int match_token(char *s, match_table_t t
 	return p->token;
 }
 
+/**
+ * match_number: scan a number in the given base from a substring_t
+ * @s: substring to be scanned
+ * @result: resulting integer on success
+ * @base: base to use when converting string
+ *
+ * Description: Given a &substring_t and a base, attempts to parse the substring
+ * as a number in that base. On success, sets @result to the integer represented
+ * by the string and returns 0. Returns either -ENOMEM or -EINVAL on failure.
+ */
 static int match_number(substring_t *s, int *result, int base)
 {
 	char *endp;
@@ -103,27 +138,71 @@ static int match_number(substring_t *s, 
 	return ret;
 }
 
+/**
+ * match_int: - scan a decimal representation of an integer from a substring_t
+ * @s: substring_t to be scanned
+ * @result: resulting integer on success
+ *
+ * Description: Attempts to parse the &substring_t @s as a decimal integer. On
+ * success, sets @result to the integer represented by the string and returns 0.
+ * Returns either -ENOMEM or -EINVAL on failure.
+ */
 int match_int(substring_t *s, int *result)
 {
 	return match_number(s, result, 0);
 }
 
+/**
+ * match_octal: - scan an octal representation of an integer from a substring_t
+ * @s: substring_t to be scanned
+ * @result: resulting integer on success
+ *
+ * Description: Attempts to parse the &substring_t @s as an octal integer. On
+ * success, sets @result to the integer represented by the string and returns
+ * 0. Returns either -ENOMEM or -EINVAL on failure.
+ */
 int match_octal(substring_t *s, int *result)
 {
 	return match_number(s, result, 8);
 }
 
+/**
+ * match_hex: - scan a hex representation of an integer from a substring_t
+ * @s: substring_t to be scanned
+ * @result: resulting integer on success
+ *
+ * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
+ * On success, sets @result to the integer represented by the string and
+ * returns 0. Returns either -ENOMEM or -EINVAL on failure.
+ */
 int match_hex(substring_t *s, int *result)
 {
 	return match_number(s, result, 16);
 }
 
+/**
+ * match_strcpy: - copies the characters from a substring_t to a string
+ * @to: string to copy characters to.
+ * @s: &substring_t to copy
+ *
+ * Description: Copies the set of characters represented by the given
+ * &substring_t @s to the c-style string @to. Caller guarantees that @to is
+ * large enough to hold the characters of @s.
+ */
 void match_strcpy(char *to, substring_t *s)
 {
 	memcpy(to, s->from, s->to - s->from);
 	to[s->to - s->from] = '\0';
 }
 
+/**
+ * match_strdup: - allocate a new string with the contents of a substring_t
+ * @s: &substring_t to copy
+ *
+ * Description: Allocates and returns a string filled with the contents of
+ * the &substring_t @s. The caller is responsible for freeing the returned
+ * string with kfree().
+ */
 char *match_strdup(substring_t *s)
 {
 	char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/filemap.c 001-linus.patch/mm/filemap.c
--- 000-virgin/mm/filemap.c	Wed Dec 17 18:58:40 2003
+++ 001-linus.patch/mm/filemap.c	Tue Dec 30 16:38:57 2003
@@ -990,7 +990,7 @@ static int page_cache_read(struct file *
  * it in the page cache, and handles the special cases reasonably without
  * having a lot of duplicated code.
  */
-struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address, int unused)
+struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address, int *type)
 {
 	int error;
 	struct file *file = area->vm_file;
@@ -999,7 +999,7 @@ struct page * filemap_nopage(struct vm_a
 	struct inode *inode = mapping->host;
 	struct page *page;
 	unsigned long size, pgoff, endoff;
-	int did_readaround = 0;
+	int did_readaround = 0, majmin = VM_FAULT_MINOR;
 
 	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 	endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
@@ -1048,6 +1048,14 @@ retry_find:
 		if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS)
 			goto no_cached_page;
 
+		/*
+		 * To keep the pgmajfault counter straight, we need to
+		 * check did_readaround, as this is an inner loop.
+		 */
+		if (!did_readaround) {
+			majmin = VM_FAULT_MAJOR;
+			inc_page_state(pgmajfault);
+		}
 		did_readaround = 1;
 		do_page_cache_readahead(mapping, file,
 				pgoff & ~(MMAP_READAROUND-1), MMAP_READAROUND);
@@ -1069,6 +1077,8 @@ success:
 	 * Found the page and have a reference on it.
 	 */
 	mark_page_accessed(page);
+	if (type)
+		*type = majmin;
 	return page;
 
 outside_data_content:
@@ -1104,7 +1114,10 @@ no_cached_page:
 	return NULL;
 
 page_not_uptodate:
-	inc_page_state(pgmajfault);
+	if (!did_readaround) {
+		majmin = VM_FAULT_MAJOR;
+		inc_page_state(pgmajfault);
+	}
 	lock_page(page);
 
 	/* Did it get unhashed while we waited for it? */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/highmem.c 001-linus.patch/mm/highmem.c
--- 000-virgin/mm/highmem.c	Wed Dec 17 18:59:04 2003
+++ 001-linus.patch/mm/highmem.c	Tue Dec 30 16:38:57 2003
@@ -285,7 +285,7 @@ static void copy_to_high_bio_irq(struct 
 	struct bio_vec *tovec, *fromvec;
 	int i;
 
-	__bio_for_each_segment(tovec, to, i, 0) {
+	bio_for_each_segment(tovec, to, i) {
 		fromvec = from->bi_io_vec + i;
 
 		/*
@@ -314,7 +314,7 @@ static void bounce_end_io(struct bio *bi
 	/*
 	 * free up bounce indirect pages used
 	 */
-	__bio_for_each_segment(bvec, bio, i, 0) {
+	bio_for_each_segment(bvec, bio, i) {
 		org_vec = bio_orig->bi_io_vec + i;
 		if (bvec->bv_page == org_vec->bv_page)
 			continue;
@@ -437,7 +437,7 @@ static void __blk_queue_bounce(request_q
 	bio->bi_rw = (*bio_orig)->bi_rw;
 
 	bio->bi_vcnt = (*bio_orig)->bi_vcnt;
-	bio->bi_idx = 0;
+	bio->bi_idx = (*bio_orig)->bi_idx;
 	bio->bi_size = (*bio_orig)->bi_size;
 
 	if (pool == page_pool) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/memory.c 001-linus.patch/mm/memory.c
--- 000-virgin/mm/memory.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/mm/memory.c	Tue Dec 30 16:38:57 2003
@@ -1400,7 +1400,7 @@ do_no_page(struct mm_struct *mm, struct 
 	pte_t entry;
 	struct pte_chain *pte_chain;
 	int sequence = 0;
-	int ret;
+	int ret = VM_FAULT_MINOR;
 
 	if (!vma->vm_ops || !vma->vm_ops->nopage)
 		return do_anonymous_page(mm, vma, page_table,
@@ -1414,7 +1414,7 @@ do_no_page(struct mm_struct *mm, struct 
 	}
 	smp_rmb();  /* Prevent CPU from reordering lock-free ->nopage() */
 retry:
-	new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0);
+	new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
 
 	/* no page was available -- either SIGBUS or OOM */
 	if (new_page == NOPAGE_SIGBUS)
@@ -1483,14 +1483,12 @@ retry:
 		pte_unmap(page_table);
 		page_cache_release(new_page);
 		spin_unlock(&mm->page_table_lock);
-		ret = VM_FAULT_MINOR;
 		goto out;
 	}
 
 	/* no need to invalidate: a not-present page shouldn't be cached */
 	update_mmu_cache(vma, address, entry);
 	spin_unlock(&mm->page_table_lock);
-	ret = VM_FAULT_MAJOR;
 	goto out;
 oom:
 	ret = VM_FAULT_OOM;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/oom_kill.c 001-linus.patch/mm/oom_kill.c
--- 000-virgin/mm/oom_kill.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/mm/oom_kill.c	Tue Dec 30 16:38:57 2003
@@ -24,20 +24,6 @@
 /* #define DEBUG */
 
 /**
- * int_sqrt - oom_kill.c internal function, rough approximation to sqrt
- * @x: integer of which to calculate the sqrt
- * 
- * A very rough approximation to the sqrt() function.
- */
-static unsigned int int_sqrt(unsigned int x)
-{
-	unsigned int out = x;
-	while (x & ~(unsigned int)1) x >>=2, out >>=1;
-	if (x) out -= out >> 2;
-	return (out ? out : 1);
-}	
-
-/**
  * oom_badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
  *
@@ -57,7 +43,7 @@ static unsigned int int_sqrt(unsigned in
 
 static int badness(struct task_struct *p)
 {
-	int points, cpu_time, run_time;
+	int points, cpu_time, run_time, s;
 
 	if (!p->mm)
 		return 0;
@@ -77,8 +63,12 @@ static int badness(struct task_struct *p
 	cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
 	run_time = (get_jiffies_64() - p->start_time) >> (SHIFT_HZ + 10);
 
-	points /= int_sqrt(cpu_time);
-	points /= int_sqrt(int_sqrt(run_time));
+	s = int_sqrt(cpu_time);
+	if (s)
+		points /= s;
+	s = int_sqrt(int_sqrt(run_time));
+	if (s)
+		points /= s;
 
 	/*
 	 * Niced processes are most likely less important, so double
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/page_alloc.c 001-linus.patch/mm/page_alloc.c
--- 000-virgin/mm/page_alloc.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/mm/page_alloc.c	Tue Dec 30 16:38:57 2003
@@ -267,9 +267,11 @@ free_pages_bulk(struct zone *zone, int c
 void __free_pages_ok(struct page *page, unsigned int order)
 {
 	LIST_HEAD(list);
+	int i;
 
 	mod_page_state(pgfree, 1 << order);
-	free_pages_check(__FUNCTION__, page);
+	for (i = 0 ; i < (1 << order) ; ++i)
+		free_pages_check(__FUNCTION__, page + i);
 	list_add(&page->list, &list);
 	kernel_map_pages(page, 1<<order, 0);
 	free_pages_bulk(page_zone(page), 1, &list, order);
@@ -1589,7 +1591,7 @@ void __init page_alloc_init(void)
  *	that the pages_{min,low,high} values for each zone are set correctly 
  *	with respect to min_free_kbytes.
  */
-void setup_per_zone_pages_min(void)
+static void setup_per_zone_pages_min(void)
 {
 	unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
 	unsigned long lowmem_pages = 0;
@@ -1633,6 +1635,45 @@ void setup_per_zone_pages_min(void)
 }
 
 /*
+ * Initialise min_free_kbytes.
+ *
+ * For small machines we want it small (128k min).  For large machines
+ * we want it large (16MB max).  But it is not linear, because network
+ * bandwidth does not increase linearly with machine size.  We use
+ *
+ *	min_free_kbytes = sqrt(lowmem_kbytes)
+ *
+ * which yields
+ *
+ * 16MB:	128k
+ * 32MB:	181k
+ * 64MB:	256k
+ * 128MB:	362k
+ * 256MB:	512k
+ * 512MB:	724k
+ * 1024MB:	1024k
+ * 2048MB:	1448k
+ * 4096MB:	2048k
+ * 8192MB:	2896k
+ * 16384MB:	4096k
+ */
+static int __init init_per_zone_pages_min(void)
+{
+	unsigned long lowmem_kbytes;
+
+	lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
+
+	min_free_kbytes = int_sqrt(lowmem_kbytes);
+	if (min_free_kbytes < 128)
+		min_free_kbytes = 128;
+	if (min_free_kbytes > 16384)
+		min_free_kbytes = 16384;
+	setup_per_zone_pages_min();
+	return 0;
+}
+module_init(init_per_zone_pages_min)
+
+/*
  * min_free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so 
  *	that we can call setup_per_zone_pages_min() whenever min_free_kbytes 
  *	changes.
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/shmem.c 001-linus.patch/mm/shmem.c
--- 000-virgin/mm/shmem.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/mm/shmem.c	Tue Dec 30 16:38:57 2003
@@ -71,7 +71,7 @@ enum sgp_type {
 };
 
 static int shmem_getpage(struct inode *inode, unsigned long idx,
-			 struct page **pagep, enum sgp_type sgp);
+			 struct page **pagep, enum sgp_type sgp, int *type);
 
 static inline struct page *shmem_dir_alloc(unsigned int gfp_mask)
 {
@@ -540,7 +540,7 @@ static int shmem_notify_change(struct de
 			if (attr->ia_size & (PAGE_CACHE_SIZE-1)) {
 				(void) shmem_getpage(inode,
 					attr->ia_size>>PAGE_CACHE_SHIFT,
-						&page, SGP_READ);
+						&page, SGP_READ, NULL);
 			}
 			/*
 			 * Reset SHMEM_PAGEIN flag so that shmem_truncate can
@@ -765,7 +765,7 @@ redirty:
  * vm. If we swap it in we mark it dirty since we also free the swap
  * entry since a page cannot live in both the swap and page cache
  */
-static int shmem_getpage(struct inode *inode, unsigned long idx, struct page **pagep, enum sgp_type sgp)
+static int shmem_getpage(struct inode *inode, unsigned long idx, struct page **pagep, enum sgp_type sgp, int *type)
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct shmem_inode_info *info = SHMEM_I(inode);
@@ -774,7 +774,7 @@ static int shmem_getpage(struct inode *i
 	struct page *swappage;
 	swp_entry_t *entry;
 	swp_entry_t swap;
-	int error;
+	int error, majmin = VM_FAULT_MINOR;
 
 	if (idx >= SHMEM_MAX_INDEX)
 		return -EFBIG;
@@ -811,6 +811,10 @@ repeat:
 		if (!swappage) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
+			/* here we actually do the io */
+			if (majmin == VM_FAULT_MINOR && type)
+				inc_page_state(pgmajfault);
+			majmin = VM_FAULT_MAJOR;
 			swapin_readahead(swap);
 			swappage = read_swap_cache_async(swap);
 			if (!swappage) {
@@ -959,6 +963,8 @@ done:
 		} else
 			*pagep = ZERO_PAGE(0);
 	}
+	if (type)
+		*type = majmin;
 	return 0;
 
 failed:
@@ -969,7 +975,7 @@ failed:
 	return error;
 }
 
-struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int unused)
+struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
 {
 	struct inode *inode = vma->vm_file->f_dentry->d_inode;
 	struct page *page = NULL;
@@ -980,7 +986,7 @@ struct page *shmem_nopage(struct vm_area
 	idx += vma->vm_pgoff;
 	idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
 
-	error = shmem_getpage(inode, idx, &page, SGP_CACHE);
+	error = shmem_getpage(inode, idx, &page, SGP_CACHE, type);
 	if (error)
 		return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;
 
@@ -1007,7 +1013,7 @@ static int shmem_populate(struct vm_area
 		/*
 		 * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE
 		 */
-		err = shmem_getpage(inode, pgoff, &page, sgp);
+		err = shmem_getpage(inode, pgoff, &page, sgp, NULL);
 		if (err)
 			return err;
 		if (page) {
@@ -1157,7 +1163,7 @@ static int
 shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
 	struct inode *inode = page->mapping->host;
-	return shmem_getpage(inode, page->index, &page, SGP_WRITE);
+	return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL);
 }
 
 static ssize_t
@@ -1214,7 +1220,7 @@ shmem_file_write(struct file *file, cons
 		 * But it still may be a good idea to prefault below.
 		 */
 
-		err = shmem_getpage(inode, index, &page, SGP_WRITE);
+		err = shmem_getpage(inode, index, &page, SGP_WRITE, NULL);
 		if (err)
 			break;
 
@@ -1296,7 +1302,7 @@ static void do_shmem_file_read(struct fi
 				break;
 		}
 
-		desc->error = shmem_getpage(inode, index, &page, SGP_READ);
+		desc->error = shmem_getpage(inode, index, &page, SGP_READ, NULL);
 		if (desc->error) {
 			if (desc->error == -EINVAL)
 				desc->error = 0;
@@ -1552,7 +1558,7 @@ static int shmem_symlink(struct inode *d
 			iput(inode);
 			return -ENOMEM;
 		}
-		error = shmem_getpage(inode, 0, &page, SGP_WRITE);
+		error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
 		if (error) {
 			vm_unacct_memory(VM_ACCT(1));
 			iput(inode);
@@ -1590,7 +1596,7 @@ static int shmem_follow_link_inline(stru
 static int shmem_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
 	struct page *page = NULL;
-	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ);
+	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
 	if (res)
 		return res;
 	res = vfs_readlink(dentry, buffer, buflen, kmap(page));
@@ -1603,7 +1609,7 @@ static int shmem_readlink(struct dentry 
 static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct page *page = NULL;
-	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ);
+	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
 	if (res)
 		return res;
 	res = vfs_follow_link(nd, kmap(page));
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/slab.c 001-linus.patch/mm/slab.c
--- 000-virgin/mm/slab.c	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/mm/slab.c	Tue Dec 30 16:38:57 2003
@@ -805,13 +805,14 @@ static inline void *kmem_getpages(kmem_c
 	void *addr;
 
 	flags |= cachep->gfpflags;
-	if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
-		atomic_add(1<<cachep->gfporder, &slab_reclaim_pages);
 	addr = (void*)__get_free_pages(flags, cachep->gfporder);
 	if (addr) {
 		int i = (1 << cachep->gfporder);
 		struct page *page = virt_to_page(addr);
 
+		if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
+			atomic_add(i, &slab_reclaim_pages);
+		add_page_state(nr_slab, i);
 		while (i--) {
 			SetPageSlab(page);
 			page++;
@@ -1608,7 +1609,6 @@ static int cache_grow (kmem_cache_t * ca
 	do {
 		SET_PAGE_CACHE(page, cachep);
 		SET_PAGE_SLAB(page, slabp);
-		inc_page_state(nr_slab);
 		page++;
 	} while (--i);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/swap.c 001-linus.patch/mm/swap.c
--- 000-virgin/mm/swap.c	Wed Dec 17 18:58:45 2003
+++ 001-linus.patch/mm/swap.c	Tue Dec 30 16:38:57 2003
@@ -386,17 +386,19 @@ EXPORT_SYMBOL(vm_acct_memory);
 #ifdef CONFIG_SMP
 void percpu_counter_mod(struct percpu_counter *fbc, long amount)
 {
+	long count;
+	long *pcount;
 	int cpu = get_cpu();
-	long count = fbc->counters[cpu].count;
 
-	count += amount;
+	pcount = per_cpu_ptr(fbc->counters, cpu);
+	count = *pcount + amount;
 	if (count >= FBC_BATCH || count <= -FBC_BATCH) {
 		spin_lock(&fbc->lock);
 		fbc->count += count;
 		spin_unlock(&fbc->lock);
 		count = 0;
 	}
-	fbc->counters[cpu].count = count;
+	*pcount = count;
 	put_cpu();
 }
 EXPORT_SYMBOL(percpu_counter_mod);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/mm/vmscan.c 001-linus.patch/mm/vmscan.c
--- 000-virgin/mm/vmscan.c	Wed Dec 17 18:58:15 2003
+++ 001-linus.patch/mm/vmscan.c	Tue Dec 30 16:38:57 2003
@@ -779,7 +779,7 @@ shrink_zone(struct zone *zone, int max_s
 		count = atomic_read(&zone->refill_counter);
 		if (count > SWAP_CLUSTER_MAX * 4)
 			count = SWAP_CLUSTER_MAX * 4;
-		atomic_sub(count, &zone->refill_counter);
+		atomic_set(&zone->refill_counter, 0);
 		refill_inactive_zone(zone, count, ps, priority);
 	}
 	return shrink_cache(nr_pages, zone, gfp_mask,
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/ax25/af_ax25.c 001-linus.patch/net/ax25/af_ax25.c
--- 000-virgin/net/ax25/af_ax25.c	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/net/ax25/af_ax25.c	Tue Dec 30 16:38:57 2003
@@ -228,45 +228,25 @@ ax25_cb *ax25_find_cb(ax25_address *src_
 	return NULL;
 }
 
-/*
- *	Look for any matching address - RAW sockets can bind to arbitrary names
- */
-struct sock *ax25_addr_match(ax25_address *addr)
+void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
 {
-	struct sock *sk = NULL;
 	ax25_cb *s;
+	struct sk_buff *copy;
 	struct hlist_node *node;
 
 	spin_lock_bh(&ax25_list_lock);
 	ax25_for_each(s, node, &ax25_list) {
 		if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
-		    s->sk->sk_type == SOCK_RAW) {
-			sk = s->sk;
-			lock_sock(sk);
-			break;
-		}
-	}
-
-	spin_unlock_bh(&ax25_list_lock);
-
-	return sk;
-}
-
-void ax25_send_to_raw(struct sock *sk, struct sk_buff *skb, int proto)
-{
-	struct sk_buff *copy;
-	struct hlist_node *node;
-
-	sk_for_each_from(sk, node)
-		if (sk->sk_type == SOCK_RAW &&
-		    sk->sk_protocol == proto &&
-		    atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
+		    s->sk->sk_type == SOCK_RAW &&
+		    s->sk->sk_protocol == proto &&
+		    s->ax25_dev->dev == skb->dev &&
+		    atomic_read(&s->sk->sk_rmem_alloc) <= s->sk->sk_rcvbuf) {
 			if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)
-				return;
-
-			if (sock_queue_rcv_skb(sk, copy) != 0)
+				continue;
+			if (sock_queue_rcv_skb(s->sk, copy) != 0)
 				kfree_skb(copy);
 		}
+	}
 }
 
 /*
@@ -318,7 +298,7 @@ void ax25_destroy_socket(ax25_cb *ax25)
 				ax25_cb *sax25 = ax25_sk(skb->sk);
 
 				/* Queue the unaccepted socket for death */
-				sock_set_flag(skb->sk, SOCK_DEAD);
+				sock_orphan(skb->sk);
 
 				ax25_start_heartbeat(sax25);
 				sax25->state = AX25_STATE_0;
@@ -913,6 +893,7 @@ struct sock *ax25_make_new(struct sock *
 	if (oax25->digipeat != NULL) {
 		if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 			sk_free(sk);
+			ax25_cb_put(ax25);
 			return NULL;
 		}
 
@@ -934,20 +915,25 @@ static int ax25_release(struct socket *s
 		return 0;
 
 	sock_hold(sk);
+	sock_orphan(sk);
 	lock_sock(sk);
 	ax25 = ax25_sk(sk);
 
 	if (sk->sk_type == SOCK_SEQPACKET) {
 		switch (ax25->state) {
 		case AX25_STATE_0:
+			release_sock(sk);
 			ax25_disconnect(ax25, 0);
+			lock_sock(sk);
 			ax25_destroy_socket(ax25);
 			break;
 
 		case AX25_STATE_1:
 		case AX25_STATE_2:
 			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
+			release_sock(sk);
 			ax25_disconnect(ax25, 0);
+			lock_sock(sk);
 			ax25_destroy_socket(ax25);
 			break;
 
@@ -980,7 +966,6 @@ static int ax25_release(struct socket *s
 			sk->sk_state                = TCP_CLOSE;
 			sk->sk_shutdown            |= SEND_SHUTDOWN;
 			sk->sk_state_change(sk);
-			sock_set_flag(sk, SOCK_DEAD);
 			sock_set_flag(sk, SOCK_DESTROY);
 			break;
 
@@ -991,12 +976,10 @@ static int ax25_release(struct socket *s
 		sk->sk_state     = TCP_CLOSE;
 		sk->sk_shutdown |= SEND_SHUTDOWN;
 		sk->sk_state_change(sk);
-		sock_set_flag(sk, SOCK_DEAD);
 		ax25_destroy_socket(ax25);
 	}
 
 	sock->sk   = NULL;
-	sk->sk_socket = NULL;	/* Not used, but we should do this */
 	release_sock(sk);
 	sock_put(sk);
 
@@ -1334,11 +1317,13 @@ static int ax25_accept(struct socket *so
 
 		release_sock(sk);
 		current->state = TASK_INTERRUPTIBLE;
-		if (flags & O_NONBLOCK)
+		if (flags & O_NONBLOCK) {
+			current->state = TASK_RUNNING;
+			remove_wait_queue(sk->sk_sleep, &wait);
 			return -EWOULDBLOCK;
+		}
 		if (!signal_pending(tsk)) {
 			schedule();
-			current->state = TASK_RUNNING;
 			lock_sock(sk);
 			continue;
 		}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/ax25/ax25_in.c 001-linus.patch/net/ax25/ax25_in.c
--- 000-virgin/net/ax25/ax25_in.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/net/ax25/ax25_in.c	Tue Dec 30 16:38:57 2003
@@ -147,7 +147,6 @@ int ax25_rx_iframe(ax25_cb *ax25, struct
 	}
 
 	if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2) {
-		bh_lock_sock(ax25->sk);
 		if ((!ax25->pidincl && ax25->sk->sk_protocol == pid) ||
 		    ax25->pidincl) {
 			if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
@@ -155,7 +154,6 @@ int ax25_rx_iframe(ax25_cb *ax25, struct
 			else
 				ax25->condition |= AX25_COND_OWN_RX_BUSY;
 		}
-		bh_unlock_sock(ax25->sk);
 	}
 
 	return queued;
@@ -195,7 +193,7 @@ static int ax25_rcv(struct sk_buff *skb,
 {
 	ax25_address src, dest, *next_digi = NULL;
 	int type = 0, mine = 0, dama;
-	struct sock *make, *sk, *raw;
+	struct sock *make, *sk;
 	ax25_digi dp, reverse_dp;
 	ax25_cb *ax25;
 	ax25_dev *ax25_dev;
@@ -243,10 +241,7 @@ static int ax25_rcv(struct sk_buff *skb,
 	if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {
 		skb->h.raw = skb->data + 2;		/* skip control and pid */
 
-		if ((raw = ax25_addr_match(&dest)) != NULL) {
-			ax25_send_to_raw(raw, skb, skb->data[1]);
-			release_sock(raw);
-		}
+		ax25_send_to_raw(&dest, skb, skb->data[1]);
 
 		if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
 			kfree_skb(skb);
@@ -381,7 +376,6 @@ static int ax25_rcv(struct sk_buff *skb,
 
 		sk->sk_ack_backlog++;
 		bh_unlock_sock(sk);
-		sock_put(sk);
 	} else {
 		if (!mine) {
 			kfree_skb(skb);
@@ -407,6 +401,8 @@ static int ax25_rcv(struct sk_buff *skb,
 	    (ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 		kfree_skb(skb);
 		ax25_destroy_socket(ax25);
+		if (sk)
+			sock_put(sk);
 		return 0;
 	}
 
@@ -446,6 +442,7 @@ static int ax25_rcv(struct sk_buff *skb,
 	if (sk) {
 		if (!sock_flag(sk, SOCK_DEAD))
 			sk->sk_data_ready(sk, skb->len);
+		sock_put(sk);
 	} else
 		kfree_skb(skb);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/bluetooth/af_bluetooth.c 001-linus.patch/net/bluetooth/af_bluetooth.c
--- 000-virgin/net/bluetooth/af_bluetooth.c	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/net/bluetooth/af_bluetooth.c	Tue Dec 30 16:38:57 2003
@@ -360,3 +360,4 @@ module_exit(bt_cleanup);
 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
 MODULE_DESCRIPTION("Bluetooth Core ver " VERSION);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/bluetooth/bnep/core.c 001-linus.patch/net/bluetooth/bnep/core.c
--- 000-virgin/net/bluetooth/bnep/core.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/net/bluetooth/bnep/core.c	Tue Dec 30 16:38:57 2003
@@ -707,4 +707,3 @@ module_exit(bnep_cleanup_module);
 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
 MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyanskiy <maxk@qualcomm.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_NETPROTO(PF_BLUETOOTH);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/bridge/br_netfilter.c 001-linus.patch/net/bridge/br_netfilter.c
--- 000-virgin/net/bridge/br_netfilter.c	Wed Dec 17 18:59:44 2003
+++ 001-linus.patch/net/bridge/br_netfilter.c	Tue Dec 30 16:38:57 2003
@@ -35,6 +35,9 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include "br_private.h"
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
 
 
 #define skb_origaddr(skb)	 (((struct bridge_skb_cb *) \
@@ -47,10 +50,21 @@
 #define has_bridge_parent(device)	((device)->br_port != NULL)
 #define bridge_parent(device)		((device)->br_port->br->dev)
 
-#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
-	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP))
-#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
-	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP))
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *brnf_sysctl_header;
+static int brnf_call_iptables = 1;
+static int brnf_call_arptables = 1;
+static int brnf_filter_vlan_tagged = 1;
+#else
+#define brnf_filter_vlan_tagged 1
+#endif
+
+#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
+	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) &&  \
+	brnf_filter_vlan_tagged)
+#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) &&   \
+	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \
+	brnf_filter_vlan_tagged)
 
 /* We need these fake structures to make netfilter happy --
  * lots of places assume that skb->dst != NULL, which isn't
@@ -74,8 +88,7 @@ static struct rtable __fake_rtable = {
 			.metrics		= {[RTAX_MTU - 1] = 1500},
 		}
 	},
-
-	.rt_flags	= 0
+	.rt_flags	= 0,
 };
 
 
@@ -251,6 +264,11 @@ static unsigned int br_nf_pre_routing(un
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
 
+#ifdef CONFIG_SYSCTL
+	if (!brnf_call_iptables)
+		return NF_ACCEPT;
+#endif
+
 	if (skb->protocol != __constant_htons(ETH_P_IP)) {
 		struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)
 					  ((*pskb)->mac.ethernet);
@@ -373,7 +391,7 @@ static int br_nf_forward_finish(struct s
  * because of the ipt_physdev.c module. For ARP, indev and outdev are the
  * bridge ports.
  */
-static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
+static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
@@ -381,9 +399,13 @@ static unsigned int br_nf_forward(unsign
 	struct nf_bridge_info *nf_bridge;
 	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
 
-	if (skb->protocol != __constant_htons(ETH_P_IP) &&
-	    skb->protocol != __constant_htons(ETH_P_ARP)) {
-		if (!IS_VLAN_IP && !IS_VLAN_ARP)
+#ifdef CONFIG_SYSCTL
+	if (!skb->nf_bridge)
+		return NF_ACCEPT;
+#endif
+
+	if (skb->protocol != __constant_htons(ETH_P_IP)) {
+		if (!IS_VLAN_IP)
 			return NF_ACCEPT;
 		skb_pull(*pskb, VLAN_HLEN);
 		(*pskb)->nh.raw += VLAN_HLEN;
@@ -392,39 +414,58 @@ static unsigned int br_nf_forward(unsign
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug ^= (1 << NF_BR_FORWARD);
 #endif
-	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
-		nf_bridge = skb->nf_bridge;
-		if (skb->pkt_type == PACKET_OTHERHOST) {
-			skb->pkt_type = PACKET_HOST;
-			nf_bridge->mask |= BRNF_PKT_TYPE;
-		}
+	nf_bridge = skb->nf_bridge;
+	if (skb->pkt_type == PACKET_OTHERHOST) {
+		skb->pkt_type = PACKET_HOST;
+		nf_bridge->mask |= BRNF_PKT_TYPE;
+	}
 
-		/* The physdev module checks on this */
-		nf_bridge->mask |= BRNF_BRIDGED;
-		nf_bridge->physoutdev = skb->dev;
+	/* The physdev module checks on this */
+	nf_bridge->mask |= BRNF_BRIDGED;
+	nf_bridge->physoutdev = skb->dev;
 
-		NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
-			bridge_parent(out), br_nf_forward_finish);
-	} else {
-		struct net_device **d = (struct net_device **)(skb->cb);
-		struct arphdr *arp = skb->nh.arph;
+	NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
+		bridge_parent(out), br_nf_forward_finish);
 
-		if (arp->ar_pln != 4) {
-			if (IS_VLAN_ARP) {
-				skb_push(*pskb, VLAN_HLEN);
-				(*pskb)->nh.raw -= VLAN_HLEN;
-			}
+	return NF_STOLEN;
+}
+
+static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
+   const struct net_device *in, const struct net_device *out,
+   int (*okfn)(struct sk_buff *))
+{
+	struct sk_buff *skb = *pskb;
+	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct net_device **d = (struct net_device **)(skb->cb);
+
+	if (!brnf_call_arptables)
+		return NF_ACCEPT;
+
+	if (skb->protocol != __constant_htons(ETH_P_ARP)) {
+		if (!IS_VLAN_ARP)
 			return NF_ACCEPT;
+		skb_pull(*pskb, VLAN_HLEN);
+		(*pskb)->nh.raw += VLAN_HLEN;
+	}
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug ^= (1 << NF_BR_FORWARD);
+#endif
+
+	if (skb->nh.arph->ar_pln != 4) {
+		if (IS_VLAN_ARP) {
+			skb_push(*pskb, VLAN_HLEN);
+			(*pskb)->nh.raw -= VLAN_HLEN;
 		}
-		*d = (struct net_device *)in;
-		NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
-			(struct net_device *)out, br_nf_forward_finish);
+		return NF_ACCEPT;
 	}
+	*d = (struct net_device *)in;
+	NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
+		(struct net_device *)out, br_nf_forward_finish);
 
 	return NF_STOLEN;
 }
 
-
 /* PF_BRIDGE/LOCAL_OUT ***********************************************/
 static int br_nf_local_out_finish(struct sk_buff *skb)
 {
@@ -475,6 +516,11 @@ static unsigned int br_nf_local_out(unsi
 	struct nf_bridge_info *nf_bridge;
 	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
 
+#ifdef CONFIG_SYSCTL
+	if (!skb->nf_bridge)
+		return NF_ACCEPT;
+#endif
+
 	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
 		return NF_ACCEPT;
 
@@ -485,6 +531,7 @@ static unsigned int br_nf_local_out(unsi
 		return NF_ACCEPT;
 
 	nf_bridge = skb->nf_bridge;
+
 	nf_bridge->physoutdev = skb->dev;
 
 	realindev = nf_bridge->physindev;
@@ -567,6 +614,11 @@ static unsigned int br_nf_post_routing(u
 		return NF_ACCEPT;
 	}
 
+#ifdef CONFIG_SYSCTL
+	if (!nf_bridge)
+		return NF_ACCEPT;
+#endif
+
 	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
 		return NF_ACCEPT;
 
@@ -632,6 +684,13 @@ static unsigned int ipv4_sabotage_out(un
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
+	struct sk_buff *skb = *pskb;
+
+#ifdef CONFIG_SYSCTL
+	if (!brnf_call_iptables && !skb->nf_bridge)
+		return NF_ACCEPT;
+#endif
+
 	if ((out->hard_start_xmit == br_dev_xmit &&
 	    okfn != br_nf_forward_finish &&
 	    okfn != br_nf_local_out_finish &&
@@ -641,7 +700,6 @@ static unsigned int ipv4_sabotage_out(un
 	    VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
 #endif
 	    ) {
-		struct sk_buff *skb = *pskb;
 		struct nf_bridge_info *nf_bridge;
 
 		if (!skb->nf_bridge && !nf_bridge_alloc(skb))
@@ -687,7 +745,12 @@ static struct nf_hook_ops br_nf_ops[] = 
 	  .pf = PF_BRIDGE,
 	  .hooknum = NF_BR_LOCAL_IN,
 	  .priority = NF_BR_PRI_BRNF, },
-	{ .hook = br_nf_forward,
+	{ .hook = br_nf_forward_ip,
+	  .owner = THIS_MODULE,
+	  .pf = PF_BRIDGE,
+	  .hooknum = NF_BR_FORWARD,
+	  .priority = NF_BR_PRI_BRNF - 1, },
+	{ .hook = br_nf_forward_arp,
 	  .owner = THIS_MODULE,
 	  .pf = PF_BRIDGE,
 	  .hooknum = NF_BR_FORWARD,
@@ -724,6 +787,69 @@ static struct nf_hook_ops br_nf_ops[] = 
 	  .priority = NF_IP_PRI_FIRST, },
 };
 
+#ifdef CONFIG_SYSCTL
+static
+int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp,
+			void *buffer, size_t *lenp)
+{
+	int ret;
+
+	ret = proc_dointvec(ctl, write, filp, buffer, lenp);
+
+	if (write && *(int *)(ctl->data))
+		*(int *)(ctl->data) = 1;
+	return ret;
+}
+
+static ctl_table brnf_table[] = {
+	{
+		.ctl_name	= NET_BRIDGE_NF_CALL_ARPTABLES,
+		.procname	= "bridge-nf-call-arptables",
+		.data		= &brnf_call_arptables,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &brnf_sysctl_call_tables,
+	},
+	{
+		.ctl_name	= NET_BRIDGE_NF_CALL_IPTABLES,
+		.procname	= "bridge-nf-call-iptables",
+		.data		= &brnf_call_iptables,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &brnf_sysctl_call_tables,
+	},
+	{
+		.ctl_name	= NET_BRIDGE_NF_FILTER_VLAN_TAGGED,
+		.procname	= "bridge-nf-filter-vlan-tagged",
+		.data		= &brnf_filter_vlan_tagged,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &brnf_sysctl_call_tables,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table brnf_bridge_table[] = {
+	{
+		.ctl_name	= NET_BRIDGE,
+		.procname	= "bridge",
+		.mode		= 0555,
+		.child		= brnf_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table brnf_net_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555,
+		.child		= brnf_bridge_table,
+	},
+	{ .ctl_name = 0 }
+};
+#endif
+
 int br_netfilter_init(void)
 {
 	int i;
@@ -740,6 +866,16 @@ int br_netfilter_init(void)
 		return ret;
 	}
 
+#ifdef CONFIG_SYSCTL
+	brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
+	if (brnf_sysctl_header == NULL) {
+		printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n");
+		for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++)
+			nf_unregister_hook(&br_nf_ops[i]);
+		return -EFAULT;
+	}
+#endif
+
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
 
 	return 0;
@@ -751,4 +887,7 @@ void br_netfilter_fini(void)
 
 	for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
 		nf_unregister_hook(&br_nf_ops[i]);
+#ifdef CONFIG_SYSCTL
+	unregister_sysctl_table(brnf_sysctl_header);
+#endif
 }
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/core/neighbour.c 001-linus.patch/net/core/neighbour.c
--- 000-virgin/net/core/neighbour.c	Wed Dec 17 18:58:06 2003
+++ 001-linus.patch/net/core/neighbour.c	Tue Dec 30 16:38:57 2003
@@ -98,7 +98,7 @@ static int neigh_blackhole(struct sk_buf
 /*
  * It is random distribution in the interval (1/2)*base...(3/2)*base.
  * It corresponds to default IPv6 settings and is not overridable,
- * because it is really reasonbale choice.
+ * because it is really reasonable choice.
  */
 
 unsigned long neigh_rand_reach_time(unsigned long base)
@@ -120,7 +120,7 @@ static int neigh_forced_gc(struct neigh_
 		while ((n = *np) != NULL) {
 			/* Neighbour record may be discarded if:
 			   - nobody refers to it.
-			   - it is not premanent
+			   - it is not permanent
 			   - (NEW and probably wrong)
 			     INCOMPLETE entries are kept at least for
 			     n->parms->retrans_time, otherwise we could
@@ -510,7 +510,7 @@ static void neigh_suspect(struct neighbo
 {
 	struct hh_cache *hh;
 
-	NEIGH_PRINTK2("neigh %p is suspecteded.\n", neigh);
+	NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
 
 	neigh->output = neigh->ops->output;
 
@@ -537,7 +537,7 @@ static void neigh_connect(struct neighbo
 
 /*
    Transitions NUD_STALE <-> NUD_REACHABLE do not occur
-   when fast path is built: we have no timers assotiated with
+   when fast path is built: we have no timers associated with
    these states, we do not have time to check state when sending.
    neigh_periodic_timer check periodically neigh->confirmed
    time and moves NUD_REACHABLE -> NUD_STALE.
@@ -962,7 +962,7 @@ static void neigh_hh_init(struct neighbo
 
 /* This function can be used in contexts, where only old dev_queue_xmit
    worked, f.e. if you want to override normal output path (eql, shaper),
-   but resoltution is not made yet.
+   but resolution is not made yet.
  */
 
 int neigh_compat_output(struct sk_buff *skb)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/ipv6/ndisc.c 001-linus.patch/net/ipv6/ndisc.c
--- 000-virgin/net/ipv6/ndisc.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/net/ipv6/ndisc.c	Tue Dec 30 16:38:57 2003
@@ -207,9 +207,8 @@ static struct ndisc_options *ndisc_parse
 		case ND_OPT_MTU:
 		case ND_OPT_REDIRECT_HDR:
 			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
-				ND_PRINTK2((KERN_WARNING
-					    "ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
-					    nd_opt->nd_opt_type));
+				ND_PRINTK2("ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
+					    nd_opt->nd_opt_type);
 			} else {
 				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
 			}
@@ -619,6 +618,7 @@ void ndisc_send_rs(struct net_device *de
 				  1, &err);
 	if (skb == NULL) {
 		ND_PRINTK1("send_ns: alloc skb failed\n");
+		dst_release(dst);
 		return;
 	}
 
@@ -1166,9 +1166,7 @@ static void ndisc_router_discovery(struc
 				ND_PRINTK0("NDISC: router announcement with mtu = %d\n",
 					   mtu);
 			}
-		}
-
-		if (in6_dev->cnf.mtu6 != mtu) {
+		} else if (in6_dev->cnf.mtu6 != mtu) {
 			in6_dev->cnf.mtu6 = mtu;
 
 			if (rt)
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/netrom/af_netrom.c 001-linus.patch/net/netrom/af_netrom.c
--- 000-virgin/net/netrom/af_netrom.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/net/netrom/af_netrom.c	Tue Dec 30 16:38:57 2003
@@ -532,7 +532,7 @@ static int nr_release(struct socket *soc
 		sk->sk_state    = TCP_CLOSE;
 		sk->sk_shutdown |= SEND_SHUTDOWN;
 		sk->sk_state_change(sk);
-		sock_set_flag(sk, SOCK_DEAD);
+		sock_orphan(sk);
 		sock_set_flag(sk, SOCK_DESTROY);
 		sk->sk_socket   = NULL;
 		break;
@@ -727,6 +727,8 @@ static int nr_connect(struct socket *soc
 				lock_sock(sk);
 				continue;
 			}
+			current->state = TASK_RUNNING;
+			remove_wait_queue(sk->sk_sleep, &wait);
 			return -ERESTARTSYS;
 		}
 		current->state = TASK_RUNNING;
@@ -780,13 +782,18 @@ static int nr_accept(struct socket *sock
 
 		current->state = TASK_INTERRUPTIBLE;
 		release_sock(sk);
-		if (flags & O_NONBLOCK)
+		if (flags & O_NONBLOCK) {
+			current->state = TASK_RUNNING;
+			remove_wait_queue(sk->sk_sleep, &wait);
 			return -EWOULDBLOCK;
+		}
 		if (!signal_pending(tsk)) {
 			schedule();
 			lock_sock(sk);
 			continue;
 		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(sk->sk_sleep, &wait);
 		return -ERESTARTSYS;
 	}
 	current->state = TASK_RUNNING;
@@ -1377,7 +1384,7 @@ static int __init nr_proto_init(void)
 {
 	int i;
 
-	if (nr_ndevs > 0x7fffffff/sizeof(struct net_device)) {
+	if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) {
 		printk(KERN_ERR "NET/ROM: nr_proto_init - nr_ndevs parameter to large\n");
 		return -1;
 	}
@@ -1405,6 +1412,7 @@ static int __init nr_proto_init(void)
 		dev->base_addr = i;
 		if (register_netdev(dev)) {
 			printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register network device\n");
+			free_netdev(dev);
 			goto fail;
 		}
 		dev_nr[i] = dev;
@@ -1433,8 +1441,10 @@ static int __init nr_proto_init(void)
 	return 0;
 
  fail:
-	while (--i >= 0)
+	while (--i >= 0) {
 		unregister_netdev(dev_nr[i]);
+		free_netdev(dev_nr[i]);
+	}
 	kfree(dev_nr);
 	return -1;
 }
@@ -1474,8 +1484,10 @@ static void __exit nr_exit(void)
 
 	for (i = 0; i < nr_ndevs; i++) {
 		struct net_device *dev = dev_nr[i];
-		if (dev) 
+		if (dev) {
 			unregister_netdev(dev);
+			free_netdev(dev);
+		}
 	}
 
 	kfree(dev_nr);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/netrom/nr_dev.c 001-linus.patch/net/netrom/nr_dev.c
--- 000-virgin/net/netrom/nr_dev.c	Wed Dec 17 18:59:38 2003
+++ 001-linus.patch/net/netrom/nr_dev.c	Tue Dec 30 16:38:57 2003
@@ -204,7 +204,6 @@ void nr_setup(struct net_device *dev)
 	dev->hard_start_xmit	= nr_xmit;
 	dev->open		= nr_open;
 	dev->stop		= nr_close;
-	dev->destructor		= free_netdev;
 
 	dev->hard_header	= nr_header;
 	dev->hard_header_len	= NR_NETWORK_LEN + NR_TRANSPORT_LEN;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/packet/af_packet.c 001-linus.patch/net/packet/af_packet.c
--- 000-virgin/net/packet/af_packet.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/net/packet/af_packet.c	Tue Dec 30 16:38:57 2003
@@ -246,6 +246,10 @@ static int packet_rcv_spkt(struct sk_buf
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto oom;
 
+	/* drop any routing info */
+	dst_release(skb->dst);
+	skb->dst = NULL;
+
 	spkt = (struct sockaddr_pkt*)skb->cb;
 
 	skb_push(skb, skb->data-skb->mac.raw);
@@ -486,6 +490,9 @@ static int packet_rcv(struct sk_buff *sk
 
 	skb_set_owner_r(skb, sk);
 	skb->dev = NULL;
+	dst_release(skb->dst);
+	skb->dst = NULL;
+
 	spin_lock(&sk->sk_receive_queue.lock);
 	po->stats.tp_packets++;
 	__skb_queue_tail(&sk->sk_receive_queue, skb);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/rose/af_rose.c 001-linus.patch/net/rose/af_rose.c
--- 000-virgin/net/rose/af_rose.c	Wed Dec 17 18:58:49 2003
+++ 001-linus.patch/net/rose/af_rose.c	Tue Dec 30 16:38:57 2003
@@ -359,7 +359,7 @@ void rose_destroy_socket(struct sock *sk
 		sk->sk_timer.data     = (unsigned long)sk;
 		add_timer(&sk->sk_timer);
 	} else
-		sk_free(sk);
+		sock_put(sk);
 }
 
 /*
@@ -634,7 +634,6 @@ static int rose_release(struct socket *s
 	}
 
 	sock->sk = NULL;
-	sk->sk_socket = NULL;	/* Not used, but we should do this. **/
 
 	return 0;
 }
@@ -813,6 +812,8 @@ static int rose_connect(struct socket *s
 				schedule();
 				continue;
 			}
+			current->state = TASK_RUNNING;
+			remove_wait_queue(sk->sk_sleep, &wait);
 			return -ERESTARTSYS;
 		}
 		current->state = TASK_RUNNING;
@@ -864,8 +865,11 @@ static int rose_accept(struct socket *so
 
 		current->state = TASK_INTERRUPTIBLE;
 		release_sock(sk);
-		if (flags & O_NONBLOCK)
+		if (flags & O_NONBLOCK) {
+			current->state = TASK_RUNNING;
+			remove_wait_queue(sk->sk_sleep, &wait);
 			return -EWOULDBLOCK;
+		}
 		if (!signal_pending(tsk)) {
 			schedule();
 			lock_sock(sk);
@@ -1482,7 +1486,7 @@ static int __init rose_proto_init(void)
 
 	rose_callsign = null_ax25_address;
 
-	if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device)) {
+	if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
 		printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n");
 		return -1;
 	}
@@ -1503,23 +1507,14 @@ static int __init rose_proto_init(void)
 				   name, rose_setup);
 		if (!dev) {
 			printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
-			while (--i >= 0)
-				kfree(dev_rose[i]);
-			return -ENOMEM;
+			goto fail;
 		}
-		dev_rose[i] = dev;
-	}
-
-	for (i = 0; i < rose_ndevs; i++) {
-		if (register_netdev(dev_rose[i])) {
+		if (register_netdev(dev)) {
 			printk(KERN_ERR "ROSE: netdevice regeistration failed\n");
-			while (--i >= 0) {
-				unregister_netdev(dev_rose[i]);
-				kfree(dev_rose[i]);
-				return -EIO;
-			}
+			free_netdev(dev);
+			goto fail;
 		}
-			
+		dev_rose[i] = dev;
 	}
 
 	sock_register(&rose_family_ops);
@@ -1542,6 +1537,13 @@ static int __init rose_proto_init(void)
 	proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
 
 	return 0;
+fail:
+	while (--i >= 0) {
+		unregister_netdev(dev_rose[i]);
+		free_netdev(dev_rose[i]);
+	}
+	kfree(dev_rose);
+	return -ENOMEM;
 }
 module_init(rose_proto_init);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/cls_api.c 001-linus.patch/net/sched/cls_api.c
--- 000-virgin/net/sched/cls_api.c	Wed Dec 17 18:58:28 2003
+++ 001-linus.patch/net/sched/cls_api.c	Tue Dec 30 16:38:57 2003
@@ -247,10 +247,7 @@ static int tc_ctl_tfilter(struct sk_buff
 			*back = tp->next;
 			spin_unlock_bh(&dev->queue_lock);
 			write_unlock(&qdisc_tree_lock);
-
-			tp->ops->destroy(tp);
-			module_put(tp->ops->owner);
-			kfree(tp);
+			tcf_destroy(tp);
 			err = 0;
 			goto errout;
 		}
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_atm.c 001-linus.patch/net/sched/sch_atm.c
--- 000-virgin/net/sched/sch_atm.c	Wed Dec 17 18:58:48 2003
+++ 001-linus.patch/net/sched/sch_atm.c	Tue Dec 30 16:38:57 2003
@@ -162,7 +162,7 @@ static void destroy_filters(struct atm_f
 	while ((filter = flow->filter_list)) {
 		DPRINTK("destroy_filters: destroying filter %p\n",filter);
 		flow->filter_list = filter->next;
-		filter->ops->destroy(filter);
+		tcf_destroy(filter);
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_cbq.c 001-linus.patch/net/sched/sch_cbq.c
--- 000-virgin/net/sched/sch_cbq.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/net/sched/sch_cbq.c	Tue Dec 30 16:38:57 2003
@@ -1705,7 +1705,7 @@ static void cbq_destroy_filters(struct c
 
 	while ((tp = cl->filter_list) != NULL) {
 		cl->filter_list = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_csz.c 001-linus.patch/net/sched/sch_csz.c
--- 000-virgin/net/sched/sch_csz.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/net/sched/sch_csz.c	Tue Dec 30 16:38:57 2003
@@ -752,7 +752,7 @@ csz_destroy(struct Qdisc* sch)
 
 	while ((tp = q->filter_list) != NULL) {
 		q->filter_list = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_dsmark.c 001-linus.patch/net/sched/sch_dsmark.c
--- 000-virgin/net/sched/sch_dsmark.c	Wed Dec 17 18:58:16 2003
+++ 001-linus.patch/net/sched/sch_dsmark.c	Tue Dec 30 16:38:57 2003
@@ -378,7 +378,7 @@ static void dsmark_destroy(struct Qdisc 
 	while (p->filter_list) {
 		tp = p->filter_list;
 		p->filter_list = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 	qdisc_destroy(p->q);
 	p->q = &noop_qdisc;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_htb.c 001-linus.patch/net/sched/sch_htb.c
--- 000-virgin/net/sched/sch_htb.c	Wed Dec 17 18:59:04 2003
+++ 001-linus.patch/net/sched/sch_htb.c	Tue Dec 30 16:38:57 2003
@@ -1338,7 +1338,7 @@ static void htb_destroy_filters(struct t
 
 	while ((tp = *fl) != NULL) {
 		*fl = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_ingress.c 001-linus.patch/net/sched/sch_ingress.c
--- 000-virgin/net/sched/sch_ingress.c	Wed Dec 17 18:59:18 2003
+++ 001-linus.patch/net/sched/sch_ingress.c	Tue Dec 30 16:38:57 2003
@@ -292,7 +292,7 @@ static void ingress_destroy(struct Qdisc
 	while (p->filter_list) {
 		tp = p->filter_list;
 		p->filter_list = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 	memset(p, 0, sizeof(*p));
 	p->filter_list = NULL;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_prio.c 001-linus.patch/net/sched/sch_prio.c
--- 000-virgin/net/sched/sch_prio.c	Wed Dec 17 18:58:46 2003
+++ 001-linus.patch/net/sched/sch_prio.c	Tue Dec 30 16:38:57 2003
@@ -162,7 +162,7 @@ prio_destroy(struct Qdisc* sch)
 
 	while ((tp = q->filter_list) != NULL) {
 		q->filter_list = tp->next;
-		tp->ops->destroy(tp);
+		tcf_destroy(tp);
 	}
 
 	for (prio=0; prio<q->bands; prio++) {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/net/sched/sch_tbf.c 001-linus.patch/net/sched/sch_tbf.c
--- 000-virgin/net/sched/sch_tbf.c	Wed Dec 17 18:58:07 2003
+++ 001-linus.patch/net/sched/sch_tbf.c	Tue Dec 30 16:38:57 2003
@@ -108,6 +108,10 @@
 	Note that the peak rate TBF is much more tough: with MTU 1500
 	P_crit = 150Kbytes/sec. So, if you need greater peak
 	rates, use alpha with HZ=1000 :-)
+
+	With classful TBF, limit is just kept for backwards compatibility.
+	It is passed to the default bfifo qdisc - if the inner qdisc is
+	changed the limit is not effective anymore.
 */
 
 struct tbf_sched_data
@@ -136,7 +140,7 @@ static int tbf_enqueue(struct sk_buff *s
 	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
 	int ret;
 
-	if (skb->len > q->max_size || sch->stats.backlog + skb->len > q->limit) {
+	if (skb->len > q->max_size) {
 		sch->stats.drops++;
 #ifdef CONFIG_NET_CLS_POLICE
 		if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
@@ -152,7 +156,6 @@ static int tbf_enqueue(struct sk_buff *s
 	}	
 	
 	sch->q.qlen++;
-	sch->stats.backlog += skb->len;
 	sch->stats.bytes += skb->len;
 	sch->stats.packets++;
 	return 0;
@@ -163,10 +166,8 @@ static int tbf_requeue(struct sk_buff *s
 	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
 	int ret;
 	
-	if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) {
+	if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0)
 		sch->q.qlen++; 
-		sch->stats.backlog += skb->len;
-	}
 	
 	return ret;
 }
@@ -178,7 +179,6 @@ static unsigned int tbf_drop(struct Qdis
 	
 	if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) {
 		sch->q.qlen--;
-		sch->stats.backlog -= len;
 		sch->stats.drops++;
 	}
 	return len;
@@ -224,7 +224,6 @@ static struct sk_buff *tbf_dequeue(struc
 			q->t_c = now;
 			q->tokens = toks;
 			q->ptokens = ptoks;
-			sch->stats.backlog -= len;
 			sch->q.qlen--;
 			sch->flags &= ~TCQ_F_THROTTLED;
 			return skb;
@@ -253,7 +252,6 @@ static struct sk_buff *tbf_dequeue(struc
 		if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
 			/* When requeue fails skb is dropped */ 
 			sch->q.qlen--;
-			sch->stats.backlog -= len;
 			sch->stats.drops++;
 		}	
 		
@@ -269,7 +267,6 @@ static void tbf_reset(struct Qdisc* sch)
 
 	qdisc_reset(q->qdisc);
 	sch->q.qlen = 0;
-	sch->stats.backlog = 0;
 	PSCHED_GET_TIME(q->t_c);
 	q->tokens = q->buffer;
 	q->ptokens = q->mtu;
@@ -456,7 +453,6 @@ static int tbf_graft(struct Qdisc *sch, 
 	*old = xchg(&q->qdisc, new);
 	qdisc_reset(*old);
 	sch->q.qlen = 0;
-	sch->stats.backlog = 0;
 	sch_tree_unlock(sch);
 	
 	return 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/scripts/modpost.c 001-linus.patch/scripts/modpost.c
--- 000-virgin/scripts/modpost.c	Wed Dec 17 18:58:17 2003
+++ 001-linus.patch/scripts/modpost.c	Tue Dec 30 16:38:57 2003
@@ -324,6 +324,19 @@ handle_modversions(struct module *mod, s
 	}
 }
 
+int
+is_vmlinux(const char *modname)
+{
+	const char *myname;
+
+	if ((myname = strrchr(modname, '/')))
+		myname++;
+	else
+		myname = modname;
+
+	return strcmp(myname, "vmlinux") == 0;
+}
+
 void
 read_symbols(char *modname)
 {
@@ -335,8 +348,7 @@ read_symbols(char *modname)
 
 	/* When there's no vmlinux, don't print warnings about
 	 * unresolved symbols (since there'll be too many ;) */
-	if (strcmp(modname, "vmlinux") == 0)
-		have_vmlinux = 1;
+	have_vmlinux = is_vmlinux(modname);
 
 	parse_elf(&info, modname);
 
@@ -460,10 +472,7 @@ add_depends(struct buffer *b, struct mod
 	int first = 1;
 
 	for (m = modules; m; m = m->next) {
-		if (strcmp(m->name, "vmlinux") == 0)
-			m->seen = 1;
-		else 
-			m->seen = 0;
+		m->seen = is_vmlinux(m->name);
 	}
 
 	buf_printf(b, "\n");
@@ -543,7 +552,7 @@ main(int argc, char **argv)
 	}
 
 	for (mod = modules; mod; mod = mod->next) {
-		if (strcmp(mod->name, "vmlinux") == 0)
+		if (is_vmlinux(mod->name))
 			continue;
 
 		buf.pos = 0;
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/core/pcm_native.c 001-linus.patch/sound/core/pcm_native.c
--- 000-virgin/sound/core/pcm_native.c	Wed Dec 17 18:58:39 2003
+++ 001-linus.patch/sound/core/pcm_native.c	Tue Dec 30 16:38:57 2003
@@ -2779,7 +2779,7 @@ unsigned int snd_pcm_capture_poll(struct
 	return mask;
 }
 
-static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
+static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
 	snd_pcm_runtime_t *runtime;
@@ -2791,6 +2791,8 @@ static struct page * snd_pcm_mmap_status
 	page = virt_to_page(runtime->status);
 	if (!PageReserved(page))
 		get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
@@ -2817,7 +2819,7 @@ int snd_pcm_mmap_status(snd_pcm_substrea
 	return 0;
 }
 
-static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
+static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
 	snd_pcm_runtime_t *runtime;
@@ -2829,6 +2831,8 @@ static struct page * snd_pcm_mmap_contro
 	page = virt_to_page(runtime->control);
 	if (!PageReserved(page))
 		get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
@@ -2867,7 +2871,7 @@ static void snd_pcm_mmap_data_close(stru
 	atomic_dec(&substream->runtime->mmap_count);
 }
 
-static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
+static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
 	snd_pcm_runtime_t *runtime;
@@ -2895,6 +2899,8 @@ static struct page * snd_pcm_mmap_data_n
 	}
 	if (!PageReserved(page))
 		get_page(page);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return page;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/core/sound.c 001-linus.patch/sound/core/sound.c
--- 000-virgin/sound/core/sound.c	Wed Dec 17 18:59:05 2003
+++ 001-linus.patch/sound/core/sound.c	Tue Dec 30 16:38:57 2003
@@ -31,6 +31,7 @@
 #include <sound/initval.h>
 #include <linux/kmod.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/device.h>
 
 #define SNDRV_OS_MINORS 256
 
@@ -52,6 +53,7 @@ MODULE_PARM_SYNTAX(major, "default:116,s
 MODULE_PARM(cards_limit, "i");
 MODULE_PARM_DESC(cards_limit, "Count of soundcards installed in the system.");
 MODULE_PARM_SYNTAX(cards_limit, "default:8,skill:advanced");
+MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 #ifdef CONFIG_DEVFS_FS
 MODULE_PARM(device_mode, "i");
 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/oss/Kconfig 001-linus.patch/sound/oss/Kconfig
--- 000-virgin/sound/oss/Kconfig	Wed Dec 17 18:59:25 2003
+++ 001-linus.patch/sound/oss/Kconfig	Tue Dec 30 16:38:57 2003
@@ -25,7 +25,7 @@ config SOUND_CMPCI
 	depends on SOUND_PRIME!=n && SOUND && PCI
 	help
 	  Say Y or M if you have a PCI sound card using the CMI8338
-	  or the CMI8378 chipset.  Data on these chips are available at
+	  or the CMI8738 chipset.  Data on these chips are available at
 	  <http://www.cmedia.com.tw/>.
 
 	  A userspace utility to control some internal registers of these
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/oss/cmpci.c 001-linus.patch/sound/oss/cmpci.c
--- 000-virgin/sound/oss/cmpci.c	Wed Dec 17 18:58:56 2003
+++ 001-linus.patch/sound/oss/cmpci.c	Tue Dec 30 16:38:57 2003
@@ -2876,7 +2876,6 @@ MODULE_DEVICE_TABLE(pci, cmpci_pci_tbl);
 void initialize_chip(struct pci_dev *pcidev)
 {
 	struct cm_state *s;
-	mm_segment_t fs;
 	int i, val;
 #if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(CONFIG_SOUND_CMPCI_FM)
 	unsigned char reg_mask = 0;
@@ -3038,8 +3037,6 @@ void initialize_chip(struct pci_dev *pci
 #endif
 		pci_set_master(pcidev);	/* enable bus mastering */
 		/* initialize the chips */
-		fs = get_fs();
-		set_fs(KERNEL_DS);
 		/* set mixer output */
 		frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, 0x1f);
 		/* set mixer input */
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/oss/emu10k1/audio.c 001-linus.patch/sound/oss/emu10k1/audio.c
--- 000-virgin/sound/oss/emu10k1/audio.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/sound/oss/emu10k1/audio.c	Tue Dec 30 16:38:57 2003
@@ -989,7 +989,7 @@ static int emu10k1_audio_ioctl(struct in
 	return 0;
 }
 
-static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int write_access)
+static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type)
 {
 	struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;
 	struct woinst *woinst = wave_dev->woinst;
@@ -1032,6 +1032,8 @@ static struct page *emu10k1_mm_nopage (s
 	get_page (dmapage);
 
 	DPD(3, "page: %#lx\n", (unsigned long) dmapage);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return dmapage;
 }
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/oss/via82cxxx_audio.c 001-linus.patch/sound/oss/via82cxxx_audio.c
--- 000-virgin/sound/oss/via82cxxx_audio.c	Wed Dec 17 18:58:38 2003
+++ 001-linus.patch/sound/oss/via82cxxx_audio.c	Tue Dec 30 16:38:57 2003
@@ -15,7 +15,7 @@
  */
 
 
-#define VIA_VERSION	"1.9.1-ac3-2.5"
+#define VIA_VERSION	"1.9.1-ac4-2.5"
 
 
 #include <linux/config.h>
@@ -1237,7 +1237,6 @@ static int via_chan_set_stereo (struct v
 		}
 	/* unknown */
 	default:
-		printk (KERN_WARNING PFX "unknown number of channels\n");
 		val = -EINVAL;
 		break;
 	}
@@ -2116,7 +2115,7 @@ static void via_dsp_cleanup (struct via_
 
 
 static struct page * via_mm_nopage (struct vm_area_struct * vma,
-				    unsigned long address, int write_access)
+				    unsigned long address, int *type)
 {
 	struct via_info *card = vma->vm_private_data;
 	struct via_channel *chan = &card->ch_out;
@@ -2124,12 +2123,11 @@ static struct page * via_mm_nopage (stru
 	unsigned long pgoff;
 	int rd, wr;
 
-	DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh, wr %d\n",
+	DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n",
 		 vma->vm_start,
 		 address - vma->vm_start,
 		 (address - vma->vm_start) >> PAGE_SHIFT,
-		 address,
-		 write_access);
+		 address);
 
         if (address > vma->vm_end) {
 		DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
@@ -2167,6 +2165,8 @@ static struct page * via_mm_nopage (stru
 	DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n",
 		 dmapage, (unsigned long) chan->pgtbl[pgoff].cpuaddr);
 	get_page (dmapage);
+	if (type)
+		*type = VM_FAULT_MINOR;
 	return dmapage;
 }
 
@@ -3367,7 +3367,7 @@ static int via_dsp_release(struct inode 
 
 	if (file->f_mode & FMODE_WRITE) {
 		rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
-		if (rc && rc != ERESTARTSYS)	/* Nobody needs to know about ^C */
+		if (rc && rc != -ERESTARTSYS)	/* Nobody needs to know about ^C */
 			printk (KERN_DEBUG "via_audio: ignoring drain playback error %d\n", rc);
 
 		via_chan_free (card, &card->ch_out);
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/oss/vidc.c 001-linus.patch/sound/oss/vidc.c
--- 000-virgin/sound/oss/vidc.c	Wed Dec 17 18:58:08 2003
+++ 001-linus.patch/sound/oss/vidc.c	Tue Dec 30 16:38:57 2003
@@ -41,6 +41,7 @@
 #endif
 
 #define VIDC_SOUND_CLOCK	(250000)
+#define VIDC_SOUND_CLOCK_EXT	(176400)
 
 /*
  * When using SERIAL SOUND mode (external DAC), the number of physical
@@ -81,18 +82,10 @@ static unsigned char	vidc_level_r[SOUND_
 static unsigned int	vidc_audio_volume_l;	/* left PCM vol, 0 - 65536 */
 static unsigned int	vidc_audio_volume_r;	/* right PCM vol, 0 - 65536 */
 
-static void	(*old_mksound)(unsigned int hz, unsigned int ticks);
-extern void	(*kd_mksound)(unsigned int hz, unsigned int ticks);
 extern void	vidc_update_filler(int bits, int channels);
 extern int	softoss_dev;
 
 static void
-vidc_mksound(unsigned int hz, unsigned int ticks)
-{
-//	printk("BEEP - %d %d!\n", hz, ticks);
-}
-
-static void
 vidc_mixer_set(int mdev, unsigned int level)
 {
 	unsigned int lev_l = level & 0x007f;
@@ -193,28 +186,50 @@ static unsigned int vidc_audio_set_forma
 	return vidc_audio_format;
 }
 
+#define my_abs(i) ((i)<0 ? -(i) : (i))
+
 static int vidc_audio_set_speed(int dev, int rate)
 {
 	if (rate) {
-		unsigned int hwctrl, hwrate;
+		unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
+		unsigned int diff_int, diff_ext;
 		unsigned int newsize, new2size;
 
-		/*
-		 * If we have selected 44.1kHz, use the DAC clock.
-		 */
-		if (0 && rate == 44100) {
-			hwctrl = 0x00000002;
-			hwrate = 3;
-		} else {
-			hwctrl = 0x00000003;
+		hwctrl = 0x00000003;
 
-			hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
-			if (hwrate < 3)
-				hwrate = 3;
-			if (hwrate > 255)
-				hwrate = 255;
+		/* Using internal clock */
+		hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
+		if (hwrate < 3)
+			hwrate = 3;
+		if (hwrate > 255)
+			hwrate = 255;
 
-			rate = VIDC_SOUND_CLOCK / hwrate;
+		/* Using exernal clock */
+		hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
+		if (hwrate_ext < 3)
+			hwrate_ext = 3;
+		if (hwrate_ext > 255)
+			hwrate_ext = 255;
+
+		rate_int = VIDC_SOUND_CLOCK / hwrate;
+		rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
+
+		/* Chose between external and internal clock */
+		diff_int = my_abs(rate_ext-rate);
+		diff_ext = my_abs(rate_int-rate);
+		if (diff_ext < diff_int) {
+			/*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
+			hwrate=hwrate_ext;
+			hwctrl=0x00000002;
+			/* Allow roughly 0.4% tolerance */
+			if (diff_ext > (rate/256))
+				rate=rate_ext;
+		} else {
+			/*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
+			hwctrl=0x00000003;
+			/* Allow rougly 0.4% tolerance */
+			if (diff_int > (rate/256))
+				rate=rate_int;
 		}
 
 		vidc_writel(0xb0000000 | (hwrate - 2));
@@ -226,13 +241,14 @@ static int vidc_audio_set_speed(int dev,
 		if (newsize > 4096)
 			newsize = 4096;
 		for (new2size = 128; new2size < newsize; new2size <<= 1);
-			if (new2size - newsize > newsize - (new2size >> 1))
-				new2size >>= 1;
+		if (new2size - newsize > newsize - (new2size >> 1))
+			new2size >>= 1;
 		if (new2size > 4096) {
 			printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
 				newsize, new2size);
 			new2size = 4096;
 		}
+		/*printk("VIDC: dma size %d\n", new2size);*/
 		dma_bufsize = new2size;
 		vidc_audio_rate = rate;
 	}
@@ -471,8 +487,6 @@ static void __init attach_vidc(struct ad
 		printk(KERN_ERR "%s: IRQ %d is in use\n", name, hw_config->irq);
 		goto irq_failed;
 	}
-	old_mksound = kd_mksound;
-	kd_mksound = vidc_mksound;
 	vidc_adev = adev;
 	vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 
@@ -510,9 +524,6 @@ static void __exit unload_vidc(struct ad
 
 	vidc_adev = -1;
 
-	if (old_mksound)
-		kd_mksound = old_mksound;
-
 	free_irq(hw_config->irq, &dma_start);
 	sound_free_dma(hw_config->dma);
 
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/sound_core.c 001-linus.patch/sound/sound_core.c
--- 000-virgin/sound/sound_core.c	Wed Dec 17 18:59:45 2003
+++ 001-linus.patch/sound/sound_core.c	Tue Dec 30 16:38:57 2003
@@ -45,6 +45,7 @@
 #include <linux/major.h>
 #include <linux/kmod.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/device.h>
 
 #define SOUND_STEP 16
 
@@ -547,6 +548,7 @@ EXPORT_SYMBOL(mod_firmware_load);
 MODULE_DESCRIPTION("Core sound module");
 MODULE_AUTHOR("Alan Cox");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR);
 
 static void __exit cleanup_soundcore(void)
 {
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/sound/usb/usbaudio.h 001-linus.patch/sound/usb/usbaudio.h
--- 000-virgin/sound/usb/usbaudio.h	Wed Dec 17 18:59:04 2003
+++ 001-linus.patch/sound/usb/usbaudio.h	Tue Dec 30 16:38:57 2003
@@ -30,12 +30,6 @@
 #define USB_SUBCLASS_MIDI_STREAMING	0x03
 #define USB_SUBCLASS_VENDOR_SPEC	0xff
 
-#define USB_DT_CS_DEVICE                0x21
-#define USB_DT_CS_CONFIG                0x22
-#define USB_DT_CS_STRING                0x23
-#define USB_DT_CS_INTERFACE             0x24
-#define USB_DT_CS_ENDPOINT              0x25
-
 #define CS_AUDIO_UNDEFINED		0x20
 #define CS_AUDIO_DEVICE			0x21
 #define CS_AUDIO_CONFIGURATION		0x22
diff -Naurp -X /home/jbarnes/dontdiff 000-virgin/usr/gen_init_cpio.c 001-linus.patch/usr/gen_init_cpio.c
--- 000-virgin/usr/gen_init_cpio.c	Wed Dec 17 18:58:57 2003
+++ 001-linus.patch/usr/gen_init_cpio.c	Tue Dec 30 16:38:57 2003
@@ -197,6 +197,7 @@ void cpio_mkfile(const char *filename, c
 
 	for (i = 0; i < buf.st_size; ++i)
 		fputc(filebuf[i], stdout);
+	offset += buf.st_size;
 	close(file);
 	free(filebuf);
 	push_pad();
