## Automatically generated incremental diff
## From:   linux-2.5.68-bk8
## To:     linux-2.5.68-bk9
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.68-bk8/Documentation/eisa.txt linux-2.5.68-bk9/Documentation/eisa.txt
--- linux-2.5.68-bk8/Documentation/eisa.txt	2003-04-19 19:50:06.000000000 -0700
+++ linux-2.5.68-bk9/Documentation/eisa.txt	2003-04-29 04:36:57.000000000 -0700
@@ -79,8 +79,9 @@
 };
 
 id_table	: an array of NULL terminated EISA id strings,
-		  followed by an empty string. Each string can be
-		  paired with a driver-dependant value (driver_data).
+		  followed by an empty string. Each string can
+		  optionnaly be paired with a driver-dependant value
+		  (driver_data).
 
 driver		: a generic driver, such as described in
 		  Documentation/driver-model/driver.txt. Only .name,
@@ -88,19 +89,19 @@
 
 An example is the 3c509 driver :
 
-struct eisa_device_id el3_eisa_ids[] = {
-        { "TCM5092" },
-        { "TCM5093" },
-        { "" }
+static struct eisa_device_id vortex_eisa_ids[] = {
+	{ "TCM5920", EISA_3C592_OFFSET },
+	{ "TCM5970", EISA_3C597_OFFSET },
+	{ "" }
 };
 
-struct eisa_driver el3_eisa_driver = {
-        .id_table = el3_eisa_ids,
-        .driver   = {
-                .name    = "3c509",
-                .probe   = el3_eisa_probe,
-                .remove  = __devexit_p (el3_device_remove)
-        }
+static struct eisa_driver vortex_eisa_driver = {
+	.id_table = vortex_eisa_ids,
+	.driver   = {
+		.name    = "3c59x",
+		.probe   = vortex_eisa_probe,
+		.remove  = vortex_eisa_remove
+	}
 };
 
 ** Device :
diff -urN linux-2.5.68-bk8/Documentation/networking/ixgb.txt linux-2.5.68-bk9/Documentation/networking/ixgb.txt
--- linux-2.5.68-bk8/Documentation/networking/ixgb.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/Documentation/networking/ixgb.txt	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,226 @@
+Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters
+================================================================
+
+January 06, 2003
+
+
+Contents
+========
+
+- In This Release
+- Supported Adapters
+- Command Line Parameters
+- Improving Performance
+- Support
+
+
+In This Release
+===============
+
+This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family 
+of Adapters, version 1.0.x. This driver is intended for 2.4.x kernels; it is 
+known to build properly on 2.4.x kernels through 2.4.18. Intel focused 
+testing on Intel architectures running kernels 2.4.18. This driver includes 
+support for Itanium(TM)-based systems.
+
+For questions related to hardware requirements, refer to the documentation 
+supplied with your Intel PRO/10GbE adapter. All hardware requirements listed 
+apply to use with Linux.
+
+
+Supported Adapters
+==================
+
+The following Intel network adapters are compatible with the drivers in this 
+release:
+
+   Controller  Adapter Name                           Board IDs
+   ----------  ------------                           ---------
+
+   82597EX     Intel(R) PRO/10GbE LR Server Adapter   A82505-xxx
+
+
+To verify your Intel adapter is supported, find the board ID number on the 
+adapter. Look for a label that has a barcode and a number in the format  
+A12345-001. Match this to the list of numbers above.
+
+For more information on how to identify your adapter, go to the Adapter & 
+Driver ID Guide at:
+
+    http://support.intel.com/support/network/adapter/pro100/21397.htm
+
+For the latest Intel network drivers for Linux, go to:
+
+    http://downloadfinder.intel.com/scripts-df/support_intel.asp
+
+Command Line Parameters
+=======================
+
+If the driver is built as a module, the  following optional parameters are 
+used by entering them on the command line with the modprobe or insmod command
+using this syntax:
+
+     modprobe ixgb [<option>=<VAL1>,<VAL2>,...]
+
+     insmod ixgb [<option>=<VAL1>,<VAL2>,...]
+
+For example, with two PRO/10GbE PCI adapters, entering:
+
+    insmod ixgb TxDescriptors=80,128
+
+loads the ixgb driver with 80 TX resources for the first adapter and 128 TX 
+resources for the second adapter.
+
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
+
+FlowControl
+Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
+Default: Read from the EEPROM
+         If EEPROM is not detected, default is 3
+    This parameter controls the automatic generation(Tx) and response(Rx) to 
+    Ethernet PAUSE frames.
+
+RxDescriptors
+Valid Range: 64-4096
+Default Value: 1024
+    This value is the number of receive descriptors allocated by the driver. 
+    Increasing this value allows the driver to buffer more incoming packets. 
+    Each descriptor is 16 bytes.  A receive buffer is also allocated for 
+    each descriptor and can be either 2048, 4056, 8192, or 16384 bytes, 
+    depending on the MTU setting. When the MTU size is 1500 or less, the 
+    receive buffer size is 2048 bytes. When the MTU is greater than 1500 the
+    receive buffer size will be either 4056, 8192, or 16384 bytes. The 
+    maximum MTU size is 16114.
+
+RxIntDelay
+Valid Range: 0-65535 (0=off)
+Default Value: 6
+    This value delays the generation of receive interrupts in units of 
+    0.8192 microseconds.  Receive interrupt reduction can improve CPU 
+    efficiency if properly tuned for specific network traffic. Increasing 
+    this value adds extra latency to frame reception and can end up 
+    decreasing the throughput of TCP traffic. If the system is reporting 
+    dropped receives, this value may be set too high, causing the driver to 
+    run out of available receive descriptors.
+
+TxDescriptors
+Valid Range: 64-4096
+Default Value: 256
+    This value is the number of transmit descriptors allocated by the driver.
+    Increasing this value allows the driver to queue more transmits. Each 
+    descriptor is 16 bytes.
+
+XsumRX
+Valid Range: 0-1
+Default Value: 1
+    A value of '1' indicates that the driver should enable IP checksum
+    offload for received packets (both UDP and TCP) to the adapter hardware.
+
+XsumTX
+Valid Range: 0-1
+Default Value: 1
+    A value of '1' indicates that the driver should enable IP checksum
+    offload for transmitted packets (both UDP and TCP) to the adapter 
+    hardware.
+
+
+Improving Performance
+=====================
+
+With the Intel PRO/10 GbE adapter, the default Linux configuration will very 
+likely limit the total available throughput artificially.  There is a set of 
+things that when applied together increase the ability of Linux to transmit 
+and receive data.  The following enhancements were originally acquired from
+settings published at http://www.spec.org/web99 for various submitted results 
+using Linux.
+
+NOTE: These changes are only suggestions, and serve as a starting point for 
+tuning your network performance.
+
+The changes are made in three major ways, listed in order of greatest effect:
+- Use ifconfig to modify the mtu (maximum transmission unit) and the txqueuelen 
+  parameter.
+- Use sysctl to modify /proc parameters (essentially kernel tuning)
+- Use setpci to modify the MMRBC field in PCI-X configuration space to increase 
+  transmit burst lengths on the bus.
+
+NOTE: setpci modifies the adapter's configuration registers to allow it to read 
+up to 4k bytes at a time (for transmits).  However, for some systems the 
+behavior after modifying this register may be undefined (possibly errors of some 
+kind). A power-cycle, hard reset or explicitly setting the e6 register back to 
+22 (setpci -d 8086:1048 e6.b=22) may be required to get back to a stable 
+configuration.
+
+- COPY these lines and paste them into ixgb_perf.sh:
+#!/bin/bash
+echo "configuring network performance , edit this file to change the interface"
+# set mmrbc to 4k reads, modify only Intel 10GbE device IDs
+setpci -d 8086:1048 e6.b=2e
+# set the MTU (max transmission unit) - it requires your switch and clients to change too!
+# set the txqueuelen
+# your ixgb adapter should be loaded as eth1 for this to work, change if needed
+ifconfig eth1 mtu 9000 txqueuelen 1000 up
+# call the sysctl utility to modify /proc/sys entries 
+sysctl -p ./sysctl_ixgb.conf 
+- END ixgb_perf.sh
+
+- COPY these lines and paste them into sysctl_ixgb.conf:
+# some of the defaults may be different for your kernel
+# call this file with sysctl -p <this file>
+# these are just suggested values that worked well to increase throughput in
+# several network benchmark tests, your mileage may vary
+
+### IPV4 specific settings
+net.ipv4.tcp_timestamps = 0 # turns TCP timestamp support off, default 1, reduces CPU use
+net.ipv4.tcp_sack = 0 # turn SACK support off, default on
+# on systems with a VERY fast bus -> memory interface this is the big gainer 
+net.ipv4.tcp_rmem = 10000000 10000000 10000000 # sets min/default/max TCP read buffer, default 4096 87380 174760
+net.ipv4.tcp_wmem = 10000000 10000000 10000000 # sets min/pressure/max TCP write buffer, default 4096 16384 131072
+net.ipv4.tcp_mem = 10000000 10000000 10000000 # sets min/pressure/max TCP buffer space, default 31744 32256 32768
+
+### CORE settings (mostly for socket and UDP effect)
+net.core.rmem_max = 524287 # maximum receive socket buffer size, default 131071
+net.core.wmem_max = 524287 # maximum send socket buffer size, default 131071
+net.core.rmem_default = 524287 # default receive socket buffer size, default 65535
+net.core.wmem_default = 524287 # default send socket buffer size, default 65535
+net.core.optmem_max = 524287 # maximum amount of option memory buffers, default 10240
+net.core.netdev_max_backlog = 300000 # number of unprocessed input packets before kernel starts dropping them, default 300
+- END sysctl_ixgb.conf
+
+Edit the ixgb_perf.sh script if necessary to change eth1 to whatever interface 
+your ixgb driver is using.
+
+NOTE: Unless these scripts are added to the boot process, these changes will 
+only last only until the next system reboot.
+
+
+Resolving Slow UDP Traffic
+--------------------------
+
+If your server does not seem to be able to receive UDP traffic as fast as it 
+can receive TCP traffic, it could be because Linux, by default, does not set 
+the network stack buffers as large as they need to be to support high UDP 
+transfer rates. One way to alleviate this problem is to allow more memory to 
+be used by the IP stack to store incoming data. 
+
+For instance, use the commands: 
+    sysctl -w net.core.rmem_max=262143
+and
+    sysctl -w net.core.rmem_default=262143
+to increase the read buffer memory max and default to 262143 (256k - 1) from 
+defaults of max=131071 (128k - 1) and default=65535 (64k - 1). These variables 
+will increase the amount of memory used by the network stack for receives, and 
+can be increased significantly more if necessary for your application.
+
+Support
+=======
+
+For general information and support, go to the Intel support website at:
+
+    http://support.intel.com
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related to 
+the issue to linux.nics@intel.com.
diff -urN linux-2.5.68-bk8/MAINTAINERS linux-2.5.68-bk9/MAINTAINERS
--- linux-2.5.68-bk8/MAINTAINERS	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/MAINTAINERS	2003-04-29 04:36:57.000000000 -0700
@@ -943,6 +943,13 @@
 W:	http://sourceforge.net/projects/e1000/
 S:	Supported
 
+INTEL PRO/10GbE SUPPORT
+P:	Ganesh Venkatesan
+M:	Ganesh.Venkatesan@intel.com
+P:	Scott Feldman
+M:	scott.feldman@intel.com
+S:	Supported
+
 INTERMEZZO FILE SYSTEM
 P:	Chen Yang
 M:	intermezzo-devel@lists.sf.net
diff -urN linux-2.5.68-bk8/Makefile linux-2.5.68-bk9/Makefile
--- linux-2.5.68-bk8/Makefile	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/Makefile	2003-04-29 04:36:57.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 68
-EXTRAVERSION = -bk8
+EXTRAVERSION = -bk9
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.68-bk8/arch/arm/Kconfig linux-2.5.68-bk9/arch/arm/Kconfig
--- linux-2.5.68-bk8/arch/arm/Kconfig	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/Kconfig	2003-04-29 04:36:57.000000000 -0700
@@ -613,23 +613,30 @@
 comment "At least one math emulation must be selected"
 
 config FPE_NWFPE
-	tristate "NWFPE math emulation"
+	bool "NWFPE math emulation"
 	---help---
 	  Say Y to include the NWFPE floating point emulator in the kernel.
 	  This is necessary to run most binaries. Linux does not currently
 	  support floating point hardware so you need to say Y here even if
 	  your machine has an FPA or floating point co-processor podule.
 
-	  It is also possible to say M to build the emulator as a module
-	  (nwfpe) or indeed to leave it out altogether. However, unless you
-	  know what you are doing this can easily render your machine
-	  unbootable. Saying Y is the safe option.
-
 	  You may say N here if you are going to load the Acorn FPEmulator
 	  early in the bootup.
 
+config FPE_NWFPE_XP
+	bool "Support extended precision"
+	depends on FPE_NWFPE
+	help
+	  Say Y to include 80-bit support in the kernel floating-point
+	  emulator.  Otherwise, only 32 and 64-bit support is compiled in.
+	  Note that gcc does not generate 80-bit operations by default,
+	  so in most cases this option only enlarges the size of the
+	  floating point emulator without any good reason.
+
+	  You almost surely want to say N here.
+
 config FPE_FASTFPE
-	tristate "FastFPE math emulation (EXPERIMENTAL)"
+	bool "FastFPE math emulation (EXPERIMENTAL)"
 	depends on !CPU_26 && !CPU_32v3 && EXPERIMENTAL
 	---help---
 	  Say Y here to include the FAST floating point emulator in the kernel.
@@ -642,11 +649,6 @@
 	  If you do not feel you need a faster FP emulation you should better
 	  choose NWFPE.
 
-	  It is also possible to say M to build the emulator as a module
-	  (fastfpe).  But keep in mind that you should only load the FP
-	  emulator early in the bootup.  You should never change from NWFPE to
-	  FASTFPE or vice versa in an active system!
-
 choice
 	prompt "Kernel core (/proc/kcore) format"
 	default KCORE_ELF
diff -urN linux-2.5.68-bk8/arch/arm/Makefile linux-2.5.68-bk9/arch/arm/Makefile
--- linux-2.5.68-bk8/arch/arm/Makefile	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/Makefile	2003-04-29 04:36:57.000000000 -0700
@@ -31,13 +31,15 @@
 apcs-$(CONFIG_CPU_26)		:=-mapcs-26 -mcpu=arm3
 
 # This selects which instruction set is used.
-# Note that GCC is lame - it doesn't numerically define an
-# architecture version macro, but instead defines a whole
-# series of macros.
-arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
+# Note that GCC does not numerically define an architecture version
+# macro, but instead defines a whole series of macros which makes
+# testing for a specific architecture or later rather impossible.
+#
+# Note - GCC does accept -march=armv5te, but someone messed up the assembler or the
+# gcc specs file - this needs fixing properly - ie in gcc and/or binutils.
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5t
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5te
-arch-$(CONFIG_CPU_XSCALE)	:=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mxscale #-march=armv5te
+arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 
 # This selects how we optimise for the processor.
 tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
@@ -48,13 +50,13 @@
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	:=-mtune=strongarm #-mtune=xscale
+tune-$(CONFIG_CPU_XSCALE)	:=-mtune=strongarm -Wa,-mxscale #-mtune=xscale
 
 # Force -mno-fpu to be passed to the assembler.  Some versions of gcc don't
 # do this with -msoft-float
 CFLAGS_BOOT	:=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
 CFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
-AFLAGS		+=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu
+AFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mno-fpu -msoft-float -Wa,-mno-fpu
 
 #Default value
 DATAADDR	:= .
@@ -208,6 +210,7 @@
 	)
 
 arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+				   include/asm-arm/.arch include/asm-arm/.proc \
 				   include/config/MARKER
 
 include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
diff -urN linux-2.5.68-bk8/arch/arm/boot/compressed/head-sa1100.S linux-2.5.68-bk9/arch/arm/boot/compressed/head-sa1100.S
--- linux-2.5.68-bk8/arch/arm/boot/compressed/head-sa1100.S	2003-04-19 19:48:51.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/boot/compressed/head-sa1100.S	2003-04-29 04:36:57.000000000 -0700
@@ -50,6 +50,10 @@
 10:
 #endif
 
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		ands	r0, r0, #0x0d
+		beq	99f
+
 		@ Data cache might be active.
 		@ Be sure to flush kernel binary out of the cache,
 		@ whatever state it is, before it is turned off.
@@ -68,11 +72,4 @@
 		bic	r0, r0, #0x0d		@ clear WB, DC, MMU
 		bic	r0, r0, #0x1000		@ clear Icache
 		mcr	p15, 0, r0, c1, c0, 0
-
-/*
- * Pause for a short time so that we give enough time
- * for the host to start a terminal up.
- */
-		mov	r0, #0x00200000
-1:		subs	r0, r0, #1
-		bne	1b
+99:
diff -urN linux-2.5.68-bk8/arch/arm/def-configs/shark linux-2.5.68-bk9/arch/arm/def-configs/shark
--- linux-2.5.68-bk8/arch/arm/def-configs/shark	2003-04-19 19:50:07.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/def-configs/shark	2003-04-29 04:36:57.000000000 -0700
@@ -2,14 +2,9 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
 
 #
 # Code maturity level options
@@ -19,15 +14,19 @@
 #
 # General setup
 #
-CONFIG_NET=y
+CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
 
@@ -58,112 +57,41 @@
 #
 # Archimedes/A5000 Implementations (select only ONE)
 #
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
 
 #
-# Footbridge Implementations
+# CLPS711X/EP721X 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 is not set
 
 #
-# SA11x0 Implementations
+# Epxa10db
 #
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_BADGE4 is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_H3600_SLEEVE is not set
 
 #
-# Intel PXA250/210 Implementations
+# Footbridge Implementations
 #
-# CONFIG_ARCH_LUBBOCK is not set
-# CONFIG_ARCH_PXA_IDP is not set
 
 #
-# CLPS711X/EP721X Implementations
+# IOP310 Implementation Options
 #
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
 
 #
-# IOP310 Implementation Options
+# IOP310 Chipset Features
 #
-# CONFIG_ARCH_IQ80310 is not set
 
 #
-# IOP310 Chipset Features
+# Intel PXA250/210 Implementations
+#
+
+#
+# SA11x0 Implementations
 #
-# CONFIG_IOP310_AAU is not set
-# CONFIG_IOP310_DMA is not set
-# CONFIG_IOP310_MU is not set
-# CONFIG_IOP310_PMON is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
 
 #
 # Processor Type
 #
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_32v5 is not set
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
+CONFIG_CPU_32=y
 CONFIG_CPU_SA110=y
-# CONFIG_CPU_SA1100 is not set
-# CONFIG_CPU_XSCALE is not set
-# CONFIG_XSCALE_PMU is not set
+CONFIG_CPU_32v4=y
 
 #
 # Processor Features
@@ -172,19 +100,16 @@
 #
 # General setup
 #
-# CONFIG_DISCONTIGMEM is not set
 CONFIG_PCI=y
-# CONFIG_PCI_HOST_PLX90X0 is not set
 CONFIG_PCI_HOST_VIA82C505=y
 CONFIG_ISA=y
 CONFIG_ISA_DMA=y
-# CONFIG_FIQ is not set
 # CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
 
 #
 # At least one math emulation must be selected
@@ -198,7 +123,6 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PM is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_APM is not set
 # CONFIG_ARTHUR is not set
 CONFIG_CMDLINE=""
 CONFIG_LEDS=y
@@ -216,11 +140,6 @@
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
 # CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
 # CONFIG_PARPORT_OTHER is not set
 # CONFIG_PARPORT_1284 is not set
 
@@ -230,11 +149,9 @@
 # CONFIG_MTD is not set
 
 #
-# Plug and Play configuration
+# Plug and Play support
 #
 # CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
 
 #
 # Block devices
@@ -244,7 +161,6 @@
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -257,13 +173,11 @@
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
 
 #
 # Networking options
@@ -272,8 +186,8 @@
 # CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK_DEV is not set
 # CONFIG_NETFILTER is not set
-CONFIG_FILTER=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
@@ -283,25 +197,23 @@
 # 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_IPV6 is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#  
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+# CONFIG_XFRM_USER is not set
 
 #
-# Appletalk devices
+# SCTP Configuration (EXPERIMENTAL)
 #
-# CONFIG_DEV_APPLETALK is not set
+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_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_LLC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -314,8 +226,9 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Network device support
+# Network testing
 #
+# CONFIG_NET_PKTGEN is not set
 CONFIG_NETDEVICES=y
 
 #
@@ -332,47 +245,43 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
-# CONFIG_SUNLANCE is not set
+# CONFIG_MII is not set
 # CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE 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 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=y
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
-# CONFIG_LNE390 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
 # CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET 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_VIA_RHINE_MMIO is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -381,10 +290,10 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
-# CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_FDDI is not set
@@ -399,9 +308,8 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices
+# Token Ring devices (depends on LLC=y)
 #
-# CONFIG_TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -412,9 +320,9 @@
 # CONFIG_WAN is not set
 
 #
-# Tulip family network device support
+# IrDA (infrared) support
 #
-# CONFIG_NET_TULIP is not set
+# CONFIG_IRDA is not set
 
 #
 # Amateur Radio support
@@ -422,75 +330,32 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA (infrared) support
+# ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IRDA is not set
+CONFIG_IDE=y
 
 #
-# ATA/ATAPI/MFM/RLL support
+# IDE, ATA and ATAPI Block devices
 #
-CONFIG_IDE=y
 CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
+
+#
+# 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_ATAPI=y
 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_BLK_DEV_IDECS is not set
+# CONFIG_IDE_TASK_IOCTL is not set
 
 #
-# ATA host controller support
+# IDE chipset support/bugfixes
 #
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-
-#
-#   PCI host controller support
-#
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_IDE_TCQ is not set
-# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC6280_BURST is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIS5513 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
 # CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
 
 #
 # SCSI support
@@ -501,12 +366,10 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=m
-CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=m
 # CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=m
 
 #
@@ -525,8 +388,10 @@
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 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_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
@@ -537,11 +402,11 @@
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 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_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
@@ -559,11 +424,11 @@
 # 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_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -575,11 +440,6 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
 
 #
 # ISDN subsystem
@@ -589,47 +449,55 @@
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
 
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX 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_TSLIBDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
-# CONFIG_INPUT_UINPUT is not set
 
 #
 # Input I/O drivers
 #
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # 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_SERIAL is not set
+# 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 is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -637,33 +505,12 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_CS is not set
 # CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# 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_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_ANAKIN is not set
-# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X_OLD_NAME is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-# CONFIG_SERIAL_SA1100 is not set
-# CONFIG_SERIAL_SA1100_CONSOLE is not set
+# CONFIG_SERIAL_DZ is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -671,6 +518,7 @@
 CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
 # CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
 
 #
 # I2C support
@@ -678,26 +526,30 @@
 # CONFIG_I2C is not set
 
 #
-# L3 serial bus support
+# I2C Hardware Sensors Mainboard support
 #
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
 
 #
-# Other L3 adapters
+# I2C Hardware Sensors Chip support
 #
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
+
+#
+# L3 serial bus support
+#
+# CONFIG_L3 is not set
 
 #
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
 # CONFIG_QIC02_TAPE is not set
 
 #
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
@@ -714,6 +566,7 @@
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # Multimedia devices
@@ -723,84 +576,83 @@
 #
 # File systems
 #
-# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
 CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
+CONFIG_FS_MBCACHE=y
+# 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_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 # CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
+
+#
+# Pseudo filesystems
+#
 CONFIG_PROC_FS=y
 CONFIG_DEVFS_FS=y
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
+# CONFIG_TMPFS 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_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE 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 is not set
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_V4 is not set
 # CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_EXPORTFS is not set
+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_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
 
 #
 # Partition Types
@@ -817,11 +669,11 @@
 # 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 is not set
 CONFIG_NLS=y
 
 #
@@ -867,28 +719,18 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
-# Console drivers
-#
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
+# Graphics support
 #
 CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_ANAKIN is not set
-# CONFIG_FB_CLPS711X is not set
-# CONFIG_FB_SA1100 is not set
 CONFIG_FB_CYBER2000=y
+# CONFIG_FB_IMSTT is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY 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
@@ -896,14 +738,11 @@
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
 
 #
 # Sound
@@ -911,13 +750,17 @@
 CONFIG_SOUND=m
 
 #
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
 # CONFIG_SOUND_CS4281 is not set
 # CONFIG_SOUND_ES1370 is not set
@@ -932,7 +775,6 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
 CONFIG_SOUND_OSS=m
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
@@ -950,7 +792,6 @@
 # CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
 # CONFIG_SOUND_PSS is not set
 CONFIG_SOUND_SB=m
 # CONFIG_SOUND_AWE32_SYNTH is not set
@@ -960,32 +801,22 @@
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_YMFPCI is not set
-# CONFIG_SOUND_YMFPCI_LEGACY is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
-# CONFIG_SOUND_WAVEARTIST is not set
-# CONFIG_SOUND_TVMIXER is not set
 
 #
-# Advanced Linux Sound Architecture
+# Misc devices
 #
-# CONFIG_SND is not set
 
 #
 # Multimedia Capabilities Port drivers
 #
 # CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
 
 #
 # Console Switches
 #
 # CONFIG_SWITCHES is not set
-# CONFIG_SWITCHES_SA1100 is not set
-# CONFIG_SWITCHES_UCB1X00 is not set
 
 #
 # USB support
@@ -1004,24 +835,18 @@
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# 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
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
 
 #
 # Security options
 #
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_CRC32=y
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
diff -urN linux-2.5.68-bk8/arch/arm/kernel/entry-armv.S linux-2.5.68-bk9/arch/arm/kernel/entry-armv.S
--- linux-2.5.68-bk8/arch/arm/kernel/entry-armv.S	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/kernel/entry-armv.S	2003-04-29 04:36:57.000000000 -0700
@@ -1093,8 +1093,10 @@
 		@
 		@ now branch to the relevant MODE handling routine
 		@
-		mov	r13, #PSR_I_BIT | MODE_SVC
-		msr	spsr_c, r13			@ switch to SVC_32 mode
+		mrs	r13, cpsr
+		bic	r13, r13, #MODE_MASK
+		orr	r13, r13, #MODE_SVC
+		msr	spsr, r13			@ switch to SVC_32 mode
 
 		and	lr, lr, #15
 		ldr	lr, [pc, lr, lsl #2]
@@ -1135,8 +1137,10 @@
 		@
 		@ now branch to the relevant MODE handling routine
 		@
-		mov	r13, #PSR_I_BIT | MODE_SVC
-		msr	spsr_c, r13			@ switch to SVC_32 mode
+		mrs	r13, cpsr
+		bic	r13, r13, #MODE_MASK
+		orr	r13, r13, #MODE_SVC
+		msr	spsr, r13			@ switch to SVC_32 mode
 
 		ands	lr, lr, #15
 		ldr	lr, [pc, lr, lsl #2]
@@ -1176,8 +1180,10 @@
 		@
 		@ now branch to the relevant MODE handling routine
 		@
-		mov	r13, #PSR_I_BIT | MODE_SVC
-		msr	spsr_c, r13			@ switch to SVC_32 mode
+		mrs	r13, cpsr
+		bic	r13, r13, #MODE_MASK
+		orr	r13, r13, #MODE_SVC
+		msr	spsr, r13			@ switch to SVC_32 mode
 
 		and	lr, lr, #15
 		ldr	lr, [pc, lr, lsl #2]
diff -urN linux-2.5.68-bk8/arch/arm/kernel/process.c linux-2.5.68-bk9/arch/arm/kernel/process.c
--- linux-2.5.68-bk8/arch/arm/kernel/process.c	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/kernel/process.c	2003-04-29 04:36:57.000000000 -0700
@@ -418,7 +418,7 @@
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
-	stack_page = 4096 + (unsigned long)p;
+	stack_page = 4096 + (unsigned long)p->thread_info;
 	fp = thread_saved_fp(p);
 	do {
 		if (fp < stack_page || fp > 4092+stack_page)
diff -urN linux-2.5.68-bk8/arch/arm/kernel/setup.c linux-2.5.68-bk9/arch/arm/kernel/setup.c
--- linux-2.5.68-bk8/arch/arm/kernel/setup.c	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/kernel/setup.c	2003-04-29 04:36:57.000000000 -0700
@@ -74,6 +74,9 @@
 #ifdef MULTI_USER
 struct cpu_user_fns cpu_user;
 #endif
+#ifdef MULTI_CACHE
+struct cpu_cache_fns cpu_cache;
+#endif
 
 unsigned char aux_device_present;
 char elf_platform[ELF_PLATFORM_SIZE];
@@ -282,6 +285,9 @@
 #ifdef MULTI_USER
 	cpu_user = *list->user;
 #endif
+#ifdef MULTI_CACHE
+	cpu_cache = *list->cache;
+#endif
 
 	printk("CPU: %s [%08x] revision %d (ARMv%s)\n",
 	       cpu_name, processor_id, (int)processor_id & 15,
@@ -323,58 +329,77 @@
 	return list;
 }
 
+static void __init early_initrd(char **p)
+{
+	unsigned long start, size;
+
+	start = memparse(*p, p);
+	if (**p == ',') {
+		size = memparse((*p) + 1, p);
+
+		phys_initrd_start = start;
+		phys_initrd_size = size;
+	}
+}
+__early_param("initrd=", early_initrd);
+
 /*
- * Initial parsing of the command line.  We need to pick out the
- * memory size.  We look for mem=size@start, where start and size
- * are "size[KkMm]"
+ * Pick out the memory size.  We look for mem=size@start,
+ * where start and size are "size[KkMm]"
  */
-static void __init
-parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from)
+static void __init early_mem(char **p)
 {
-	char c = ' ', *to = command_line;
-	int usermem = 0, len = 0;
-
-	for (;;) {
-		if (c == ' ' && !memcmp(from, "mem=", 4)) {
-			unsigned long size, start;
+	static int usermem __initdata = 0;
+	unsigned long size, start;
 
-			if (to != command_line)
-				to -= 1;
+	/*
+	 * If the user specifies memory size, we
+	 * blow away any automatically generated
+	 * size.
+	 */
+	if (usermem == 0) {
+		usermem = 1;
+		meminfo.nr_banks = 0;
+	}
 
-			/*
-			 * If the user specifies memory size, we
-			 * blow away any automatically generated
-			 * size.
-			 */
-			if (usermem == 0) {
-				usermem = 1;
-				mi->nr_banks = 0;
-			}
+	start = PHYS_OFFSET;
+	size  = memparse(*p, p);
+	if (**p == '@')
+		start = memparse(*p + 1, p);
+
+	meminfo.bank[meminfo.nr_banks].start = start;
+	meminfo.bank[meminfo.nr_banks].size  = size;
+	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
+	meminfo.nr_banks += 1;
+}
+__early_param("mem=", early_mem);
 
-			start = PHYS_OFFSET;
-			size  = memparse(from + 4, &from);
-			if (*from == '@')
-				start = memparse(from + 1, &from);
-
-			mi->bank[mi->nr_banks].start = start;
-			mi->bank[mi->nr_banks].size  = size;
-			mi->bank[mi->nr_banks].node  = PHYS_TO_NID(start);
-			mi->nr_banks += 1;
-		} else if (c == ' ' && !memcmp(from, "initrd=", 7)) {
-			unsigned long start, size;
-
-			/*
-			 * Remove space character
-			 */
-			if (to != command_line)
-				to -= 1;
-
-			start = memparse(from + 7, &from);
-			if (*from == ',') {
-				size = memparse(from + 1, &from);
+/*
+ * Initial parsing of the command line.
+ */
+static void __init parse_cmdline(char **cmdline_p, char *from)
+{
+	char c = ' ', *to = command_line;
+	int len = 0;
 
-				phys_initrd_start = start;
-				phys_initrd_size = size;
+	for (;;) {
+		if (c == ' ') {
+			extern struct early_params __early_begin, __early_end;
+			struct early_params *p;
+
+			for (p = &__early_begin; p < &__early_end; p++) {
+				int len = strlen(p->arg);
+
+				if (memcmp(from, p->arg, len) == 0) {
+					if (to != command_line)
+						to -= 1;
+					from += len;
+					p->fn(&from);
+
+					while (*from != ' ' && *from != '\0')
+						from++;
+					break;
+				}
 			}
 		}
 		c = *from++;
@@ -536,6 +561,8 @@
 
 static int __init parse_tag_initrd(const struct tag *tag)
 {
+	printk(KERN_WARNING "ATAG_INITRD is deprecated; "
+		"please update your bootloader.\n");
 	phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
 	phys_initrd_size = tag->u.initrd.size;
 	return 0;
@@ -668,7 +695,7 @@
 
 	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-	parse_cmdline(&meminfo, cmdline_p, from);
+	parse_cmdline(cmdline_p, from);
 	bootmem_init(&meminfo);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
diff -urN linux-2.5.68-bk8/arch/arm/kernel/signal.c linux-2.5.68-bk9/arch/arm/kernel/signal.c
--- linux-2.5.68-bk8/arch/arm/kernel/signal.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/kernel/signal.c	2003-04-29 04:36:57.000000000 -0700
@@ -362,8 +362,8 @@
 		 * Ensure that the instruction cache sees
 		 * the return code written onto the stack.
 		 */
-		cpu_icache_invalidate_range((unsigned long)rc,
-					    (unsigned long)(rc + 1));
+		flush_icache_range((unsigned long)rc,
+				   (unsigned long)(rc + 1));
 
 		retcode = ((unsigned long)rc) + thumb;
 	}
@@ -570,6 +570,9 @@
 				/* ldr	pc, [sp], #12 */
 				put_user(0xe49df00c, &usp[2]);
 
+				flush_icache_range((unsigned long)usp,
+						   (unsigned long)(usp + 3));
+
 				regs->ARM_pc = regs->ARM_sp + 4;
 			}
 		}
diff -urN linux-2.5.68-bk8/arch/arm/mach-integrator/cpu.c linux-2.5.68-bk9/arch/arm/mach-integrator/cpu.c
--- linux-2.5.68-bk8/arch/arm/mach-integrator/cpu.c	2003-04-19 19:49:28.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mach-integrator/cpu.c	2003-04-29 04:36:57.000000000 -0700
@@ -12,6 +12,7 @@
  * CPU support functions
  */
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/cpufreq.h>
@@ -173,9 +174,9 @@
 	return 0;
 }
 
-static int integrator_cpufreq_init(struct cpufreq *policy)
+static int integrator_cpufreq_init(struct cpufreq_policy *policy)
 {
-	unsigned long cus_allowed;
+	unsigned long cpus_allowed;
 	unsigned int cpu = policy->cpu;
 	u_int cm_osc, cm_stat, mem_freq_khz;
 	struct vco vco;
diff -urN linux-2.5.68-bk8/arch/arm/mach-integrator/irq.c linux-2.5.68-bk9/arch/arm/mach-integrator/irq.c
--- linux-2.5.68-bk8/arch/arm/mach-integrator/irq.c	2003-04-19 19:51:19.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mach-integrator/irq.c	2003-04-29 04:36:57.000000000 -0700
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
+#include <linux/list.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff -urN linux-2.5.68-bk8/arch/arm/mach-sa1100/assabet.c linux-2.5.68-bk9/arch/arm/mach-sa1100/assabet.c
--- linux-2.5.68-bk8/arch/arm/mach-sa1100/assabet.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mach-sa1100/assabet.c	2003-04-29 04:36:57.000000000 -0700
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/module.h>
+#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/serial_core.h>
 #include <linux/delay.h>
@@ -25,6 +26,7 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
diff -urN linux-2.5.68-bk8/arch/arm/mach-sa1100/h3600.c linux-2.5.68-bk9/arch/arm/mach-sa1100/h3600.c
--- linux-2.5.68-bk8/arch/arm/mach-sa1100/h3600.c	2003-04-19 19:48:55.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mach-sa1100/h3600.c	2003-04-29 04:36:57.000000000 -0700
@@ -51,12 +51,6 @@
 struct ipaq_model_ops ipaq_model_ops;
 EXPORT_SYMBOL(ipaq_model_ops);
 
-static void msleep(unsigned int msec)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((msec * HZ + 999) / 1000);
-}
-
 /*
  * low-level UART features
  */
diff -urN linux-2.5.68-bk8/arch/arm/mach-sa1100/sleep.S linux-2.5.68-bk9/arch/arm/mach-sa1100/sleep.S
--- linux-2.5.68-bk8/arch/arm/mach-sa1100/sleep.S	2003-04-29 04:36:48.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mach-sa1100/sleep.S	2003-04-29 04:36:57.000000000 -0700
@@ -54,7 +54,7 @@
 	str	r0, [r1]
 
 	@ clean data cache and invalidate WB
-	bl	cpu_sa1100_cache_clean_invalidate_all
+	bl	v4wb_flush_kern_cache_all
 
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
diff -urN linux-2.5.68-bk8/arch/arm/mm/Makefile linux-2.5.68-bk9/arch/arm/mm/Makefile
--- linux-2.5.68-bk8/arch/arm/mm/Makefile	2003-04-19 19:51:22.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/Makefile	2003-04-29 04:36:57.000000000 -0700
@@ -20,16 +20,16 @@
 p-$(CONFIG_CPU_26)	+= proc-arm2_3.o
 
 # ARMv3
-p-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o  tlb-v3.o    copypage-v3.o
-p-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o  tlb-v3.o    copypage-v3.o
+p-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o  tlb-v3.o    cache-v3.o    copypage-v3.o
+p-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o  tlb-v3.o    cache-v3.o    copypage-v3.o
 
 # ARMv4
-p-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o  tlb-v4.o    copypage-v4wt.o abort-lv4t.o
-p-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o  tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o  tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o
-p-$(CONFIG_CPU_SA110)	+= proc-sa110.o   tlb-v4wb.o  copypage-v4wb.o abort-ev4.o   minicache.o
-p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o   tlb-v4wb.o  copypage-v4mc.o abort-ev4.o   minicache.o
+p-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o  tlb-v4.o    cache-v4.o    copypage-v4wt.o abort-lv4t.o
+p-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o  tlb-v4wbi.o cache-v4wt.o  copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_ARM922T)	+= proc-arm922.o  tlb-v4wbi.o cache-v4wt.o  copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o tlb-v4wbi.o cache-v4wt.o  copypage-v4wb.o abort-ev4t.o
+p-$(CONFIG_CPU_SA110)	+= proc-sa110.o   tlb-v4wb.o  cache-v4wb.o  copypage-v4wb.o abort-ev4.o
+p-$(CONFIG_CPU_SA1100)	+= proc-sa1100.o  tlb-v4wb.o  cache-v4wb.o  copypage-v4mc.o abort-ev4.o   minicache.o
 
 # ARMv5
 p-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o  tlb-v4wbi.o copypage-v4wb.o abort-ev5tej.o
diff -urN linux-2.5.68-bk8/arch/arm/mm/cache-v3.S linux-2.5.68-bk9/arch/arm/mm/cache-v3.S
--- linux-2.5.68-bk8/arch/arm/mm/cache-v3.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/arch/arm/mm/cache-v3.S	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,118 @@
+/*
+ *  linux/arch/arm/mm/cache-v3.S
+ *
+ *  Copyright (C) 1997-2002 Russell king
+ *
+ * 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>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Invalidate all cache entries in a particular address
+ *	space.
+ *
+ *	- mm	- mm_struct describing address space
+ */
+ENTRY(v3_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(v3_flush_kern_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_user_cache_range(start, end, vm_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
+ */
+ENTRY(v3_flush_user_cache_range)
+	mov	ip, #0
+	mcreq	p15, 0, ip, c7, c0, 0		@ flush ID cache
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_coherent_kern_range)
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(v3_flush_kern_dcache_page)
+	/* FALLTHROUGH */
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_dma_inv_range)
+	/* FALLTHROUGH */
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_dma_flush_range)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c0, 0		@ flush ID cache
+	/* FALLTHROUGH */
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean (write back) the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_dma_clean_range)
+	mov	pc, lr
+
+ENTRY(v3_cache_fns)
+	.long	v3_flush_kern_cache_all
+	.long	v3_flush_user_cache_all
+	.long	v3_flush_user_cache_range
+	.long	v3_coherent_kern_range
+	.long	v3_flush_kern_dcache_page
+	.long	v3_dma_inv_range
+	.long	v3_dma_clean_range
+	.long	v3_dma_flush_range
diff -urN linux-2.5.68-bk8/arch/arm/mm/cache-v4.S linux-2.5.68-bk9/arch/arm/mm/cache-v4.S
--- linux-2.5.68-bk8/arch/arm/mm/cache-v4.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/arch/arm/mm/cache-v4.S	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,120 @@
+/*
+ *  linux/arch/arm/mm/cache-v4.S
+ *
+ *  Copyright (C) 1997-2002 Russell king
+ *
+ * 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>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Invalidate all cache entries in a particular address
+ *	space.
+ *
+ *	- mm	- mm_struct describing address space
+ */
+ENTRY(v4_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(v4_flush_kern_cache_all)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, vma)
+ *
+ *	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
+ */
+ENTRY(v4_flush_user_cache_range)
+	mov	ip, #0
+	mcreq	p15, 0, ip, c7, c7, 0		@ flush ID cache
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_coherent_kern_range)
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(v4_flush_kern_dcache_page)
+	/* FALLTHROUGH */
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_dma_inv_range)
+	/* FALLTHROUGH */
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_dma_flush_range)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache
+	/* FALLTHROUGH */
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean (write back) the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_dma_clean_range)
+	mov	pc, lr
+
+ENTRY(v4_cache_fns)
+	.long	v4_flush_kern_cache_all
+	.long	v4_flush_user_cache_all
+	.long	v4_flush_user_cache_range
+	.long	v4_coherent_kern_range
+	.long	v4_flush_kern_dcache_page
+	.long	v4_dma_inv_range
+	.long	v4_dma_clean_range
+	.long	v4_dma_flush_range
diff -urN linux-2.5.68-bk8/arch/arm/mm/cache-v4wb.S linux-2.5.68-bk9/arch/arm/mm/cache-v4wb.S
--- linux-2.5.68-bk8/arch/arm/mm/cache-v4wb.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/arch/arm/mm/cache-v4wb.S	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,196 @@
+/*
+ *  linux/arch/arm/mm/cache-v4wb.S
+ *
+ *  Copyright (C) 1997-2002 Russell king
+ *
+ * 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>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
+
+/*
+ * The size of one data cache line.
+ */
+#define CACHE_DLINESIZE	32
+
+/*
+ * The total size of the data cache.
+ */
+#if defined(CONFIG_CPU_SA110)
+# define CACHE_DSIZE	16384
+#elif defined(CONFIG_CPU_SA1100)
+# define CACHE_DSIZE	8192
+#else
+# error Unknown cache size
+#endif
+
+/*
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.
+ *
+ *  Size  Clean (ticks) Dirty (ticks)
+ *   4096   21  20  21    53  55  54
+ *   8192   40  41  40   106 100 102
+ *  16384   77  77  76   140 140 138
+ *  32768  150 149 150   214 216 212 <---
+ *  65536  296 297 296   351 358 361
+ * 131072  591 591 591   656 657 651
+ *  Whole  132 136 132   221 217 207 <---
+ */
+#define CACHE_DLIMIT	(CACHE_DSIZE * 4)
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Clean and invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(v4wb_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(v4wb_flush_kern_cache_all)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+__flush_whole_cache:
+	mov	r0, #FLUSH_BASE
+	add	r1, r0, #CACHE_DSIZE
+1:	ldr	r2, [r0], #32
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, ip, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, vm_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
+ */
+ENTRY(v4wb_flush_user_cache_range)
+	sub	r3, r1, r0			@ calculate total size
+	tst	r2, #VM_EXEC			@ executable region?
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+
+	cmp	r3, #CACHE_DLIMIT		@ total size >= limit?
+	bhs	__flush_whole_cache		@ flush whole D cache
+
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(v4wb_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+	/* fall through */
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wb_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wb_dma_inv_range)
+	tst	r0, #CACHE_DLINESIZE - 1
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean (write back) the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wb_dma_clean_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ *
+ *	This is actually the same as v4wb_coherent_kern_range()
+ */
+	.globl	v4wb_dma_flush_range
+	.set	v4wb_dma_flush_range, v4wb_coherent_kern_range
+
+ENTRY(v4wb_cache_fns)
+	.long	v4wb_flush_kern_cache_all
+	.long	v4wb_flush_user_cache_all
+	.long	v4wb_flush_user_cache_range
+	.long	v4wb_coherent_kern_range
+	.long	v4wb_flush_kern_dcache_page
+	.long	v4wb_dma_inv_range
+	.long	v4wb_dma_clean_range
+	.long	v4wb_dma_flush_range
diff -urN linux-2.5.68-bk8/arch/arm/mm/cache-v4wt.S linux-2.5.68-bk9/arch/arm/mm/cache-v4wt.S
--- linux-2.5.68-bk8/arch/arm/mm/cache-v4wt.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/arch/arm/mm/cache-v4wt.S	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,170 @@
+/*
+ *  linux/arch/arm/mm/cache-v4wt.S
+ *
+ *  Copyright (C) 1997-2002 Russell king
+ *
+ * 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.
+ *
+ *  ARMv4 write through cache operations support.
+ *
+ *  We assume that the write buffer is not enabled.
+ */
+#include <linux/linkage.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
+
+/*
+ * The size of one data cache line.
+ */
+#define CACHE_DLINESIZE	32
+
+/*
+ * The number of data cache segments.
+ */
+#define CACHE_DSEGMENTS	8
+
+/*
+ * The number of lines in a cache segment.
+ */
+#define CACHE_DENTRIES	64
+
+/*
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.
+ *
+ * *** This needs benchmarking
+ */
+#define CACHE_DLIMIT	16384
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(v4wt_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(v4wt_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, vm_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
+ */
+ENTRY(v4wt_flush_user_cache_range)
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bhs	__flush_whole_cache
+
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wt_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(v4wt_flush_kern_dcache_page)
+	mov	r2, #0
+	mcr	p15, 0, r2, c7, c5, 0		@ invalidate I cache
+	add	r1, r0, #PAGE_SZ
+	/* fallthrough */
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wt_dma_inv_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	/* FALLTHROUGH */
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wt_dma_clean_range)
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+	.globl	v4wt_dma_flush_range
+	.equ	v4wt_dma_flush_range, v4wt_dma_inv_range
+
+ENTRY(v4wt_cache_fns)
+	.long	v4wt_flush_kern_cache_all
+	.long	v4wt_flush_user_cache_all
+	.long	v4wt_flush_user_cache_range
+	.long	v4wt_coherent_kern_range
+	.long	v4wt_flush_kern_dcache_page
+	.long	v4wt_dma_inv_range
+	.long	v4wt_dma_clean_range
+	.long	v4wt_dma_flush_range
+
diff -urN linux-2.5.68-bk8/arch/arm/mm/consistent.c linux-2.5.68-bk9/arch/arm/mm/consistent.c
--- linux-2.5.68-bk8/arch/arm/mm/consistent.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/consistent.c	2003-04-29 04:36:57.000000000 -0700
@@ -161,11 +161,11 @@
 
 	/*
 	 * Invalidate any data that might be lurking in the
-	 * kernel direct-mapped region.
+	 * kernel direct-mapped region for device DMA.
 	 */
 	{
 		unsigned long kaddr = (unsigned long)page_address(page);
-		invalidate_dcache_range(kaddr, kaddr + size);
+		dmac_inv_range(kaddr, kaddr + size);
 	}
 
 	/*
@@ -330,7 +330,7 @@
 core_initcall(consistent_init);
 
 /*
- * make an area consistent.
+ * make an area consistent for devices.
  */
 void consistent_sync(void *vaddr, size_t size, int direction)
 {
@@ -339,13 +339,13 @@
 
 	switch (direction) {
 	case DMA_FROM_DEVICE:		/* invalidate only */
-		invalidate_dcache_range(start, end);
+		dmac_inv_range(start, end);
 		break;
 	case DMA_TO_DEVICE:		/* writeback only */
-		clean_dcache_range(start, end);
+		dmac_clean_range(start, end);
 		break;
 	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
-		flush_dcache_range(start, end);
+		dmac_flush_range(start, end);
 		break;
 	default:
 		BUG();
diff -urN linux-2.5.68-bk8/arch/arm/mm/fault-armv.c linux-2.5.68-bk9/arch/arm/mm/fault-armv.c
--- linux-2.5.68-bk8/arch/arm/mm/fault-armv.c	2003-04-19 19:48:55.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/fault-armv.c	2003-04-29 04:36:57.000000000 -0700
@@ -184,9 +184,8 @@
 {
 	struct mm_struct *mm = current->active_mm;
 	struct list_head *l;
-	unsigned long kaddr = (unsigned long)page_address(page);
 
-	cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0);
+	__cpuc_flush_dcache_page(page_address(page));
 
 	if (!page->mapping)
 		return;
@@ -291,10 +290,9 @@
 	page = pfn_to_page(pfn);
 	if (page->mapping) {
 		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
-		unsigned long kaddr = (unsigned long)page_address(page);
 
 		if (dirty)
-			cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0);
+			__cpuc_flush_dcache_page(page_address(page));
 
 		make_coherent(vma, addr, page, dirty);
 	}
diff -urN linux-2.5.68-bk8/arch/arm/mm/fault-common.c linux-2.5.68-bk9/arch/arm/mm/fault-common.c
--- linux-2.5.68-bk8/arch/arm/mm/fault-common.c	2003-04-19 19:49:59.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/fault-common.c	2003-04-29 04:36:57.000000000 -0700
@@ -12,19 +12,15 @@
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/types.h>
 #include <linux/ptrace.h>
-#include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-#include <linux/proc_fs.h>
 #include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 
 #include "fault.h"
diff -urN linux-2.5.68-bk8/arch/arm/mm/mm-armv.c linux-2.5.68-bk9/arch/arm/mm/mm-armv.c
--- linux-2.5.68-bk8/arch/arm/mm/mm-armv.c	2003-04-19 19:50:06.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/mm-armv.c	2003-04-29 04:36:57.000000000 -0700
@@ -24,30 +24,82 @@
 
 #include <asm/mach/map.h>
 
+static unsigned int cachepolicy __initdata = PMD_SECT_WB;
+static unsigned int ecc_mask __initdata = 0;
+
+struct cachepolicy {
+	char		*policy;
+	unsigned int	cr_mask;
+	unsigned int	pmd;
+};
+
+static struct cachepolicy cache_policies[] __initdata = {
+	{ "uncached",		CR1_W|CR1_C,	PMD_SECT_UNCACHED },
+	{ "buffered",		CR1_C,		PMD_SECT_BUFFERED },
+	{ "writethrough",	0,		PMD_SECT_WT       },
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	{ "writeback",		0,		PMD_SECT_WB       },
+	{ "writealloc",		0,		PMD_SECT_WBWA     }
+#endif
+};
+
 /*
  * These are useful for identifing cache coherency
  * problems by allowing the cache or the cache and
  * writebuffer to be turned off.  (Note: the write
  * buffer should not be on and the cache off).
  */
-static int __init nocache_setup(char *__unused)
+static void __init early_cachepolicy(char **p)
 {
-	cr_alignment &= ~CR1_C;
-	cr_no_alignment &= ~CR1_C;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
+		int len = strlen(cache_policies[i].policy);
+
+		if (memcmp(*p, cache_policies[i].policy, len) == 0) {
+			cachepolicy = cache_policies[i].pmd;
+			cr_alignment &= ~cache_policies[i].cr_mask;
+			cr_no_alignment &= ~cache_policies[i].cr_mask;
+			*p += len;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(cache_policies))
+		printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
 	flush_cache_all();
 	set_cr(cr_alignment);
-	return 1;
 }
 
-static int __init nowrite_setup(char *__unused)
+static void __init early_nocache(char **__unused)
 {
-	cr_alignment &= ~(CR1_W|CR1_C);
-	cr_no_alignment &= ~(CR1_W|CR1_C);
-	flush_cache_all();
-	set_cr(cr_alignment);
-	return 1;
+	char *p = "buffered";
+	printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
+	early_cachepolicy(&p);
+}
+
+static void __init early_nowrite(char **__unused)
+{
+	char *p = "uncached";
+	printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
+	early_cachepolicy(&p);
 }
 
+static void __init early_ecc(char **p)
+{
+	if (memcmp(*p, "on", 2) == 0) {
+		ecc_mask = PMD_PROTECTION;
+		*p += 2;
+	} else if (memcmp(*p, "off", 3) == 0) {
+		ecc_mask = 0;
+		*p += 3;
+	}
+}
+
+__early_param("nocache", early_nocache);
+__early_param("nowb", early_nowrite);
+__early_param("cachepolicy=", early_cachepolicy);
+__early_param("ecc=", early_ecc);
+
 static int __init noalign_setup(char *__unused)
 {
 	cr_alignment &= ~CR1_A;
@@ -57,8 +109,6 @@
 }
 
 __setup("noalign", noalign_setup);
-__setup("nocache", nocache_setup);
-__setup("nowb", nowrite_setup);
 
 #define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
 
@@ -197,7 +247,7 @@
 		pmdval = __pa(ptep) | prot_l1;
 		pmdp[0] = __pmd(pmdval);
 		pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
-		cpu_flush_pmd(pmdp);
+		flush_pmd_entry(pmdp);
 	}
 	ptep = pte_offset_kernel(pmdp, virt);
 
@@ -231,32 +281,20 @@
 		.domain    = DOMAIN_IO,
 	},
 	[MT_CACHECLEAN] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_CACHEABLE | L_PTE_BUFFERABLE,
-		.prot_l1   = PMD_TYPE_TABLE | PMD_BIT4,
 		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
 		.domain    = DOMAIN_KERNEL,
 	},
 	[MT_MINICLEAN] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_CACHEABLE,
-		.prot_l1   = PMD_TYPE_TABLE | PMD_BIT4,
 		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE,
 		.domain    = DOMAIN_KERNEL,
 	},
 	[MT_VECTORS] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
 				L_PTE_EXEC,
 		.prot_l1   = PMD_TYPE_TABLE | PMD_BIT4,
-		.prot_sect = PMD_TYPE_SECT | PMD_BIT4,
 		.domain    = DOMAIN_USER,
 	},
 	[MT_MEMORY] = {
-		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
-				L_PTE_EXEC | L_PTE_WRITE,
-		.prot_l1   = PMD_TYPE_TABLE | PMD_BIT4,
 		.prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
 	}
@@ -268,37 +306,50 @@
 static void __init build_mem_type_table(void)
 {
 	int cpu_arch = cpu_architecture();
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	int writethrough = 1;
-#else
-	int writethrough = 0;
-#endif
-	int writealloc = 0, ecc = 0;
+	const char *policy;
 
-	if (cpu_arch < CPU_ARCH_ARMv5) {
-		writealloc = 0;
-		ecc = 0;
+	/*
+	 * ARMv5 can use ECC memory.
+	 */
+	if (cpu_arch == CPU_ARCH_ARMv5) {
+		mem_types[MT_VECTORS].prot_l1 |= ecc_mask;
+		mem_types[MT_MEMORY].prot_sect |= ecc_mask;
+	} else {
 		mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
-	}
-
-	if (writethrough) {
+		if (cachepolicy == PMD_SECT_WBWA)
+			cachepolicy = PMD_SECT_WB;
+		ecc_mask = 0;
+	}
+
+	mem_types[MT_MEMORY].prot_sect |= cachepolicy;
+
+	switch (cachepolicy) {
+	default:
+	case PMD_SECT_UNCACHED:
+		policy = "uncached";
+		break;
+	case PMD_SECT_BUFFERED:
+		mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE;
+		policy = "buffered";
+		break;
+	case PMD_SECT_WT:
+		mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE;
 		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
-		mem_types[MT_VECTORS].prot_sect |= PMD_SECT_WT;
-		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WT;
-	} else {
+		policy = "write through";
+		break;
+	case PMD_SECT_WB:
+		mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE;
 		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
-		mem_types[MT_VECTORS].prot_sect |= PMD_SECT_WB;
-
-		if (writealloc)
-			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WBWA;
-		else
-			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WB;
-	}
-
-	if (ecc) {
-		mem_types[MT_VECTORS].prot_sect |= PMD_PROTECTION;
-		mem_types[MT_MEMORY].prot_sect |= PMD_PROTECTION;
+		policy = "write back";
+		break;
+	case PMD_SECT_WBWA:
+		mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE;
+		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
+		policy = "write back, write allocate";
+		break;
 	}
+	printk("Memory policy: ECC %sabled, Data cache %s\n",
+		ecc_mask ? "en" : "dis", policy);
 }
 
 /*
@@ -330,6 +381,14 @@
 	off    = md->physical - virt;
 	length = md->length;
 
+	if (mem_types[md->type].prot_l1 == 0 &&
+	    (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
+		printk(KERN_WARNING "MM: map for 0x%08lx at 0x%08lx can not "
+		       "be mapped using pages, ignoring.\n",
+		       md->physical, md->virtual);
+		return;
+	}
+
 	while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
 		alloc_init_page(virt, virt + off, prot_l1, prot_pte);
 
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm1020.S linux-2.5.68-bk9/arch/arm/mm/proc-arm1020.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm1020.S	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm1020.S	2003-04-29 04:36:57.000000000 -0700
@@ -43,27 +43,29 @@
 #define MAX_AREA_SIZE	32768
 
 /*
- * the cache line size of the I and D cache
+ * The size of one data cache line.
  */
-#define DCACHELINESIZE	32
-#define ICACHELINESIZE	32
+#define CACHE_DLINESIZE	32
 
 /*
- * and the page size
+ * The number of data cache segments.
  */
-#define PAGESIZE	4096
+#define CACHE_DSEGMENTS	16
 
-	.text
 /*
- * cpu_arm1020_check_bugs()
+ * The number of lines in a cache segment.
  */
-ENTRY(cpu_arm1020_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
+#define CACHE_DENTRIES	64
 
 /*
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.
+ */
+#define CACHE_DLIMIT	32768
+
+	.text
+/*
  * cpu_arm1020_proc_init()
  */
 ENTRY(cpu_arm1020_proc_init)
@@ -114,230 +116,233 @@
 
 /* ================================= CACHE ================================ */
 
-
+	.align	5
 /*
- * cpu_arm1020_cache_clean_invalidate_all()
+ *	flush_user_cache_all()
  *
- * clean and invalidate all cache lines
+ *	Invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(arm1020_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
  *
- * Note:
- *  1. we should preserve r0 at all times
+ *	Clean and invalidate the entire cache.
  */
-	.align	5
-ENTRY(cpu_arm1020_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_arm1020_cache_clean_invalidate_all_r2:
+ENTRY(arm1020_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	mcr	p15, 0, ip, c7, c10, 4
-
-	mov	r1, #0xf			@ 16 segments
-1:	mov	r3, #0x3F			@ 64 entries
-2:	mov	ip, r3, LSL #26 		@ shift up entry
-	orr	ip, ip, r1, LSL #5		@ shift in/up index
-	mcr	p15, 0, ip, c7, c14, 2		@ Clean & Inval DCache entry
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB 
-	subs	r3, r3, #1
-	cmp	r3, #0
-	bge	2b				@ entries 3F to 0
-	subs	r1, r1, #1
-	cmp	r1, #0
-	bge	1b				@ segments 7 to 0
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 5	@ 16 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean+invalidate D index
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	subs	r3, r3, #1 << 26
+	bcs	2b				@ entries 63 to 0
+	subs	r1, r1, #1 << 5
+	bcs	1b				@ segments 15 to 0
 #endif
+	tst	r2, #VM_EXEC
 #ifndef CONFIG_CPU_ICACHE_DISABLE
-	teq	r2, #0
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm1020_cache_clean_invalidate_range(start, end, flags)
+ *	flush_user_cache_range(start, end, flags)
  *
- * clean and invalidate all cache lines associated with this area of memory
+ *	Invalidate a range of cache entries in the specified
+ *	address space.
  *
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags for this space
  */
-	.align	5
-ENTRY(cpu_arm1020_cache_clean_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bgt	cpu_arm1020_cache_clean_invalidate_all_r2
-	mcr	p15, 0, r3, c7, c10, 4
+ENTRY(arm1020_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bhs	__flush_whole_cache
+
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
+	mcr	p15, 0, ip, c7, c10, 4
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
+	blo	1b
 #endif
-
+	tst	r2, #VM_EXEC
 #ifndef CONFIG_CPU_ICACHE_DISABLE
-	teq	r2, #0
-	movne	r0, #0
-	mcrne	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ D-CACHE =============================== */
-
 /*
- * cpu_arm1020_dcache_invalidate_range(start, end)
+ *	coherent_kern_range(start, end)
  *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.	Note however that we must clean the D-cached entries
- * around the boundaries if the start and/or end address are not cache
- * aligned.
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm1020_dcache_invalidate_range)
+ENTRY(arm1020_coherent_kern_range)
+	mov	ip, #0
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcr	p15, 0, ip, c7, c10, 4
+1:
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	/* D cache are on */
-	tst	r0, #DCACHELINESIZE - 1
-	bic	r0, r0, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 4
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry at start
-	mcrne	p15, 0, r0, c7, c10, 4		@ drain WB
-	tst	r1, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 4
-	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry at end
-	mcrne	p15, 0, r1, c7, c10, 4		@ drain WB
-        
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	cmp	r0, r1
-	blt	1b
-#else
-	/* D cache off, but still drain the write buffer */
-	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 #endif
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+#endif
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm1020_dcache_clean_range(start, end)
+ *	flush_kern_dcache_page(void *page)
  *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- page	- page aligned address
  */
-	.align	5
-ENTRY(cpu_arm1020_dcache_clean_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bgt	cpu_arm1020_cache_clean_invalidate_all_r2
-	mcr	p15, 0, r3, c7, c10, 4
+ENTRY(arm1020_flush_kern_dcache_page)
+	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
+	blo	1b
 #endif
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm1020_dcache_clean_page(page)
+ *	dma_inv_range(start, end)
  *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
  *
- * page: virtual address of page to clean from dcache
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * Note:
- *  1. we don't need to flush the write buffer in this case.
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm1020_dcache_clean_page)
-	mov	r1, #PAGESIZE
-	mcr	p15, 0, r0, c7, c10, 4
+ENTRY(arm1020_dma_inv_range)
+	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  (drain is done by TLB fns)
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bhi	1b
+	tst	r0, #CACHE_DLINESIZE - 1
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, ip, c7, c10, 4
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, ip, c7, c10, 4
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 #endif
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm1020_dcache_clean_entry(addr)
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
  *
- * Clean the specified entry of any caches such that the MMU
- * translation fetches will obtain correct data.
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * addr: cache-unaligned virtual address
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm1020_dcache_clean_entry)
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c10, 4
+ENTRY(arm1020_dma_clean_range)
+	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean single D entry
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-#endif
-#ifndef CONFIG_CPU_ICACHE_DISABLE
-	mcr	p15, 0, r1, c7, c5, 1		@ invalidate I entry
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 #endif
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ I-CACHE =============================== */
-
 /*
- * cpu_arm1020_icache_invalidate_range(start, end)
+ *	dma_flush_range(start, end)
  *
- * invalidate a range of virtual addresses from the Icache
+ *	Clean and invalidate the specified virtual address range.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm1020_icache_invalidate_range)
-1:	mcr	p15, 0, r0, c7, c10, 4
+ENTRY(arm1020_dma_flush_range)
+	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#endif
-	add	r0, r0, #DCACHELINESIZE
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcr	p15, 0, ip, c7, c10, 4
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
 	blo	1b
-ENTRY(cpu_arm1020_icache_invalidate_page)
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+#endif
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+ENTRY(arm1020_cache_fns)
+	.long	arm1020_flush_kern_cache_all
+	.long	arm1020_flush_user_cache_all
+	.long	arm1020_flush_user_cache_range
+	.long	arm1020_coherent_kern_range
+	.long	arm1020_flush_kern_dcache_page
+	.long	arm1020_dma_inv_range
+	.long	arm1020_dma_clean_range
+	.long	arm1020_dma_flush_range
+
+	.align	5
+ENTRY(cpu_arm1020_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	mov	ip, #0
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
 	mov	pc, lr
 
 /* =============================== PageTable ============================== */
 
 /*
- * cpu_arm1020_set_pgd(pgd)
+ * cpu_arm1020_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_arm1020_set_pgd)
+ENTRY(cpu_arm1020_switch_mm)
 #ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r3, c7, c10, 4
 	mov	r1, #0xF			@ 16 segments
@@ -365,23 +370,6 @@
 	mov	pc, lr
         
 /*
- * cpu_arm1020_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_arm1020_flush_pmd)
-#ifndef CONFIG_CPU_DCACHE_DISABLE
-	mcr	p15, 0, r0, c7, c10, 4
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  (drain is done by TLB fns)
-#endif
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
  * cpu_arm1020_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
@@ -396,7 +384,7 @@
 	bic	r2, r2, #3
 	orr	r2, r2, #HPTE_TYPE_SMALL
 
-	tst	r1, #LPTE_USER | LPTE_EXEC	@ User or Exec?
+	tst	r1, #LPTE_USER			@ User?
 	orrne	r2, r2, #HPTE_AP_READ
 
 	tst	r1, #LPTE_WRITE | LPTE_DIRTY	@ Write and Dirty?
@@ -489,29 +477,12 @@
 	.type	arm1020_processor_functions, #object
 arm1020_processor_functions:
 	.word	v4t_early_abort
-	.word	cpu_arm1020_check_bugs
 	.word	cpu_arm1020_proc_init
 	.word	cpu_arm1020_proc_fin
 	.word	cpu_arm1020_reset
 	.word	cpu_arm1020_do_idle
-
-	/* cache */
-	.word	cpu_arm1020_cache_clean_invalidate_all
-	.word	cpu_arm1020_cache_clean_invalidate_range
-
-	/* dcache */
-	.word	cpu_arm1020_dcache_invalidate_range
-	.word	cpu_arm1020_dcache_clean_range
-	.word	cpu_arm1020_dcache_clean_page
-	.word	cpu_arm1020_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_arm1020_icache_invalidate_range
-	.word	cpu_arm1020_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_arm1020_set_pgd
-	.word	cpu_arm1020_flush_pmd
+	.word	cpu_arm1020_dcache_clean_area
+	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte
 
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
@@ -542,4 +513,5 @@
 	.long	arm1020_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
+	.long	arm1020_cache_fns
 	.size	__arm1020_proc_info, . - __arm1020_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm2_3.S linux-2.5.68-bk9/arch/arm/mm/proc-arm2_3.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm2_3.S	2003-04-19 19:49:33.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm2_3.S	2003-04-29 04:36:57.000000000 -0700
@@ -162,7 +162,7 @@
  * and inaccessible (0x01f00000).
  * Params  : r0 = page table pointer
  */
-clear_tables:	ldr	r1, _arm3_set_pgd - 4
+clear_tables:	ldr	r1, _arm3_switch_mm - 4
 		ldr	r2, [r1]
 		sub	r1, r0, #256 * 4		@ start of MEMC tables
 		add	r2, r1, r2, lsl #2		@ end of tables
@@ -186,14 +186,16 @@
 		mov	pc, lr
 
 /*
- * Function: *_set_pgd(pgd_t *pgd)
+ * Function: *_switch_mm(pgd_t *pgd)
  * Params  : pgd	New page tables/MEMC mapping
  * Purpose : update MEMC hardware with new mapping
  */
 		.word	page_nr
-_arm3_set_pgd:	mcr	p15, 0, r1, c1, c0, 0		@ flush cache
-_arm2_set_pgd:	stmfd	sp!, {lr}
-		ldr	r1, _arm3_set_pgd - 4
+_arm3_switch_mm:
+		mcr	p15, 0, r1, c1, c0, 0		@ flush cache
+_arm2_switch_mm:
+		stmfd	sp!, {lr}
+		ldr	r1, _arm3_switch_mm - 4
 		ldr	r2, [r1]
 		sub	r0, r0, #256 * 4		@ start of MEMC tables
 		add	r1, r0, r2, lsl #2		@ end of tables
@@ -273,9 +275,6 @@
 _arm3_xchg_4:	swp	r0, r0, [r1]
 		movs	pc, lr
 
-_arm2_3_check_bugs:
-		bics	pc, lr, #0x04000000		@ Clear FIQ disable bit
-
 cpu_arm2_name:
 		.asciz	"ARM 2"
 cpu_arm250_name:
@@ -290,28 +289,25 @@
  */
 		.globl	arm2_processor_functions
 arm2_processor_functions:
-		.word	_arm2_3_check_bugs
 		.word	_arm2_proc_init
 		.word	_arm2_proc_fin
-		.word	_arm2_set_pgd
+		.word	_arm2_switch_mm
 		.word	_arm2_xchg_1
 		.word	_arm2_xchg_4
 
 		.globl	arm250_processor_functions
 arm250_processor_functions:
-		.word	_arm2_3_check_bugs
 		.word	_arm2_proc_init
 		.word	_arm2_proc_fin
-		.word	_arm2_set_pgd
+		.word	_arm2_switch_mm
 		.word	_arm3_xchg_1
 		.word	_arm3_xchg_4
 
 		.globl	arm3_processor_functions
 arm3_processor_functions:
-		.word	_arm2_3_check_bugs
 		.word	_arm3_proc_init
 		.word	_arm3_proc_fin
-		.word	_arm3_set_pgd
+		.word	_arm3_switch_mm
 		.word	_arm3_xchg_1
 		.word	_arm3_xchg_4
 
@@ -334,6 +330,7 @@
 		.long	arm2_processor_functions
 		.long	0
 		.long	0
+		.long	0
 
 		.long	0x41560250
 		.long	0xfffffff0
@@ -346,6 +343,7 @@
 		.long	arm250_processor_functions
 		.long	0
 		.long	0
+		.long	0
 
 		.long	0x41560300
 		.long	0xfffffff0
@@ -358,4 +356,5 @@
 		.long	arm3_processor_functions
 		.long	0
 		.long	0
+		.long	0
 
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm6_7.S linux-2.5.68-bk9/arch/arm/mm/proc-arm6_7.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm6_7.S	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm6_7.S	2003-04-29 04:36:57.000000000 -0700
@@ -16,192 +16,162 @@
 #include <asm/constants.h>
 #include <asm/procinfo.h>
 
-/*
- * Function: arm6_7_cache_clean_invalidate_all (void)
- *	   : arm6_7_cache_clean_invalidate_page (unsigned long address, int size, int flags)
- *
- * Params  : address	Area start address
- *	   : size	size of area
- *	   : flags	b0 = I cache as well
- *
- * Purpose : Flush all cache lines
- */
-ENTRY(cpu_arm6_cache_clean_invalidate_all)
-ENTRY(cpu_arm7_cache_clean_invalidate_all)
-ENTRY(cpu_arm6_cache_clean_invalidate_range)
-ENTRY(cpu_arm7_cache_clean_invalidate_range)
-ENTRY(cpu_arm6_icache_invalidate_range)
-ENTRY(cpu_arm7_icache_invalidate_range)
-ENTRY(cpu_arm6_icache_invalidate_page)
-ENTRY(cpu_arm7_icache_invalidate_page)
-ENTRY(cpu_arm6_dcache_clean_range)
-ENTRY(cpu_arm7_dcache_clean_range)
-ENTRY(cpu_arm6_dcache_invalidate_range)
-ENTRY(cpu_arm7_dcache_invalidate_range)
-		mov	r0, #0
-		mcr	p15, 0, r0, c7, c0, 0		@ flush cache
-ENTRY(cpu_arm6_dcache_clean_page)
-ENTRY(cpu_arm7_dcache_clean_page)
-ENTRY(cpu_arm6_dcache_clean_entry)
-ENTRY(cpu_arm7_dcache_clean_entry)
+ENTRY(cpu_arm6_dcache_clean_area)
+ENTRY(cpu_arm7_dcache_clean_area)
 		mov	pc, lr
 
 /*
  * Function: arm6_7_data_abort ()
  *
- * Params  : r0 = address of aborted instruction
+ * Params  : r2 = address of aborted instruction
+ *	   : sp = pointer to registers
  *
  * Purpose : obtain information about current aborted instruction
  *
  * Returns : r0 = address of abort
- *	   : r1 != 0 if writing
- *	   : r3 = FSR
- *	   : sp = pointer to registers
+ *	   : r1 = FSR
  */
 
-ENTRY(cpu_arm6_data_abort)
-		ldr	r4, [r0]			@ read instruction causing problem
-		tst	r4, r4, lsr #21			@ C = bit 20
-		sbc	r1, r1, r1			@ r1 = C - 1
-		and	r2, r4, #14 << 24
-		teq	r2, #8 << 24			@ was it ldm/stm
-		bne	Ldata_simple
-
-Ldata_ldmstm:	tst	r4, #1 << 21			@ check writeback bit
-		beq	Ldata_simple
-		mov	r7, #0x11
-		orr	r7, r7, r7, lsl #8
-		and	r0, r4, r7
-		and	r2, r4, r7, lsl #1
-		add	r0, r0, r2, lsr #1
-		and	r2, r4, r7, lsl #2
-		add	r0, r0, r2, lsr #2
-		and	r2, r4, r7, lsl #3
-		add	r0, r0, r2, lsr #3
-		add	r0, r0, r0, lsr #8
-		add	r0, r0, r0, lsr #4
-		and	r7, r0, #15			@ r7 = no. of registers to transfer.
-		and	r5, r4, #15 << 16		@ Get Rn
-		ldr	r0, [sp, r5, lsr #14]		@ Get register
-		tst	r4, #1 << 23			@ U bit
-		subne	r7, r0, r7, lsl #2
-		addeq	r7, r0, r7, lsl #2		@ Do correction (signed)
-Ldata_saver7:	str	r7, [sp, r5, lsr #14]		@ Put register
-Ldata_simple:	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-		mrc	p15, 0, r3, c5, c0, 0		@ get FSR
-		and	r3, r3, #255
-		mov	pc, lr
-
 ENTRY(cpu_arm7_data_abort)
-		ldr	r4, [r0]			@ read instruction causing problem
-		tst	r4, r4, lsr #21			@ C = bit 20
-		sbc	r1, r1, r1			@ r1 = C - 1
-		and	r2, r4, #15 << 24
-		add	pc, pc, r2, lsr #22		@ Now branch to the relevant processing routine
-		movs	pc, lr
-
-		b	Ldata_unknown
-		b	Ldata_unknown
-		b	Ldata_unknown
-		b	Ldata_unknown
-		b	Ldata_lateldrpostconst		@ ldr	rd, [rn], #m
-		b	Ldata_lateldrpreconst		@ ldr	rd, [rn, #m]	@ RegVal
-		b	Ldata_lateldrpostreg		@ ldr	rd, [rn], rm
-		b	Ldata_lateldrprereg		@ ldr	rd, [rn, rm]
-		b	Ldata_ldmstm			@ ldm*a	rn, <rlist>
-		b	Ldata_ldmstm			@ ldm*b	rn, <rlist>
-		b	Ldata_unknown
-		b	Ldata_unknown
-		b	Ldata_simple			@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
-		b	Ldata_simple			@ ldc	rd, [rn, #m]
-		b	Ldata_unknown
-Ldata_unknown:	@ Part of jumptable
-		mov	r0, r2
-		mov	r1, r4
-		mov	r2, r3
-		bl	baddataabort
-		b	ret_from_exception
-
-Ldata_lateldrpreconst:
-		tst	r4, #1 << 21			@ check writeback bit
-		beq	Ldata_simple
-Ldata_lateldrpostconst:
-		movs	r2, r4, lsl #20			@ Get offset
-		beq	Ldata_simple
-		and	r5, r4, #15 << 16		@ Get Rn
-		ldr	r0, [sp, r5, lsr #14]
-		tst	r4, #1 << 23			@ U bit
-		subne	r7, r0, r2, lsr #20
-		addeq	r7, r0, r2, lsr #20
-		b	Ldata_saver7
-
-Ldata_lateldrprereg:
-		tst	r4, #1 << 21			@ check writeback bit
-		beq	Ldata_simple
-Ldata_lateldrpostreg:
-		and	r5, r4, #15
-		ldr	r2, [sp, r5, lsl #2]		@ Get Rm
-		mov	r3, r4, lsr #7
-		ands	r3, r3, #31
-		and	r6, r4, #0x70
-		orreq	r6, r6, #8
-		add	pc, pc, r6
-		mov	r0, r0
-
-		mov	r2, r2, lsl r3			@ 0: LSL #!0
-		b	1f
-		b	1f				@ 1: LSL #0
-		mov	r0, r0
-		b	1f				@ 2: MUL?
-		mov	r0, r0
-		b	1f				@ 3: MUL?
-		mov	r0, r0
-		mov	r2, r2, lsr r3			@ 4: LSR #!0
-		b	1f
-		mov	r2, r2, lsr #32			@ 5: LSR #32
-		b	1f
-		b	1f				@ 6: MUL?
-		mov	r0, r0
-		b	1f				@ 7: MUL?
-		mov	r0, r0
-		mov	r2, r2, asr r3			@ 8: ASR #!0
-		b	1f
-		mov	r2, r2, asr #32			@ 9: ASR #32
-		b	1f
-		b	1f				@ A: MUL?
-		mov	r0, r0
-		b	1f				@ B: MUL?
-		mov	r0, r0
-		mov	r2, r2, ror r3			@ C: ROR #!0
-		b	1f
-		mov	r2, r2, rrx			@ D: RRX
-		b	1f
-		mov	r0, r0				@ E: MUL?
-		mov	r0, r0
-		mov	r0, r0				@ F: MUL?
-
-
-1:		and	r5, r4, #15 << 16		@ Get Rn
-		ldr	r0, [sp, r5, lsr #14]
-		tst	r4, #1 << 23			@ U bit
-		subne	r7, r0, r2
-		addeq	r7, r0, r2
-		b	Ldata_saver7
+	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
+	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
+	ldr	r8, [r0]			@ read arm instruction
+	tst	r8, #1 << 20			@ L = 1 -> write?
+	orreq	r1, r1, #1 << 8			@ yes.
+	and	r7, r8, #15 << 24
+	add	pc, pc, r7, lsr #22		@ Now branch to the relevant processing routine
+	nop
+
+/* 0 */	b	.data_unknown
+/* 1 */	mov	pc, lr				@ swp
+/* 2 */	b	.data_unknown
+/* 3 */	b	.data_unknown
+/* 4 */	b	.data_arm_lateldrpostconst	@ ldr	rd, [rn], #m
+/* 5 */	b	.data_arm_lateldrpreconst	@ ldr	rd, [rn, #m]
+/* 6 */	b	.data_arm_lateldrpostreg	@ ldr	rd, [rn], rm
+/* 7 */	b	.data_arm_lateldrprereg		@ ldr	rd, [rn, rm]
+/* 8 */	b	.data_arm_ldmstm		@ ldm*a	rn, <rlist>
+/* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>
+/* a */	b	.data_unknown
+/* b */	b	.data_unknown
+/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
+/* d */	mov	pc, lr				@ ldc	rd, [rn, #m]
+/* e */	b	.data_unknown
+/* f */
+.data_unknown:	@ Part of jumptable
+	mov	r0, r2
+	mov	r1, r8
+	mov	r2, sp
+	bl	baddataabort
+	b	ret_from_exception
+
+ENTRY(cpu_arm6_data_abort)
+	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
+	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
+	ldr	r8, [r2]			@ read arm instruction
+	tst	r8, #1 << 20			@ L = 1 -> write?
+	orreq	r1, r1, #1 << 8			@ yes.
+	and	r7, r8, #14 << 24
+	teq	r7, #8 << 24			@ was it ldm/stm
+	movne	pc, lr
+
+.data_arm_ldmstm:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+	mov	r7, #0x11
+	orr	r7, r7, #0x1100
+	and	r6, r8, r7
+	and	r2, r8, r7, lsl #1
+	add	r6, r6, r2, lsr #1
+	and	r2, r8, r7, lsl #2
+	add	r6, r6, r2, lsr #2
+	and	r2, r8, r7, lsl #3
+	add	r6, r6, r2, lsr #3
+	add	r6, r6, r6, lsr #8
+	add	r6, r6, r6, lsr #4
+	and	r6, r6, #15			@ r6 = no. of registers to transfer.
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r6, lsl #2		@ Undo increment
+	addeq	r7, r7, r6, lsl #2		@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_apply_r6_and_rn:
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r6			@ Undo incrmenet
+	addeq	r7, r7, r6			@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_lateldrpreconst:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+.data_arm_lateldrpostconst:
+	movs	r2, r8, lsl #20			@ Get offset
+	moveq	pc, lr				@ zero -> no fixup
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r2, lsr #20		@ Undo increment
+	addeq	r7, r7, r2, lsr #20		@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_lateldrprereg:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+.data_arm_lateldrpostreg:
+	and	r7, r8, #15			@ Extract 'm' from instruction
+	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm'
+	mov	r5, r8, lsr #7			@ get shift count
+	ands	r5, r5, #31
+	and	r7, r8, #0x70			@ get shift type
+	orreq	r7, r7, #8			@ shift count = 0
+	add	pc, pc, r7
+	nop
+
+	mov	r6, r6, lsl r5			@ 0: LSL #!0
+	b	.data_arm_apply_r6_and_rn
+	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0
+	nop
+	b	.data_unknown			@ 2: MUL?
+	nop
+	b	.data_unknown			@ 3: MUL?
+	nop
+	mov	r6, r6, lsr r5			@ 4: LSR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, lsr #32			@ 5: LSR #32
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ 6: MUL?
+	nop
+	b	.data_unknown			@ 7: MUL?
+	nop
+	mov	r6, r6, asr r5			@ 8: ASR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, asr #32			@ 9: ASR #32
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ A: MUL?
+	nop
+	b	.data_unknown			@ B: MUL?
+	nop
+	mov	r6, r6, ror r5			@ C: ROR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, rrx			@ D: RRX
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ E: MUL?
+	nop
+	b	.data_unknown			@ F: MUL?
 
 /*
- * Function: arm6_7_check_bugs (void)
- *	   : arm6_7_proc_init (void)
+ * Function: arm6_7_proc_init (void)
  *	   : arm6_7_proc_fin (void)
  *
  * Notes   : This processor does not require these
  */
-ENTRY(cpu_arm6_check_bugs)
-ENTRY(cpu_arm7_check_bugs)
-		mrs	ip, cpsr
-		bic	ip, ip, #PSR_F_BIT
-		msr	cpsr, ip
-		mov	pc, lr
-
 ENTRY(cpu_arm6_proc_init)
 ENTRY(cpu_arm7_proc_init)
 		mov	pc, lr
@@ -216,17 +186,16 @@
 
 ENTRY(cpu_arm6_do_idle)
 ENTRY(cpu_arm7_do_idle)
-		mov	r0, #-EINVAL
 		mov	pc, lr
 
 /*
- * Function: arm6_7_set_pgd(unsigned long pgd_phys)
+ * Function: arm6_7_switch_mm(unsigned long pgd_phys)
  * Params  : pgd_phys	Physical address of page table
  * Purpose : Perform a task switch, saving the old processes state, and restoring
  *	     the new.
  */
-ENTRY(cpu_arm6_set_pgd)
-ENTRY(cpu_arm7_set_pgd)
+ENTRY(cpu_arm6_switch_mm)
+ENTRY(cpu_arm7_switch_mm)
 		mov	r1, #0
 		mcr	p15, 0, r1, c7, c0, 0		@ flush cache
 		mcr	p15, 0, r0, c2, c0, 0		@ update page table ptr
@@ -234,17 +203,6 @@
 		mov	pc, lr
 
 /*
- * Function: arm6_flush_pmd(pmdp)
- *
- * Params  : r0 = Address to set
- *
- * Purpose : Set a PMD and flush it out of any WB cache
- */
-ENTRY(cpu_arm6_flush_pmd)
-ENTRY(cpu_arm7_flush_pmd)
-		mov	pc, lr
-
-/*
  * Function: arm6_7_set_pte(pte_t *ptep, pte_t pte)
  * Params  : r0 = Address to set
  *	   : r1 = value to set
@@ -324,31 +282,13 @@
 		.type	arm6_processor_functions, #object
 ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_data_abort
-		.word	cpu_arm6_check_bugs
 		.word	cpu_arm6_proc_init
 		.word	cpu_arm6_proc_fin
 		.word	cpu_arm6_reset
 		.word	cpu_arm6_do_idle
-
-		/* cache */
-		.word	cpu_arm6_cache_clean_invalidate_all
-		.word	cpu_arm6_cache_clean_invalidate_range
-
-		/* dcache */
-		.word	cpu_arm6_dcache_invalidate_range
-		.word	cpu_arm6_dcache_clean_range
-		.word	cpu_arm6_dcache_clean_page
-		.word	cpu_arm6_dcache_clean_entry
-
-		/* icache */
-		.word	cpu_arm6_icache_invalidate_range
-		.word	cpu_arm6_icache_invalidate_page
-
-		/* pgtable */
-		.word	cpu_arm6_set_pgd
-		.word	cpu_arm6_flush_pmd
+		.word	cpu_arm6_dcache_clean_area
+		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte
-
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -358,31 +298,13 @@
 		.type	arm7_processor_functions, #object
 ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_data_abort
-		.word	cpu_arm7_check_bugs
 		.word	cpu_arm7_proc_init
 		.word	cpu_arm7_proc_fin
 		.word	cpu_arm7_reset
 		.word	cpu_arm7_do_idle
-
-		/* cache */
-		.word	cpu_arm7_cache_clean_invalidate_all
-		.word	cpu_arm7_cache_clean_invalidate_range
-
-		/* dcache */
-		.word	cpu_arm7_dcache_invalidate_range
-		.word	cpu_arm7_dcache_clean_range
-		.word	cpu_arm7_dcache_clean_page
-		.word	cpu_arm7_dcache_clean_entry
-
-		/* icache */
-		.word	cpu_arm7_icache_invalidate_range
-		.word	cpu_arm7_icache_invalidate_page
-
-		/* pgtable */
-		.word	cpu_arm7_set_pgd
-		.word	cpu_arm7_flush_pmd
+		.word	cpu_arm7_dcache_clean_area
+		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte
-
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.type	cpu_arch_name, #object
@@ -409,6 +331,7 @@
 		.long	arm6_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
+		.long	v3_cache_fns
 		.size	__arm6_proc_info, . - __arm6_proc_info
 
 		.type	__arm610_proc_info, #object
@@ -424,6 +347,7 @@
 		.long	arm6_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
+		.long	v3_cache_fns
 		.size	__arm610_proc_info, . - __arm610_proc_info
 
 		.type	__arm7_proc_info, #object
@@ -439,6 +363,7 @@
 		.long	arm7_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
+		.long	v3_cache_fns
 		.size	__arm7_proc_info, . - __arm7_proc_info
 
 		.type	__arm710_proc_info, #object
@@ -454,4 +379,5 @@
 		.long	arm7_processor_functions
 		.long	v3_tlb_fns
 		.long	v3_user_fns
+		.long	v3_cache_fns
 		.size	__arm710_proc_info, . - __arm710_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm720.S linux-2.5.68-bk9/arch/arm/mm/proc-arm720.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm720.S	2003-04-19 19:50:06.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm720.S	2003-04-29 04:36:57.000000000 -0700
@@ -38,47 +38,12 @@
 #include <asm/hardware.h>
 
 /*
- * Function: arm720_cache_clean_invalidate_all (void)
- *	   : arm720_cache_clean_invalidate_page (unsigned long address, int size,
- *                                    int flags)
- *
- * Params  : address	Area start address
- *	   : size	size of area
- *	   : flags	b0 = I cache as well
- *
- * Purpose : Flush all cache lines
- */
-ENTRY(cpu_arm720_cache_clean_invalidate_all)
-ENTRY(cpu_arm720_cache_clean_invalidate_range)
-ENTRY(cpu_arm720_icache_invalidate_range)
-ENTRY(cpu_arm720_icache_invalidate_page)
-ENTRY(cpu_arm720_dcache_invalidate_range)
-		mov	r0, #0
-		mcr	p15, 0, r0, c7, c7, 0		@ flush cache
-		mov	pc, lr
-
-/*
- * These just expect cache lines to be cleaned.  Since we have a writethrough
- * cache, we never have any dirty cachelines to worry about.
- */
-ENTRY(cpu_arm720_dcache_clean_range)
-ENTRY(cpu_arm720_dcache_clean_page)
-ENTRY(cpu_arm720_dcache_clean_entry)
-		mov	pc, lr
-
-/*
- * Function: arm720_check_bugs (void)
- *	   : arm720_proc_init (void)
+ * Function: arm720_proc_init (void)
  *	   : arm720_proc_fin (void)
  *
  * Notes   : This processor does not require these
  */
-ENTRY(cpu_arm720_check_bugs)
-		mrs	ip, cpsr
-		bic	ip, ip, #PSR_F_BIT
-		msr	cpsr, ip
-		mov	pc, lr
-
+ENTRY(cpu_arm720_dcache_clean_area)
 ENTRY(cpu_arm720_proc_init)
 		mov	pc, lr
 
@@ -102,12 +67,12 @@
 		mov	pc, lr
 
 /*
- * Function: arm720_set_pgd(unsigned long pgd_phys)
+ * Function: arm720_switch_mm(unsigned long pgd_phys)
  * Params  : pgd_phys	Physical address of page table
  * Purpose : Perform a task switch, saving the old process' state and restoring
  *	     the new.
  */
-ENTRY(cpu_arm720_set_pgd)
+ENTRY(cpu_arm720_switch_mm)
 		mov	r1, #0
 		mcr	p15, 0, r1, c7, c7, 0		@ invalidate cache
 		mcr	p15, 0, r0, c2, c0, 0		@ update page table ptr
@@ -115,16 +80,6 @@
 		mov	pc, lr
 
 /*
- * Function: arm720_flush_pmd(pmdp)
- *
- * Params  : r0 = Address to set
- *
- * Purpose : Set a PMD and flush it out of any WB cache
- */
-ENTRY(cpu_arm720_flush_pmd)
-		mov	pc, lr
-
-/*
  * Function: arm720_set_pte(pte_t *ptep, pte_t pte)
  * Params  : r0 = Address to set
  *	   : r1 = value to set
@@ -140,7 +95,7 @@
 		bic	r2, r2, #3
 		orr	r2, r2, #HPTE_TYPE_SMALL
 
-		tst	r1, #LPTE_USER | LPTE_EXEC	@ User or Exec?
+		tst	r1, #LPTE_USER			@ User?
 		orrne	r2, r2, #HPTE_AP_READ
 
 		tst	r1, #LPTE_WRITE | LPTE_DIRTY	@ Write and Dirty?
@@ -194,31 +149,13 @@
 		.type	arm720_processor_functions, #object
 ENTRY(arm720_processor_functions)
 		.word	v4t_late_abort
-		.word	cpu_arm720_check_bugs
 		.word	cpu_arm720_proc_init
 		.word	cpu_arm720_proc_fin
 		.word	cpu_arm720_reset
 		.word	cpu_arm720_do_idle
-
-		/* cache */
-		.word	cpu_arm720_cache_clean_invalidate_all
-		.word	cpu_arm720_cache_clean_invalidate_range
-
-		/* dcache */
-		.word	cpu_arm720_dcache_invalidate_range
-		.word	cpu_arm720_dcache_clean_range
-		.word	cpu_arm720_dcache_clean_page
-		.word	cpu_arm720_dcache_clean_entry
-
-		/* icache */
-		.word	cpu_arm720_icache_invalidate_range
-		.word	cpu_arm720_icache_invalidate_page
-
-		/* pgtable */
-		.word	cpu_arm720_set_pgd
-		.word	cpu_arm720_flush_pmd
+		.word	cpu_arm720_dcache_clean_area
+		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte
-
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.type	cpu_arch_name, #object
@@ -249,4 +186,5 @@
 		.long	arm720_processor_functions
 		.long	v4_tlb_fns
 		.long	v4wt_user_fns
+		.long	v4_cache_fns
 		.size	__arm720_proc_info, . - __arm720_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm920.S linux-2.5.68-bk9/arch/arm/mm/proc-arm920.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm920.S	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm920.S	2003-04-29 04:36:57.000000000 -0700
@@ -28,41 +28,35 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
 
 /*
- * This is the maximum size of an area which will be invalidated
- * using the single invalidate entry instructions.  Anything larger
- * than this, and we go for the whole cache.
- *
- * This value should be chosen such that we choose the cheapest
- * alternative.
+ * The size of one data cache line.
  */
-#define MAX_AREA_SIZE	16384
+#define CACHE_DLINESIZE	32
 
 /*
- * the cache line size of the I and D cache
+ * The number of data cache segments.
  */
-#define DCACHELINESIZE	32
-#define ICACHELINESIZE	32
+#define CACHE_DSEGMENTS	8
 
 /*
- * and the page size
+ * The number of lines in a cache segment.
  */
-#define PAGESIZE	4096
+#define CACHE_DENTRIES	64
 
-	.text
 /*
- * cpu_arm920_check_bugs()
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.
  */
-ENTRY(cpu_arm920_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
+#define CACHE_DLIMIT	65536
 
+
+	.text
 /*
  * cpu_arm920_proc_init()
  */
@@ -76,7 +70,11 @@
 	stmfd	sp!, {lr}
 	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, ip
-	bl	cpu_arm920_cache_clean_invalidate_all
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	bl	arm920_flush_kern_cache_all
+#else
+	bl	v4wt_flush_kern_cache_all
+#endif
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
@@ -112,249 +110,207 @@
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
 	mov	pc, lr
 
-/* ================================= CACHE ================================ */
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 
 /*
- * cpu_arm920_cache_clean_invalidate_all()
+ *	flush_user_cache_all()
  *
- * clean and invalidate all cache lines
- *
- * Note:
- *  1. we should preserve r0 at all times
+ *	Invalidate all cache entries in a particular address
+ *	space.
  */
-	.align	5
-ENTRY(cpu_arm920_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_arm920_cache_clean_invalidate_all_r2:
-	mov	ip, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
-#else
+ENTRY(arm920_flush_user_cache_all)
+	/* FALLTHROUGH */
+
 /*
- * 'Clean & Invalidate whole DCache'
- * Re-written to use Index Ops.
- * Uses registers r1, r3 and ip
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
  */
-	mov	r1, #7 << 5			@ 8 segments
-1:	orr	r3, r1, #63 << 26		@ 64 entries
-2:	mcr	p15, 0, r3, c7, c14, 2		@ clean & invalidate D index
+ENTRY(arm920_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 5	@ 8 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean+invalidate D index
 	subs	r3, r3, #1 << 26
 	bcs	2b				@ entries 63 to 0
 	subs	r1, r1, #1 << 5
 	bcs	1b				@ segments 7 to 0
-#endif
-	teq	r2, #0
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm920_cache_clean_invalidate_range(start, end, flags)
+ *	flush_user_cache_range(start, end, flags)
  *
- * clean and invalidate all cache lines associated with this area of memory
+ *	Invalidate a range of cache entries in the specified
+ *	address space.
  *
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
- */
-		.align	5
-ENTRY(cpu_arm920_cache_clean_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1	@ && added by PGM
-	bic	r1, r1, #DCACHELINESIZE - 1     @ && added by DHM
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bgt	cpu_arm920_cache_clean_invalidate_all_r2
-1:	teq	r2, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-#else
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags for address space
+ */
+ENTRY(arm920_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bhs	__flush_whole_cache
+
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-#endif
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
-
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ D-CACHE =============================== */
-
 /*
- * cpu_arm920_dcache_invalidate_range(start, end)
+ *	coherent_kern_range(start, end)
  *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.  Note however that we must clean the D-cached entries
- * around the boundaries if the start and/or end address are not cache
- * aligned.
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm920_dcache_invalidate_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	tst	r0, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
-	tst	r1, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
-#endif		@ clean D entry
-	bic	r0, r0, #DCACHELINESIZE - 1
-	bic	r1, r1, #DCACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
+ENTRY(arm920_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm920_dcache_clean_range(start, end)
+ *	flush_kern_dcache_page(void *page)
  *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- addr	- page aligned address
  */
-	.align	5
-ENTRY(cpu_arm920_dcache_clean_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	mov	r2, #0
-	bgt	cpu_arm920_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #DCACHELINESIZE -1
-	add	r1, r1, #DCACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #DCACHELINESIZE
-	bpl	1b
-#endif
-	mcr	p15, 0, r2, c7, c10, 4		@ drain WB
+ENTRY(arm920_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm920_dcache_clean_page(page)
+ *	dma_inv_range(start, end)
  *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
  *
- * page: virtual address of page to clean from dcache
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * Note:
- *  1. we don't need to flush the write buffer in this case.
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm920_dcache_clean_page)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-#endif
+ENTRY(arm920_dma_inv_range)
+	tst	r0, #CACHE_DLINESIZE - 1
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm920_dcache_clean_entry(addr)
+ *	dma_clean_range(start, end)
  *
- * Clean the specified entry of any caches such that the MMU
- * translation fetches will obtain correct data.
+ *	Clean the specified virtual address range.
  *
- * addr: cache-unaligned virtual address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm920_dcache_clean_entry)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-#endif
+ENTRY(arm920_dma_clean_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ I-CACHE =============================== */
-
 /*
- * cpu_arm920_icache_invalidate_range(start, end)
- *
- * invalidate a range of virtual addresses from the Icache
+ *	dma_flush_range(start, end)
  *
- * This is a little misleading, it is not intended to clean out
- * the i-cache but to make sure that any data written to the
- * range is made consistent.  This means that when we execute code
- * in that region, everything works as we expect.
+ *	Clean and invalidate the specified virtual address range.
  *
- * This generally means writing back data in the Dcache and
- * write buffer and flushing the Icache over that region
- *
- * start: virtual start address
- * end:   virtual end address
- *
- * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
- * loop twice, once for i-cache, once for d-cache)
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm920_icache_invalidate_range)
-	bic	r0, r0, #ICACHELINESIZE - 1	@ Safety check
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	bgt	cpu_arm920_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #ICACHELINESIZE - 1
-	add	r1, r1, #ICACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c5, 1		@ Clean I entry
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
-	add	r0, r0, #ICACHELINESIZE
-	subs	r1, r1, #ICACHELINESIZE
-	bne	1b
-
-	mov	r0, #0
+ENTRY(arm920_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-ENTRY(cpu_arm920_icache_invalidate_page)
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+ENTRY(arm920_cache_fns)
+	.long	arm920_flush_kern_cache_all
+	.long	arm920_flush_user_cache_all
+	.long	arm920_flush_user_cache_range
+	.long	arm920_coherent_kern_range
+	.long	arm920_flush_kern_dcache_page
+	.long	arm920_dma_inv_range
+	.long	arm920_dma_clean_range
+	.long	arm920_dma_flush_range
+
+#endif
+
+
+ENTRY(cpu_arm920_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
 	mov	pc, lr
 
 /* =============================== PageTable ============================== */
 
 /*
- * cpu_arm920_set_pgd(pgd)
+ * cpu_arm920_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_arm920_set_pgd)
+ENTRY(cpu_arm920_switch_mm)
 	mov	ip, #0
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 @ && 'Clean & Invalidate whole DCache'
 @ && Re-written to use Index Ops.
 @ && Uses registers r1, r3 and ip
 
-	mov	r1, #7 << 5			@ 8 segments
-1:	orr	r3, r1, #63 << 26		@ 64 entries
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 5	@ 8 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
 2:	mcr	p15, 0, r3, c7, c14, 2		@ clean & invalidate D index
 	subs	r3, r3, #1 << 26
 	bcs	2b				@ entries 63 to 0
@@ -368,28 +324,12 @@
 	mov	pc, lr
 
 /*
- * cpu_arm920_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_arm920_flush_pmd)
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
  * cpu_arm920_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
  */
 	.align	5
 ENTRY(cpu_arm920_set_pte)
-	tst	r0, #2048
-	streq	r0, [r0, -r0]			@ BUG_ON
 	str	r1, [r0], #-2048		@ linux version
 
 	eor	r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
@@ -398,7 +338,7 @@
 	bic	r2, r2, #3
 	orr	r2, r2, #HPTE_TYPE_SMALL
 
-	tst	r1, #LPTE_USER | LPTE_EXEC	@ User or Exec?
+	tst	r1, #LPTE_USER			@ User or Exec?
 	orrne	r2, r2, #HPTE_AP_READ
 
 	tst	r1, #LPTE_WRITE | LPTE_DIRTY	@ Write and Dirty?
@@ -477,31 +417,13 @@
 	.type	arm920_processor_functions, #object
 arm920_processor_functions:
 	.word	v4t_early_abort
-	.word	cpu_arm920_check_bugs
 	.word	cpu_arm920_proc_init
 	.word	cpu_arm920_proc_fin
 	.word	cpu_arm920_reset
 	.word   cpu_arm920_do_idle
-
-	/* cache */
-	.word	cpu_arm920_cache_clean_invalidate_all
-	.word	cpu_arm920_cache_clean_invalidate_range
-
-	/* dcache */
-	.word	cpu_arm920_dcache_invalidate_range
-	.word	cpu_arm920_dcache_clean_range
-	.word	cpu_arm920_dcache_clean_page
-	.word	cpu_arm920_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_arm920_icache_invalidate_range
-	.word	cpu_arm920_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_arm920_set_pgd
-	.word	cpu_arm920_flush_pmd
+	.word	cpu_arm920_dcache_clean_area
+	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte
-
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.type	cpu_arch_name, #object
@@ -530,4 +452,9 @@
 	.long	arm920_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	.long	arm920_cache_fns
+#else
+	.long	v4wt_cache_fns
+#endif
 	.size	__arm920_proc_info, . - __arm920_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm922.S linux-2.5.68-bk9/arch/arm/mm/proc-arm922.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm922.S	2003-04-19 19:50:45.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm922.S	2003-04-29 04:36:57.000000000 -0700
@@ -29,41 +29,36 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
 
 /*
- * This is the maximum size of an area which will be invalidated
- * using the single invalidate entry instructions.  Anything larger
- * than this, and we go for the whole cache.
- *
- * This value should be chosen such that we choose the cheapest
- * alternative.
+ * The size of one data cache line.
  */
-#define MAX_AREA_SIZE	8192
+#define CACHE_DLINESIZE	32
 
 /*
- * the cache line size of the I and D cache
+ * The number of data cache segments.
  */
-#define DCACHELINESIZE	32
-#define ICACHELINESIZE	32
+#define CACHE_DSEGMENTS	4
 
 /*
- * and the page size
+ * The number of lines in a cache segment.
  */
-#define PAGESIZE	4096
+#define CACHE_DENTRIES	64
 
-	.text
 /*
- * cpu_arm922_check_bugs()
+ * This is the size at which it becomes more efficient to
+ * clean the whole cache, rather than using the individual
+ * cache line maintainence instructions.  (I think this should
+ * be 32768).
  */
-ENTRY(cpu_arm922_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
+#define CACHE_DLIMIT	8192
 
+
+	.text
 /*
  * cpu_arm922_proc_init()
  */
@@ -77,7 +72,11 @@
 	stmfd	sp!, {lr}
 	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, ip
-	bl	cpu_arm922_cache_clean_invalidate_all
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	bl	arm922_flush_kern_cache_all
+#else
+	bl	v4wt_flush_kern_cache_all
+#endif
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
@@ -113,249 +112,209 @@
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
 	mov	pc, lr
 
-/* ================================= CACHE ================================ */
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 
 /*
- * cpu_arm922_cache_clean_invalidate_all()
+ *	flush_user_cache_all()
  *
- * clean and invalidate all cache lines
- *
- * Note:
- *  1. we should preserve r0 at all times
+ *	Clean and invalidate all cache entries in a particular
+ *	address space.
  */
-	.align	5
-ENTRY(cpu_arm922_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_arm922_cache_clean_invalidate_all_r2:
-	mov	ip, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
-#else
+ENTRY(arm922_flush_user_cache_all)
+	/* FALLTHROUGH */
+
 /*
- * 'Clean & Invalidate whole DCache'
- * Re-written to use Index Ops.
- * Uses registers r1, r3 and ip
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
  */
-	mov	r1, #3 << 5			@ 4 segments
-1:	orr	r3, r1, #63 << 26		@ 64 entries
-2:	mcr	p15, 0, r3, c7, c14, 2		@ clean & invalidate D index
+ENTRY(arm922_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 5	@ 8 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
+2:	mcr	p15, 0, r3, c7, c14, 2		@ clean+invalidate D index
 	subs	r3, r3, #1 << 26
 	bcs	2b				@ entries 63 to 0
 	subs	r1, r1, #1 << 5
 	bcs	1b				@ segments 7 to 0
-#endif
-	teq	r2, #0
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm922_cache_clean_invalidate_range(start, end, flags)
+ *	flush_user_cache_range(start, end, flags)
  *
- * clean and invalidate all cache lines associated with this area of memory
+ *	Clean and invalidate a range of cache entries in the
+ *	specified address range.
  *
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
- */
-		.align	5
-ENTRY(cpu_arm922_cache_clean_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1	@ && added by PGM
-	bic	r1, r1, #DCACHELINESIZE - 1     @ && added by DHM
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bgt	cpu_arm922_cache_clean_invalidate_all_r2
-1:	teq	r2, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-#else
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
+ */
+ENTRY(arm922_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bhs	__flush_whole_cache
+
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
-#endif
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
-
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ D-CACHE =============================== */
-
 /*
- * cpu_arm922_dcache_invalidate_range(start, end)
+ *	coherent_kern_range(start, end)
  *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.  Note however that we must clean the D-cached entries
- * around the boundaries if the start and/or end address are not cache
- * aligned.
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm922_dcache_invalidate_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	tst	r0, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
-	tst	r1, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
-#endif		@ clean D entry
-	bic	r0, r0, #DCACHELINESIZE - 1
-	bic	r1, r1, #DCACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
+ENTRY(arm922_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm922_dcache_clean_range(start, end)
+ *	flush_kern_dcache_page(void *page)
  *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- addr	- page aligned address
  */
-	.align	5
-ENTRY(cpu_arm922_dcache_clean_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	mov	r2, #0
-	bgt	cpu_arm922_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #DCACHELINESIZE -1
-	add	r1, r1, #DCACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #DCACHELINESIZE
-	bpl	1b
-#endif
-	mcr	p15, 0, r2, c7, c10, 4		@ drain WB
+ENTRY(arm922_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm922_dcache_clean_page(page)
+ *	dma_inv_range(start, end)
  *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
  *
- * page: virtual address of page to clean from dcache
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * Note:
- *  1. we don't need to flush the write buffer in this case.
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm922_dcache_clean_page)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-#endif
+ENTRY(arm922_dma_inv_range)
+	tst	r0, #CACHE_DLINESIZE - 1
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm922_dcache_clean_entry(addr)
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
  *
- * Clean the specified entry of any caches such that the MMU
- * translation fetches will obtain correct data.
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * addr: cache-unaligned virtual address
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm922_dcache_clean_entry)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-#endif
+ENTRY(arm922_dma_clean_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ I-CACHE =============================== */
-
 /*
- * cpu_arm922_icache_invalidate_range(start, end)
- *
- * invalidate a range of virtual addresses from the Icache
- *
- * This is a little misleading, it is not intended to clean out
- * the i-cache but to make sure that any data written to the
- * range is made consistent.  This means that when we execute code
- * in that region, everything works as we expect.
+ *	dma_flush_range(start, end)
  *
- * This generally means writing back data in the Dcache and
- * write buffer and flushing the Icache over that region
+ *	Clean and invalidate the specified virtual address range.
  *
- * start: virtual start address
- * end:   virtual end address
- *
- * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
- * loop twice, once for i-cache, once for d-cache)
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm922_icache_invalidate_range)
-	bic	r0, r0, #ICACHELINESIZE - 1	@ Safety check
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	bgt	cpu_arm922_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #ICACHELINESIZE - 1
-	add	r1, r1, #ICACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c5, 1		@ Clean I entry
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
-	add	r0, r0, #ICACHELINESIZE
-	subs	r1, r1, #ICACHELINESIZE
-	bne	1b
-
-	mov	r0, #0
+ENTRY(arm922_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-ENTRY(cpu_arm922_icache_invalidate_page)
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+ENTRY(arm922_cache_fns)
+	.long	arm922_flush_kern_cache_all
+	.long	arm922_flush_user_cache_all
+	.long	arm922_flush_user_cache_range
+	.long	arm922_coherent_kern_range
+	.long	arm922_flush_kern_dcache_page
+	.long	arm922_dma_inv_range
+	.long	arm922_dma_clean_range
+	.long	arm922_dma_flush_range
+
+#endif
+
+
+ENTRY(cpu_arm922_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
 	mov	pc, lr
 
 /* =============================== PageTable ============================== */
 
 /*
- * cpu_arm922_set_pgd(pgd)
+ * cpu_arm922_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_arm922_set_pgd)
+ENTRY(cpu_arm922_switch_mm)
 	mov	ip, #0
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 @ && 'Clean & Invalidate whole DCache'
 @ && Re-written to use Index Ops.
 @ && Uses registers r1, r3 and ip
 
-	mov	r1, #3 << 5			@ 4 segments
-1:	orr	r3, r1, #63 << 26		@ 64 entries
+	mov	r1, #(CACHE_DSEGMENTS - 1) << 5	@ 4 segments
+1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
 2:	mcr	p15, 0, r3, c7, c14, 2		@ clean & invalidate D index
 	subs	r3, r3, #1 << 26
 	bcs	2b				@ entries 63 to 0
@@ -369,20 +328,6 @@
 	mov	pc, lr
 
 /*
- * cpu_arm922_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_arm922_flush_pmd)
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
  * cpu_arm922_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
@@ -397,7 +342,7 @@
 	bic	r2, r2, #3
 	orr	r2, r2, #HPTE_TYPE_SMALL
 
-	tst	r1, #LPTE_USER | LPTE_EXEC	@ User or Exec?
+	tst	r1, #LPTE_USER			@ User?
 	orrne	r2, r2, #HPTE_AP_READ
 
 	tst	r1, #LPTE_WRITE | LPTE_DIRTY	@ Write and Dirty?
@@ -476,31 +421,13 @@
 	.type	arm922_processor_functions, #object
 arm922_processor_functions:
 	.word	v4t_early_abort
-	.word	cpu_arm922_check_bugs
 	.word	cpu_arm922_proc_init
 	.word	cpu_arm922_proc_fin
 	.word	cpu_arm922_reset
 	.word   cpu_arm922_do_idle
-
-	/* cache */
-	.word	cpu_arm922_cache_clean_invalidate_all
-	.word	cpu_arm922_cache_clean_invalidate_range
-
-	/* dcache */
-	.word	cpu_arm922_dcache_invalidate_range
-	.word	cpu_arm922_dcache_clean_range
-	.word	cpu_arm922_dcache_clean_page
-	.word	cpu_arm922_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_arm922_icache_invalidate_range
-	.word	cpu_arm922_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_arm922_set_pgd
-	.word	cpu_arm922_flush_pmd
+	.word	cpu_arm922_dcache_clean_area
+	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte
-
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.type	cpu_arch_name, #object
@@ -529,4 +456,9 @@
 	.long	arm922_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	.long	arm922_cache_fns
+#else
+	.long	v4wt_cache_fns
+#endif
 	.size	__arm922_proc_info, . - __arm922_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-arm926.S linux-2.5.68-bk9/arch/arm/mm/proc-arm926.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-arm926.S	2003-04-19 19:49:52.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-arm926.S	2003-04-29 04:36:57.000000000 -0700
@@ -28,9 +28,10 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
 
 /*
  * This is the maximum size of an area which will be invalidated
@@ -40,30 +41,14 @@
  * This value should be chosen such that we choose the cheapest
  * alternative.
  */
-#define MAX_AREA_SIZE	16384
+#define CACHE_DLIMIT	16384
 
 /*
  * the cache line size of the I and D cache
  */
-#define DCACHELINESIZE	32
-#define ICACHELINESIZE	32
-
-/*
- * and the page size
- */
-#define PAGESIZE	4096
+#define CACHE_DLINESIZE	32
 
 	.text
-
-/*
- * cpu_arm926_check_bugs()
- */
-ENTRY(cpu_arm926_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
-
 /*
  * cpu_arm926_proc_init()
  */
@@ -77,17 +62,17 @@
 	stmfd	sp!, {lr}
 	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, ip
-	bl	cpu_arm926_cache_clean_invalidate_all
+	bl	arm926_flush_kern_cache_all
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
-	bic	r0, r0, #0x1000 		@ ...i............
-	bic	r0, r0, #0x000e 		@ ............wca.
+	bic	r0, r0, #0x1000			@ ...i............
+	bic	r0, r0, #0x000e			@ ............wca.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
 	ldmfd	sp!, {pc}
 
 /*
  * cpu_arm926_reset(loc)
  *
- * Perform a soft reset of the system.	Put the CPU into the
+ * Perform a soft reset of the system.  Put the CPU into the
  * same state as it would be if it had been reset, and branch
  * to what would be the reset vector.
  *
@@ -100,243 +85,236 @@
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
 	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
-	bic	ip, ip, #0x000f 		@ ............wcam
-	bic	ip, ip, #0x1100 		@ ...i...s........
+	bic	ip, ip, #0x000f			@ ............wcam
+	bic	ip, ip, #0x1100			@ ...i...s........
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
 	mov	pc, r0
 
 /*
  * cpu_arm926_do_idle()
+ *
+ * Called with IRQs disabled
  */
-	.align	5
+	.align	10
 ENTRY(cpu_arm926_do_idle)
+	mov	r0, #0
+	mrc	p15, 0, r1, c1, c0, 0		@ Read control register
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
+	bic	r2, r1, #1 << 12
+	mcr	p15, 0, r2, c1, c0, 0		@ Disable I cache
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+	mcr	p15, 0, r1, c1, c0, 0		@ Restore ICache enable
 	mov	pc, lr
 
-/* ================================= CACHE ================================ */
-
-
 /*
- * cpu_arm926_cache_clean_invalidate_all()
+ *	flush_user_cache_all()
  *
- * clean and invalidate all cache lines
+ *	Clean and invalidate all cache entries in a particular
+ *	address space.
+ */
+ENTRY(arm926_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
  *
- * Note:
- *  1. we should preserve r0 at all times
+ *	Clean and invalidate the entire cache.
  */
-	.align	5
-ENTRY(cpu_arm926_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_arm926_cache_clean_invalidate_all_r2:
+ENTRY(arm926_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
 	mov	ip, #0
+__flush_whole_cache:
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 1:	mrc	p15, 0, r15, c7, c14, 3 	@ test,clean,invalidate
 	bne	1b
 #endif
-	teq	r2, #0
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm926_cache_clean_invalidate_range(start, end, flags)
+ *	flush_user_cache_range(start, end, flags)
  *
- * clean and invalidate all cache lines associated with this area of memory
+ *	Clean and invalidate a range of cache entries in the
+ *	specified address range.
  *
- * This is a little misleading, it is not intended to clean out
- * the i-cache but to make sure that any data written to the
- * range is made consistent.  This means that when we execute code
- * in that region, everything works as we expect.
- *
- * This generally means writing back data in the Dcache and
- * write buffer and flushing the Icache over that region
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
  */
-	.align	5
-ENTRY(cpu_arm926_cache_clean_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1	@ && added by PGM
-	bic	r1, r1, #DCACHELINESIZE - 1	@ && added by DHM
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bgt	cpu_arm926_cache_clean_invalidate_all_r2
-
-1:	teq	r2, #0
+ENTRY(arm926_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bgt	__flush_whole_cache
+1:	tst	r2, #VM_EXEC
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
+	add	r0, r0, #CACHE_DLINESIZE
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
+	add	r0, r0, #CACHE_DLINESIZE
 #else
 	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
+	add	r0, r0, #CACHE_DLINESIZE
 	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
-	add	r0, r0, #DCACHELINESIZE
+	add	r0, r0, #CACHE_DLINESIZE
 #endif
-        
 	cmp	r0, r1
-	blt	1b
-
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ D-CACHE =============================== */
-
 /*
- * cpu_arm926_dcache_invalidate_range(start, end)
+ *	coherent_kern_range(start, end)
  *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.	Note however that we must clean the D-cached entries
- * around the boundaries if the start and/or end address are not cache
- * aligned.
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm926_dcache_invalidate_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	tst	r0, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
-	tst	r1, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1
-#endif		@ clean D entry
-	bic	r0, r0, #DCACHELINESIZE - 1
-	bic	r1, r1, #DCACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
+ENTRY(arm926_coherent_kern_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
-	blt	1b
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm926_dcache_clean_range(start, end)
+ *	flush_kern_dcache_page(void *page)
  *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- addr	- page aligned address
  */
-	.align	5
-ENTRY(cpu_arm926_dcache_clean_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	mov	r2, #0
-	bgt	cpu_arm926_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #DCACHELINESIZE -1
-	add	r1, r1, #DCACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #DCACHELINESIZE
-	bpl	1b
-#endif
-	mcr	p15, 0, r2, c7, c10, 4		@ drain WB
+ENTRY(arm926_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm926_dcache_clean_page(page)
+ *	dma_inv_range(start, end)
  *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
  *
- * page: virtual address of page to clean from dcache
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  *
- * Note:
- *  1. we don't need to flush the write buffer in this case.
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm926_dcache_clean_page)
+ENTRY(arm926_dma_inv_range)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
+	tst	r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
 #endif
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
 /*
- * cpu_arm926_dcache_clean_entry(addr)
+ *	dma_clean_range(start, end)
  *
- * Clean the specified entry of any caches such that the MMU
- * translation fetches will obtain correct data.
+ *	Clean the specified virtual address range.
  *
- * addr: cache-unaligned virtual address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
  */
-	.align	5
-ENTRY(cpu_arm926_dcache_clean_entry)
+ENTRY(arm926_dma_clean_range)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/* ================================ I-CACHE =============================== */
-
 /*
- * cpu_arm926_icache_invalidate_range(start, end)
+ *	dma_flush_range(start, end)
  *
- * invalidate a range of virtual addresses from the Icache
+ *	Clean and invalidate the specified virtual address range.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start	- virtual start address
+ *	- end	- virtual end address
  */
-	.align	5
-ENTRY(cpu_arm926_icache_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1	@ Safety check
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	bgt	cpu_arm926_cache_clean_invalidate_all_r2
-
-	bic	r1, r1, #DCACHELINESIZE - 1
-	add	r1, r1, #DCACHELINESIZE
-
-1:	mcr	p15, 0, r0, c7, c5, 1		@ clean I entries
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #DCACHELINESIZE
-	bne	1b
-
-	mov	r0, #0
+ENTRY(arm926_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+#else
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+#endif
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-ENTRY(cpu_arm926_icache_invalidate_page)
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
+ENTRY(arm926_cache_fns)
+	.long	arm926_flush_kern_cache_all
+	.long	arm926_flush_user_cache_all
+	.long	arm926_flush_user_cache_range
+	.long	arm926_coherent_kern_range
+	.long	arm926_flush_kern_dcache_page
+	.long	arm926_dma_inv_range
+	.long	arm926_dma_clean_range
+	.long	arm926_dma_flush_range
 
+ENTRY(cpu_arm926_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
 
 /* =============================== PageTable ============================== */
 
 /*
- * cpu_arm926_set_pgd(pgd)
+ * cpu_arm926_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_arm926_set_pgd)
+ENTRY(cpu_arm926_switch_mm)
 	mov	ip, #0
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 @ && 'Clean & Invalidate whole DCache'
@@ -350,22 +328,6 @@
 	mov	pc, lr
 
 /*
- * cpu_arm926_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_arm926_flush_pmd)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-#endif
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
  * cpu_arm926_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
@@ -380,7 +342,7 @@
 	bic	r2, r2, #3
 	orr	r2, r2, #HPTE_TYPE_SMALL
 
-	tst	r1, #LPTE_USER | LPTE_EXEC	@ User or Exec?
+	tst	r1, #LPTE_USER			@ User?
 	orrne	r2, r2, #HPTE_AP_READ
 
 	tst	r1, #LPTE_WRITE | LPTE_DIRTY	@ Write and Dirty?
@@ -447,21 +409,21 @@
 	bic	r0, r0, #0x0e00
 	bic	r0, r0, #0x0002
 	bic	r0, r0, #0x000c
-	bic	r0, r0, #0x1000 		@ ...0 000. .... 000.
+	bic	r0, r0, #0x1000			@ ...0 000. .... 000.
 /*
  * Turn on what we want
  */
 	orr	r0, r0, #0x0031
-	orr	r0, r0, #0x2100 		@ ..1. ...1 ..11 ...1
+	orr	r0, r0, #0x2100			@ ..1. ...1 ..11 ...1
 
 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-	orr	r0, r0, #0x4000 		@ .1.. .... .... ....
+	orr	r0, r0, #0x4000			@ .1.. .... .... ....
 #endif
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	orr	r0, r0, #0x0004 		@ .... .... .... .1..
+	orr	r0, r0, #0x0004			@ .... .... .... .1..
 #endif
 #ifndef CONFIG_CPU_ICACHE_DISABLE
-	orr	r0, r0, #0x1000 		@ ...1 .... .... ....
+	orr	r0, r0, #0x1000			@ ...1 .... .... ....
 #endif
 	mov	pc, lr
 
@@ -474,31 +436,13 @@
 	.type	arm926_processor_functions, #object
 arm926_processor_functions:
 	.word	v5tej_early_abort
-	.word	cpu_arm926_check_bugs
 	.word	cpu_arm926_proc_init
 	.word	cpu_arm926_proc_fin
 	.word	cpu_arm926_reset
 	.word	cpu_arm926_do_idle
-
-	/* cache */
-	.word	cpu_arm926_cache_clean_invalidate_all
-	.word	cpu_arm926_cache_clean_invalidate_range
-
-	/* dcache */
-	.word	cpu_arm926_dcache_invalidate_range
-	.word	cpu_arm926_dcache_clean_range
-	.word	cpu_arm926_dcache_clean_page
-	.word	cpu_arm926_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_arm926_icache_invalidate_range
-	.word	cpu_arm926_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_arm926_set_pgd
-	.word	cpu_arm926_flush_pmd
+	.word	cpu_arm926_dcache_clean_area
+	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte
-
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.type	cpu_arch_name, #object
@@ -522,10 +466,10 @@
 	b	__arm926_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \
-		HWCAP_FAST_MULT | HWCAP_JAVA
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA
 	.long	cpu_arm926_name
 	.long	arm926_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
+	.long	arm926_cache_fns
 	.size	__arm926_proc_info, . - __arm926_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-sa110.S linux-2.5.68-bk9/arch/arm/mm/proc-sa110.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-sa110.S	2003-04-19 19:49:26.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-sa110.S	2003-04-29 04:36:57.000000000 -0700
@@ -10,12 +10,7 @@
  *  MMU functions for SA110
  *
  *  These are the low level assembler for performing cache and TLB
- *  functions on the StrongARM-110, StrongARM-1100 and StrongARM-1110.
- * 
- *  Note that SA1100 and SA1110 share everything but their name and CPU ID.
- *
- *  12-jun-2000, Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
- *    Flush the read buffer at context switches
+ *  functions on the StrongARM-110.
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
@@ -25,71 +20,32 @@
 #include <asm/hardware.h>
 #include <asm/proc/pgtable.h>
 
-/* This is the maximum size of an area which will be flushed.  If the area
- * is larger than this, then we flush the whole cache
- */
-#define MAX_AREA_SIZE	32768
-
 /*
  * the cache line size of the I and D cache
  */
 #define DCACHELINESIZE	32
-
-/*
- * and the page size
- */
-#define PAGESIZE	4096
-
 #define FLUSH_OFFSET	32768
 
-		.macro flush_110_dcache	rd, ra, re
-		ldr	\rd, =flush_base
-		ldr	\ra, [\rd]
-		eor	\ra, \ra, #FLUSH_OFFSET
-		str	\ra, [\rd]
-		add	\re, \ra, #16384		@ only necessary for 16k
-1001:		ldr	\rd, [\ra], #DCACHELINESIZE
-		teq	\re, \ra
-		bne	1001b
-		.endm
-
-		.macro flush_1100_dcache	rd, ra, re
-		ldr	\rd, =flush_base
-		ldr	\ra, [\rd]
-		eor	\ra, \ra, #FLUSH_OFFSET
-		str	\ra, [\rd]
-		add	\re, \ra, #8192			@ only necessary for 8k
-1001:		ldr	\rd, [\ra], #DCACHELINESIZE
-		teq	\re, \ra
-		bne	1001b
-#ifdef FLUSH_BASE_MINICACHE
-		add	\ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
-		add	\re, \ra, #512			@ only 512 bytes
-1002:		ldr	\rd, [\ra], #DCACHELINESIZE
-		teq	\re, \ra
-		bne	1002b
-#endif
-		.endm
-
-		.data
-flush_base:	.long	FLUSH_BASE
-		.text
-
-/*
- * cpu_sa110_check_bugs()
- */
-ENTRY(cpu_sa110_check_bugs)
-ENTRY(cpu_sa1100_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
+	.macro flush_110_dcache	rd, ra, re
+	ldr	\rd, =flush_base
+	ldr	\ra, [\rd]
+	eor	\ra, \ra, #FLUSH_OFFSET
+	str	\ra, [\rd]
+	add	\re, \ra, #16384		@ only necessary for 16k
+1001:	ldr	\rd, [\ra], #DCACHELINESIZE
+	teq	\re, \ra
+	bne	1001b
+	.endm
+
+	.data
+flush_base:
+	.long	FLUSH_BASE
+	.text
 
 /*
  * cpu_sa110_proc_init()
  */
 ENTRY(cpu_sa110_proc_init)
-ENTRY(cpu_sa1100_proc_init)
 	mov	r0, #0
 	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
 	mov	pc, lr
@@ -101,7 +57,7 @@
 	stmfd	sp!, {lr}
 	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, ip
-	bl	cpu_sa110_cache_clean_invalidate_all	@ clean caches
+	bl	v4wb_flush_kern_cache_all	@ clean caches
 1:	mov	r0, #0
 	mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
@@ -110,13 +66,6 @@
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
 	ldmfd	sp!, {pc}
 
-ENTRY(cpu_sa1100_proc_fin)
-	stmfd	sp!, {lr}
-	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
-	msr	cpsr_c, ip
-	bl	cpu_sa1100_cache_clean_invalidate_all	@ clean caches
-	b	1b
-
 /*
  * cpu_sa110_reset(loc)
  *
@@ -128,7 +77,6 @@
  */
 	.align	5
 ENTRY(cpu_sa110_reset)
-ENTRY(cpu_sa1100_reset)
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
@@ -151,204 +99,25 @@
  *   3 = switch to fast processor clock
  */
 	.align	5
-idle:	mcr	p15, 0, r0, c15, c8, 2		@ Wait for interrupt, cache aligned
-	mov	r0, r0				@ safety
-	mov	pc, lr
 
 ENTRY(cpu_sa110_do_idle)
-	mov	ip, #0
-	cmp	r0, #4
-	addcc	pc, pc, r0, lsl #2
-	mov	pc, lr
-
-	b	idle
-	b	idle
-	b	slow_clock
-	b	fast_clock
-
-fast_clock:
-	mcr	p15, 0, ip, c15, c1, 2		@ enable clock switching
-	mov	pc, lr
-
-slow_clock:
 	mcr	p15, 0, ip, c15, c2, 2		@ disable clock switching
 	ldr	r1, =UNCACHEABLE_ADDR		@ load from uncacheable loc
 	ldr	r1, [r1, #0]			@ force switch to MCLK
-	mov	pc, lr
-
-	.align	5
-ENTRY(cpu_sa1100_do_idle)
-	mov	r0, r0				@ 4 nop padding
-	mov	r0, r0
-	mov	r0, r0
-	mov	r0, #0
-	ldr	r1, =UNCACHEABLE_ADDR		@ ptr to uncacheable address
-	mrs	r2, cpsr
-	orr	r3, r2, #192			@ disallow interrupts
-	msr	cpsr_c, r3
-	@ --- aligned to a cache line
-	mcr	p15, 0, r0, c15, c2, 2		@ disable clock switching
-	ldr	r1, [r1, #0]			@ force switch to MCLK
-	mcr	p15, 0, r0, c15, c8, 2		@ wait for interrupt
+	mov	r0, r0				@ safety
+	mov	r0, r0				@ safety
+	mov	r0, r0				@ safety
+	mcr	p15, 0, r0, c15, c8, 2		@ Wait for interrupt, cache aligned
+	mov	r0, r0				@ safety
+	mov	r0, r0				@ safety
 	mov	r0, r0				@ safety
 	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
-	msr	cpsr_c, r2			@ allow interrupts
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
 
-
-/*
- * cpu_sa110_cache_clean_invalidate_all (void)
- *
- * clean and invalidate all cache lines
- *
- * Note:
- *  1. we should preserve r0 at all times
- */
-	.align	5
-ENTRY(cpu_sa110_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_sa110_cache_clean_invalidate_all_r2:
-	flush_110_dcache	r3, ip, r1
-	mov	ip, #0
-	teq	r2, #0
-	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-	.align	5
-ENTRY(cpu_sa1100_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_sa1100_cache_clean_invalidate_all_r2:
-	flush_1100_dcache	r3, ip, r1
-	mov	ip, #0
-	teq	r2, #0
-	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
- * cpu_sa110_cache_clean_invalidate_range(start, end, flags)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
- */
-	.align	5
-ENTRY(cpu_sa110_cache_clean_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bhi	cpu_sa110_cache_clean_invalidate_all_r2
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	cmp	r0, r1
-	blo	1b
-	teq	r2, #0
-	movne	r0, #0
-	mcrne	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mov	pc, lr
-
-ENTRY(cpu_sa1100_cache_clean_invalidate_range)
-	sub	r3, r1, r0
-	cmp	r3, #MAX_AREA_SIZE
-	bhi	cpu_sa1100_cache_clean_invalidate_all_r2
-	b	1b
-
-/* ================================ D-CACHE =============================== */
-
-/*
- * cpu_sa110_dcache_invalidate_range(start, end)
- *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.  Note however that we must clean the D-cached entries
- * around the boundaries if the start and/or end address are not cache
- * aligned.
- *
- * start: virtual start address
- * end:   virtual end address
- */
-	.align	5
-ENTRY(cpu_sa110_dcache_invalidate_range)
-ENTRY(cpu_sa1100_dcache_invalidate_range)
-	tst	r0, #DCACHELINESIZE - 1
-	bic	r0, r0, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
-	tst	r1, #DCACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	cmp	r0, r1
-	blo	1b
-	mov	pc, lr
-
-/*
- * cpu_sa110_dcache_clean_range(start, end)
- *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
- *
- * start: virtual start address
- * end:   virtual end address
- */
-	.align	5
-ENTRY(cpu_sa110_dcache_clean_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	mov	r2, #0
-	bhi	cpu_sa110_cache_clean_invalidate_all_r2
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bpl	1b
-	mcr	p15, 0, r2, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-ENTRY(cpu_sa1100_dcache_clean_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-	sub	r1, r1, r0
-	cmp	r1, #MAX_AREA_SIZE
-	mov	r2, #0
-	bhi	cpu_sa1100_cache_clean_invalidate_all_r2
-	b	1b
-
-/*
- * cpu_sa110_clean_dcache_page(page)
- *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
- *
- * Note:
- *  1. we don't need to flush the write buffer in this case.
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
- */
-	.align	5
-ENTRY(cpu_sa110_dcache_clean_page)
-ENTRY(cpu_sa1100_dcache_clean_page)
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mov	pc, lr
-
 /*
- * cpu_sa110_dcache_clean_entry(addr)
+ * cpu_sa110_dcache_clean_area(addr,sz)
  *
  * Clean the specified entry of any caches such that the MMU
  * translation fetches will obtain correct data.
@@ -356,48 +125,24 @@
  * addr: cache-unaligned virtual address
  */
 	.align	5
-ENTRY(cpu_sa110_dcache_clean_entry)
-ENTRY(cpu_sa1100_dcache_clean_entry)
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/* ================================ I-CACHE =============================== */
-
-/*
- * cpu_sa110_icache_invalidate_range(start, end)
- *
- * invalidate a range of virtual addresses from the Icache
- *
- * start: virtual start address
- * end:   virtual end address
- */
-	.align	5
-ENTRY(cpu_sa110_icache_invalidate_range)
-ENTRY(cpu_sa1100_icache_invalidate_range)
-	bic	r0, r0, #DCACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
+ENTRY(cpu_sa110_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #DCACHELINESIZE
-	cmp	r0, r1
-	blo	1b
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-ENTRY(cpu_sa110_icache_invalidate_page)
-ENTRY(cpu_sa1100_icache_invalidate_page)
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	subs	r1, r1, #DCACHELINESIZE
+	bhi	1b
 	mov	pc, lr
 
 /* =============================== PageTable ============================== */
 
 /*
- * cpu_sa110_set_pgd(pgd)
+ * cpu_sa110_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_sa110_set_pgd)
+ENTRY(cpu_sa110_switch_mm)
 	flush_110_dcache	r3, ip, r1
 	mov	r1, #0
 	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I cache
@@ -407,48 +152,12 @@
 	mov	pc, lr
 
 /*
- * cpu_sa1100_set_pgd(pgd)
- *
- * Set the translation base pointer to be as described by pgd.
- *
- * pgd: new page tables
- */
-	.align	5
-ENTRY(cpu_sa1100_set_pgd)
-	flush_1100_dcache	r3, ip, r1
-	mov	ip, #0
-	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, ip, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
-	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, lr
-
-/*
- * cpu_sa110_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_sa110_flush_pmd)
-ENTRY(cpu_sa1100_flush_pmd)
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
-/*
  * cpu_sa110_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
  */
 	.align	5
 ENTRY(cpu_sa110_set_pte)
-ENTRY(cpu_sa1100_set_pte)
-	tst	r0, #2048
-	streq	r0, [r0, -r0]			@ BUG_ON
 	str	r1, [r0], #-2048		@ linux version
 
 	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
@@ -457,7 +166,7 @@
 	bic	r2, r2, #3
 	orr	r2, r2, #PTE_TYPE_SMALL
 
-	tst	r1, #L_PTE_USER | L_PTE_EXEC	@ User or Exec?
+	tst	r1, #L_PTE_USER			@ User or Exec?
 	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
 
 	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
@@ -475,30 +184,16 @@
 
 cpu_sa110_name:
 	.asciz	"StrongARM-110"
-cpu_sa1100_name:
-	.asciz	"StrongARM-1100"
-cpu_sa1110_name:
-	.asciz	"StrongARM-1110"
 	.align
 
 	__INIT
 
-__sa1100_setup:	@ Allow read-buffer operations from userland
-	mcr	p15, 0, r0, c9, c0, 5
-	mrc	p15, 0, r0, c1, c0		@ get control register v4
-	bic	r0, r0, #0x0e00			@ ..VI ZFRS BLDP WCAM
-	bic	r0, r0, #0x0002			@ .... 000. .... ..0.
-	orr	r0, r0, #0x003d
-	orr	r0, r0, #0x3100			@ ..11 ...1 ..11 11.1
-	b	__setup_common
-
 __sa110_setup:
 	mrc	p15, 0, r0, c1, c0		@ get control register v4
 	bic	r0, r0, #0x2e00			@ ..VI ZFRS BLDP WCAM
 	bic	r0, r0, #0x0002			@ ..0. 000. .... ..0.
 	orr	r0, r0, #0x003d
 	orr	r0, r0, #0x1100			@ ...1 ...1 ..11 11.1
-__setup_common:
 	mov	r10, #0
 	mcr	p15, 0, r10, c7, c7		@ invalidate I,D caches on v4
 	mcr	p15, 0, r10, c7, c10, 4		@ drain write buffer on v4
@@ -518,66 +213,20 @@
 	.type	sa110_processor_functions, #object
 ENTRY(sa110_processor_functions)
 	.word	v4_early_abort
-	.word	cpu_sa110_check_bugs
 	.word	cpu_sa110_proc_init
 	.word	cpu_sa110_proc_fin
 	.word	cpu_sa110_reset
 	.word	cpu_sa110_do_idle
 
-	/* cache */
-	.word	cpu_sa110_cache_clean_invalidate_all
-	.word	cpu_sa110_cache_clean_invalidate_range
-
 	/* dcache */
-	.word	cpu_sa110_dcache_invalidate_range
-	.word	cpu_sa110_dcache_clean_range
-	.word	cpu_sa110_dcache_clean_page
-	.word	cpu_sa110_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_sa110_icache_invalidate_range
-	.word	cpu_sa110_icache_invalidate_page
+	.word	cpu_sa110_dcache_clean_area
 
 	/* pgtable */
-	.word	cpu_sa110_set_pgd
-	.word	cpu_sa110_flush_pmd
+	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte
 
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
-/*
- * SA1100 and SA1110 share the same function calls
- */
-	.type	sa1100_processor_functions, #object
-ENTRY(sa1100_processor_functions)
-	.word	v4_early_abort
-	.word	cpu_sa1100_check_bugs
-	.word	cpu_sa1100_proc_init
-	.word	cpu_sa1100_proc_fin
-	.word	cpu_sa1100_reset
-	.word	cpu_sa1100_do_idle
-
-	/* cache */
-	.word	cpu_sa1100_cache_clean_invalidate_all
-	.word	cpu_sa1100_cache_clean_invalidate_range
-
-	/* dcache */
-	.word	cpu_sa1100_dcache_invalidate_range
-	.word	cpu_sa1100_dcache_clean_range
-	.word	cpu_sa1100_dcache_clean_page
-	.word	cpu_sa1100_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_sa1100_icache_invalidate_range
-	.word	cpu_sa1100_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_sa1100_set_pgd
-	.word	cpu_sa1100_flush_pmd
-	.word	cpu_sa1100_set_pte
-
-	.size	sa1100_processor_functions, . - sa1100_processor_functions
-
 	.type	cpu_arch_name, #object
 cpu_arch_name:
 	.asciz	"armv4"
@@ -591,7 +240,6 @@
 
 	.section ".proc.info", #alloc, #execinstr
 
-#ifdef CONFIG_CPU_SA110
 	.type	__sa110_proc_info,#object
 __sa110_proc_info:
 	.long	0x4401a100
@@ -605,37 +253,5 @@
 	.long	sa110_processor_functions
 	.long	v4wb_tlb_fns
 	.long	v4wb_user_fns
+	.long	v4wb_cache_fns
 	.size	__sa110_proc_info, . - __sa110_proc_info
-#endif
-
-#ifdef CONFIG_CPU_SA1100
-	.type	__sa1100_proc_info,#object
-__sa1100_proc_info:
-	.long	0x4401a110
-	.long	0xfffffff0
-	.long	0x00000c0e
-	b	__sa1100_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1100_name
-	.long	sa1100_processor_functions
-	.long	v4wb_tlb_fns
-	.long	v4_mc_user_fns
-	.size	__sa1100_proc_info, . - __sa1100_proc_info
-
-	.type	__sa1110_proc_info,#object
-__sa1110_proc_info:
-	.long	0x6901b110
-	.long	0xfffffff0
-	.long	0x00000c0e
-	b	__sa1100_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1110_name
-	.long	sa1100_processor_functions
-	.long	v4wb_tlb_fns
-	.long	v4_mc_user_fns
-	.size	__sa1110_proc_info, . - __sa1110_proc_info
-#endif
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-sa1100.S linux-2.5.68-bk9/arch/arm/mm/proc-sa1100.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-sa1100.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/arch/arm/mm/proc-sa1100.S	2003-04-29 04:36:57.000000000 -0700
@@ -0,0 +1,297 @@
+/*
+ *  linux/arch/arm/mm/proc-sa110.S
+ *
+ *  Copyright (C) 1997-2002 Russell King
+ *
+ * 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.
+ *
+ *  MMU functions for SA110
+ *
+ *  These are the low level assembler for performing cache and TLB
+ *  functions on the StrongARM-1100 and StrongARM-1110.
+ *
+ *  Note that SA1100 and SA1110 share everything but their name and CPU ID.
+ *
+ *  12-jun-2000, Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
+ *    Flush the read buffer at context switches
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/proc/pgtable.h>
+
+/*
+ * the cache line size of the I and D cache
+ */
+#define DCACHELINESIZE	32
+#define FLUSH_OFFSET	32768
+
+	.macro flush_1100_dcache rd, ra, re
+	ldr	\rd, =flush_base
+	ldr	\ra, [\rd]
+	eor	\ra, \ra, #FLUSH_OFFSET
+	str	\ra, [\rd]
+	add	\re, \ra, #8192			@ only necessary for 8k
+1001:	ldr	\rd, [\ra], #DCACHELINESIZE
+	teq	\re, \ra
+	bne	1001b
+#ifdef FLUSH_BASE_MINICACHE
+	add	\ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
+	add	\re, \ra, #512			@ only 512 bytes
+1002:	ldr	\rd, [\ra], #DCACHELINESIZE
+	teq	\re, \ra
+	bne	1002b
+#endif
+	.endm
+
+	.data
+flush_base:
+	.long	FLUSH_BASE
+	.text
+
+	__INIT
+
+/*
+ * cpu_sa1100_proc_init()
+ */
+ENTRY(cpu_sa1100_proc_init)
+	mov	r0, #0
+	mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
+	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland
+	mov	pc, lr
+
+	.previous
+
+/*
+ * cpu_sa1100_proc_fin()
+ *
+ * Prepare the CPU for reset:
+ *  - Disable interrupts
+ *  - Clean and turn off caches.
+ */
+ENTRY(cpu_sa1100_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	flush_1100_dcache r0, r1, r2		@ clean caches
+	mov	r0, #0
+	mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1000			@ ...i............
+	bic	r0, r0, #0x000e			@ ............wca.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_sa1100_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_sa1100_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x000f			@ ............wcam
+	bic	ip, ip, #0x1100			@ ...i...s........
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+/*
+ * cpu_sa1100_do_idle(type)
+ *
+ * Cause the processor to idle
+ *
+ * type: call type:
+ *   0 = slow idle
+ *   1 = fast idle
+ *   2 = switch to slow processor clock
+ *   3 = switch to fast processor clock
+ */
+	.align	5
+ENTRY(cpu_sa1100_do_idle)
+	mov	r0, r0				@ 4 nop padding
+	mov	r0, r0
+	mov	r0, r0
+	mov	r0, r0				@ 4 nop padding
+	mov	r0, r0
+	mov	r0, r0
+	mov	r0, #0
+	ldr	r1, =UNCACHEABLE_ADDR		@ ptr to uncacheable address
+	@ --- aligned to a cache line
+	mcr	p15, 0, r0, c15, c2, 2		@ disable clock switching
+	ldr	r1, [r1, #0]			@ force switch to MCLK
+	mcr	p15, 0, r0, c15, c8, 2		@ wait for interrupt
+	mov	r0, r0				@ safety
+	mcr	p15, 0, r0, c15, c1, 2		@ enable clock switching
+	mov	pc, lr
+
+/* ================================= CACHE ================================ */
+
+/*
+ * cpu_sa1100_dcache_clean_area(addr,sz)
+ *
+ * Clean the specified entry of any caches such that the MMU
+ * translation fetches will obtain correct data.
+ *
+ * addr: cache-unaligned virtual address
+ */
+	.align	5
+ENTRY(cpu_sa1100_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #DCACHELINESIZE
+	subs	r1, r1, #DCACHELINESIZE
+	bhi	1b
+	mov	pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_sa1100_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	5
+ENTRY(cpu_sa1100_switch_mm)
+	flush_1100_dcache r3, ip, r1
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mov	pc, lr
+
+/*
+ * cpu_sa1100_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ */
+	.align	5
+ENTRY(cpu_sa1100_set_pte)
+	str	r1, [r0], #-2048		@ linux version
+
+	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+	bic	r2, r1, #0xff0
+	bic	r2, r2, #3
+	orr	r2, r2, #PTE_TYPE_SMALL
+
+	tst	r1, #L_PTE_USER			@ User or Exec?
+	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
+
+	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
+	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
+
+	tst	r1, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
+	movne	r2, #0
+
+	str	r2, [r0]			@ hardware version
+	mov	r0, r0
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+
+cpu_sa1100_name:
+	.asciz	"StrongARM-1100"
+cpu_sa1110_name:
+	.asciz	"StrongARM-1110"
+	.align
+
+	__INIT
+
+__sa1100_setup:
+	mov	r10, #0
+	mcr	p15, 0, r10, c7, c7		@ invalidate I,D caches on v4
+	mcr	p15, 0, r10, c7, c10, 4		@ drain write buffer on v4
+	mcr	p15, 0, r10, c8, c7		@ invalidate I,D TLBs on v4
+	mov	r0, #0x1f			@ Domains 0, 1 = client
+	mcr	p15, 0, r0, c3, c0		@ load domain access register
+	mcr	p15, 0, r4, c2, c0		@ load page table pointer
+	mrc	p15, 0, r0, c1, c0		@ get control register v4
+	bic	r0, r0, #0x0e00			@ ..VI ZFRS BLDP WCAM
+	bic	r0, r0, #0x0002			@ .... 000. .... ..0.
+	orr	r0, r0, #0x003d
+	orr	r0, r0, #0x3100			@ ..11 ...1 ..11 11.1
+	mov	pc, lr
+
+	.text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+
+/*
+ * SA1100 and SA1110 share the same function calls
+ */
+	.type	sa1100_processor_functions, #object
+ENTRY(sa1100_processor_functions)
+	.word	v4_early_abort
+	.word	cpu_sa1100_proc_init
+	.word	cpu_sa1100_proc_fin
+	.word	cpu_sa1100_reset
+	.word	cpu_sa1100_do_idle
+	.word	cpu_sa1100_dcache_clean_area
+	.word	cpu_sa1100_switch_mm
+	.word	cpu_sa1100_set_pte
+	.size	sa1100_processor_functions, . - sa1100_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info", #alloc, #execinstr
+
+	.type	__sa1100_proc_info,#object
+__sa1100_proc_info:
+	.long	0x4401a110
+	.long	0xfffffff0
+	.long	0x00000c0e
+	b	__sa1100_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
+	.long	cpu_sa1100_name
+	.long	sa1100_processor_functions
+	.long	v4wb_tlb_fns
+	.long	v4_mc_user_fns
+	.long	v4wb_cache_fns
+	.size	__sa1100_proc_info, . - __sa1100_proc_info
+
+	.type	__sa1110_proc_info,#object
+__sa1110_proc_info:
+	.long	0x6901b110
+	.long	0xfffffff0
+	.long	0x00000c0e
+	b	__sa1100_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
+	.long	cpu_sa1110_name
+	.long	sa1100_processor_functions
+	.long	v4wb_tlb_fns
+	.long	v4_mc_user_fns
+	.long	v4wb_cache_fns
+	.size	__sa1110_proc_info, . - __sa1110_proc_info
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-syms.c linux-2.5.68-bk9/arch/arm/mm/proc-syms.c
--- linux-2.5.68-bk8/arch/arm/mm/proc-syms.c	2003-04-19 19:49:25.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-syms.c	2003-04-29 04:36:57.000000000 -0700
@@ -11,28 +11,28 @@
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
-#include <asm/pgalloc.h>
 #include <asm/proc-fns.h>
 #include <asm/tlbflush.h>
 
 EXPORT_SYMBOL(__flush_dcache_page);
 
 #ifndef MULTI_CPU
-EXPORT_SYMBOL(cpu_cache_clean_invalidate_all);
-EXPORT_SYMBOL(cpu_cache_clean_invalidate_range);
-EXPORT_SYMBOL(cpu_dcache_clean_page);
-EXPORT_SYMBOL(cpu_dcache_clean_entry);
-EXPORT_SYMBOL(cpu_dcache_clean_range);
-EXPORT_SYMBOL(cpu_dcache_invalidate_range);
-EXPORT_SYMBOL(cpu_icache_invalidate_range);
-EXPORT_SYMBOL(cpu_icache_invalidate_page);
-EXPORT_SYMBOL(cpu_set_pgd);
-EXPORT_SYMBOL(cpu_flush_pmd);
+EXPORT_SYMBOL(cpu_dcache_clean_area);
 EXPORT_SYMBOL(cpu_set_pte);
 #else
 EXPORT_SYMBOL(processor);
 #endif
 
+#ifndef MULTI_CACHE
+EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all);
+EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all);
+EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range);
+EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL_NOVERS(__cpuc_flush_dcache_page);
+#else
+EXPORT_SYMBOL(cpu_cache);
+#endif
+
 /*
  * No module should need to touch the TLB (and currently
  * no modules do.  We export this for "loadkernel" support
diff -urN linux-2.5.68-bk8/arch/arm/mm/proc-xscale.S linux-2.5.68-bk9/arch/arm/mm/proc-xscale.S
--- linux-2.5.68-bk8/arch/arm/mm/proc-xscale.S	2003-04-19 19:50:44.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/mm/proc-xscale.S	2003-04-29 04:36:57.000000000 -0700
@@ -23,10 +23,11 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
 #include <asm/proc/pgtable.h>
+#include <asm/page.h>
+#include "proc-macros.S"
 
 /*
  * This is the maximum size of an area which will be flushed.  If the area
@@ -45,11 +46,6 @@
 #define CACHESIZE	32768
 
 /*
- * and the page size
- */
-#define PAGESIZE	4096
-
-/*
  * Virtual address used to allocate the cache when flushed
  *
  * This must be an address range which is _never_ used.  It should
@@ -112,15 +108,6 @@
 	.text
 
 /*
- * cpu_xscale_check_bugs()
- */
-ENTRY(cpu_xscale_check_bugs)
-	mrs	ip, cpsr
-	bic	ip, ip, #PSR_F_BIT
-	msr	cpsr, ip
-	mov	pc, lr
-
-/*
  * cpu_xscale_proc_init()
  *
  * Nothing too exciting at the moment
@@ -135,11 +122,11 @@
 	str	lr, [sp, #-4]!
 	mov	r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 	msr	cpsr_c, r0
+	bl	xscale_flush_kern_cache_all	@ clean caches
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 	bic	r0, r0, #0x1800			@ ...IZ...........
 	bic	r0, r0, #0x0006			@ .............CA.
 	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
-	bl	cpu_xscale_cache_clean_invalidate_all	@ clean caches
 	ldr	pc, [sp], #4
 
 /*
@@ -168,16 +155,10 @@
 	mov	pc, r0
 
 /*
- * cpu_xscale_do_idle(type)
+ * cpu_xscale_do_idle()
  *
  * Cause the processor to idle
  *
- * type:
- *   0 = slow idle
- *   1 = fast idle
- *   2 = switch to slow processor clock
- *   3 = switch to fast processor clock
- *
  * For now we do nothing but go to idle mode for every case
  *
  * XScale supports clock switching, but using idle mode support
@@ -193,226 +174,179 @@
 /* ================================= CACHE ================================ */
 
 /*
- * cpu_xscale_cache_clean_invalidate_all (void)
+ *	flush_user_cache_all()
  *
- * clean and invalidate all cache lines
+ *	Invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(xscale_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
  *
- * Note:
- *  1. We should preserve r0 at all times.
- *  2. Even if this function implies cache "invalidation" by its name,
- *     we don't need to actually use explicit invalidation operations
- *     since the goal is to discard all valid references from the cache
- *     and the cleaning of it already has that effect.
- *  3. Because of 2 above and the fact that kernel space memory is always
- *     coherent across task switches there is no need to worry about
- *     inconsistencies due to interrupts, ence no irq disabling.
+ *	Clean and invalidate the entire cache.
  */
-	.align	5
-ENTRY(cpu_xscale_cache_clean_invalidate_all)
-	mov	r2, #1
-cpu_xscale_cache_clean_invalidate_all_r2:
+ENTRY(xscale_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
 	clean_d_cache r0, r1
-	teq	r2, #0
+	tst	r2, #VM_EXEC
 	mcrne	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
 /*
- * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
+ *	flush_user_cache_range(start, end, vm_flags)
  *
- * clean and invalidate all cache lines associated with this area of memory
+ *	Invalidate a range of cache entries in the specified
+ *	address space.
  *
- * start: Area start address
- * end:   Area end address
- * flags: nonzero for I cache as well
+ *	- start - start address (may not be aligned)
+ *	- end	- end address (exclusive, may not be aligned)
+ *	- vma	- vma_area_struct describing address space
  */
 	.align	5
-ENTRY(cpu_xscale_cache_clean_invalidate_range)
-	bic	r0, r0, #CACHELINESIZE - 1	@ round down to cache line
-	sub	r3, r1, r0
+ENTRY(xscale_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
 	cmp	r3, #MAX_AREA_SIZE
-	bhi	cpu_xscale_cache_clean_invalidate_all_r2
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	bhs	__flush_whole_cache
+
+1:	tst	r2, #VM_EXEC
+	mcrne	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
 	mcr	p15, 0, r0, c7, c6, 1		@ Invalidate D cache line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	teq	r2, #0
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	moveq	pc, lr
-	sub	r0, r0, r3
-1:	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
-	add	r0, r0, #CACHELINESIZE
-	cmp	r0, r1
-	blo	1b
-	mcr	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
+	mcrne	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
 /*
- * cpu_xscale_flush_ram_page(page)
+ *	coherent_kern_range(start, end)
  *
- * clean all cache lines associated with this memory page
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
  *
- * page: page to clean
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
  */
-	.align	5
-ENTRY(cpu_xscale_flush_ram_page)
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+ENTRY(xscale_coherent_kern_range)
+	bic	r0, r0, #CACHELINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
-	subs	r1, r1, #2 * CACHELINESIZE
-	bne	1b
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
-/* ================================ D-CACHE =============================== */
-
 /*
- * cpu_xscale_dcache_invalidate_range(start, end)
+ *	flush_kern_dcache_page(void *page)
  *
- * throw away all D-cached data in specified region without an obligation
- * to write them back.  Note however that on XScale we must clean all
- * entries also due to hardware errata (80200 A0 & A1 only).
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- addr	- page aligned address
  */
-	.align	5
-ENTRY(cpu_xscale_dcache_invalidate_range)
-	mrc	p15, 0, r2, c0, c0, 0		@ Read part no.
-	eor	r2, r2, #0x69000000
-	eor	r2, r2, #0x00052000		@ 80200 XX part no.
-	bics	r2, r2, #0x1			@ Clear LSB in revision field
-	moveq	r2, #0
-	beq	cpu_xscale_cache_clean_invalidate_range	@ An 80200 A0 or A1
-
-	tst	r0, #CACHELINESIZE - 1
-	mcrne	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	tst	r1, #CACHELINESIZE - 1
-	mcrne	p15, 0, r1, c7, c10, 1		@ Clean D cache line
-	bic	r0, r0, #CACHELINESIZE - 1	@ round down to cache line
-1:	mcr	p15, 0, r0, c7, c6, 1		@ Invalidate D cache line
+ENTRY(xscale_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ Invalidate I cache & BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
 /*
- * cpu_xscale_dcache_clean_range(start, end)
+ *	dma_inv_range(start, end)
  *
- * For the specified virtual address range, ensure that all caches contain
- * clean data, such that peripheral accesses to the physical RAM fetch
- * correct data.
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
  *
- * start: virtual start address
- * end:   virtual end address
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
  */
-	.align	5
-ENTRY(cpu_xscale_dcache_clean_range)
-	bic	r0, r0, #CACHELINESIZE - 1
-	sub	r2, r1, r0
-	cmp	r2, #MAX_AREA_SIZE
-	movhi	r2, #0
-	bhi	cpu_xscale_cache_clean_invalidate_all_r2
+ENTRY(xscale_dma_inv_range)
+	mrc	p15, 0, r2, c0, c0, 0		@ read ID
+	eor	r2, r2, #0x69000000
+	eor	r2, r2, #0x00052000
+	bics	r2, r2, #1
+	beq	xscale_dma_flush_range
 
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+	tst	r0, #CACHELINESIZE - 1
+	bic	r0, r0, #CACHELINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHELINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, r0, c7, c10, 1		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
 /*
- * cpu_xscale_clean_dcache_page(page)
+ *	dma_clean_range(start, end)
  *
- * Cleans a single page of dcache so that if we have any future aliased
- * mappings, they will be consistent at the time that they are created.
+ *	Clean the specified virtual address range.
  *
- * Note:
- *  1. we don't need to flush the write buffer in this case. [really? -Nico]
- *  2. we don't invalidate the entries since when we write the page
- *     out to disk, the entries may get reloaded into the cache.
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
  */
-	.align	5
-ENTRY(cpu_xscale_dcache_clean_page)
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
+ENTRY(xscale_dma_clean_range)
+	bic	r0, r0, #CACHELINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
-	subs	r1, r1, #4 * CACHELINESIZE
-	bne	1b
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
-
-/*
- * cpu_xscale_dcache_clean_entry(addr)
- *
- * Clean the specified entry of any caches such that the MMU
- * translation fetches will obtain correct data.
- *
- * addr: cache-unaligned virtual address
- */
-	.align	5
-ENTRY(cpu_xscale_dcache_clean_entry)
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 1		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
-/* ================================ I-CACHE =============================== */
-
 /*
- * cpu_xscale_icache_invalidate_range(start, end)
- *
- * invalidate a range of virtual addresses from the Icache
+ *	dma_flush_range(start, end)
  *
- * start: virtual start address
- * end:   virtual end address
+ *	Clean and invalidate the specified virtual address range.
  *
- * Note: This is vaguely defined as supposed to bring the dcache and the
- *       icache in sync by the way this function is used.
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
  */
-	.align	5
-ENTRY(cpu_xscale_icache_invalidate_range)
+ENTRY(xscale_dma_flush_range)
 	bic	r0, r0, #CACHELINESIZE - 1
-1:	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, ip, c7, c5, 6		@ Invalidate BTB
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
+	mcr	p15, 0, r0, c7, c10, 1		@ Drain Write (& Fill) Buffer
 	mov	pc, lr
 
-/*
- * cpu_xscale_icache_invalidate_page(page)
- *
- * invalidate all Icache lines associated with this area of memory
- *
- * page: page to invalidate
- */
-	.align	5
-ENTRY(cpu_xscale_icache_invalidate_page)
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
-	add	r0, r0, #CACHELINESIZE
-	mcr	p15, 0, r0, c7, c5, 1		@ Invalidate I cache line
+ENTRY(xscale_cache_fns)
+	.long	xscale_flush_kern_cache_all
+	.long	xscale_flush_user_cache_all
+	.long	xscale_flush_user_cache_range
+	.long	xscale_coherent_kern_range
+	.long	xscale_flush_kern_dcache_page
+	.long	xscale_dma_inv_range
+	.long	xscale_dma_clean_range
+	.long	xscale_dma_flush_range
+
+ENTRY(cpu_xscale_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
-	subs	r1, r1, #4 * CACHELINESIZE
-	bne	1b
-	mcr	p15, 0, r0, c7, c5, 6		@ Invalidate BTB
+	subs	r1, r1, #CACHELINESIZE
+	bhi	1b
 	mov	pc, lr
 
 /* ================================ CACHE LOCKING============================
@@ -553,18 +487,17 @@
 
 /* =============================== PageTable ============================== */
 
-#define PMD_CACHE_WRITE_ALLOCATE 0
 #define PTE_CACHE_WRITE_ALLOCATE 0
 
 /*
- * cpu_xscale_set_pgd(pgd)
+ * cpu_xscale_switch_mm(pgd)
  *
  * Set the translation base pointer to be as described by pgd.
  *
  * pgd: new page tables
  */
 	.align	5
-ENTRY(cpu_xscale_set_pgd)
+ENTRY(cpu_xscale_switch_mm)
 	clean_d_cache r1, r2
 	mcr	p15, 0, ip, c7, c5, 0		@ Invalidate I cache & BTB
 	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
@@ -573,21 +506,6 @@
 	cpwait_ret lr, ip
 
 /*
- * cpu_xscale_flush_pmd(pmdp)
- *
- * Set a level 1 translation table entry, and clean it out of
- * any caches such that the MMUs can load it correctly.
- *
- * pmdp: pointer to PMD entry
- */
-	.align	5
-ENTRY(cpu_xscale_flush_pmd)
-	mov	ip, #0
-	mcr	p15, 0, r0, c7, c10, 1		@ Clean D cache line
-	mcr	p15, 0, ip, c7, c10, 4		@ Drain Write (& Fill) Buffer
-	mov	pc, lr
-
-/*
  * cpu_xscale_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
@@ -603,7 +521,7 @@
 
 	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
 
-	tst	r3, #L_PTE_USER | L_PTE_EXEC	@ User or Exec?
+	tst	r3, #L_PTE_USER			@ User?
 	orrne	r2, r2, #PTE_EXT_AP_URO_SRW	@ yes -> user r/o, system r/w
 
 	tst	r3, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
@@ -631,12 +549,10 @@
 	@ Erratum 40: The B bit must be cleared for a user read-only
 	@ cacheable page.
 	@
-	@  B = B & ~((U|E) & C & ~W)
+	@  B = B & ~(U & C & ~W)
 	@
-	and	ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
+	and	ip, r1, #L_PTE_USER | L_PTE_WRITE | L_PTE_CACHEABLE
 	teq	ip, #L_PTE_USER | L_PTE_CACHEABLE
-	teqne	ip, #L_PTE_EXEC | L_PTE_CACHEABLE
-	teqne	ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
 	biceq	r2, r2, #PTE_BUFFERABLE
 
 	tst	r3, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
@@ -696,30 +612,12 @@
 	.type	xscale_processor_functions, #object
 ENTRY(xscale_processor_functions)
 	.word	xscale_abort
-	.word	cpu_xscale_check_bugs
 	.word	cpu_xscale_proc_init
 	.word	cpu_xscale_proc_fin
 	.word	cpu_xscale_reset
 	.word	cpu_xscale_do_idle
-
-	/* cache */
-	.word	cpu_xscale_cache_clean_invalidate_all
-	.word	cpu_xscale_cache_clean_invalidate_range
-	.word	cpu_xscale_flush_ram_page
-
-	/* dcache */
-	.word	cpu_xscale_dcache_invalidate_range
-	.word	cpu_xscale_dcache_clean_range
-	.word	cpu_xscale_dcache_clean_page
-	.word	cpu_xscale_dcache_clean_entry
-
-	/* icache */
-	.word	cpu_xscale_icache_invalidate_range
-	.word	cpu_xscale_icache_invalidate_page
-
-	/* pgtable */
-	.word	cpu_xscale_set_pgd
-	.word	cpu_xscale_flush_pmd
+	.word	cpu_xscale_dcache_clean_area
+	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
@@ -749,6 +647,7 @@
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
 	.size	__80200_proc_info, . - __80200_proc_info
 
 	.type	__80321_proc_info,#object
@@ -780,6 +679,7 @@
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
 	.size	__pxa250_proc_info, . - __pxa250_proc_info
 
 	.type	__pxa210_proc_info,#object
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/ChangeLog linux-2.5.68-bk9/arch/arm/nwfpe/ChangeLog
--- linux-2.5.68-bk8/arch/arm/nwfpe/ChangeLog	2003-04-19 19:49:33.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/ChangeLog	2003-04-29 04:36:57.000000000 -0700
@@ -1,3 +1,11 @@
+2003-03-22  Ralph Siemsen <ralphs@netwinder.org>
+	* Reformat all but softfloat files to get a consistent coding style.
+	  Used "indent -kr -i8 -ts8 -sob -l132 -ss" and a few manual fixups.
+	* Removed dead code and fixed function protypes to match definitions.
+	* Consolidated use of (opcode && MASK_ARITHMETIC_OPCODE) >> 20.
+	* Make 80-bit precision a compile-time option. (1%)
+	* Only initialize FPE state once in repeat-FP situations. (6%)
+
 2002-01-19  Russell King <rmk@arm.linux.org.uk>
 
 	* fpa11.h - Add documentation
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/Makefile linux-2.5.68-bk9/arch/arm/nwfpe/Makefile
--- linux-2.5.68-bk8/arch/arm/nwfpe/Makefile	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/Makefile	2003-04-29 04:36:57.000000000 -0700
@@ -2,18 +2,12 @@
 # Copyright (C) 1998, 1999, 2001 Philip Blundell
 #
 
-obj-y			:=
-obj-m			:=
-obj-n			:=
+obj-$(CONFIG_FPE_NWFPE)		+= nwfpe.o
 
-obj-$(CONFIG_FPE_NWFPE)	+= nwfpe.o
+nwfpe-y				+= fpa11.o fpa11_cpdo.o fpa11_cpdt.o \
+				   fpa11_cprt.o fpmodule.o fpopcode.o \
+				   softfloat.o single_cpdo.o double_cpdo.o
 
-nwfpe-objs		:= fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
-			   fpmodule.o fpopcode.o softfloat.o \
-			   single_cpdo.o double_cpdo.o extended_cpdo.o
-
-ifeq ($(CONFIG_CPU_26),y)
-nwfpe-objs		+= entry26.o
-else
-nwfpe-objs		+= entry.o
-endif
+nwfpe-$(CONFIG_FPE_NWFPE_XP)	+= extended_cpdo.o
+nwfpe-$(CONFIG_CPU_26)		+= entry26.o
+nwfpe-$(CONFIG_CPU_32)		+= entry.o
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/double_cpdo.c linux-2.5.68-bk9/arch/arm/nwfpe/double_cpdo.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/double_cpdo.c	2003-04-19 19:48:48.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/double_cpdo.c	2003-04-29 04:36:57.000000000 -0700
@@ -23,6 +23,11 @@
 #include "softfloat.h"
 #include "fpopcode.h"
 
+union float64_components {
+	float64 f64;
+	unsigned int i[2];
+};
+
 float64 float64_exp(float64 Fm);
 float64 float64_ln(float64 Fm);
 float64 float64_sin(float64 rFm);
@@ -32,257 +37,123 @@
 float64 float64_log(float64 rFm);
 float64 float64_tan(float64 rFm);
 float64 float64_arccos(float64 rFm);
-float64 float64_pow(float64 rFn,float64 rFm);
-float64 float64_pol(float64 rFn,float64 rFm);
+float64 float64_pow(float64 rFn, float64 rFm);
+float64 float64_pol(float64 rFn, float64 rFm);
 
-unsigned int DoubleCPDO(const unsigned int opcode)
+static float64 float64_rsf(float64 rFn, float64 rFm)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   float64 rFm, rFn;
-   unsigned int Fd, Fm, Fn, nRc = 1;
-
-   //printk("DoubleCPDO(0x%08x)\n",opcode);
-   
-   Fm = getFm(opcode);
-   if (CONSTANT_FM(opcode))
-   {
-     rFm = getDoubleConstant(Fm);
-   }
-   else
-   {  
-     switch (fpa11->fType[Fm])
-     {
-        case typeSingle:
-          rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
-        break;
-
-        case typeDouble:
-          rFm = fpa11->fpreg[Fm].fDouble;
-          break;
-
-        case typeExtended:
-            // !! patb
-	    //printk("not implemented! why not?\n");
-            //!! ScottB
-            // should never get here, if extended involved
-            // then other operand should be promoted then
-            // ExtendedCPDO called.
-            break;
-
-        default: return 0;
-     }
-   }
-
-   if (!MONADIC_INSTRUCTION(opcode))
-   {
-      Fn = getFn(opcode);
-      switch (fpa11->fType[Fn])
-      {
-        case typeSingle:
-          rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
-        break;
-
-        case typeDouble:
-          rFn = fpa11->fpreg[Fn].fDouble;
-        break;
-        
-        default: return 0;
-      }
-   }
-
-   Fd = getFd(opcode);
-   /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
-   switch (opcode & MASK_ARITHMETIC_OPCODE)
-   {
-      /* dyadic opcodes */
-      case ADF_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm);
-      break;
-
-      case MUF_CODE:
-      case FML_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm);
-      break;
-
-      case SUF_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm);
-      break;
-
-      case RSF_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn);
-      break;
-
-      case DVF_CODE:
-      case FDV_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm);
-      break;
-
-      case RDF_CODE:
-      case FRD_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn);
-      break;
-
-#if 0
-      case POW_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
-      break;
-
-      case RPW_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
-      break;
-#endif
-
-      case RMF_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm);
-      break;
-
-#if 0
-      case POL_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
-      break;
-#endif
-
-      /* monadic opcodes */
-      case MVF_CODE:
-         fpa11->fpreg[Fd].fDouble = rFm;
-      break;
-
-      case MNF_CODE:
-      {
-         unsigned int *p = (unsigned int*)&rFm;
-         p[1] ^= 0x80000000;
-         fpa11->fpreg[Fd].fDouble = rFm;
-      }
-      break;
-
-      case ABS_CODE:
-      {
-         unsigned int *p = (unsigned int*)&rFm;
-         p[1] &= 0x7fffffff;
-         fpa11->fpreg[Fd].fDouble = rFm;
-      }
-      break;
-
-      case RND_CODE:
-      case URD_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm);
-      break;
-
-      case SQT_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm);
-      break;
-
-#if 0
-      case LOG_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_log(rFm);
-      break;
-
-      case LGN_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
-      break;
-
-      case EXP_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
-      break;
-
-      case SIN_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
-      break;
-
-      case COS_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
-      break;
-
-      case TAN_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
-      break;
-
-      case ASN_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
-      break;
-
-      case ACS_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
-      break;
-
-      case ATN_CODE:
-         fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
-      break;
-#endif
-
-      case NRM_CODE:
-      break;
-      
-      default:
-      {
-        nRc = 0;
-      }
-   }
-
-   if (0 != nRc) fpa11->fType[Fd] = typeDouble;
-   return nRc;
+	return float64_sub(rFm, rFn);
 }
 
-#if 0
-float64 float64_exp(float64 rFm)
+static float64 float64_rdv(float64 rFn, float64 rFm)
 {
-  return rFm;
-//series
+	return float64_div(rFm, rFn);
 }
 
-float64 float64_ln(float64 rFm)
-{
-  return rFm;
-//series
-}
+static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
+	[ADF_CODE >> 20] = float64_add,
+	[MUF_CODE >> 20] = float64_mul,
+	[SUF_CODE >> 20] = float64_sub,
+	[RSF_CODE >> 20] = float64_rsf,
+	[DVF_CODE >> 20] = float64_div,
+	[RDF_CODE >> 20] = float64_rdv,
+	[RMF_CODE >> 20] = float64_rem,
 
-float64 float64_sin(float64 rFm)
-{
-  return rFm;
-//series
-}
+	/* strictly, these opcodes should not be implemented */
+	[FML_CODE >> 20] = float64_mul,
+	[FDV_CODE >> 20] = float64_div,
+	[FRD_CODE >> 20] = float64_rdv,
+};
 
-float64 float64_cos(float64 rFm)
+static float64 float64_mvf(float64 rFm)
 {
-   return rFm;
-   //series
+	return rFm;
 }
 
-#if 0
-float64 float64_arcsin(float64 rFm)
+static float64 float64_mnf(float64 rFm)
 {
-//series
-}
+	union float64_components u;
 
-float64 float64_arctan(float64 rFm)
-{
-  //series
-}
-#endif
+	u.f64 = rFm;
+	u.i[1] ^= 0x80000000;
 
-float64 float64_log(float64 rFm)
-{
-  return float64_div(float64_ln(rFm),getDoubleConstant(7));
+	return u.f64;
 }
 
-float64 float64_tan(float64 rFm)
+static float64 float64_abs(float64 rFm)
 {
-  return float64_div(float64_sin(rFm),float64_cos(rFm));
-}
+	union float64_components u;
 
-float64 float64_arccos(float64 rFm)
-{
-return rFm;
-   //return float64_sub(halfPi,float64_arcsin(rFm));
-}
+	u.f64 = rFm;
+	u.i[1] &= 0x7fffffff;
 
-float64 float64_pow(float64 rFn,float64 rFm)
-{
-  return float64_exp(float64_mul(rFm,float64_ln(rFn))); 
+	return u.f64;
 }
 
-float64 float64_pol(float64 rFn,float64 rFm)
+static float64 (*const monadic_double[16])(float64 rFm) = {
+	[MVF_CODE >> 20] = float64_mvf,
+	[MNF_CODE >> 20] = float64_mnf,
+	[ABS_CODE >> 20] = float64_abs,
+	[RND_CODE >> 20] = float64_round_to_int,
+	[URD_CODE >> 20] = float64_round_to_int,
+	[SQT_CODE >> 20] = float64_sqrt,
+	[NRM_CODE >> 20] = float64_mvf,
+};
+
+unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
 {
-  return float64_arctan(float64_div(rFn,rFm)); 
+	FPA11 *fpa11 = GET_FPA11();
+	float64 rFm;
+	unsigned int Fm, opc_mask_shift;
+
+	Fm = getFm(opcode);
+	if (CONSTANT_FM(opcode)) {
+		rFm = getDoubleConstant(Fm);
+	} else {
+		switch (fpa11->fType[Fm]) {
+		case typeSingle:
+			rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
+			break;
+
+		case typeDouble:
+			rFm = fpa11->fpreg[Fm].fDouble;
+			break;
+
+		default:
+			return 0;
+		}
+	}
+
+	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
+	if (!MONADIC_INSTRUCTION(opcode)) {
+		unsigned int Fn = getFn(opcode);
+		float64 rFn;
+
+		switch (fpa11->fType[Fn]) {
+		case typeSingle:
+			rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
+			break;
+
+		case typeDouble:
+			rFn = fpa11->fpreg[Fn].fDouble;
+			break;
+
+		default:
+			return 0;
+		}
+
+		if (dyadic_double[opc_mask_shift]) {
+			rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
+		} else {
+			return 0;
+		}
+	} else {
+		if (monadic_double[opc_mask_shift]) {
+			rFd->fDouble = monadic_double[opc_mask_shift](rFm);
+		} else {
+			return 0;
+		}
+	}
+
+	return 1;
 }
-#endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/entry.S linux-2.5.68-bk9/arch/arm/nwfpe/entry.S
--- linux-2.5.68-bk8/arch/arm/nwfpe/entry.S	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/entry.S	2003-04-29 04:36:57.000000000 -0700
@@ -72,37 +72,37 @@
 
 	.globl	nwfpe_enter
 nwfpe_enter:
-        mov r4, lr			@ save the failure-return addresses
-	mov sl, sp
+	mov	r4, lr			@ save the failure-return addresses
+	mov	sl, sp			@ we access the registers via 'sl'
 
-        ldr r5, [sp, #60]	 	@ get contents of PC;
+	ldr	r5, [sp, #60]		@ get contents of PC;
 emulate:
-	bl EmulateAll			@ emulate the instruction
-   	cmp r0, #0			@ was emulation successful
-        moveq pc, r4			@ no, return failure
+	bl	EmulateAll		@ emulate the instruction
+	cmp	r0, #0			@ was emulation successful
+	moveq	pc, r4			@ no, return failure
 
 next:
-.Lx1:	ldrt r6, [r5], #4		@ get the next instruction and
+.Lx1:	ldrt	r6, [r5], #4		@ get the next instruction and
 					@ increment PC
 
-	and   r2, r6, #0x0F000000	@ test for FP insns
-        teq   r2, #0x0C000000
-        teqne r2, #0x0D000000
-        teqne r2, #0x0E000000
-        movne pc, r9			@ return ok if not a fp insn
-
-        str r5, [sp, #60]		@ update PC copy in regs
-
-        mov r0, r6			@ save a copy
-        ldr r1, [sp, #64]		@ fetch the condition codes
-   	bl  checkCondition		@ check the condition
-   	cmp r0, #0			@ r0 = 0 ==> condition failed
-
-        @ if condition code failed to match, next insn
-   	beq next			@ get the next instruction;
-   	    
-        mov r0, r6			@ prepare for EmulateAll()
-   	b emulate			@ if r0 != 0, goto EmulateAll
+	and	r2, r6, #0x0F000000	@ test for FP insns
+	teq	r2, #0x0C000000
+	teqne	r2, #0x0D000000
+	teqne	r2, #0x0E000000
+	movne	pc, r9			@ return ok if not a fp insn
+
+	str	r5, [sp, #60]		@ update PC copy in regs
+
+	mov	r0, r6			@ save a copy
+	ldr	r1, [sp, #64]		@ fetch the condition codes
+	bl	checkCondition		@ check the condition
+	cmp	r0, #0			@ r0 = 0 ==> condition failed
+
+	@ if condition code failed to match, next insn
+	beq	next			@ get the next instruction;
+
+	mov	r0, r6			@ prepare for EmulateAll()
+	b	emulate			@ if r0 != 0, goto EmulateAll
 
 	@ We need to be prepared for the instructions at .Lx1 and .Lx2 
 	@ to fault.  Emit the appropriate exception gunk to fix things up.
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/entry26.S linux-2.5.68-bk9/arch/arm/nwfpe/entry26.S
--- linux-2.5.68-bk8/arch/arm/nwfpe/entry26.S	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/entry26.S	2003-04-29 04:36:57.000000000 -0700
@@ -66,7 +66,6 @@
 	.globl	nwfpe_enter
 nwfpe_enter:
 	mov	sl, sp
-
 	ldr	r5, [sp, #60]		@ get contents of PC
 	bic	r5, r5, #0xfc000003
 	ldr	r0, [r5, #-4]		@ get actual instruction into r0
@@ -96,7 +95,7 @@
 
 	@ if condition code failed to match, next insn
 	beq	next			@ get the next instruction;
-	    
+
 	mov	r0, r6			@ prepare for EmulateAll()
 	adr	lr, 1b
 	orr	lr, lr, #3
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/extended_cpdo.c linux-2.5.68-bk9/arch/arm/nwfpe/extended_cpdo.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/extended_cpdo.c	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/extended_cpdo.c	2003-04-29 04:36:57.000000000 -0700
@@ -32,242 +32,123 @@
 floatx80 floatx80_log(floatx80 rFm);
 floatx80 floatx80_tan(floatx80 rFm);
 floatx80 floatx80_arccos(floatx80 rFm);
-floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm);
-floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm);
+floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
+floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
 
-unsigned int ExtendedCPDO(const unsigned int opcode)
+static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   floatx80 rFm, rFn;
-   unsigned int Fd, Fm, Fn, nRc = 1;
-
-   //printk("ExtendedCPDO(0x%08x)\n",opcode);
-   
-   Fm = getFm(opcode);
-   if (CONSTANT_FM(opcode))
-   {
-     rFm = getExtendedConstant(Fm);
-   }
-   else
-   {  
-     switch (fpa11->fType[Fm])
-     {
-        case typeSingle:
-          rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
-        break;
-
-        case typeDouble:
-          rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
-        break;
-        
-        case typeExtended:
-          rFm = fpa11->fpreg[Fm].fExtended;
-        break;
-        
-        default: return 0;
-     }
-   }
-   
-   if (!MONADIC_INSTRUCTION(opcode))
-   {
-      Fn = getFn(opcode);
-      switch (fpa11->fType[Fn])
-      {
-        case typeSingle:
-          rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
-        break;
-
-        case typeDouble:
-          rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
-        break;
-        
-        case typeExtended:
-          rFn = fpa11->fpreg[Fn].fExtended;
-        break;
-        
-        default: return 0;
-      }
-   }
-
-   Fd = getFd(opcode);
-   switch (opcode & MASK_ARITHMETIC_OPCODE)
-   {
-      /* dyadic opcodes */
-      case ADF_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm);
-      break;
-
-      case MUF_CODE:
-      case FML_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm);
-      break;
-
-      case SUF_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm);
-      break;
-
-      case RSF_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn);
-      break;
-
-      case DVF_CODE:
-      case FDV_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm);
-      break;
-
-      case RDF_CODE:
-      case FRD_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn);
-      break;
-
-#if 0
-      case POW_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm);
-      break;
-
-      case RPW_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn);
-      break;
-#endif
-
-      case RMF_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm);
-      break;
-
-#if 0
-      case POL_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm);
-      break;
-#endif
-
-      /* monadic opcodes */
-      case MVF_CODE:
-         fpa11->fpreg[Fd].fExtended = rFm;
-      break;
-
-      case MNF_CODE:
-         rFm.high ^= 0x8000;
-         fpa11->fpreg[Fd].fExtended = rFm;
-      break;
-
-      case ABS_CODE:
-         rFm.high &= 0x7fff;
-         fpa11->fpreg[Fd].fExtended = rFm;
-      break;
-
-      case RND_CODE:
-      case URD_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm);
-      break;
-
-      case SQT_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm);
-      break;
-
-#if 0
-      case LOG_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_log(rFm);
-      break;
-
-      case LGN_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm);
-      break;
-
-      case EXP_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm);
-      break;
-
-      case SIN_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm);
-      break;
-
-      case COS_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm);
-      break;
-
-      case TAN_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm);
-      break;
-
-      case ASN_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm);
-      break;
-
-      case ACS_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm);
-      break;
-
-      case ATN_CODE:
-         fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm);
-      break;
-#endif
-
-      case NRM_CODE:
-      break;
-      
-      default:
-      {
-        nRc = 0;
-      }
-   }
-   
-   if (0 != nRc) fpa11->fType[Fd] = typeExtended;
-   return nRc;
+	return floatx80_sub(rFm, rFn);
 }
 
-#if 0
-floatx80 floatx80_exp(floatx80 Fm)
+static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
 {
-//series
+	return floatx80_div(rFm, rFn);
 }
 
-floatx80 floatx80_ln(floatx80 Fm)
-{
-//series
-}
+static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
+	[ADF_CODE >> 20] = floatx80_add,
+	[MUF_CODE >> 20] = floatx80_mul,
+	[SUF_CODE >> 20] = floatx80_sub,
+	[RSF_CODE >> 20] = floatx80_rsf,
+	[DVF_CODE >> 20] = floatx80_div,
+	[RDF_CODE >> 20] = floatx80_rdv,
+	[RMF_CODE >> 20] = floatx80_rem,
 
-floatx80 floatx80_sin(floatx80 rFm)
-{
-//series
-}
+	/* strictly, these opcodes should not be implemented */
+	[FML_CODE >> 20] = floatx80_mul,
+	[FDV_CODE >> 20] = floatx80_div,
+	[FRD_CODE >> 20] = floatx80_rdv,
+};
 
-floatx80 floatx80_cos(floatx80 rFm)
+static floatx80 floatx80_mvf(floatx80 rFm)
 {
-//series
+	return rFm;
 }
 
-floatx80 floatx80_arcsin(floatx80 rFm)
+static floatx80 floatx80_mnf(floatx80 rFm)
 {
-//series
+	rFm.high ^= 0x8000;
+	return rFm;
 }
 
-floatx80 floatx80_arctan(floatx80 rFm)
+static floatx80 floatx80_abs(floatx80 rFm)
 {
-  //series
+	rFm.high &= 0x7fff;
+	return rFm;
 }
 
-floatx80 floatx80_log(floatx80 rFm)
-{
-  return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7));
-}
+static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
+	[MVF_CODE >> 20] = floatx80_mvf,
+	[MNF_CODE >> 20] = floatx80_mnf,
+	[ABS_CODE >> 20] = floatx80_abs,
+	[RND_CODE >> 20] = floatx80_round_to_int,
+	[URD_CODE >> 20] = floatx80_round_to_int,
+	[SQT_CODE >> 20] = floatx80_sqrt,
+	[NRM_CODE >> 20] = floatx80_mvf,
+};
 
-floatx80 floatx80_tan(floatx80 rFm)
+unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
 {
-  return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm));
-}
+	FPA11 *fpa11 = GET_FPA11();
+	floatx80 rFm;
+	unsigned int Fm, opc_mask_shift;
 
-floatx80 floatx80_arccos(floatx80 rFm)
-{
-   //return floatx80_sub(halfPi,floatx80_arcsin(rFm));
-}
+	Fm = getFm(opcode);
+	if (CONSTANT_FM(opcode)) {
+		rFm = getExtendedConstant(Fm);
+	} else {
+		switch (fpa11->fType[Fm]) {
+		case typeSingle:
+			rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
+			break;
 
-floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm)
-{
-  return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); 
-}
+		case typeDouble:
+			rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
+			break;
 
-floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm)
-{
-  return floatx80_arctan(floatx80_div(rFn,rFm)); 
+		case typeExtended:
+			rFm = fpa11->fpreg[Fm].fExtended;
+			break;
+
+		default:
+			return 0;
+		}
+	}
+
+	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
+	if (!MONADIC_INSTRUCTION(opcode)) {
+		unsigned int Fn = getFn(opcode);
+		floatx80 rFn;
+
+		switch (fpa11->fType[Fn]) {
+		case typeSingle:
+			rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
+			break;
+
+		case typeDouble:
+			rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
+			break;
+
+		case typeExtended:
+			rFn = fpa11->fpreg[Fn].fExtended;
+			break;
+
+		default:
+			return 0;
+		}
+
+		if (dyadic_extended[opc_mask_shift]) {
+			rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
+		} else {
+			return 0;
+		}
+	} else {
+		if (monadic_extended[opc_mask_shift]) {
+			rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
+		} else {
+			return 0;
+		}
+	}
+
+	return 1;
 }
-#endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.c linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.c	2003-04-29 04:36:57.000000000 -0700
@@ -1,6 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.COM, 1998,1999
+    (c) Philip Blundell, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -37,184 +38,105 @@
 /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
 static void resetFPA11(void)
 {
-  int i;
-  FPA11 *fpa11 = GET_FPA11();
-  
-  /* initialize the register type array */
-  for (i=0;i<=7;i++)
-  {
-    fpa11->fType[i] = typeNone;
-  }
-  
-  /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
-  fpa11->fpsr = FP_EMULATOR | BIT_AC;
-  
-  /* FPCR: set SB, AB and DA bits, clear all others */
-#if MAINTAIN_FPCR
-  fpa11->fpcr = MASK_RESET;
-#endif
+	int i;
+	FPA11 *fpa11 = GET_FPA11();
+
+	/* initialize the register type array */
+	for (i = 0; i <= 7; i++) {
+		fpa11->fType[i] = typeNone;
+	}
+
+	/* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
+	fpa11->fpsr = FP_EMULATOR | BIT_AC;
 }
 
 void SetRoundingMode(const unsigned int opcode)
 {
-#if MAINTAIN_FPCR
-   FPA11 *fpa11 = GET_FPA11();
-   fpa11->fpcr &= ~MASK_ROUNDING_MODE;
-#endif   
-   switch (opcode & MASK_ROUNDING_MODE)
-   {
-      default:
-      case ROUND_TO_NEAREST:
-         float_rounding_mode = float_round_nearest_even;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_TO_NEAREST;
-#endif         
-      break;
-      
-      case ROUND_TO_PLUS_INFINITY:
-         float_rounding_mode = float_round_up;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
-#endif         
-      break;
-      
-      case ROUND_TO_MINUS_INFINITY:
-         float_rounding_mode = float_round_down;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
-#endif         
-      break;
-      
-      case ROUND_TO_ZERO:
-         float_rounding_mode = float_round_to_zero;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_TO_ZERO;
-#endif         
-      break;
-  }
+	switch (opcode & MASK_ROUNDING_MODE) {
+	default:
+	case ROUND_TO_NEAREST:
+		float_rounding_mode = float_round_nearest_even;
+		break;
+
+	case ROUND_TO_PLUS_INFINITY:
+		float_rounding_mode = float_round_up;
+		break;
+
+	case ROUND_TO_MINUS_INFINITY:
+		float_rounding_mode = float_round_down;
+		break;
+
+	case ROUND_TO_ZERO:
+		float_rounding_mode = float_round_to_zero;
+		break;
+	}
 }
 
 void SetRoundingPrecision(const unsigned int opcode)
 {
-#if MAINTAIN_FPCR
-   FPA11 *fpa11 = GET_FPA11();
-   fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
-#endif   
-   switch (opcode & MASK_ROUNDING_PRECISION)
-   {
-      case ROUND_SINGLE:
-         floatx80_rounding_precision = 32;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_SINGLE;
-#endif         
-      break;
-      
-      case ROUND_DOUBLE:
-         floatx80_rounding_precision = 64;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_DOUBLE;
-#endif         
-      break;
-      
-      case ROUND_EXTENDED:
-         floatx80_rounding_precision = 80;
-#if MAINTAIN_FPCR         
-         fpa11->fpcr |= ROUND_EXTENDED;
-#endif         
-      break;
-      
-      default: floatx80_rounding_precision = 80;
-  }
+#ifdef CONFIG_FPE_NWFPE_XP
+	switch (opcode & MASK_ROUNDING_PRECISION) {
+	case ROUND_SINGLE:
+		floatx80_rounding_precision = 32;
+		break;
+
+	case ROUND_DOUBLE:
+		floatx80_rounding_precision = 64;
+		break;
+
+	case ROUND_EXTENDED:
+		floatx80_rounding_precision = 80;
+		break;
+
+	default:
+		floatx80_rounding_precision = 80;
+	}
+#endif
 }
 
-void nwfpe_init(union fp_state *fp)
+void nwfpe_init_fpa(union fp_state *fp)
 {
-  FPA11 *fpa11 = (FPA11 *)fp;
-  memset(fpa11, 0, sizeof(FPA11));
-  resetFPA11();
-  SetRoundingMode(ROUND_TO_NEAREST);
-  SetRoundingPrecision(ROUND_EXTENDED);
-  fpa11->initflag = 1;
+	FPA11 *fpa11 = (FPA11 *)fp;
+#ifdef NWFPE_DEBUG
+	printk("NWFPE: setting up state.\n");
+#endif
+ 	memset(fpa11, 0, sizeof(FPA11));
+	resetFPA11();
+	SetRoundingMode(ROUND_TO_NEAREST);
+	SetRoundingPrecision(ROUND_EXTENDED);
+	fpa11->initflag = 1;
 }
 
 /* Emulate the instruction in the opcode. */
 unsigned int EmulateAll(unsigned int opcode)
 {
-  unsigned int nRc = 1, code;
-
-  code = opcode & 0x00000f00;
-  if (code == 0x00000100 || code == 0x00000200)
-  {
-    /* For coprocessor 1 or 2 (FPA11) */
-    code = opcode & 0x0e000000;
-    if (code == 0x0e000000)
-    {
-      if (opcode & 0x00000010)
-      {
-        /* Emulate conversion opcodes. */
-        /* Emulate register transfer opcodes. */
-        /* Emulate comparison opcodes. */
-        nRc = EmulateCPRT(opcode);
-      }
-      else
-      {
-        /* Emulate monadic arithmetic opcodes. */
-        /* Emulate dyadic arithmetic opcodes. */
-        nRc = EmulateCPDO(opcode);
-      }
-    }
-    else if (code == 0x0c000000)
-    {
-      /* Emulate load/store opcodes. */
-      /* Emulate load/store multiple opcodes. */
-      nRc = EmulateCPDT(opcode);
-    }
-    else
-    {
-      /* Invalid instruction detected.  Return FALSE. */
-      nRc = 0;
-    }
-  }
+	unsigned int code;
 
-  return(nRc);
-}
-
-#if 0
-unsigned int EmulateAll1(unsigned int opcode)
-{
-  switch ((opcode >> 24) & 0xf)
-  {
-     case 0xc:
-     case 0xd:
-       if ((opcode >> 20) & 0x1)
-       {
-          switch ((opcode >> 8) & 0xf)
-          {
-             case 0x1: return PerformLDF(opcode); break;
-             case 0x2: return PerformLFM(opcode); break;
-             default: return 0;
-          }
-       }
-       else
-       {
-          switch ((opcode >> 8) & 0xf)
-          {
-             case 0x1: return PerformSTF(opcode); break;
-             case 0x2: return PerformSFM(opcode); break;
-             default: return 0;
-          }
-      }
-     break;
-     
-     case 0xe: 
-       if (opcode & 0x10)
-         return EmulateCPDO(opcode);
-       else
-         return EmulateCPRT(opcode);
-     break;
-  
-     default: return 0;
-  }
-}
+#ifdef NWFPE_DEBUG
+	printk("NWFPE: emulating opcode %08x\n", opcode);
 #endif
+	code = opcode & 0x00000f00;
+	if (code == 0x00000100 || code == 0x00000200) {
+		/* For coprocessor 1 or 2 (FPA11) */
+		code = opcode & 0x0e000000;
+		if (code == 0x0e000000) {
+			if (opcode & 0x00000010) {
+				/* Emulate conversion opcodes. */
+				/* Emulate register transfer opcodes. */
+				/* Emulate comparison opcodes. */
+				return EmulateCPRT(opcode);
+			} else {
+				/* Emulate monadic arithmetic opcodes. */
+				/* Emulate dyadic arithmetic opcodes. */
+				return EmulateCPDO(opcode);
+			}
+		} else if (code == 0x0c000000) {
+			/* Emulate load/store opcodes. */
+			/* Emulate load/store multiple opcodes. */
+			return EmulateCPDT(opcode);
+		}
+	}
 
+	/* Invalid instruction detected.  Return FALSE. */
+	return 0;
+}
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.h linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.h
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.h	2003-04-19 19:49:21.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.h	2003-04-29 04:36:57.000000000 -0700
@@ -37,6 +37,7 @@
 
 /* includes */
 #include "fpsr.h"		/* FP control and status register definitions */
+#include "milieu.h"
 #include "softfloat.h"
 
 #define		typeNone		0x00
@@ -48,9 +49,13 @@
  * This must be no more and no less than 12 bytes.
  */
 typedef union tagFPREG {
-   floatx80 fExtended;
-   float64  fDouble;
-   float32  fSingle;
+	float32 fSingle;
+	float64 fDouble;
+#ifdef CONFIG_FPE_NWFPE_XP
+	floatx80 fExtended;
+#else
+	int padding[3];
+#endif
 } FPREG;
 
 /*
@@ -67,21 +72,21 @@
  * not initialise.
  */
 typedef struct tagFPA11 {
-/*   0 */  FPREG fpreg[8];		/* 8 floating point registers */
-/*  96 */  FPSR fpsr;			/* floating point status register */
-/* 100 */  FPCR fpcr;			/* floating point control register */
-/* 104 */  unsigned char fType[8];	/* type of floating point value held in
-					   floating point registers.  One of none
-					   single, double or extended. */
-/* 112 */  int initflag;		/* this is special.  The kernel guarantees
-					   to set it to 0 when a thread is launched,
-					   so we can use it to detect whether this
-					   instance of the emulator needs to be
-					   initialised. */
+/*   0 */ FPREG fpreg[8];	/* 8 floating point registers */
+/*  96 */ FPSR fpsr;		/* floating point status register */
+/* 100 */ FPCR fpcr;		/* floating point control register */
+/* 104 */ unsigned char fType[8];	/* type of floating point value held in
+					   floating point registers.  One of
+					   none, single, double or extended. */
+/* 112 */ int initflag;		/* this is special.  The kernel guarantees
+				   to set it to 0 when a thread is launched,
+				   so we can use it to detect whether this
+				   instance of the emulator needs to be
+				   initialised. */
 } FPA11;
 
 extern void SetRoundingMode(const unsigned int);
 extern void SetRoundingPrecision(const unsigned int);
-extern void nwfpe_init(union fp_state *fp);
+extern void nwfpe_init_fpa(union fp_state *fp);
 
 #endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.inl linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.inl
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11.inl	2003-04-19 19:49:30.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11.inl	2003-04-29 04:36:57.000000000 -0700
@@ -24,28 +24,28 @@
 /* Read and write floating point status register */
 extern __inline__ unsigned int readFPSR(void)
 {
-  FPA11 *fpa11 = GET_FPA11();
-  return(fpa11->fpsr);
+	FPA11 *fpa11 = GET_FPA11();
+	return (fpa11->fpsr);
 }
 
 extern __inline__ void writeFPSR(FPSR reg)
 {
-  FPA11 *fpa11 = GET_FPA11();
-  /* the sysid byte in the status register is readonly */
-  fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID);
+	FPA11 *fpa11 = GET_FPA11();
+	/* the sysid byte in the status register is readonly */
+	fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID);
 }
 
 /* Read and write floating point control register */
 extern __inline__ FPCR readFPCR(void)
 {
-  FPA11 *fpa11 = GET_FPA11();
-  /* clear SB, AB and DA bits before returning FPCR */
-  return(fpa11->fpcr & ~MASK_RFC);
+	FPA11 *fpa11 = GET_FPA11();
+	/* clear SB, AB and DA bits before returning FPCR */
+	return (fpa11->fpcr & ~MASK_RFC);
 }
 
 extern __inline__ void writeFPCR(FPCR reg)
 {
-  FPA11 *fpa11 = GET_FPA11();
-  fpa11->fpcr &= ~MASK_WFC;		/* clear SB, AB and DA bits */
-  fpa11->fpcr |= (reg & MASK_WFC);	/* write SB, AB and DA bits */
+	FPA11 *fpa11 = GET_FPA11();
+	fpa11->fpcr &= ~MASK_WFC;		/* clear SB, AB and DA bits */
+	fpa11->fpcr |= (reg & MASK_WFC);	/* write SB, AB and DA bits */
 }
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cpdo.c linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cpdo.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cpdo.c	2003-04-19 19:50:32.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cpdo.c	2003-04-29 04:36:57.000000000 -0700
@@ -1,6 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.COM, 1998,1999
+    (c) Philip Blundell, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -22,96 +23,109 @@
 #include "fpa11.h"
 #include "fpopcode.h"
 
-unsigned int SingleCPDO(const unsigned int opcode);
-unsigned int DoubleCPDO(const unsigned int opcode);
-unsigned int ExtendedCPDO(const unsigned int opcode);
+unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
 
 unsigned int EmulateCPDO(const unsigned int opcode)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   unsigned int Fd, nType, nDest, nRc = 1;
-   
-   //printk("EmulateCPDO(0x%08x)\n",opcode);
-
-   /* Get the destination size.  If not valid let Linux perform
-      an invalid instruction trap. */
-   nDest = getDestinationSize(opcode);
-   if (typeNone == nDest) return 0;
-   
-   SetRoundingMode(opcode);
-     
-   /* Compare the size of the operands in Fn and Fm.
-      Choose the largest size and perform operations in that size,
-      in order to make use of all the precision of the operands. 
-      If Fm is a constant, we just grab a constant of a size 
-      matching the size of the operand in Fn. */
-   if (MONADIC_INSTRUCTION(opcode))
-     nType = nDest;
-   else
-     nType = fpa11->fType[getFn(opcode)];
-   
-   if (!CONSTANT_FM(opcode))
-   {
-     register unsigned int Fm = getFm(opcode);
-     if (nType < fpa11->fType[Fm])
-     {
-        nType = fpa11->fType[Fm];
-     }
-   }
-
-   switch (nType)
-   {
-      case typeSingle   : nRc = SingleCPDO(opcode);   break;
-      case typeDouble   : nRc = DoubleCPDO(opcode);   break;
-      case typeExtended : nRc = ExtendedCPDO(opcode); break;
-      default           : nRc = 0;
-   }
-
-   /* If the operation succeeded, check to see if the result in the
-      destination register is the correct size.  If not force it
-      to be. */
-   Fd = getFd(opcode);
-   nType = fpa11->fType[Fd];
-   if ((0 != nRc) && (nDest != nType))
-   {
-     switch (nDest)
-     {
-       case typeSingle:
-       {
-         if (typeDouble == nType)
-           fpa11->fpreg[Fd].fSingle = 
-              float64_to_float32(fpa11->fpreg[Fd].fDouble);
-         else
-           fpa11->fpreg[Fd].fSingle = 
-              floatx80_to_float32(fpa11->fpreg[Fd].fExtended);
-       }
-       break;
-          
-       case typeDouble:
-       {
-         if (typeSingle == nType)
-           fpa11->fpreg[Fd].fDouble = 
-              float32_to_float64(fpa11->fpreg[Fd].fSingle);
-         else
-           fpa11->fpreg[Fd].fDouble = 
-              floatx80_to_float64(fpa11->fpreg[Fd].fExtended);
-       }
-       break;
-          
-       case typeExtended:
-       {
-         if (typeSingle == nType)
-           fpa11->fpreg[Fd].fExtended = 
-              float32_to_floatx80(fpa11->fpreg[Fd].fSingle);
-         else
-           fpa11->fpreg[Fd].fExtended = 
-              float64_to_floatx80(fpa11->fpreg[Fd].fDouble);
-       }
-       break;
-     }
-     
-     fpa11->fType[Fd] = nDest;
-   }
-   
-   return nRc;
+	FPA11 *fpa11 = GET_FPA11();
+	FPREG *rFd;
+	unsigned int nType, nDest, nRc;
+
+	/* Get the destination size.  If not valid let Linux perform
+	   an invalid instruction trap. */
+	nDest = getDestinationSize(opcode);
+	if (typeNone == nDest)
+		return 0;
+
+	SetRoundingMode(opcode);
+
+	/* Compare the size of the operands in Fn and Fm.
+	   Choose the largest size and perform operations in that size,
+	   in order to make use of all the precision of the operands.
+	   If Fm is a constant, we just grab a constant of a size
+	   matching the size of the operand in Fn. */
+	if (MONADIC_INSTRUCTION(opcode))
+		nType = nDest;
+	else
+		nType = fpa11->fType[getFn(opcode)];
+
+	if (!CONSTANT_FM(opcode)) {
+		register unsigned int Fm = getFm(opcode);
+		if (nType < fpa11->fType[Fm]) {
+			nType = fpa11->fType[Fm];
+		}
+	}
+
+	rFd = &fpa11->fpreg[getFd(opcode)];
+
+	switch (nType) {
+	case typeSingle:
+		nRc = SingleCPDO(opcode, rFd);
+		break;
+	case typeDouble:
+		nRc = DoubleCPDO(opcode, rFd);
+		break;
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		nRc = ExtendedCPDO(opcode, rFd);
+		break;
+#endif
+	default:
+		nRc = 0;
+	}
+
+	/* The CPDO functions used to always set the destination type
+	   to be the same as their working size. */
+
+	if (nRc != 0) {
+		/* If the operation succeeded, check to see if the result in the
+		   destination register is the correct size.  If not force it
+		   to be. */
+
+		fpa11->fType[getFd(opcode)] = nDest;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+		if (nDest != nType) {
+			switch (nDest) {
+			case typeSingle:
+				{
+					if (typeDouble == nType)
+						rFd->fSingle = float64_to_float32(rFd->fDouble);
+					else
+						rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+				}
+				break;
+
+			case typeDouble:
+				{
+					if (typeSingle == nType)
+						rFd->fDouble = float32_to_float64(rFd->fSingle);
+					else
+						rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+				}
+				break;
+
+			case typeExtended:
+				{
+					if (typeSingle == nType)
+						rFd->fExtended = float32_to_floatx80(rFd->fSingle);
+					else
+						rFd->fExtended = float64_to_floatx80(rFd->fDouble);
+				}
+				break;
+			}
+		}
+#else
+		if (nDest != nType) {
+			if (nDest == typeSingle)
+				rFd->fSingle = float64_to_float32(rFd->fDouble);
+			else
+				rFd->fDouble = float32_to_float64(rFd->fSingle);
+		}
+#endif
+	}
+
+	return nRc;
 }
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cpdt.c linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cpdt.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cpdt.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cpdt.c	2003-04-29 04:36:57.000000000 -0700
@@ -1,7 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.com, 1998-1999
-    (c) Philip Blundell, 1998
+    (c) Philip Blundell, 1998, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -28,341 +28,354 @@
 
 #include <asm/uaccess.h>
 
-static inline
-void loadSingle(const unsigned int Fn,const unsigned int *pMem)
+static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   fpa11->fType[Fn] = typeSingle;
-   get_user(fpa11->fpreg[Fn].fSingle, pMem);
-}
-
-static inline
-void loadDouble(const unsigned int Fn,const unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   unsigned int *p;
-   p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
-   fpa11->fType[Fn] = typeDouble;
-   get_user(p[0], &pMem[1]);
-   get_user(p[1], &pMem[0]); /* sign & exponent */
-}
-
-static inline
-void loadExtended(const unsigned int Fn,const unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   unsigned int *p;
-   p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
-   fpa11->fType[Fn] = typeExtended;
-   get_user(p[0], &pMem[0]);  /* sign & exponent */
-   get_user(p[1], &pMem[2]);  /* ls bits */
-   get_user(p[2], &pMem[1]);  /* ms bits */
-}
-
-static inline
-void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   register unsigned int *p;
-   unsigned long x;
-
-   p = (unsigned int*)&(fpa11->fpreg[Fn]);
-   get_user(x, &pMem[0]);
-   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
-
-   switch (fpa11->fType[Fn])
-   {
-      case typeSingle:
-      case typeDouble:
-      {
-         get_user(p[0], &pMem[2]);  /* Single */
-         get_user(p[1], &pMem[1]);  /* double msw */
-         p[2] = 0;        /* empty */
-      }
-      break;
-
-      case typeExtended:
-      {
-         get_user(p[1], &pMem[2]);
-         get_user(p[2], &pMem[1]);  /* msw */
-         p[0] = (x & 0x80003fff);
-      }
-      break;
-   }
-}
-
-static inline
-void storeSingle(const unsigned int Fn,unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   union
-   {
-     float32 f;
-     unsigned int i[1];
-   } val;
-
-   switch (fpa11->fType[Fn])
-   {
-      case typeDouble:
-         val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
-      break;
-
-      case typeExtended:
-         val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
-      break;
-
-      default: val.f = fpa11->fpreg[Fn].fSingle;
-   }
-
-   put_user(val.i[0], pMem);
-}
-
-static inline
-void storeDouble(const unsigned int Fn,unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   union
-   {
-     float64 f;
-     unsigned int i[2];
-   } val;
-
-   switch (fpa11->fType[Fn])
-   {
-      case typeSingle:
-         val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
-      break;
-
-      case typeExtended:
-         val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
-      break;
-
-      default: val.f = fpa11->fpreg[Fn].fDouble;
-   }
-
-   put_user(val.i[1], &pMem[0]);	/* msw */
-   put_user(val.i[0], &pMem[1]);	/* lsw */
-}
-
-static inline
-void storeExtended(const unsigned int Fn,unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   union
-   {
-     floatx80 f;
-     unsigned int i[3];
-   } val;
-
-   switch (fpa11->fType[Fn])
-   {
-      case typeSingle:
-         val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
-      break;
-
-      case typeDouble:
-         val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
-      break;
-
-      default: val.f = fpa11->fpreg[Fn].fExtended;
-   }
-
-   put_user(val.i[0], &pMem[0]); /* sign & exp */
-   put_user(val.i[1], &pMem[2]);
-   put_user(val.i[2], &pMem[1]); /* msw */
-}
-
-static inline
-void storeMultiple(const unsigned int Fn,unsigned int *pMem)
-{
-   FPA11 *fpa11 = GET_FPA11();
-   register unsigned int nType, *p;
-
-   p = (unsigned int*)&(fpa11->fpreg[Fn]);
-   nType = fpa11->fType[Fn];
-
-   switch (nType)
-   {
-      case typeSingle:
-      case typeDouble:
-      {
-	 put_user(p[0], &pMem[2]); /* single */
-	 put_user(p[1], &pMem[1]); /* double msw */
-	 put_user(nType << 14, &pMem[0]);
-      }
-      break;
-
-      case typeExtended:
-      {
-	 put_user(p[2], &pMem[1]); /* msw */
-	 put_user(p[1], &pMem[2]);
-	 put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
-      }
-      break;
-   }
+	FPA11 *fpa11 = GET_FPA11();
+	fpa11->fType[Fn] = typeSingle;
+	get_user(fpa11->fpreg[Fn].fSingle, pMem);
 }
 
-unsigned int PerformLDF(const unsigned int opcode)
+static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	unsigned int *p;
+	p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
+	fpa11->fType[Fn] = typeDouble;
+	get_user(p[0], &pMem[1]);
+	get_user(p[1], &pMem[0]);	/* sign & exponent */
+}
+
+#ifdef CONFIG_FPE_NWFPE_XP
+static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	unsigned int *p;
+	p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
+	fpa11->fType[Fn] = typeExtended;
+	get_user(p[0], &pMem[0]);	/* sign & exponent */
+	get_user(p[1], &pMem[2]);	/* ls bits */
+	get_user(p[2], &pMem[1]);	/* ms bits */
+}
+#endif
+
+static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem)
 {
-   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
-     write_back = WRITE_BACK(opcode);
+	FPA11 *fpa11 = GET_FPA11();
+	register unsigned int *p;
+	unsigned long x;
+
+	p = (unsigned int *) &(fpa11->fpreg[Fn]);
+	get_user(x, &pMem[0]);
+	fpa11->fType[Fn] = (x >> 14) & 0x00000003;
+
+	switch (fpa11->fType[Fn]) {
+	case typeSingle:
+	case typeDouble:
+		{
+			get_user(p[0], &pMem[2]);	/* Single */
+			get_user(p[1], &pMem[1]);	/* double msw */
+			p[2] = 0;			/* empty */
+		}
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		{
+			get_user(p[1], &pMem[2]);
+			get_user(p[2], &pMem[1]);	/* msw */
+			p[0] = (x & 0x80003fff);
+		}
+		break;
+#endif
+	}
+}
 
-   //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
+static inline void storeSingle(const unsigned int Fn, unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	union {
+		float32 f;
+		unsigned int i[1];
+	} val;
+
+	switch (fpa11->fType[Fn]) {
+	case typeDouble:
+		val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+		break;
+#endif
 
-   pBase = (unsigned int*)readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
-   {
-     pBase += 2;
-     write_back = 0;
-   }
-
-   pFinal = pBase;
-   if (BIT_UP_SET(opcode))
-     pFinal += getOffset(opcode);
-   else
-     pFinal -= getOffset(opcode);
-
-   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
-
-   switch (opcode & MASK_TRANSFER_LENGTH)
-   {
-      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
-      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
-      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
-      default: nRc = 0;
-   }
+	default:
+		val.f = fpa11->fpreg[Fn].fSingle;
+	}
+
+	put_user(val.i[0], pMem);
+}
+
+static inline void storeDouble(const unsigned int Fn, unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	union {
+		float64 f;
+		unsigned int i[2];
+	} val;
+
+	switch (fpa11->fType[Fn]) {
+	case typeSingle:
+		val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+		break;
+#endif
 
-   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
-   return nRc;
+	default:
+		val.f = fpa11->fpreg[Fn].fDouble;
+	}
+
+	put_user(val.i[1], &pMem[0]);	/* msw */
+	put_user(val.i[0], &pMem[1]);	/* lsw */
+}
+
+#ifdef CONFIG_FPE_NWFPE_XP
+static inline void storeExtended(const unsigned int Fn, unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	union {
+		floatx80 f;
+		unsigned int i[3];
+	} val;
+
+	switch (fpa11->fType[Fn]) {
+	case typeSingle:
+		val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
+		break;
+
+	case typeDouble:
+		val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
+		break;
+
+	default:
+		val.f = fpa11->fpreg[Fn].fExtended;
+	}
+
+	put_user(val.i[0], &pMem[0]);	/* sign & exp */
+	put_user(val.i[1], &pMem[2]);
+	put_user(val.i[2], &pMem[1]);	/* msw */
 }
+#endif
 
-unsigned int PerformSTF(const unsigned int opcode)
+static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem)
+{
+	FPA11 *fpa11 = GET_FPA11();
+	register unsigned int nType, *p;
+
+	p = (unsigned int *) &(fpa11->fpreg[Fn]);
+	nType = fpa11->fType[Fn];
+
+	switch (nType) {
+	case typeSingle:
+	case typeDouble:
+		{
+			put_user(p[0], &pMem[2]);	/* single */
+			put_user(p[1], &pMem[1]);	/* double msw */
+			put_user(nType << 14, &pMem[0]);
+		}
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		{
+			put_user(p[2], &pMem[1]);	/* msw */
+			put_user(p[1], &pMem[2]);
+			put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
+		}
+		break;
+#endif
+	}
+}
+
+unsigned int PerformLDF(const unsigned int opcode)
 {
-   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
-     write_back = WRITE_BACK(opcode);
+	unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
+	    write_back = WRITE_BACK(opcode);
+
+	pBase = (unsigned int *) readRegister(getRn(opcode));
+	if (REG_PC == getRn(opcode)) {
+		pBase += 2;
+		write_back = 0;
+	}
+
+	pFinal = pBase;
+	if (BIT_UP_SET(opcode))
+		pFinal += getOffset(opcode);
+	else
+		pFinal -= getOffset(opcode);
+
+	if (PREINDEXED(opcode))
+		pAddress = pFinal;
+	else
+		pAddress = pBase;
+
+	switch (opcode & MASK_TRANSFER_LENGTH) {
+	case TRANSFER_SINGLE:
+		loadSingle(getFd(opcode), pAddress);
+		break;
+	case TRANSFER_DOUBLE:
+		loadDouble(getFd(opcode), pAddress);
+		break;
+#ifdef CONFIG_FPE_NWFPE_XP
+	case TRANSFER_EXTENDED:
+		loadExtended(getFd(opcode), pAddress);
+		break;
+#endif
+	default:
+		nRc = 0;
+	}
+
+	if (write_back)
+		writeRegister(getRn(opcode), (unsigned int) pFinal);
+	return nRc;
+}
 
-   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
-   SetRoundingMode(ROUND_TO_NEAREST);
+unsigned int PerformSTF(const unsigned int opcode)
+{
+	unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
+	    write_back = WRITE_BACK(opcode);
 
-   pBase = (unsigned int*)readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
-   {
-     pBase += 2;
-     write_back = 0;
-   }
-
-   pFinal = pBase;
-   if (BIT_UP_SET(opcode))
-     pFinal += getOffset(opcode);
-   else
-     pFinal -= getOffset(opcode);
-
-   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
-
-   switch (opcode & MASK_TRANSFER_LENGTH)
-   {
-      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
-      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
-      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
-      default: nRc = 0;
-   }
+	SetRoundingMode(ROUND_TO_NEAREST);
 
-   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
-   return nRc;
+	pBase = (unsigned int *) readRegister(getRn(opcode));
+	if (REG_PC == getRn(opcode)) {
+		pBase += 2;
+		write_back = 0;
+	}
+
+	pFinal = pBase;
+	if (BIT_UP_SET(opcode))
+		pFinal += getOffset(opcode);
+	else
+		pFinal -= getOffset(opcode);
+
+	if (PREINDEXED(opcode))
+		pAddress = pFinal;
+	else
+		pAddress = pBase;
+
+	switch (opcode & MASK_TRANSFER_LENGTH) {
+	case TRANSFER_SINGLE:
+		storeSingle(getFd(opcode), pAddress);
+		break;
+	case TRANSFER_DOUBLE:
+		storeDouble(getFd(opcode), pAddress);
+		break;
+#ifdef CONFIG_FPE_NWFPE_XP
+	case TRANSFER_EXTENDED:
+		storeExtended(getFd(opcode), pAddress);
+		break;
+#endif
+	default:
+		nRc = 0;
+	}
+
+	if (write_back)
+		writeRegister(getRn(opcode), (unsigned int) pFinal);
+	return nRc;
 }
 
 unsigned int PerformLFM(const unsigned int opcode)
 {
-   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
-     write_back = WRITE_BACK(opcode);
+	unsigned int i, Fd, *pBase, *pAddress, *pFinal,
+	    write_back = WRITE_BACK(opcode);
 
-   pBase = (unsigned int*)readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
-   {
-     pBase += 2;
-     write_back = 0;
-   }
-
-   pFinal = pBase;
-   if (BIT_UP_SET(opcode))
-     pFinal += getOffset(opcode);
-   else
-     pFinal -= getOffset(opcode);
-
-   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
-
-   Fd = getFd(opcode);
-   for (i=getRegisterCount(opcode);i>0;i--)
-   {
-     loadMultiple(Fd,pAddress);
-     pAddress += 3; Fd++;
-     if (Fd == 8) Fd = 0;
-   }
-
-   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
-   return 1;
+	pBase = (unsigned int *) readRegister(getRn(opcode));
+	if (REG_PC == getRn(opcode)) {
+		pBase += 2;
+		write_back = 0;
+	}
+
+	pFinal = pBase;
+	if (BIT_UP_SET(opcode))
+		pFinal += getOffset(opcode);
+	else
+		pFinal -= getOffset(opcode);
+
+	if (PREINDEXED(opcode))
+		pAddress = pFinal;
+	else
+		pAddress = pBase;
+
+	Fd = getFd(opcode);
+	for (i = getRegisterCount(opcode); i > 0; i--) {
+		loadMultiple(Fd, pAddress);
+		pAddress += 3;
+		Fd++;
+		if (Fd == 8)
+			Fd = 0;
+	}
+
+	if (write_back)
+		writeRegister(getRn(opcode), (unsigned int) pFinal);
+	return 1;
 }
 
 unsigned int PerformSFM(const unsigned int opcode)
 {
-   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
-     write_back = WRITE_BACK(opcode);
-
-   pBase = (unsigned int*)readRegister(getRn(opcode));
-   if (REG_PC == getRn(opcode))
-   {
-     pBase += 2;
-     write_back = 0;
-   }
-
-   pFinal = pBase;
-   if (BIT_UP_SET(opcode))
-     pFinal += getOffset(opcode);
-   else
-     pFinal -= getOffset(opcode);
-
-   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
-
-   Fd = getFd(opcode);
-   for (i=getRegisterCount(opcode);i>0;i--)
-   {
-     storeMultiple(Fd,pAddress);
-     pAddress += 3; Fd++;
-     if (Fd == 8) Fd = 0;
-   }
+	unsigned int i, Fd, *pBase, *pAddress, *pFinal,
+	    write_back = WRITE_BACK(opcode);
 
-   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
-   return 1;
+	pBase = (unsigned int *) readRegister(getRn(opcode));
+	if (REG_PC == getRn(opcode)) {
+		pBase += 2;
+		write_back = 0;
+	}
+
+	pFinal = pBase;
+	if (BIT_UP_SET(opcode))
+		pFinal += getOffset(opcode);
+	else
+		pFinal -= getOffset(opcode);
+
+	if (PREINDEXED(opcode))
+		pAddress = pFinal;
+	else
+		pAddress = pBase;
+
+	Fd = getFd(opcode);
+	for (i = getRegisterCount(opcode); i > 0; i--) {
+		storeMultiple(Fd, pAddress);
+		pAddress += 3;
+		Fd++;
+		if (Fd == 8)
+			Fd = 0;
+	}
+
+	if (write_back)
+		writeRegister(getRn(opcode), (unsigned int) pFinal);
+	return 1;
 }
 
-#if 1
 unsigned int EmulateCPDT(const unsigned int opcode)
 {
-  unsigned int nRc = 0;
+	unsigned int nRc = 0;
 
-  //printk("EmulateCPDT(0x%08x)\n",opcode);
+	if (LDF_OP(opcode)) {
+		nRc = PerformLDF(opcode);
+	} else if (LFM_OP(opcode)) {
+		nRc = PerformLFM(opcode);
+	} else if (STF_OP(opcode)) {
+		nRc = PerformSTF(opcode);
+	} else if (SFM_OP(opcode)) {
+		nRc = PerformSFM(opcode);
+	} else {
+		nRc = 0;
+	}
 
-  if (LDF_OP(opcode))
-  {
-    nRc = PerformLDF(opcode);
-  }
-  else if (LFM_OP(opcode))
-  {
-    nRc = PerformLFM(opcode);
-  }
-  else if (STF_OP(opcode))
-  {
-    nRc = PerformSTF(opcode);
-  }
-  else if (SFM_OP(opcode))
-  {
-    nRc = PerformSFM(opcode);
-  }
-  else
-  {
-    nRc = 0;
-  }
-
-  return nRc;
+	return nRc;
 }
-#endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cprt.c linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cprt.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpa11_cprt.c	2003-04-19 19:50:08.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpa11_cprt.c	2003-04-29 04:36:57.000000000 -0700
@@ -1,7 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.COM, 1998,1999
-    (c) Philip Blundell, 1999
+    (c) Philip Blundell, 1999, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -21,269 +21,348 @@
 */
 
 #include "fpa11.h"
-#include "milieu.h"
-#include "softfloat.h"
 #include "fpopcode.h"
 #include "fpa11.inl"
 #include "fpmodule.h"
 #include "fpmodule.inl"
 
+#ifdef CONFIG_FPE_NWFPE_XP
 extern flag floatx80_is_nan(floatx80);
-extern flag float64_is_nan( float64);
-extern flag float32_is_nan( float32);
+#endif
+extern flag float64_is_nan(float64);
+extern flag float32_is_nan(float32);
 
 void SetRoundingMode(const unsigned int opcode);
 
 unsigned int PerformFLT(const unsigned int opcode);
 unsigned int PerformFIX(const unsigned int opcode);
 
-static unsigned int
-PerformComparison(const unsigned int opcode);
+static unsigned int PerformComparison(const unsigned int opcode);
 
 unsigned int EmulateCPRT(const unsigned int opcode)
 {
-  unsigned int nRc = 1;
-
-  //printk("EmulateCPRT(0x%08x)\n",opcode);
 
-  if (opcode & 0x800000)
-  {
-     /* This is some variant of a comparison (PerformComparison will
-	sort out which one).  Since most of the other CPRT
-	instructions are oddball cases of some sort or other it makes
-	sense to pull this out into a fast path.  */
-     return PerformComparison(opcode);
-  }
-
-  /* Hint to GCC that we'd like a jump table rather than a load of CMPs */
-  switch ((opcode & 0x700000) >> 20)
-  {
-    case  FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
-    case  FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
-    
-    case  WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
-    case  RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
-
-#if 0    /* We currently have no use for the FPCR, so there's no point
-	    in emulating it. */
-    case  WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
-    case  RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
-#endif
+	if (opcode & 0x800000) {
+		/* This is some variant of a comparison (PerformComparison
+		   will sort out which one).  Since most of the other CPRT
+		   instructions are oddball cases of some sort or other it
+		   makes sense to pull this out into a fast path.  */
+		return PerformComparison(opcode);
+	}
+
+	/* Hint to GCC that we'd like a jump table rather than a load of CMPs */
+	switch ((opcode & 0x700000) >> 20) {
+	case FLT_CODE >> 20:
+		return PerformFLT(opcode);
+		break;
+	case FIX_CODE >> 20:
+		return PerformFIX(opcode);
+		break;
+
+	case WFS_CODE >> 20:
+		writeFPSR(readRegister(getRd(opcode)));
+		break;
+	case RFS_CODE >> 20:
+		writeRegister(getRd(opcode), readFPSR());
+		break;
+
+	default:
+		return 0;
+	}
 
-    default: nRc = 0;
-  }
-  
-  return nRc;
+	return 1;
 }
 
 unsigned int PerformFLT(const unsigned int opcode)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   
-   unsigned int nRc = 1;
-   SetRoundingMode(opcode);
-
-   switch (opcode & MASK_ROUNDING_PRECISION)
-   {
-      case ROUND_SINGLE:
-      {
-        fpa11->fType[getFn(opcode)] = typeSingle;
-        fpa11->fpreg[getFn(opcode)].fSingle =
-	   int32_to_float32(readRegister(getRd(opcode)));
-      }
-      break;
-
-      case ROUND_DOUBLE:
-      {
-        fpa11->fType[getFn(opcode)] = typeDouble;
-        fpa11->fpreg[getFn(opcode)].fDouble =
-            int32_to_float64(readRegister(getRd(opcode)));
-      }
-      break;
-        
-      case ROUND_EXTENDED:
-      {
-        fpa11->fType[getFn(opcode)] = typeExtended;
-        fpa11->fpreg[getFn(opcode)].fExtended =
-	   int32_to_floatx80(readRegister(getRd(opcode)));
-      }
-      break;
-      
-      default: nRc = 0;
-  }
-  
-  return nRc;
+	FPA11 *fpa11 = GET_FPA11();
+	SetRoundingMode(opcode);
+	SetRoundingPrecision(opcode);
+
+	switch (opcode & MASK_ROUNDING_PRECISION) {
+	case ROUND_SINGLE:
+		{
+			fpa11->fType[getFn(opcode)] = typeSingle;
+			fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
+		}
+		break;
+
+	case ROUND_DOUBLE:
+		{
+			fpa11->fType[getFn(opcode)] = typeDouble;
+			fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode)));
+		}
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case ROUND_EXTENDED:
+		{
+			fpa11->fType[getFn(opcode)] = typeExtended;
+			fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode)));
+		}
+		break;
+#endif
+
+	default:
+		return 0;
+	}
+
+	return 1;
 }
 
 unsigned int PerformFIX(const unsigned int opcode)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   unsigned int nRc = 1;
-   unsigned int Fn = getFm(opcode);
-   
-   SetRoundingMode(opcode);
-
-   switch (fpa11->fType[Fn])
-   {
-      case typeSingle:
-      {
-         writeRegister(getRd(opcode),
-	               float32_to_int32(fpa11->fpreg[Fn].fSingle));
-      }
-      break;
-
-      case typeDouble:
-      {
-         writeRegister(getRd(opcode),
-	               float64_to_int32(fpa11->fpreg[Fn].fDouble));
-      }
-      break;
-      	               
-      case typeExtended:
-      {
-         writeRegister(getRd(opcode),
-	               floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
-      }
-      break;
-      
-      default: nRc = 0;
-  }
-  
-  return nRc;
-}
+	FPA11 *fpa11 = GET_FPA11();
+	unsigned int Fn = getFm(opcode);
 
-   
-static unsigned int __inline__
-PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
-{
-   unsigned int flags = 0;
+	SetRoundingMode(opcode);
 
-   /* test for less than condition */
-   if (floatx80_lt(Fn,Fm))
-   {
-      flags |= CC_NEGATIVE;
-   }
-  
-   /* test for equal condition */
-   if (floatx80_eq(Fn,Fm))
-   {
-      flags |= CC_ZERO;
-   }
-
-   /* test for greater than or equal condition */
-   if (floatx80_lt(Fm,Fn))
-   {
-      flags |= CC_CARRY;
-   }
-   
-   writeConditionCodes(flags);
-   return 1;
+	switch (fpa11->fType[Fn]) {
+	case typeSingle:
+		{
+			writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
+		}
+		break;
+
+	case typeDouble:
+		{
+			writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
+		}
+		break;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	case typeExtended:
+		{
+			writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
+		}
+		break;
+#endif
+
+	default:
+		return 0;
+	}
+
+	return 1;
 }
 
 /* This instruction sets the flags N, Z, C, V in the FPSR. */
-   
 static unsigned int PerformComparison(const unsigned int opcode)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   unsigned int Fn, Fm;
-   floatx80 rFn, rFm;
-   int e_flag = opcode & 0x400000;	/* 1 if CxFE */
-   int n_flag = opcode & 0x200000;	/* 1 if CNxx */
-   unsigned int flags = 0;
-
-   //printk("PerformComparison(0x%08x)\n",opcode);
-
-   Fn = getFn(opcode);
-   Fm = getFm(opcode);
-
-   /* Check for unordered condition and convert all operands to 80-bit
-      format.
-      ?? Might be some mileage in avoiding this conversion if possible.
-      Eg, if both operands are 32-bit, detect this and do a 32-bit
-      comparison (cheaper than an 80-bit one).  */
-   switch (fpa11->fType[Fn])
-   {
-      case typeSingle: 
-        //printk("single.\n");
-	if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
-	   goto unordered;
-        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
-      break;
-
-      case typeDouble: 
-        //printk("double.\n");
-	if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
-	   goto unordered;
-        rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
-      break;
-      
-      case typeExtended: 
-        //printk("extended.\n");
-	if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
-	   goto unordered;
-        rFn = fpa11->fpreg[Fn].fExtended;
-      break;
-      
-      default: return 0;
-   }
-
-   if (CONSTANT_FM(opcode))
-   {
-     //printk("Fm is a constant: #%d.\n",Fm);
-     rFm = getExtendedConstant(Fm);
-     if (floatx80_is_nan(rFm))
-        goto unordered;
-   }
-   else
-   {
-     //printk("Fm = r%d which contains a ",Fm);
-      switch (fpa11->fType[Fm])
-      {
-         case typeSingle: 
-           //printk("single.\n");
-	   if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
-	      goto unordered;
-           rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
-         break;
-
-         case typeDouble: 
-           //printk("double.\n");
-	   if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
-	      goto unordered;
-           rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
-         break;
-      
-         case typeExtended: 
-           //printk("extended.\n");
-	   if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
-	      goto unordered;
-           rFm = fpa11->fpreg[Fm].fExtended;
-         break;
-      
-         default: return 0;
-      }
-   }
-
-   if (n_flag)
-   {
-      rFm.high ^= 0x8000;
-   }
-
-   return PerformComparisonOperation(rFn,rFm);
-
- unordered:
-   /* ?? The FPA data sheet is pretty vague about this, in particular
-      about whether the non-E comparisons can ever raise exceptions.
-      This implementation is based on a combination of what it says in
-      the data sheet, observation of how the Acorn emulator actually
-      behaves (and how programs expect it to) and guesswork.  */
-   flags |= CC_OVERFLOW;
-   flags &= ~(CC_ZERO | CC_NEGATIVE);
+	FPA11 *fpa11 = GET_FPA11();
+	unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
+	int e_flag = opcode & 0x400000;	/* 1 if CxFE */
+	int n_flag = opcode & 0x200000;	/* 1 if CNxx */
+	unsigned int flags = 0;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+	floatx80 rFn, rFm;
+
+	/* Check for unordered condition and convert all operands to 80-bit
+	   format.
+	   ?? Might be some mileage in avoiding this conversion if possible.
+	   Eg, if both operands are 32-bit, detect this and do a 32-bit
+	   comparison (cheaper than an 80-bit one).  */
+	switch (fpa11->fType[Fn]) {
+	case typeSingle:
+		//printk("single.\n");
+		if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
+			goto unordered;
+		rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
+		break;
+
+	case typeDouble:
+		//printk("double.\n");
+		if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
+			goto unordered;
+		rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
+		break;
+
+	case typeExtended:
+		//printk("extended.\n");
+		if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
+			goto unordered;
+		rFn = fpa11->fpreg[Fn].fExtended;
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (CONSTANT_FM(opcode)) {
+		//printk("Fm is a constant: #%d.\n",Fm);
+		rFm = getExtendedConstant(Fm);
+		if (floatx80_is_nan(rFm))
+			goto unordered;
+	} else {
+		//printk("Fm = r%d which contains a ",Fm);
+		switch (fpa11->fType[Fm]) {
+		case typeSingle:
+			//printk("single.\n");
+			if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
+				goto unordered;
+			rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
+			break;
+
+		case typeDouble:
+			//printk("double.\n");
+			if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
+				goto unordered;
+			rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
+			break;
+
+		case typeExtended:
+			//printk("extended.\n");
+			if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
+				goto unordered;
+			rFm = fpa11->fpreg[Fm].fExtended;
+			break;
+
+		default:
+			return 0;
+		}
+	}
+
+	if (n_flag)
+		rFm.high ^= 0x8000;
+
+	/* test for less than condition */
+	if (floatx80_lt(rFn, rFm))
+		flags |= CC_NEGATIVE;
+
+	/* test for equal condition */
+	if (floatx80_eq(rFn, rFm))
+		flags |= CC_ZERO;
+
+	/* test for greater than or equal condition */
+	if (floatx80_lt(rFm, rFn))
+		flags |= CC_CARRY;
+
+#else
+	if (CONSTANT_FM(opcode)) {
+		/* Fm is a constant.  Do the comparison in whatever precision
+		   Fn happens to be stored in.  */
+		if (fpa11->fType[Fn] == typeSingle) {
+			float32 rFm = getSingleConstant(Fm);
+			float32 rFn = fpa11->fpreg[Fn].fSingle;
+
+			if (float32_is_nan(rFn))
+				goto unordered;
+
+			if (n_flag)
+				rFm ^= 0x80000000;
+
+			/* test for less than condition */
+			if (float32_lt_nocheck(rFn, rFm))
+				flags |= CC_NEGATIVE;
+
+			/* test for equal condition */
+			if (float32_eq_nocheck(rFn, rFm))
+				flags |= CC_ZERO;
+
+			/* test for greater than or equal condition */
+			if (float32_lt_nocheck(rFm, rFn))
+				flags |= CC_CARRY;
+		} else {
+			float64 rFm = getDoubleConstant(Fm);
+			float64 rFn = fpa11->fpreg[Fn].fDouble;
+
+			if (float64_is_nan(rFn))
+				goto unordered;
+
+			if (n_flag)
+				rFm ^= 0x8000000000000000ULL;
+
+			/* test for less than condition */
+			if (float64_lt_nocheck(rFn, rFm))
+				flags |= CC_NEGATIVE;
+
+			/* test for equal condition */
+			if (float64_eq_nocheck(rFn, rFm))
+				flags |= CC_ZERO;
+
+			/* test for greater than or equal condition */
+			if (float64_lt_nocheck(rFm, rFn))
+				flags |= CC_CARRY;
+		}
+	} else {
+		/* Both operands are in registers.  */
+		if (fpa11->fType[Fn] == typeSingle
+		    && fpa11->fType[Fm] == typeSingle) {
+			float32 rFm = fpa11->fpreg[Fm].fSingle;
+			float32 rFn = fpa11->fpreg[Fn].fSingle;
+
+			if (float32_is_nan(rFn)
+			    || float32_is_nan(rFm))
+				goto unordered;
+
+			if (n_flag)
+				rFm ^= 0x80000000;
+
+			/* test for less than condition */
+			if (float32_lt_nocheck(rFn, rFm))
+				flags |= CC_NEGATIVE;
+
+			/* test for equal condition */
+			if (float32_eq_nocheck(rFn, rFm))
+				flags |= CC_ZERO;
+
+			/* test for greater than or equal condition */
+			if (float32_lt_nocheck(rFm, rFn))
+				flags |= CC_CARRY;
+		} else {
+			/* Promote 32-bit operand to 64 bits.  */
+			float64 rFm, rFn;
+
+			rFm = (fpa11->fType[Fm] == typeSingle) ?
+			    float32_to_float64(fpa11->fpreg[Fm].fSingle)
+			    : fpa11->fpreg[Fm].fDouble;
+
+			rFn = (fpa11->fType[Fn] == typeSingle) ?
+			    float32_to_float64(fpa11->fpreg[Fn].fSingle)
+			    : fpa11->fpreg[Fn].fDouble;
+
+			if (float64_is_nan(rFn)
+			    || float64_is_nan(rFm))
+				goto unordered;
+
+			if (n_flag)
+				rFm ^= 0x8000000000000000ULL;
+
+			/* test for less than condition */
+			if (float64_lt_nocheck(rFn, rFm))
+				flags |= CC_NEGATIVE;
+
+			/* test for equal condition */
+			if (float64_eq_nocheck(rFn, rFm))
+				flags |= CC_ZERO;
+
+			/* test for greater than or equal condition */
+			if (float64_lt_nocheck(rFm, rFn))
+				flags |= CC_CARRY;
+		}
+	}
+
+#endif
+
+	writeConditionCodes(flags);
+
+	return 1;
+
+      unordered:
+	/* ?? The FPA data sheet is pretty vague about this, in particular
+	   about whether the non-E comparisons can ever raise exceptions.
+	   This implementation is based on a combination of what it says in
+	   the data sheet, observation of how the Acorn emulator actually
+	   behaves (and how programs expect it to) and guesswork.  */
+	flags |= CC_OVERFLOW;
+	flags &= ~(CC_ZERO | CC_NEGATIVE);
 
-   if (BIT_AC & readFPSR()) flags |= CC_CARRY;
+	if (BIT_AC & readFPSR())
+		flags |= CC_CARRY;
 
-   if (e_flag) float_raise(float_flag_invalid);
+	if (e_flag)
+		float_raise(float_flag_invalid);
 
-   writeConditionCodes(flags);
-   return 1;
+	writeConditionCodes(flags);
+	return 1;
 }
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpmodule.c linux-2.5.68-bk9/arch/arm/nwfpe/fpmodule.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpmodule.c	2003-04-19 19:49:21.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpmodule.c	2003-04-29 04:36:57.000000000 -0700
@@ -42,11 +42,17 @@
 #include "fpa11.inl"
 
 /* kernel symbols required for signal handling */
+#ifdef CONFIG_FPE_NWFPE_XP
+#define NWFPE_BITS "extended"
+#else
+#define NWFPE_BITS "double"
+#endif
+
 #ifdef MODULE
 void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
 #if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
-MODULE_DESCRIPTION("NWFPE floating point emulator");
+MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)");
 #endif
 
 #else
@@ -63,63 +69,45 @@
 extern void (*kern_fp_enter)(void);
 extern void (*fp_init)(union fp_state *);
 
-/* Original value of fp_enter from kernel before patched by fpe_init. */ 
+/* Original value of fp_enter from kernel before patched by fpe_init. */
 static void (*orig_fp_enter)(void);
 static void (*orig_fp_init)(union fp_state *);
 
 /* forward declarations */
 extern void nwfpe_enter(void);
 
-#ifdef MODULE
-/*
- * Return 0 if we can be unloaded.  This can only happen if
- * kern_fp_enter is still pointing at nwfpe_enter
- */
-static int fpe_unload(void)
-{
-  return (kern_fp_enter == nwfpe_enter) ? 0 : 1;
-}
-#endif
-
 static int __init fpe_init(void)
 {
-  if (sizeof(FPA11) > sizeof(union fp_state)) {
-    printk(KERN_ERR "nwfpe: bad structure size\n");
-    return -EINVAL;
-  }
-
-  if (sizeof(FPREG) != 12) {
-    printk(KERN_ERR "nwfpe: bad register size\n");
-    return -EINVAL;
-  }
+	if (sizeof(FPA11) > sizeof(union fp_state)) {
+		printk(KERN_ERR "nwfpe: bad structure size\n");
+		return -EINVAL;
+	}
+
+	if (sizeof(FPREG) != 12) {
+		printk(KERN_ERR "nwfpe: bad register size\n");
+		return -EINVAL;
+	}
+	if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
+		return 0;
+
+	/* Display title, version and copyright information. */
+	printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
+	       NWFPE_BITS " precision)\n");
+
+	/* Save pointer to the old FP handler and then patch ourselves in */
+	orig_fp_enter = kern_fp_enter;
+	orig_fp_init = fp_init;
+	kern_fp_enter = nwfpe_enter;
+	fp_init = nwfpe_init_fpa;
 
-#ifdef MODULE
-  if (!mod_member_present(&__this_module, can_unload))
-    return -EINVAL;
-  __this_module.can_unload = fpe_unload;
-#else
-  if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
-    return 0;
-#endif
-
-  /* Display title, version and copyright information. */
-  printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
-	 "(c) 1998-1999 Rebel.com\n");
-
-  /* Save pointer to the old FP handler and then patch ourselves in */
-  orig_fp_enter = kern_fp_enter;
-  orig_fp_init = fp_init;
-  kern_fp_enter = nwfpe_enter;
-  fp_init = nwfpe_init;
-
-  return 0;
+	return 0;
 }
 
 static void __exit fpe_exit(void)
 {
-  /* Restore the values we saved earlier. */
-  kern_fp_enter = orig_fp_enter;
-  fp_init = orig_fp_init;
+	/* Restore the values we saved earlier. */
+	kern_fp_enter = orig_fp_enter;
+	fp_init = orig_fp_init;
 }
 
 /*
@@ -144,41 +132,42 @@
 
 void float_raise(signed char flags)
 {
-  register unsigned int fpsr, cumulativeTraps;
-  
+	register unsigned int fpsr, cumulativeTraps;
+
 #ifdef CONFIG_DEBUG_USER
-  printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
-	 current->comm, current->pid, flags,
-	 __builtin_return_address(0), GET_USERREG()[15]);
+	printk(KERN_DEBUG
+	       "NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
+	       current->comm, current->pid, flags,
+	       __builtin_return_address(0), GET_USERREG()[15]);
 #endif
 
-  /* Keep SoftFloat exception flags up to date.  */
-  float_exception_flags |= flags;
+	/* Keep SoftFloat exception flags up to date.  */
+	float_exception_flags |= flags;
 
-  /* Read fpsr and initialize the cumulativeTraps.  */
-  fpsr = readFPSR();
-  cumulativeTraps = 0;
-  
-  /* For each type of exception, the cumulative trap exception bit is only
-     set if the corresponding trap enable bit is not set.  */
-  if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
-     cumulativeTraps |= BIT_IXC;  
-  if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
-     cumulativeTraps |= BIT_UFC;  
-  if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
-     cumulativeTraps |= BIT_OFC;  
-  if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
-     cumulativeTraps |= BIT_DZC;  
-  if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
-     cumulativeTraps |= BIT_IOC;  
-
-  /* Set the cumulative exceptions flags.  */
-  if (cumulativeTraps)
-    writeFPSR(fpsr | cumulativeTraps);
-
-  /* Raise an exception if necessary.  */
-  if (fpsr & (flags << 16))
-    fp_send_sig(SIGFPE, current, 1);
+	/* Read fpsr and initialize the cumulativeTraps.  */
+	fpsr = readFPSR();
+	cumulativeTraps = 0;
+
+	/* For each type of exception, the cumulative trap exception bit is only
+	   set if the corresponding trap enable bit is not set.  */
+	if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
+		cumulativeTraps |= BIT_IXC;
+	if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
+		cumulativeTraps |= BIT_UFC;
+	if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
+		cumulativeTraps |= BIT_OFC;
+	if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
+		cumulativeTraps |= BIT_DZC;
+	if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
+		cumulativeTraps |= BIT_IOC;
+
+	/* Set the cumulative exceptions flags.  */
+	if (cumulativeTraps)
+		writeFPSR(fpsr | cumulativeTraps);
+
+	/* Raise an exception if necessary.  */
+	if (fpsr & (flags << 16))
+		fp_send_sig(SIGFPE, current, 1);
 }
 
 module_init(fpe_init);
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpmodule.inl linux-2.5.68-bk9/arch/arm/nwfpe/fpmodule.inl
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpmodule.inl	2003-04-19 19:51:08.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpmodule.inl	2003-04-29 04:36:57.000000000 -0700
@@ -22,63 +22,64 @@
 extern __inline__
 unsigned int readRegister(const unsigned int nReg)
 {
-  /* Note: The CPU thinks it has dealt with the current instruction.  As
-           a result the program counter has been advanced to the next
-           instruction, and points 4 bytes beyond the actual instruction
-           that caused the invalid instruction trap to occur.  We adjust
-           for this in this routine.  LDF/STF instructions with Rn = PC
-           depend on the PC being correct, as they use PC+8 in their 
-           address calculations. */
-  unsigned int *userRegisters = GET_USERREG();
-  unsigned int val = userRegisters[nReg];
-  if (REG_PC == nReg) val -= 4;
-  return val;
+	/* Note: The CPU thinks it has dealt with the current instruction.
+	   As a result the program counter has been advanced to the next
+	   instruction, and points 4 bytes beyond the actual instruction
+	   that caused the invalid instruction trap to occur.  We adjust
+	   for this in this routine.  LDF/STF instructions with Rn = PC
+	   depend on the PC being correct, as they use PC+8 in their
+	   address calculations. */
+	unsigned int *userRegisters = GET_USERREG();
+	unsigned int val = userRegisters[nReg];
+	if (REG_PC == nReg)
+		val -= 4;
+	return val;
 }
 
 extern __inline__
 void writeRegister(const unsigned int nReg, const unsigned int val)
 {
-  unsigned int *userRegisters = GET_USERREG();
-  userRegisters[nReg] = val;
+	unsigned int *userRegisters = GET_USERREG();
+	userRegisters[nReg] = val;
 }
 
 extern __inline__
 unsigned int readCPSR(void)
 {
-  return(readRegister(REG_CPSR));
+	return (readRegister(REG_CPSR));
 }
 
 extern __inline__
 void writeCPSR(const unsigned int val)
 {
-  writeRegister(REG_CPSR,val);
+	writeRegister(REG_CPSR, val);
 }
 
 extern __inline__
 unsigned int readConditionCodes(void)
 {
 #ifdef __FPEM_TEST__
-   return(0);
+	return (0);
 #else
-   return(readCPSR() & CC_MASK);
+	return (readCPSR() & CC_MASK);
 #endif
 }
 
 extern __inline__
 void writeConditionCodes(const unsigned int val)
 {
-  unsigned int *userRegisters = GET_USERREG();
-  unsigned int rval;
-  /*
-   * Operate directly on userRegisters since
-   * the CPSR may be the PC register itself.
-   */
-  rval = userRegisters[REG_CPSR] & ~CC_MASK;
-  userRegisters[REG_CPSR] = rval | (val & CC_MASK);
+	unsigned int *userRegisters = GET_USERREG();
+	unsigned int rval;
+	/*
+	 * Operate directly on userRegisters since
+	 * the CPSR may be the PC register itself.
+	 */
+	rval = userRegisters[REG_CPSR] & ~CC_MASK;
+	userRegisters[REG_CPSR] = rval | (val & CC_MASK);
 }
 
 extern __inline__
 unsigned int readMemoryInt(unsigned int *pMem)
 {
-  return *pMem;
+	return *pMem;
 }
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpopcode.c linux-2.5.68-bk9/arch/arm/nwfpe/fpopcode.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpopcode.c	2003-04-19 19:49:20.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpopcode.c	2003-04-29 04:36:57.000000000 -0700
@@ -26,123 +26,64 @@
 #include "fpmodule.h"
 #include "fpmodule.inl"
 
+#ifdef CONFIG_FPE_NWFPE_XP
 const floatx80 floatx80Constant[] = {
-  { 0x0000, 0x0000000000000000ULL},	/* extended 0.0 */
-  { 0x3fff, 0x8000000000000000ULL},	/* extended 1.0 */
-  { 0x4000, 0x8000000000000000ULL},	/* extended 2.0 */
-  { 0x4000, 0xc000000000000000ULL},	/* extended 3.0 */
-  { 0x4001, 0x8000000000000000ULL},	/* extended 4.0 */
-  { 0x4001, 0xa000000000000000ULL},	/* extended 5.0 */
-  { 0x3ffe, 0x8000000000000000ULL},	/* extended 0.5 */
-  { 0x4002, 0xa000000000000000ULL}	/* extended 10.0 */
-};  
+	{0x0000, 0x0000000000000000ULL},	/* extended 0.0 */
+	{0x3fff, 0x8000000000000000ULL},	/* extended 1.0 */
+	{0x4000, 0x8000000000000000ULL},	/* extended 2.0 */
+	{0x4000, 0xc000000000000000ULL},	/* extended 3.0 */
+	{0x4001, 0x8000000000000000ULL},	/* extended 4.0 */
+	{0x4001, 0xa000000000000000ULL},	/* extended 5.0 */
+	{0x3ffe, 0x8000000000000000ULL},	/* extended 0.5 */
+	{0x4002, 0xa000000000000000ULL}		/* extended 10.0 */
+};
+#endif
 
 const float64 float64Constant[] = {
-  0x0000000000000000ULL,		/* double 0.0 */
-  0x3ff0000000000000ULL,		/* double 1.0 */
-  0x4000000000000000ULL,		/* double 2.0 */
-  0x4008000000000000ULL,		/* double 3.0 */
-  0x4010000000000000ULL,		/* double 4.0 */
-  0x4014000000000000ULL,		/* double 5.0 */
-  0x3fe0000000000000ULL,		/* double 0.5 */
-  0x4024000000000000ULL			/* double 10.0 */
-};  
+	0x0000000000000000ULL,	/* double 0.0 */
+	0x3ff0000000000000ULL,	/* double 1.0 */
+	0x4000000000000000ULL,	/* double 2.0 */
+	0x4008000000000000ULL,	/* double 3.0 */
+	0x4010000000000000ULL,	/* double 4.0 */
+	0x4014000000000000ULL,	/* double 5.0 */
+	0x3fe0000000000000ULL,	/* double 0.5 */
+	0x4024000000000000ULL	/* double 10.0 */
+};
 
 const float32 float32Constant[] = {
-  0x00000000,				/* single 0.0 */
-  0x3f800000,				/* single 1.0 */
-  0x40000000,				/* single 2.0 */
-  0x40400000,				/* single 3.0 */
-  0x40800000,				/* single 4.0 */
-  0x40a00000,				/* single 5.0 */
-  0x3f000000,				/* single 0.5 */
-  0x41200000				/* single 10.0 */
-};  
-
-unsigned int getTransferLength(const unsigned int opcode)
-{
-  unsigned int nRc;
-  
-  switch (opcode & MASK_TRANSFER_LENGTH)
-  {
-    case 0x00000000: nRc = 1; break; /* single precision */
-    case 0x00008000: nRc = 2; break; /* double precision */
-    case 0x00400000: nRc = 3; break; /* extended precision */
-    default: nRc = 0;
-  }
-  
-  return(nRc);
-}
-
-unsigned int getRegisterCount(const unsigned int opcode)
-{
-  unsigned int nRc;
-  
-  switch (opcode & MASK_REGISTER_COUNT)
-  {
-    case 0x00000000: nRc = 4; break;
-    case 0x00008000: nRc = 1; break;
-    case 0x00400000: nRc = 2; break;
-    case 0x00408000: nRc = 3; break;
-    default: nRc = 0;
-  }
-  
-  return(nRc);
-}
-
-unsigned int getRoundingPrecision(const unsigned int opcode)
-{
-  unsigned int nRc;
-  
-  switch (opcode & MASK_ROUNDING_PRECISION)
-  {
-    case 0x00000000: nRc = 1; break;
-    case 0x00000080: nRc = 2; break;
-    case 0x00080000: nRc = 3; break;
-    default: nRc = 0;
-  }
-  
-  return(nRc);
-}
-
-unsigned int getDestinationSize(const unsigned int opcode)
-{
-  unsigned int nRc;
-  
-  switch (opcode & MASK_DESTINATION_SIZE)
-  {
-    case 0x00000000: nRc = typeSingle; break;
-    case 0x00000080: nRc = typeDouble; break;
-    case 0x00080000: nRc = typeExtended; break;
-    default: nRc = typeNone;
-  }
-  
-  return(nRc);
-}
+	0x00000000,		/* single 0.0 */
+	0x3f800000,		/* single 1.0 */
+	0x40000000,		/* single 2.0 */
+	0x40400000,		/* single 3.0 */
+	0x40800000,		/* single 4.0 */
+	0x40a00000,		/* single 5.0 */
+	0x3f000000,		/* single 0.5 */
+	0x41200000		/* single 10.0 */
+};
 
 /* condition code lookup table
  index into the table is test code: EQ, NE, ... LT, GT, AL, NV
  bit position in short is condition code: NZCV */
 static const unsigned short aCC[16] = {
-    0xF0F0, // EQ == Z set
-    0x0F0F, // NE
-    0xCCCC, // CS == C set
-    0x3333, // CC
-    0xFF00, // MI == N set
-    0x00FF, // PL
-    0xAAAA, // VS == V set
-    0x5555, // VC
-    0x0C0C, // HI == C set && Z clear
-    0xF3F3, // LS == C clear || Z set
-    0xAA55, // GE == (N==V)
-    0x55AA, // LT == (N!=V)
-    0x0A05, // GT == (!Z && (N==V))
-    0xF5FA, // LE == (Z || (N!=V))
-    0xFFFF, // AL always
-    0 // NV
+	0xF0F0,			// EQ == Z set
+	0x0F0F,			// NE
+	0xCCCC,			// CS == C set
+	0x3333,			// CC
+	0xFF00,			// MI == N set
+	0x00FF,			// PL
+	0xAAAA,			// VS == V set
+	0x5555,			// VC
+	0x0C0C,			// HI == C set && Z clear
+	0xF3F3,			// LS == C clear || Z set
+	0xAA55,			// GE == (N==V)
+	0x55AA,			// LT == (N!=V)
+	0x0A05,			// GT == (!Z && (N==V))
+	0xF5FA,			// LE == (Z || (N!=V))
+	0xFFFF,			// AL always
+	0			// NV
 };
 
 unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes)
 {
-  return (aCC[opcode>>28] >> (ccodes>>28)) & 1;
+	return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1;
 }
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpopcode.h linux-2.5.68-bk9/arch/arm/nwfpe/fpopcode.h
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpopcode.h	2003-04-19 19:48:58.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpopcode.h	2003-04-29 04:36:57.000000000 -0700
@@ -1,6 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.COM, 1998,1999
+    (c) Philip Blundell, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -186,7 +187,7 @@
 #define BIT_LOAD	0x00100000
 
 /* masks for load/store */
-#define MASK_CPDT		0x0c000000  /* data processing opcode */
+#define MASK_CPDT		0x0c000000	/* data processing opcode */
 #define MASK_OFFSET		0x000000ff
 #define MASK_TRANSFER_LENGTH	0x00408000
 #define MASK_REGISTER_COUNT	MASK_TRANSFER_LENGTH
@@ -236,7 +237,7 @@
 #define MONADIC_INSTRUCTION(opcode)	((opcode & BIT_MONADIC) != 0)
 
 /* instruction identification masks */
-#define MASK_CPDO		0x0e000000  /* arithmetic opcode */
+#define MASK_CPDO		0x0e000000	/* arithmetic opcode */
 #define MASK_ARITHMETIC_OPCODE	0x00f08000
 #define MASK_DESTINATION_SIZE	0x00080080
 
@@ -282,7 +283,7 @@
 ===
 */
 
-#define MASK_CPRT		0x0e000010  /* register transfer opcode */
+#define MASK_CPRT		0x0e000010	/* register transfer opcode */
 #define MASK_CPRT_CODE		0x00f00000
 #define FLT_CODE		0x00000000
 #define FIX_CODE		0x00100000
@@ -366,25 +367,111 @@
 /* Get the rounding mode from the opcode. */
 #define getRoundingMode(opcode)		((opcode & MASK_ROUNDING_MODE) >> 5)
 
+#ifdef CONFIG_FPE_NWFPE_XP
 static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
 {
-   extern const floatx80 floatx80Constant[];
-   return floatx80Constant[nIndex];
-} 
+	extern const floatx80 floatx80Constant[];
+	return floatx80Constant[nIndex];
+}
+#endif
 
 static inline const float64 getDoubleConstant(const unsigned int nIndex)
 {
-   extern const float64 float64Constant[];
-   return float64Constant[nIndex];
-} 
+	extern const float64 float64Constant[];
+	return float64Constant[nIndex];
+}
 
 static inline const float32 getSingleConstant(const unsigned int nIndex)
 {
-   extern const float32 float32Constant[];
-   return float32Constant[nIndex];
-} 
+	extern const float32 float32Constant[];
+	return float32Constant[nIndex];
+}
+
+static inline unsigned int getTransferLength(const unsigned int opcode)
+{
+	unsigned int nRc;
+
+	switch (opcode & MASK_TRANSFER_LENGTH) {
+	case 0x00000000:
+		nRc = 1;
+		break;		/* single precision */
+	case 0x00008000:
+		nRc = 2;
+		break;		/* double precision */
+	case 0x00400000:
+		nRc = 3;
+		break;		/* extended precision */
+	default:
+		nRc = 0;
+	}
+
+	return (nRc);
+}
+
+static inline unsigned int getRegisterCount(const unsigned int opcode)
+{
+	unsigned int nRc;
+
+	switch (opcode & MASK_REGISTER_COUNT) {
+	case 0x00000000:
+		nRc = 4;
+		break;
+	case 0x00008000:
+		nRc = 1;
+		break;
+	case 0x00400000:
+		nRc = 2;
+		break;
+	case 0x00408000:
+		nRc = 3;
+		break;
+	default:
+		nRc = 0;
+	}
+
+	return (nRc);
+}
+
+static inline unsigned int getRoundingPrecision(const unsigned int opcode)
+{
+	unsigned int nRc;
+
+	switch (opcode & MASK_ROUNDING_PRECISION) {
+	case 0x00000000:
+		nRc = 1;
+		break;
+	case 0x00000080:
+		nRc = 2;
+		break;
+	case 0x00080000:
+		nRc = 3;
+		break;
+	default:
+		nRc = 0;
+	}
+
+	return (nRc);
+}
+
+static inline unsigned int getDestinationSize(const unsigned int opcode)
+{
+	unsigned int nRc;
+
+	switch (opcode & MASK_DESTINATION_SIZE) {
+	case 0x00000000:
+		nRc = typeSingle;
+		break;
+	case 0x00000080:
+		nRc = typeDouble;
+		break;
+	case 0x00080000:
+		nRc = typeExtended;
+		break;
+	default:
+		nRc = typeNone;
+	}
 
-extern unsigned int getRegisterCount(const unsigned int opcode);
-extern unsigned int getDestinationSize(const unsigned int opcode);
+	return (nRc);
+}
 
 #endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/fpsr.h linux-2.5.68-bk9/arch/arm/nwfpe/fpsr.h
--- linux-2.5.68-bk8/arch/arm/nwfpe/fpsr.h	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/fpsr.h	2003-04-29 04:36:57.000000000 -0700
@@ -38,12 +38,12 @@
 ------------
 Note: the system id byte is read only  */
 
-typedef unsigned int FPSR;  /* type for floating point status register */
-typedef unsigned int FPCR;  /* type for floating point control register */
+typedef unsigned int FPSR;	/* type for floating point status register */
+typedef unsigned int FPCR;	/* type for floating point control register */
 
 #define MASK_SYSID		0xff000000
 #define BIT_HARDWARE		0x80000000
-#define FP_EMULATOR		0x01000000	/* System ID for emulator */ 
+#define FP_EMULATOR		0x01000000	/* System ID for emulator */
 #define FP_ACCELERATOR		0x81000000	/* System ID for FPA11 */
 
 /* EXCEPTION TRAP ENABLE BYTE
@@ -51,11 +51,11 @@
 
 #define MASK_TRAP_ENABLE	0x00ff0000
 #define MASK_TRAP_ENABLE_STRICT	0x001f0000
-#define BIT_IXE		0x00100000   /* inexact exception enable */
-#define BIT_UFE		0x00080000   /* underflow exception enable */
-#define BIT_OFE		0x00040000   /* overflow exception enable */
-#define BIT_DZE		0x00020000   /* divide by zero exception enable */
-#define BIT_IOE		0x00010000   /* invalid operation exception enable */
+#define BIT_IXE		0x00100000	/* inexact exception enable */
+#define BIT_UFE		0x00080000	/* underflow exception enable */
+#define BIT_OFE		0x00040000	/* overflow exception enable */
+#define BIT_DZE		0x00020000	/* divide by zero exception enable */
+#define BIT_IOE		0x00010000	/* invalid operation exception enable */
 
 /* SYSTEM CONTROL BYTE
 ---------------------- */
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/single_cpdo.c linux-2.5.68-bk9/arch/arm/nwfpe/single_cpdo.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/single_cpdo.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/single_cpdo.c	2003-04-29 04:36:57.000000000 -0700
@@ -1,6 +1,7 @@
 /*
     NetWinder Floating Point Emulator
     (c) Rebel.COM, 1998,1999
+    (c) Philip Blundell, 2001
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -32,224 +33,92 @@
 float32 float32_log(float32 rFm);
 float32 float32_tan(float32 rFm);
 float32 float32_arccos(float32 rFm);
-float32 float32_pow(float32 rFn,float32 rFm);
-float32 float32_pol(float32 rFn,float32 rFm);
+float32 float32_pow(float32 rFn, float32 rFm);
+float32 float32_pol(float32 rFn, float32 rFm);
 
-unsigned int SingleCPDO(const unsigned int opcode)
+static float32 float32_rsf(float32 rFn, float32 rFm)
 {
-   FPA11 *fpa11 = GET_FPA11();
-   float32 rFm, rFn;
-   unsigned int Fd, Fm, Fn, nRc = 1;
-
-   Fm = getFm(opcode);
-   if (CONSTANT_FM(opcode))
-   {
-     rFm = getSingleConstant(Fm);
-   }
-   else
-   {  
-     switch (fpa11->fType[Fm])
-     {
-        case typeSingle:
-          rFm = fpa11->fpreg[Fm].fSingle;
-        break;
-        
-        default: return 0;
-     }
-   }
-
-   if (!MONADIC_INSTRUCTION(opcode))
-   {
-      Fn = getFn(opcode);
-      switch (fpa11->fType[Fn])
-      {
-        case typeSingle:
-          rFn = fpa11->fpreg[Fn].fSingle;
-        break;
-
-        default: return 0;
-      }
-   }
-
-   Fd = getFd(opcode);
-   switch (opcode & MASK_ARITHMETIC_OPCODE)
-   {
-      /* dyadic opcodes */
-      case ADF_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm);
-      break;
-
-      case MUF_CODE:
-      case FML_CODE:
-        fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm);
-      break;
-
-      case SUF_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm);
-      break;
-
-      case RSF_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn);
-      break;
-
-      case DVF_CODE:
-      case FDV_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm);
-      break;
-
-      case RDF_CODE:
-      case FRD_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn);
-      break;
-
-#if 0
-      case POW_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);
-      break;
-
-      case RPW_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);
-      break;
-#endif
-
-      case RMF_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm);
-      break;
-
-#if 0
-      case POL_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);
-      break;
-#endif
-
-      /* monadic opcodes */
-      case MVF_CODE:
-         fpa11->fpreg[Fd].fSingle = rFm;
-      break;
-
-      case MNF_CODE:
-         rFm ^= 0x80000000;
-         fpa11->fpreg[Fd].fSingle = rFm;
-      break;
-
-      case ABS_CODE:
-         rFm &= 0x7fffffff;
-         fpa11->fpreg[Fd].fSingle = rFm;
-      break;
-
-      case RND_CODE:
-      case URD_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm);
-      break;
-
-      case SQT_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm);
-      break;
-
-#if 0
-      case LOG_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_log(rFm);
-      break;
-
-      case LGN_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_ln(rFm);
-      break;
-
-      case EXP_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_exp(rFm);
-      break;
-
-      case SIN_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_sin(rFm);
-      break;
-
-      case COS_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_cos(rFm);
-      break;
-
-      case TAN_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_tan(rFm);
-      break;
-
-      case ASN_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);
-      break;
-
-      case ACS_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);
-      break;
-
-      case ATN_CODE:
-         fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);
-      break;
-#endif
-
-      case NRM_CODE:
-      break;
-      
-      default:
-      {
-        nRc = 0;
-      }
-   }
-
-   if (0 != nRc) fpa11->fType[Fd] = typeSingle;
-   return nRc;
+	return float32_sub(rFm, rFn);
 }
 
-#if 0
-float32 float32_exp(float32 Fm)
+static float32 float32_rdv(float32 rFn, float32 rFm)
 {
-//series
+	return float32_div(rFm, rFn);
 }
 
-float32 float32_ln(float32 Fm)
-{
-//series
-}
+static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
+	[ADF_CODE >> 20] = float32_add,
+	[MUF_CODE >> 20] = float32_mul,
+	[SUF_CODE >> 20] = float32_sub,
+	[RSF_CODE >> 20] = float32_rsf,
+	[DVF_CODE >> 20] = float32_div,
+	[RDF_CODE >> 20] = float32_rdv,
+	[RMF_CODE >> 20] = float32_rem,
 
-float32 float32_sin(float32 rFm)
-{
-//series
-}
+	[FML_CODE >> 20] = float32_mul,
+	[FDV_CODE >> 20] = float32_div,
+	[FRD_CODE >> 20] = float32_rdv,
+};
 
-float32 float32_cos(float32 rFm)
+static float32 float32_mvf(float32 rFm)
 {
-//series
+	return rFm;
 }
 
-float32 float32_arcsin(float32 rFm)
+static float32 float32_mnf(float32 rFm)
 {
-//series
+	return rFm ^ 0x80000000;
 }
 
-float32 float32_arctan(float32 rFm)
+static float32 float32_abs(float32 rFm)
 {
-  //series
+	return rFm & 0x7fffffff;
 }
 
-float32 float32_arccos(float32 rFm)
-{
-   //return float32_sub(halfPi,float32_arcsin(rFm));
-}
+static float32 (*const monadic_single[16])(float32 rFm) = {
+	[MVF_CODE >> 20] = float32_mvf,
+	[MNF_CODE >> 20] = float32_mnf,
+	[ABS_CODE >> 20] = float32_abs,
+	[RND_CODE >> 20] = float32_round_to_int,
+	[URD_CODE >> 20] = float32_round_to_int,
+	[SQT_CODE >> 20] = float32_sqrt,
+	[NRM_CODE >> 20] = float32_mvf,
+};
 
-float32 float32_log(float32 rFm)
+unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
 {
-  return float32_div(float32_ln(rFm),getSingleConstant(7));
-}
+	FPA11 *fpa11 = GET_FPA11();
+	float32 rFm;
+	unsigned int Fm, opc_mask_shift;
 
-float32 float32_tan(float32 rFm)
-{
-  return float32_div(float32_sin(rFm),float32_cos(rFm));
-}
+	Fm = getFm(opcode);
+	if (CONSTANT_FM(opcode)) {
+		rFm = getSingleConstant(Fm);
+	} else if (fpa11->fType[Fm] == typeSingle) {
+		rFm = fpa11->fpreg[Fm].fSingle;
+	} else {
+		return 0;
+	}
 
-float32 float32_pow(float32 rFn,float32 rFm)
-{
-  return float32_exp(float32_mul(rFm,float32_ln(rFn))); 
-}
+	opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
+	if (!MONADIC_INSTRUCTION(opcode)) {
+		unsigned int Fn = getFn(opcode);
+		float32 rFn;
 
-float32 float32_pol(float32 rFn,float32 rFm)
-{
-  return float32_arctan(float32_div(rFn,rFm)); 
+		if (fpa11->fType[Fn] == typeSingle &&
+		    dyadic_single[opc_mask_shift]) {
+			rFn = fpa11->fpreg[Fn].fSingle;
+			rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
+		} else {
+			return 0;
+		}
+	} else {
+		if (monadic_single[opc_mask_shift]) {
+			rFd->fSingle = monadic_single[opc_mask_shift](rFm);
+		} else {
+			return 0;
+		}
+	}
+
+	return 1;
 }
-#endif
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/softfloat.c linux-2.5.68-bk9/arch/arm/nwfpe/softfloat.c
--- linux-2.5.68-bk8/arch/arm/nwfpe/softfloat.c	2003-04-19 19:51:22.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/softfloat.c	2003-04-29 04:36:57.000000000 -0700
@@ -29,8 +29,8 @@
 */
 
 #include "fpa11.h"
-#include "milieu.h"
-#include "softfloat.h"
+//#include "milieu.h"
+//#include "softfloat.h"
 
 /*
 -------------------------------------------------------------------------------
@@ -142,12 +142,14 @@
 Returns the sign bit of the single-precision floating-point value `a'.
 -------------------------------------------------------------------------------
 */
+#if 0	/* in softfloat.h */
 INLINE flag extractFloat32Sign( float32 a )
 {
 
     return a>>31;
 
 }
+#endif
 
 /*
 -------------------------------------------------------------------------------
@@ -184,9 +186,9 @@
 {
 #if 0
    float32 f;
-   __asm__("@ packFloat32;		\n\
-   	    mov %0, %1, asl #31;	\n\
-   	    orr %0, %2, asl #23;	\n\
+   __asm__("@ packFloat32				\n\
+   	    mov %0, %1, asl #31				\n\
+   	    orr %0, %2, asl #23				\n\
    	    orr %0, %3"
    	    : /* no outputs */
    	    : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig)
@@ -321,12 +323,14 @@
 Returns the sign bit of the double-precision floating-point value `a'.
 -------------------------------------------------------------------------------
 */
+#if 0	/* in softfloat.h */
 INLINE flag extractFloat64Sign( float64 a )
 {
 
     return a>>63;
 
 }
+#endif
 
 /*
 -------------------------------------------------------------------------------
diff -urN linux-2.5.68-bk8/arch/arm/nwfpe/softfloat.h linux-2.5.68-bk9/arch/arm/nwfpe/softfloat.h
--- linux-2.5.68-bk8/arch/arm/nwfpe/softfloat.h	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/nwfpe/softfloat.h	2003-04-29 04:36:57.000000000 -0700
@@ -40,7 +40,9 @@
 input or output the `floatx80' type will be defined.
 -------------------------------------------------------------------------------
 */
+#ifdef CONFIG_FPE_NWFPE_XP
 #define FLOATX80
+#endif
 
 /*
 -------------------------------------------------------------------------------
@@ -229,4 +231,46 @@
 
 #endif
 
+static inline flag extractFloat32Sign(float32 a)
+{
+	return a >> 31;
+}
+
+static inline flag float32_eq_nocheck(float32 a, float32 b)
+{
+	return (a == b) || ((bits32) ((a | b) << 1) == 0);
+}
+
+static inline flag float32_lt_nocheck(float32 a, float32 b)
+{
+	flag aSign, bSign;
+
+	aSign = extractFloat32Sign(a);
+	bSign = extractFloat32Sign(b);
+	if (aSign != bSign)
+		return aSign && ((bits32) ((a | b) << 1) != 0);
+	return (a != b) && (aSign ^ (a < b));
+}
+
+static inline flag extractFloat64Sign(float64 a)
+{
+	return a >> 63;
+}
+
+static inline flag float64_eq_nocheck(float64 a, float64 b)
+{
+	return (a == b) || ((bits64) ((a | b) << 1) == 0);
+}
+
+static inline flag float64_lt_nocheck(float64 a, float64 b)
+{
+	flag aSign, bSign;
+
+	aSign = extractFloat64Sign(a);
+	bSign = extractFloat64Sign(b);
+	if (aSign != bSign)
+		return aSign && ((bits64) ((a | b) << 1) != 0);
+	return (a != b) && (aSign ^ (a < b));
+}
+
 #endif
diff -urN linux-2.5.68-bk8/arch/arm/tools/mach-types linux-2.5.68-bk9/arch/arm/tools/mach-types
--- linux-2.5.68-bk8/arch/arm/tools/mach-types	2003-04-19 19:49:26.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/tools/mach-types	2003-04-29 04:36:57.000000000 -0700
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Tue Mar 25 16:34:29 2003
+# Last update: Sat Apr 26 11:41:41 2003
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -313,3 +313,18 @@
 armmodul		ARCH_ARMMODUL		ARMMODUL		302
 ketop			SA1100_KETOP		KETOP			303
 av7200			ARCH_AV7200		AV7200			304
+arch_ti925		ARCH_ARCH_TI925		ARCH_TI925		305
+acq200			ARCH_ACQ200		ACQ200			306
+pt_dafit		SA1100_PT_DAFIT		PT_DAFIT		307
+ihba			ARCH_IHBA		IHBA			308
+quinque			ARCH_QUINQUE		QUINQUE			309
+nimbraone		ARCH_NIMBRAONE		NIMBRAONE		310
+nimbra29x		ARCH_NIMBRA29X		NIMBRA29X		311
+nimbra210		ARCH_NIMBRA210		NIMBRA210		312
+hhp_d95xx		ARCH_HHP_D95XX		HHP_D95XX		313
+labarm			ARCH_LABARM		LABARM			314
+m825xx			ARCH_M825XX		M825XX			315
+m7100			SA1100_M7100		M7100			316
+nipc2			ARCH_NIPC2		NIPC2			317
+fu7202			ARCH_FU7202		FU7202			318
+adsagx			ARCH_ADSAGX		ADSAGX			319
diff -urN linux-2.5.68-bk8/arch/arm/vmlinux-armv.lds.in linux-2.5.68-bk9/arch/arm/vmlinux-armv.lds.in
--- linux-2.5.68-bk8/arch/arm/vmlinux-armv.lds.in	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/arch/arm/vmlinux-armv.lds.in	2003-04-29 04:36:57.000000000 -0700
@@ -35,6 +35,9 @@
 		__setup_start = .;
 			*(.init.setup)
 		__setup_end = .;
+		__early_begin = .;
+			*(__early_param)
+		__early_end = .;
 		__start___param = .;
 			*(__param)
 		__stop___param = .;
diff -urN linux-2.5.68-bk8/arch/i386/kernel/traps.c linux-2.5.68-bk9/arch/i386/kernel/traps.c
--- linux-2.5.68-bk8/arch/i386/kernel/traps.c	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/arch/i386/kernel/traps.c	2003-04-29 04:36:57.000000000 -0700
@@ -833,7 +833,6 @@
 
 #ifdef CONFIG_EISA
 int EISA_bus;
-static struct resource eisa_id = { "EISA ID", 0xc80, 0xc83, IORESOURCE_BUSY };
 #endif
 
 void __init trap_init(void)
@@ -841,8 +840,6 @@
 #ifdef CONFIG_EISA
 	if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
 		EISA_bus = 1;
-		if (request_resource(&ioport_resource, &eisa_id) == -EBUSY)
-			printk ("EISA port was EBUSY :-(\n");
 	}
 #endif
 
diff -urN linux-2.5.68-bk8/drivers/block/ataflop.c linux-2.5.68-bk9/drivers/block/ataflop.c
--- linux-2.5.68-bk8/drivers/block/ataflop.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/block/ataflop.c	2003-04-29 04:36:58.000000000 -0700
@@ -237,6 +237,8 @@
 				   disk change detection) */
 	int flags;		/* flags */
 	struct gendisk *disk;
+	int ref;
+	int type;
 } unit[FD_MAX_UNITS];
 
 #define	UD	unit[drive]
@@ -1328,12 +1330,6 @@
 	DPRINT(("finish_fdc() finished\n"));
 }
 
-
-/* Prevent "aliased" accesses. */
-static int fd_ref[4] = { 0,0,0,0 };
-static int fd_device[4] = { 0,0,0,0 };
-
-
 /* The detection of disk changes is a dark chapter in Atari history :-(
  * Because the "Drive ready" signal isn't present in the Atari
  * hardware, one has to rely on the "Write Protect". This works fine,
@@ -1378,7 +1374,7 @@
 
 	if (test_bit(drive, &changed_floppies) ||
 	    test_bit(drive, &fake_change) ||
-	    unit[drive].disktype == 0) {
+	    p->disktype == 0) {
 		if (UD.flags & FTD_MSG)
 			printk(KERN_ERR "floppy: clear format %p!\n", UDT);
 		BufferDrive = -1;
@@ -1445,7 +1441,7 @@
 
 	floppy = CURRENT->rq_disk->private_data;
 	drive = floppy - unit;
-	type = fd_device[drive];
+	type = floppy->type;
 	
 	if (!UD.connected) {
 		/* drive not connected */
@@ -1458,7 +1454,7 @@
 		if (!UDT) {
 			Probing = 1;
 			UDT = disk_type + StartDiskType[DriveType];
-			set_capacity(unit[drive].disk, UDT->blocks);
+			set_capacity(floppy->disk, UDT->blocks);
 			UD.autoprobe = 1;
 		}
 	} 
@@ -1476,7 +1472,7 @@
 		}
 		type = minor2disktype[type].index;
 		UDT = &disk_type[type];
-		set_capacity(unit[drive].disk, UDT->blocks);
+		set_capacity(floppy->disk, UDT->blocks);
 		UD.autoprobe = 0;
 	}
 	
@@ -1522,19 +1518,16 @@
 static int fd_ioctl(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long param)
 {
-	int drive, type;
-	kdev_t device;
 	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct atari_floppy_struct *floppy = disk->private_data;
+	int drive = floppy - unit;
+	int type = floppy->type;
 	struct atari_format_descr fmt_desc;
 	struct atari_disk_type *dtp;
 	struct floppy_struct getprm;
 	int settype;
 	struct floppy_struct setprm;
 
-	device = inode->i_rdev;
-	drive = minor (device);
-	type  = drive >> 2;
-	drive &= 3;
 	switch (cmd) {
 	case FDGETPRM:
 		if (type) {
@@ -1577,7 +1570,7 @@
 		 */
 
 		/* get the parameters from user space */
-		if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
+		if (p->ref != 1 && p->ref != -1)
 			return -EBUSY;
 		if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
 			return -EFAULT;
@@ -1624,7 +1617,7 @@
 				    printk (KERN_INFO "floppy%d: setting %s %p!\n",
 				        drive, dtp->name, dtp);
 				UDT = dtp;
-				set_capacity(unit[drive].disk, UDT->blocks);
+				set_capacity(p->disk, UDT->blocks);
 
 				if (cmd == FDDEFPRM) {
 				  /* save settings as permanent default type */
@@ -1670,7 +1663,7 @@
 		}
 
 		UDT = dtp;
-		set_capacity(unit[drive].disk, UDT->blocks);
+		set_capacity(p->disk, UDT->blocks);
 
 		return 0;
 	case FDMSGON:
@@ -1684,7 +1677,7 @@
 	case FDFMTBEG:
 		return 0;
 	case FDFMTTRK:
-		if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
+		if (p->ref != 1 && p->ref != -1)
 			return -EBUSY;
 		if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
 			return -EFAULT;
@@ -1693,7 +1686,7 @@
 		UDT = NULL;
 		/* MSch: invalidate default_params */
 		default_params[drive].blocks  = 0;
-		set_capacity(unit[drive].disk, MAX_DISK_SIZE * 2);
+		set_capacity(p->disk, MAX_DISK_SIZE * 2);
 	case FDFMTEND:
 	case FDFLUSH:
 		/* invalidate the buffer track to force a reread */
@@ -1844,23 +1837,22 @@
 
 static int floppy_open( struct inode *inode, struct file *filp )
 {
-	int drive = minor(inode->i_rdev) & 3;
+	struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
 	int type  = minor(inode->i_rdev) >> 2;
-	int old_dev = fd_device[drive];
 
 	DPRINT(("fd_open: type=%d\n",type));
-	if (fd_ref[drive] && old_dev != type)
+	if (p->ref && p->type != type)
 		return -EBUSY;
 
-	if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
+	if (p->ref == -1 || (p->ref && filp->f_flags & O_EXCL))
 		return -EBUSY;
 
 	if (filp->f_flags & O_EXCL)
-		fd_ref[drive] = -1;
+		p->ref = -1;
 	else
-		fd_ref[drive]++;
+		p->ref++;
 
-	fd_device[drive] = type;
+	p->type = type;
 
 	if (filp->f_flags & O_NDELAY)
 		return 0;
@@ -1868,28 +1860,29 @@
 	if (filp->f_mode & 3) {
 		check_disk_change(inode->i_bdev);
 		if (filp->f_mode & 2) {
-			if (UD.wpstat) {
+			if (p->wpstat) {
+				if (p->ref < 0)
+					p->ref = 0;
+				else
+					p->ref--;
 				floppy_release(inode, filp);
 				return -EROFS;
 			}
 		}
 	}
-
 	return 0;
 }
 
 
 static int floppy_release( struct inode * inode, struct file * filp )
 {
-	int drive = minor(inode->i_rdev) & 3;
-
-	if (fd_ref[drive] < 0)
-		fd_ref[drive] = 0;
-	else if (!fd_ref[drive]--) {
+	struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
+	if (p->ref < 0)
+		p->ref = 0;
+	else if (!p->ref--) {
 		printk(KERN_ERR "floppy_release with fd_ref == 0");
-		fd_ref[drive] = 0;
+		p->ref = 0;
 	}
-
 	return 0;
 }
 
@@ -1912,7 +1905,7 @@
 	return get_disk(unit[drive].disk);
 }
 
-int __init atari_floppy_init (void)
+static int __init atari_floppy_init (void)
 {
 	int i;
 
@@ -2014,18 +2007,7 @@
 	}
 }
 
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module (void)
-{
-	if (!MACH_IS_ATARI)
-		return -ENXIO;
-	return atari_floppy_init ();
-}
-
-void cleanup_module (void)
+static void atari_floppy_exit(void)
 {
 	int i;
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
@@ -2039,5 +2021,8 @@
 	del_timer_sync(&fd_timer);
 	atari_stram_free( DMABuffer );
 }
-#endif
 
+module_init(atari_floppy_init)
+module_exit(atari_floppy_exit)
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.68-bk8/drivers/block/floppy.c linux-2.5.68-bk9/drivers/block/floppy.c
--- linux-2.5.68-bk8/drivers/block/floppy.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/block/floppy.c	2003-04-29 04:36:58.000000000 -0700
@@ -3885,7 +3885,7 @@
 	struct block_device *bdev;
 	int ret;
 
-	bdev = bdget(MKDEV(disk->major, disk->first_minor));
+	bdev = bdget_disk(disk, 0);
 	if (!bdev) {
 		printk("No block device for %s\n", disk->disk_name);
 		BUG();
diff -urN linux-2.5.68-bk8/drivers/block/floppy98.c linux-2.5.68-bk9/drivers/block/floppy98.c
--- linux-2.5.68-bk8/drivers/block/floppy98.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/block/floppy98.c	2003-04-29 04:36:58.000000000 -0700
@@ -3995,7 +3995,7 @@
 	struct block_device *bdev;
 	int ret;
 
-	bdev = bdget(MKDEV(disk->major, disk->first_minor));
+	bdev = bdget_disk(disk, 0);
 	if (!bdev) {
 		printk("No block device for %s\n", disk->disk_name);
 		BUG();
diff -urN linux-2.5.68-bk8/drivers/block/genhd.c linux-2.5.68-bk9/drivers/block/genhd.c
--- linux-2.5.68-bk8/drivers/block/genhd.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/block/genhd.c	2003-04-29 04:36:58.000000000 -0700
@@ -721,6 +721,17 @@
 		return disk->policy;
 }
 
+int invalidate_partition(struct gendisk *disk, int index)
+{
+	int res = 0;
+	struct block_device *bdev = bdget_disk(disk, index);
+	if (bdev)
+		res = __invalidate_device(bdev, 1);
+	bdput(bdev);
+	return res;
+}
+
 EXPORT_SYMBOL(bdev_read_only);
 EXPORT_SYMBOL(set_device_ro);
 EXPORT_SYMBOL(set_disk_ro);
+EXPORT_SYMBOL(invalidate_partition);
diff -urN linux-2.5.68-bk8/drivers/block/ioctl.c linux-2.5.68-bk9/drivers/block/ioctl.c
--- linux-2.5.68-bk8/drivers/block/ioctl.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/block/ioctl.c	2003-04-29 04:36:58.000000000 -0700
@@ -62,7 +62,7 @@
 			if (disk->part[part - 1]->nr_sects == 0)
 				return -ENXIO;
 			/* partition in use? Incomplete check for now. */
-			bdevp = bdget(MKDEV(disk->major, disk->first_minor) + part);
+			bdevp = bdget_disk(disk, part);
 			if (!bdevp)
 				return -ENOMEM;
 			if (bd_claim(bdevp, &holder) < 0) {
diff -urN linux-2.5.68-bk8/drivers/bluetooth/Kconfig linux-2.5.68-bk9/drivers/bluetooth/Kconfig
--- linux-2.5.68-bk8/drivers/bluetooth/Kconfig	2003-04-19 19:49:11.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/Kconfig	2003-04-29 04:36:59.000000000 -0700
@@ -13,11 +13,18 @@
 	  Say Y here to compile support for Bluetooth USB devices into the
 	  kernel or say M to compile it as module (hci_usb).
 
+config BT_USB_SCO
+	bool "SCO over HCI USB support"
+	depends on BT_HCIUSB
+	help
+	  This option enables the SCO support in the HCI USB driver. You need this
+	  to transmit voice data with your Bluetooth USB device. 
+	  Say Y here to compile support for SCO over HCI USB.
+
 config BT_USB_ZERO_PACKET
 	bool "USB zero packet support"
 	depends on BT_HCIUSB
 	help
-	  Support for USB zero packets. 
 	  This option is provided only as a work around for buggy Bluetooth USB 
 	  devices. Do _not_ enable it unless you know for sure that your device 
 	  requires zero packets.
diff -urN linux-2.5.68-bk8/drivers/bluetooth/bluecard_cs.c linux-2.5.68-bk9/drivers/bluetooth/bluecard_cs.c
--- linux-2.5.68-bk8/drivers/bluetooth/bluecard_cs.c	2003-04-19 19:49:27.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/bluecard_cs.c	2003-04-29 04:36:59.000000000 -0700
@@ -1075,36 +1075,29 @@
 	return 0;
 }
 
+static struct pcmcia_driver bluecard_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "bluecard_cs",
+	},
+	.attach		= bluecard_attach,
+	.detach		= bluecard_detach,
+};
 
-
-/* ======================== Module initialization ======================== */
-
-
-int __init init_bluecard_cs(void)
+static int __init init_bluecard_cs(void)
 {
-	servinfo_t serv;
-	int err;
-
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "bluecard_cs: Card Services release does not match!\n");
-		return -1;
-	}
-
-	err = register_pccard_driver(&dev_info, &bluecard_attach, &bluecard_detach);
-
-	return err;
+	return pcmcia_register_driver(&bluecard_driver);
 }
 
 
-void __exit exit_bluecard_cs(void)
+static void __exit exit_bluecard_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&bluecard_driver);
 
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL)
 		bluecard_detach(dev_list);
 }
 
-
 module_init(init_bluecard_cs);
 module_exit(exit_bluecard_cs);
diff -urN linux-2.5.68-bk8/drivers/bluetooth/bt3c_cs.c linux-2.5.68-bk9/drivers/bluetooth/bt3c_cs.c
--- linux-2.5.68-bk8/drivers/bluetooth/bt3c_cs.c	2003-04-19 19:51:14.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/bt3c_cs.c	2003-04-29 04:36:59.000000000 -0700
@@ -861,36 +861,29 @@
 	return 0;
 }
 
+static struct pcmcia_driver bt3c_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "bt3c_cs",
+	},
+	.attach		= bt3c_attach,
+	.detach		= bt3c_detach,
+};
 
-
-/* ======================== Module initialization ======================== */
-
-
-int __init init_bt3c_cs(void)
+static int __init init_bt3c_cs(void)
 {
-	servinfo_t serv;
-	int err;
-
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n");
-		return -1;
-	}
-
-	err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach);
-
-	return err;
+	return pcmcia_register_driver(&bt3c_driver);
 }
 
 
-void __exit exit_bt3c_cs(void)
+static void __exit exit_bt3c_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&bt3c_driver);
 
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL)
 		bt3c_detach(dev_list);
 }
 
-
 module_init(init_bt3c_cs);
 module_exit(exit_bt3c_cs);
diff -urN linux-2.5.68-bk8/drivers/bluetooth/btuart_cs.c linux-2.5.68-bk9/drivers/bluetooth/btuart_cs.c
--- linux-2.5.68-bk8/drivers/bluetooth/btuart_cs.c	2003-04-19 19:51:13.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/btuart_cs.c	2003-04-29 04:36:59.000000000 -0700
@@ -868,36 +868,29 @@
 	return 0;
 }
 
+static struct pcmcia_driver btuart_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "btuart_cs",
+	},
+	.attach		= btuart_attach,
+	.detach		= btuart_detach,
+};
 
-
-/* ======================== Module initialization ======================== */
-
-
-int __init init_btuart_cs(void)
+static int __init init_btuart_cs(void)
 {
-	servinfo_t serv;
-	int err;
-
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "btuart_cs: Card Services release does not match!\n");
-		return -1;
-	}
-
-	err = register_pccard_driver(&dev_info, &btuart_attach, &btuart_detach);
-
-	return err;
+	return pcmcia_register_driver(&btuart_driver);
 }
 
 
-void __exit exit_btuart_cs(void)
+static void __exit exit_btuart_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&btuart_driver);
 
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL)
 		btuart_detach(dev_list);
 }
 
-
 module_init(init_btuart_cs);
 module_exit(exit_btuart_cs);
diff -urN linux-2.5.68-bk8/drivers/bluetooth/dtl1_cs.c linux-2.5.68-bk9/drivers/bluetooth/dtl1_cs.c
--- linux-2.5.68-bk8/drivers/bluetooth/dtl1_cs.c	2003-04-19 19:49:11.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/dtl1_cs.c	2003-04-29 04:36:59.000000000 -0700
@@ -820,36 +820,29 @@
 	return 0;
 }
 
+static struct pcmcia_driver dtl1_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "dtl1_cs",
+	},
+	.attach		= dtl1_attach,
+	.detach		= dtl1_detach,
+};
 
-
-/* ======================== Module initialization ======================== */
-
-
-int __init init_dtl1_cs(void)
+static int __init init_dtl1_cs(void)
 {
-	servinfo_t serv;
-	int err;
-
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
-		return -1;
-	}
-
-	err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
-
-	return err;
+	return pcmcia_register_driver(&dtl1_driver);
 }
 
 
-void __exit exit_dtl1_cs(void)
+static void __exit exit_dtl1_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&dtl1_driver);
 
+	/* XXX: this really needs to move into generic code.. */
 	while (dev_list != NULL)
 		dtl1_detach(dev_list);
 }
 
-
 module_init(init_dtl1_cs);
 module_exit(exit_dtl1_cs);
diff -urN linux-2.5.68-bk8/drivers/bluetooth/hci_usb.c linux-2.5.68-bk9/drivers/bluetooth/hci_usb.c
--- linux-2.5.68-bk8/drivers/bluetooth/hci_usb.c	2003-04-19 19:51:08.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/hci_usb.c	2003-04-29 04:36:59.000000000 -0700
@@ -1,9 +1,10 @@
 /* 
-   BlueZ - Bluetooth protocol stack for Linux
+   HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
    Copyright (C) 2000-2001 Qualcomm Incorporated
-
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
+   Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
+
    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;
@@ -30,13 +31,11 @@
  *
  * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $    
  */
-#define VERSION "2.1"
+#define VERSION "2.4"
 
 #include <linux/config.h>
 #include <linux/module.h>
 
-#define __KERNEL_SYSCALLS__
-
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -49,17 +48,15 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
-#include <linux/kmod.h>
 
 #include <linux/usb.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
-#include "hci_usb.h"
 
-#define HCI_MAX_PENDING (HCI_MAX_BULK_RX + HCI_MAX_BULK_TX + 1)
+#include "hci_usb.h"
 
-#ifndef CONFIG_BT_HCIUSB_DEBUG
+#ifndef HCI_USB_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
 #undef  BT_DMP
@@ -67,8 +64,8 @@
 #endif
 
 #ifndef CONFIG_BT_USB_ZERO_PACKET
-#undef  URB_ZERO_PACKET
-#define URB_ZERO_PACKET 0
+#undef  USB_ZERO_PACKET
+#define USB_ZERO_PACKET 0
 #endif
 
 static struct usb_driver hci_usb_driver; 
@@ -80,6 +77,9 @@
 	/* Ericsson with non-standard id */
 	{ USB_DEVICE(0x0bdb, 0x1002) },
 
+	/* Bluetooth Ultraport Module from IBM */
+	{ USB_DEVICE(0x04bf, 0x030a) },
+
 	{ }	/* Terminating entry */
 };
 
@@ -92,108 +92,196 @@
 	{ }	/* Terminating entry */
 };
 
-static void hci_usb_interrupt(struct urb *urb, struct pt_regs *regs);
+struct _urb *_urb_alloc(int isoc, int gfp)
+{
+	struct _urb *_urb = kmalloc(sizeof(struct _urb) +
+				sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
+	if (_urb) {
+		memset(_urb, 0, sizeof(*_urb));
+		_urb->urb.count = (atomic_t)ATOMIC_INIT(1);
+		spin_lock_init(&_urb->urb.lock);
+	}
+	return _urb;
+}
+
+struct _urb *_urb_dequeue(struct _urb_queue *q)
+{
+	struct _urb *_urb = NULL;
+        unsigned long flags;
+        spin_lock_irqsave(&q->lock, flags);
+	{
+		struct list_head *head = &q->head;
+		struct list_head *next = head->next;
+		if (next != head) {
+			_urb = list_entry(next, struct _urb, list);
+			list_del(next); _urb->queue = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&q->lock, flags);
+	return _urb;
+}
+
 static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs);
 static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs);
 
-static struct urb *hci_usb_get_completed(struct hci_usb *husb)
+#define __pending_tx(husb, type)  (&husb->pending_tx[type-1])
+#define __pending_q(husb, type)   (&husb->pending_q[type-1])
+#define __completed_q(husb, type) (&husb->completed_q[type-1])
+#define __transmit_q(husb, type)  (&husb->transmit_q[type-1])
+#define __reassembly(husb, type)  (husb->reassembly[type-1])
+
+static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
 {
-	struct sk_buff *skb;
-	struct urb *urb = NULL;
+	return _urb_dequeue(__completed_q(husb, type)); 
+}
 
-	skb = skb_dequeue(&husb->completed_q);
-	if (skb) {
-		urb = ((struct hci_usb_scb *) skb->cb)->urb;
-		kfree_skb(skb);
-	}
+#ifdef CONFIG_BT_USB_SCO
+static void __fill_isoc_desc(struct urb *urb, int len, int mtu)
+{
+	int offset = 0, i;
 
-	BT_DBG("%s urb %p", husb->hdev.name, urb);
-	return urb;
+	BT_DBG("len %d mtu %d", len, mtu);
+
+	for (i=0; i < HCI_MAX_ISOC_FRAMES && len >= mtu; i++, offset += mtu, len -= mtu) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = mtu;
+		BT_DBG("desc %d offset %d len %d", i, offset, mtu);
+	}
+	if (len && i < HCI_MAX_ISOC_FRAMES) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = len;
+		BT_DBG("desc %d offset %d len %d", i, offset, len);
+		i++;
+	}
+	urb->number_of_packets = i;
 }
+#endif
 
-static int hci_usb_enable_intr(struct hci_usb *husb)
+static int hci_usb_intr_rx_submit(struct hci_usb *husb)
 {
+	struct _urb *_urb;
 	struct urb *urb;
-	int pipe, size;
+	int err, pipe, interval, size;
 	void *buf;
 
 	BT_DBG("%s", husb->hdev.name);
 
- 	if (!(urb = usb_alloc_urb(0, GFP_KERNEL)))
+        size = husb->intr_in_ep->desc.wMaxPacketSize;
+
+	buf = kmalloc(size, GFP_ATOMIC);
+	if (!buf)
 		return -ENOMEM;
 
-	if (!(buf = kmalloc(HCI_MAX_EVENT_SIZE, GFP_KERNEL))) {
-		usb_free_urb(urb);
+	_urb = _urb_alloc(0, GFP_ATOMIC);
+	if (!_urb) {
+		kfree(buf);
 		return -ENOMEM;
 	}
+	_urb->type = HCI_EVENT_PKT;
+	_urb_queue_tail(__pending_q(husb, _urb->type), _urb);
 
-	husb->intr_urb = urb;
-	
-        pipe = usb_rcvintpipe(husb->udev, husb->intr_ep);
-        size = usb_maxpacket(husb->udev, pipe, usb_pipeout(pipe));
-	usb_fill_int_urb(urb, husb->udev, pipe, buf, size, 
-			hci_usb_interrupt, husb, husb->intr_interval);
+	urb = &_urb->urb;
+	pipe     = usb_rcvintpipe(husb->udev, husb->intr_in_ep->desc.bEndpointAddress);
+	interval = husb->intr_in_ep->desc.bInterval;
+	usb_fill_int_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb, interval);
 	
-	return usb_submit_urb(urb, GFP_KERNEL);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err) {
+		BT_ERR("%s intr rx submit failed urb %p err %d",
+				husb->hdev.name, urb, err);
+		_urb_unlink(_urb);
+		_urb_free(_urb);
+		kfree(buf);
+	}
+	return err;
 }
 
-static int hci_usb_disable_intr(struct hci_usb *husb)
+static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
 {
-	struct urb *urb = husb->intr_urb;
-	struct sk_buff *skb;
-
-	BT_DBG("%s", husb->hdev.name);
+	struct _urb *_urb;
+	struct urb *urb;
+	int err, pipe, size = HCI_MAX_FRAME_SIZE;
+	void *buf;
 
-	usb_unlink_urb(urb); usb_free_urb(urb);
-	husb->intr_urb = NULL;
+	buf = kmalloc(size, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
 
-	skb = husb->intr_skb;
-	if (skb) {
-		husb->intr_skb = NULL;
-		kfree_skb(skb);
+	_urb = _urb_alloc(0, GFP_ATOMIC);
+	if (!_urb) {
+		kfree(buf);
+		return -ENOMEM;
 	}
+	_urb->type = HCI_ACLDATA_PKT;
+	_urb_queue_tail(__pending_q(husb, _urb->type), _urb);
 
-	return 0;
+	urb  = &_urb->urb;
+	pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress);
+        usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb);
+        urb->transfer_flags = 0;
+
+	BT_DBG("%s urb %p", husb->hdev.name, urb);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err) {
+		BT_ERR("%s bulk rx submit failed urb %p err %d",
+				husb->hdev.name, urb, err);
+		_urb_unlink(_urb);
+		_urb_free(_urb);
+		kfree(buf);
+	}
+	return err;
 }
 
-static int hci_usb_rx_submit(struct hci_usb *husb, struct urb *urb)
+#ifdef CONFIG_BT_USB_SCO
+static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
 {
-	struct hci_usb_scb *scb;
-	struct sk_buff *skb;
-	int    pipe, size, err;
+	struct _urb *_urb;
+	struct urb *urb;
+	int err, mtu, size;
+	void *buf;
 
-	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
-		return -ENOMEM;
+	mtu  = husb->isoc_in_ep->desc.wMaxPacketSize;
+        size = mtu * HCI_MAX_ISOC_FRAMES;
 
-        size = HCI_MAX_FRAME_SIZE;
+	buf = kmalloc(size, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
 
-	if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) {
-		usb_free_urb(urb);
+	_urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
+	if (!_urb) {
+		kfree(buf);
 		return -ENOMEM;
 	}
-	
-	BT_DBG("%s urb %p", husb->hdev.name, urb);
+	_urb->type = HCI_SCODATA_PKT;
+	_urb_queue_tail(__pending_q(husb, _urb->type), _urb);
 
-	skb->dev = (void *) &husb->hdev;
-	skb->pkt_type = HCI_ACLDATA_PKT;
+	urb = &_urb->urb;
 
-	scb = (struct hci_usb_scb *) skb->cb;
-	scb->urb = urb;
+	urb->context  = husb;
+	urb->dev      = husb->udev;
+	urb->pipe     = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress);
+	urb->complete = hci_usb_rx_complete;
 
-        pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep);
+	urb->transfer_buffer_length = size;
+	urb->transfer_buffer = buf;
+	urb->transfer_flags  = URB_ISO_ASAP;
 
-        usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, size, hci_usb_rx_complete, skb);
+	__fill_isoc_desc(urb, size, mtu);
+
+	BT_DBG("%s urb %p", husb->hdev.name, urb);
 
-	skb_queue_tail(&husb->pending_q, skb);
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
-		BT_ERR("%s bulk rx submit failed urb %p err %d",
+		BT_ERR("%s isoc rx submit failed urb %p err %d",
 				husb->hdev.name, urb, err);
-		skb_unlink(skb);
-		usb_free_urb(urb);
+		_urb_unlink(_urb);
+		_urb_free(_urb);
+		kfree(buf);
 	}
 	return err;
 }
+#endif
 
 /* Initialize device */
 static int hci_usb_open(struct hci_dev *hdev)
@@ -209,13 +297,17 @@
 
 	write_lock_irqsave(&husb->completion_lock, flags);
 
-	err = hci_usb_enable_intr(husb);
+	err = hci_usb_intr_rx_submit(husb);
 	if (!err) {
 		for (i = 0; i < HCI_MAX_BULK_RX; i++)
-			hci_usb_rx_submit(husb, NULL);
-	} else
+			hci_usb_bulk_rx_submit(husb);
+
+#ifdef CONFIG_BT_USB_SCO
+		hci_usb_isoc_rx_submit(husb);
+#endif
+	} else {
 		clear_bit(HCI_RUNNING, &hdev->flags);
-	
+	}
 
 	write_unlock_irqrestore(&husb->completion_lock, flags);
 	return err;
@@ -225,29 +317,52 @@
 static int hci_usb_flush(struct hci_dev *hdev)
 {
 	struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
+	int i;
 
 	BT_DBG("%s", hdev->name);
 
-	skb_queue_purge(&husb->cmd_q);
-	skb_queue_purge(&husb->acl_q);
+	for (i=0; i < 4; i++)
+		skb_queue_purge(&husb->transmit_q[i]);
 	return 0;
 }
 
-static inline void hci_usb_unlink_urbs(struct hci_usb *husb)
+static void hci_usb_unlink_urbs(struct hci_usb *husb)
 {
-	struct sk_buff *skb;
-	struct urb *urb;
+	int i;
 
 	BT_DBG("%s", husb->hdev.name);
 
-	while ((skb = skb_dequeue(&husb->pending_q))) {
-		urb = ((struct hci_usb_scb *) skb->cb)->urb;
-		usb_unlink_urb(urb);
-		kfree_skb(skb);
-	}
+	for (i=0; i < 4; i++) {
+		struct _urb *_urb;
+		struct urb *urb;
+
+		/* Kill pending requests */
+		while ((_urb = _urb_dequeue(&husb->pending_q[i]))) {
+			urb = &_urb->urb;
+			BT_DBG("%s unlinking _urb %p type %d urb %p", 
+					husb->hdev.name, _urb, _urb->type, urb);
+			usb_unlink_urb(urb);
+			_urb_queue_tail(__completed_q(husb, _urb->type), _urb);
+		}
 
-	while ((urb = hci_usb_get_completed(husb)))
-		usb_free_urb(urb);
+		/* Release completed requests */
+		while ((_urb = _urb_dequeue(&husb->completed_q[i]))) {
+			urb = &_urb->urb;
+			BT_DBG("%s freeing _urb %p type %d urb %p",
+					husb->hdev.name, _urb, _urb->type, urb);
+			if (urb->setup_packet)
+				kfree(urb->setup_packet);
+			if (urb->transfer_buffer)
+				kfree(urb->transfer_buffer);
+			_urb_free(_urb);
+		}
+
+		/* Release reassembly buffers */
+		if (husb->reassembly[i]) {
+			kfree_skb(husb->reassembly[i]);
+			husb->reassembly[i] = NULL;
+		}
+	}
 }
 
 /* Close device */
@@ -261,114 +376,166 @@
 
 	BT_DBG("%s", hdev->name);
 
+	/* Synchronize with completion handlers */
 	write_lock_irqsave(&husb->completion_lock, flags);
+	write_unlock_irqrestore(&husb->completion_lock, flags);
 	
-	hci_usb_disable_intr(husb);
 	hci_usb_unlink_urbs(husb);
 	hci_usb_flush(hdev);
-
-	write_unlock_irqrestore(&husb->completion_lock, flags);
 	return 0;
 }
 
-static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
+static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
 {
-	struct hci_usb_scb *scb = (void *) skb->cb;
-	struct urb *urb = hci_usb_get_completed(husb);
-	struct usb_ctrlrequest *cr;
-	int pipe, err;
-
-	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
-		return -ENOMEM;
+	struct urb *urb = &_urb->urb;
+	int err;
 
-	if (!(cr = kmalloc(sizeof(*cr), GFP_ATOMIC))) {
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
+	BT_DBG("%s urb %p type %d", husb->hdev.name, urb, _urb->type);
 	
-	pipe = usb_sndctrlpipe(husb->udev, 0);
+	_urb_queue_tail(__pending_q(husb, _urb->type), _urb);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err) {
+		BT_ERR("%s tx submit failed urb %p type %d err %d",
+				husb->hdev.name, urb, _urb->type, err);
+		_urb_unlink(_urb);
+		_urb_queue_tail(__completed_q(husb, _urb->type), _urb);
+	} else
+		atomic_inc(__pending_tx(husb, _urb->type));
 
-	cr->bRequestType = HCI_CTRL_REQ;
-	cr->bRequest = 0;
-	cr->wIndex   = 0;
-	cr->wValue   = 0;
-	cr->wLength  = __cpu_to_le16(skb->len);
+	return err;
+}
 
-	usb_fill_control_urb(urb, husb->udev, pipe, (void *) cr,
-			skb->data, skb->len, hci_usb_tx_complete, skb);
+static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
+{
+	struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
 
-	BT_DBG("%s urb %p len %d", husb->hdev.name, urb, skb->len);
+	if (!_urb) {
+	       	_urb = _urb_alloc(0, GFP_ATOMIC);
+	       	if (!_urb)
+			return -ENOMEM;
+		_urb->type = skb->pkt_type;
+
+		dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+		if (!dr) {
+			_urb_free(_urb);
+			return -ENOMEM;
+		}
+	} else
+		dr = (void *) _urb->urb.setup_packet;
 
-	scb->urb = urb;
+	dr->bRequestType = HCI_CTRL_REQ;
+	dr->bRequest = 0;
+	dr->wIndex   = 0;
+	dr->wValue   = 0;
+	dr->wLength  = __cpu_to_le16(skb->len);
+
+	urb = &_urb->urb;
+	usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0),
+		(void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb);
 
-	skb_queue_tail(&husb->pending_q, skb);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err) {
-		BT_ERR("%s ctrl tx submit failed urb %p err %d", 
-				husb->hdev.name, urb, err);
-		skb_unlink(skb);
-		usb_free_urb(urb); kfree(cr);
-	}
-	return err;
+	BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len);
+	
+	_urb->priv = skb;
+	return __tx_submit(husb, _urb);
 }
 
 static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
 {
-	struct hci_usb_scb *scb = (void *) skb->cb;
-	struct urb *urb = hci_usb_get_completed(husb);
-	int pipe, err;
+	struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+	struct urb *urb;
+	int pipe;
 
-	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
-		return -ENOMEM;
+	if (!_urb) {
+	       	_urb = _urb_alloc(0, GFP_ATOMIC);
+	       	if (!_urb)
+			return -ENOMEM;
+		_urb->type = skb->pkt_type;
+	}
 
-	pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep);
-        
-	usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len,
-	              hci_usb_tx_complete, skb);
-	urb->transfer_flags = URB_ZERO_PACKET;
+	urb  = &_urb->urb;
+	pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress);
+	usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len, 
+			hci_usb_tx_complete, husb);
+	urb->transfer_flags = USB_ZERO_PACKET;
 
-	BT_DBG("%s urb %p len %d", husb->hdev.name, urb, skb->len);
+	BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len);
 
-	scb->urb = urb;
+	_urb->priv = skb;
+	return __tx_submit(husb, _urb);
+}
 
-	skb_queue_tail(&husb->pending_q, skb);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err) {
-		BT_ERR("%s bulk tx submit failed urb %p err %d", 
-				husb->hdev.name, urb, err);
-		skb_unlink(skb);
-		usb_free_urb(urb);
+#ifdef CONFIG_BT_USB_SCO
+static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
+{
+	struct _urb *_urb = __get_completed(husb, skb->pkt_type);
+	struct urb *urb;
+	
+	if (!_urb) {
+	       	_urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
+	       	if (!_urb)
+			return -ENOMEM;
+		_urb->type = skb->pkt_type;
 	}
-	return err;
+
+	BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len);
+
+	urb = &_urb->urb;
+	
+	urb->context  = husb;
+	urb->dev      = husb->udev;
+	urb->pipe     = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress);
+	urb->complete = hci_usb_tx_complete;
+	urb->transfer_flags = URB_ISO_ASAP;
+
+	urb->transfer_buffer = skb->data;
+	urb->transfer_buffer_length = skb->len;
+	
+	__fill_isoc_desc(urb, skb->len, husb->isoc_out_ep->desc.wMaxPacketSize);
+
+	_urb->priv = skb;
+	return __tx_submit(husb, _urb);
 }
+#endif
 
 static void hci_usb_tx_process(struct hci_usb *husb)
 {
+	struct sk_buff_head *q;
 	struct sk_buff *skb;
 
 	BT_DBG("%s", husb->hdev.name);
 
 	do {
 		clear_bit(HCI_USB_TX_WAKEUP, &husb->state);
+
+		/* Process command queue */
+		q = __transmit_q(husb, HCI_COMMAND_PKT);
+		if (!atomic_read(__pending_tx(husb, HCI_COMMAND_PKT)) &&
+				(skb = skb_dequeue(q))) {
+			if (hci_usb_send_ctrl(husb, skb) < 0)
+				skb_queue_head(q, skb);
+		}
+
+#ifdef CONFIG_BT_USB_SCO
+		/* Process SCO queue */
+		q = __transmit_q(husb, HCI_SCODATA_PKT);
+		if (!atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) &&
+				(skb = skb_dequeue(q))) {
+			if (hci_usb_send_isoc(husb, skb) < 0)
+				skb_queue_head(q, skb);
+		}
+#endif
 		
 		/* Process ACL queue */
-		while (skb_queue_len(&husb->pending_q) < HCI_MAX_PENDING &&
-				(skb = skb_dequeue(&husb->acl_q))) {
+		q = __transmit_q(husb, HCI_ACLDATA_PKT);
+		while (atomic_read(__pending_tx(husb, HCI_ACLDATA_PKT)) < HCI_MAX_BULK_TX &&
+				(skb = skb_dequeue(q))) {
 			if (hci_usb_send_bulk(husb, skb) < 0) {
-				skb_queue_head(&husb->acl_q, skb);
+				skb_queue_head(q, skb);
 				break;
 			}
 		}
-
-		/* Process command queue */
-		if (!test_bit(HCI_USB_CTRL_TX, &husb->state) &&
-			(skb = skb_dequeue(&husb->cmd_q)) != NULL) {
-			set_bit(HCI_USB_CTRL_TX, &husb->state);
-			if (hci_usb_send_ctrl(husb, skb) < 0) {
-				skb_queue_head(&husb->cmd_q, skb);
-				clear_bit(HCI_USB_CTRL_TX, &husb->state);
-			}
-		}
 	} while(test_bit(HCI_USB_TX_WAKEUP, &husb->state));
 }
 
@@ -383,7 +550,7 @@
 }
 
 /* Send frames from HCI layer */
-int hci_usb_send_frame(struct sk_buff *skb)
+static int hci_usb_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
 	struct hci_usb *husb;
@@ -396,247 +563,227 @@
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return -EBUSY;
 
-	husb = (struct hci_usb *) hdev->driver_data;
-
 	BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len);
 
-	read_lock(&husb->completion_lock);
+	husb = (struct hci_usb *) hdev->driver_data;
 
 	switch (skb->pkt_type) {
 	case HCI_COMMAND_PKT:
-		skb_queue_tail(&husb->cmd_q, skb);
 		hdev->stat.cmd_tx++;
 		break;
 
 	case HCI_ACLDATA_PKT:
-		skb_queue_tail(&husb->acl_q, skb);
 		hdev->stat.acl_tx++;
 		break;
 
+#ifdef CONFIG_BT_USB_SCO
 	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+#endif
+
 	default:
 		kfree_skb(skb);
-		break;
+		return 0;
 	}
+
+	read_lock(&husb->completion_lock);
+
+	skb_queue_tail(__transmit_q(husb, skb->pkt_type), skb);
 	hci_usb_tx_wakeup(husb);
 
 	read_unlock(&husb->completion_lock);
 	return 0;
 }
 
-static void hci_usb_interrupt(struct urb *urb, struct pt_regs *regs)
+static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count)
 {
-	struct hci_usb *husb = (void *) urb->context;
-	struct hci_usb_scb *scb;
-	struct sk_buff *skb;
-	struct hci_event_hdr *eh;
-	__u8 *data = urb->transfer_buffer;
-	int count = urb->actual_length;
-	int len = HCI_EVENT_HDR_SIZE;
-	int status;
-
-	BT_DBG("%s urb %p count %d", husb->hdev.name, urb, count);
+	BT_DBG("%s type %d data %p count %d", husb->hdev.name, type, data, count);
 
-	if (!test_bit(HCI_RUNNING, &husb->hdev.flags))
-		return;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		BT_DBG("%s urb shutting down with status: %d",
-				husb->hdev.name, urb->status);
-		return;
-	default:
-		BT_ERR("%s nonzero urb status received: %d",
-				husb->hdev.name, urb->status);
-		goto exit;
-	}
-
-	if (!count) {
-		BT_DBG("%s intr status %d, count %d", 
-				husb->hdev.name, urb->status, count);
-		goto exit;
-	}
-
-	read_lock(&husb->completion_lock);
-	
 	husb->hdev.stat.byte_rx += count;
 
-	if (!(skb = husb->intr_skb)) {
-		/* Start of the frame */
-		if (count < HCI_EVENT_HDR_SIZE)
-			goto bad_len;
+	while (count) {
+		struct sk_buff *skb = __reassembly(husb, type);
+		struct { int expect; } *scb;
+		int len = 0;
+	
+		if (!skb) {
+			/* Start of the frame */
 
-		eh  = (struct hci_event_hdr *) data;
-		len = eh->plen + HCI_EVENT_HDR_SIZE;
+			switch (type) {
+			case HCI_EVENT_PKT:
+				if (count >= HCI_EVENT_HDR_SIZE) {
+					struct hci_event_hdr *h = data;
+					len = HCI_EVENT_HDR_SIZE + h->plen;
+				} else
+					return -EILSEQ;
+				break;
 
-		if (count > len)
-			goto bad_len;
+			case HCI_ACLDATA_PKT:
+				if (count >= HCI_ACL_HDR_SIZE) {
+					struct hci_acl_hdr *h = data;
+					len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
+				} else
+					return -EILSEQ;
+				break;
+#ifdef CONFIG_BT_USB_SCO
+			case HCI_SCODATA_PKT:
+				if (count >= HCI_SCO_HDR_SIZE) {
+					struct hci_sco_hdr *h = data;
+					len = HCI_SCO_HDR_SIZE + h->dlen;
+				} else 
+					return -EILSEQ;
+				break;
+#endif
+			}
+			BT_DBG("new packet len %d", len);
+				
+			skb = bt_skb_alloc(len, GFP_ATOMIC);
+			if (!skb) {
+				BT_ERR("%s no memory for the packet", husb->hdev.name);
+				return -ENOMEM;
+			}
+			skb->dev = (void *) &husb->hdev;
+			skb->pkt_type = type;
+	
+			__reassembly(husb, type) = skb;
 
-		skb = bt_skb_alloc(len, GFP_ATOMIC);
-		if (!skb) {
-			BT_ERR("%s no memory for event packet", husb->hdev.name);
-			goto done;
+			scb = (void *) skb->cb;
+			scb->expect = len;
+		} else {
+			/* Continuation */
+			scb = (void *) skb->cb;
+			len = scb->expect;
 		}
-		scb = (void *) skb->cb;
 
-		skb->dev = (void *) &husb->hdev;
-		skb->pkt_type = HCI_EVENT_PKT;
+		len = min(len, count);
+		
+		memcpy(skb_put(skb, len), data, len);
 
-		husb->intr_skb = skb;
-		scb->intr_len  = len;
-	} else {
-		/* Continuation */
-		scb = (void *) skb->cb;
-		len = scb->intr_len;
-		if (count > len) {
-			husb->intr_skb = NULL;
-			kfree_skb(skb);
-			goto bad_len;
+		scb->expect -= len;
+		if (!scb->expect) {
+			/* Complete frame */
+			__reassembly(husb, type) = NULL;
+			hci_recv_frame(skb);
 		}
-	}
 
-	memcpy(skb_put(skb, count), data, count);
-	scb->intr_len -= count;
-
-	if (!scb->intr_len) {
-		/* Complete frame */
-		husb->intr_skb = NULL;
-		hci_recv_frame(skb);
+		count -= len; data += len;
 	}
-
-done:
-	read_unlock(&husb->completion_lock);
-	goto exit;
-
-bad_len:
-	BT_ERR("%s bad frame len %d expected %d", husb->hdev.name, count, len);
-	husb->hdev.stat.err_rx++;
-	read_unlock(&husb->completion_lock);
-
-exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
-		BT_ERR ("%s usb_submit_urb failed with result %d",
-				husb->hdev.name, status);
+	return 0;
 }
 
-static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
+static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs)
 {
-	struct sk_buff *skb  = (struct sk_buff *) urb->context;
-	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-	struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
+	struct _urb *_urb = container_of(urb, struct _urb, urb);
+	struct hci_usb *husb = (void *) urb->context;
+	struct hci_dev *hdev = &husb->hdev;
+	int    err, count = urb->actual_length;
 
-	BT_DBG("%s urb %p status %d flags %x", husb->hdev.name, urb,
-			urb->status, urb->transfer_flags);
-
-	if (urb->pipe == usb_sndctrlpipe(husb->udev, 0)) {
-		kfree(urb->setup_packet);
-		clear_bit(HCI_USB_CTRL_TX, &husb->state);
-	}
+	BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb,
+			_urb->type, urb->status, count, urb->transfer_flags);
 
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return;
 
 	read_lock(&husb->completion_lock);
-	
-	if (!urb->status)
-		husb->hdev.stat.byte_tx += skb->len;
-	else
-		husb->hdev.stat.err_tx++;
 
-	skb_unlink(skb);
-	skb_queue_tail(&husb->completed_q, skb);
-	hci_usb_tx_wakeup(husb);
-	
+	if (urb->status || !count)
+		goto resubmit;
+
+	if (_urb->type == HCI_SCODATA_PKT) {
+#ifdef CONFIG_BT_USB_SCO
+		int i;
+		for (i=0; i < urb->number_of_packets; i++) {
+			BT_DBG("desc %d status %d offset %d len %d", i,
+					urb->iso_frame_desc[i].status,
+					urb->iso_frame_desc[i].offset,
+					urb->iso_frame_desc[i].actual_length);
+	
+			if (!urb->iso_frame_desc[i].status)
+				__recv_frame(husb, _urb->type, 
+					urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+					urb->iso_frame_desc[i].actual_length);
+		}
+#else
+		;
+#endif
+	} else {
+		err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count);
+		if (err < 0) { 
+			BT_ERR("%s corrupted packet: type %d count %d",
+					husb->hdev.name, _urb->type, count);
+			hdev->stat.err_rx++;
+		}
+	}
+
+resubmit:
+	urb->dev = husb->udev;
+	err      = usb_submit_urb(urb, GFP_ATOMIC);
+	BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb,
+			_urb->type, err);
+
 	read_unlock(&husb->completion_lock);
-	return;
 }
 
-static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs)
+static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
 {
-	struct sk_buff *skb  = (struct sk_buff *) urb->context;
-	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-	struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
-	int status, count = urb->actual_length;
-	struct hci_acl_hdr *ah;
-	int dlen, size;
-
-	BT_DBG("%s urb %p status %d count %d flags %x", husb->hdev.name, urb,
-			urb->status, count, urb->transfer_flags);
+	struct _urb *_urb = container_of(urb, struct _urb, urb);
+	struct hci_usb *husb = (void *) urb->context;
+	struct hci_dev *hdev = &husb->hdev;
 
-	if (!test_bit(HCI_RUNNING, &hdev->flags))
-		return;
+	BT_DBG("%s urb %p status %d flags %x", hdev->name, urb,
+			urb->status, urb->transfer_flags);
 
-	read_lock(&husb->completion_lock);
+	atomic_dec(__pending_tx(husb, _urb->type));
 
-	if (urb->status || !count)
-		goto resubmit;
+	urb->transfer_buffer = NULL;
+	kfree_skb((struct sk_buff *) _urb->priv);
 
-	husb->hdev.stat.byte_rx += count;
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return;
 
-	ah   = (struct hci_acl_hdr *) skb->data;
-	dlen = __le16_to_cpu(ah->dlen);
-	size = HCI_ACL_HDR_SIZE + dlen;
-
-	/* Verify frame len and completeness */
-	if (count != size) {
-		BT_ERR("%s corrupted ACL packet: count %d, dlen %d",
-				husb->hdev.name, count, dlen);
-		bt_dump("hci_usb", skb->data, count);
-		husb->hdev.stat.err_rx++;
-		goto resubmit;
-	}
+	if (!urb->status)
+		hdev->stat.byte_tx += urb->transfer_buffer_length;
+	else
+		hdev->stat.err_tx++;
 
-	skb_unlink(skb);
-	skb_put(skb, count);
-	hci_recv_frame(skb);
+	read_lock(&husb->completion_lock);
 
-	hci_usb_rx_submit(husb, urb);
+	_urb_unlink(_urb);
+	_urb_queue_tail(__completed_q(husb, _urb->type), _urb);
 
-	read_unlock(&husb->completion_lock);
-	return;
-		
-resubmit:
-	urb->dev = husb->udev;
-	status   = usb_submit_urb(urb, GFP_ATOMIC);
-	BT_DBG("%s URB resubmit status %d", husb->hdev.name, status);
+	hci_usb_tx_wakeup(husb);
+	
 	read_unlock(&husb->completion_lock);
 }
 
 static void hci_usb_destruct(struct hci_dev *hdev)
 {
-	struct hci_usb *husb;
-
-	if (!hdev) return;
+	struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
 
 	BT_DBG("%s", hdev->name);
 
-	husb = (struct hci_usb *) hdev->driver_data;
 	kfree(husb);
 }
 
 int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(intf);	
+	struct usb_device *udev = interface_to_usbdev(intf);
 	struct usb_host_endpoint *bulk_out_ep[HCI_MAX_IFACE_NUM];
 	struct usb_host_endpoint *isoc_out_ep[HCI_MAX_IFACE_NUM];
 	struct usb_host_endpoint *bulk_in_ep[HCI_MAX_IFACE_NUM];
 	struct usb_host_endpoint *isoc_in_ep[HCI_MAX_IFACE_NUM];
 	struct usb_host_endpoint *intr_in_ep[HCI_MAX_IFACE_NUM];
+	struct usb_host_endpoint  *ep;
 	struct usb_host_interface *uif;
-	struct usb_host_endpoint *ep;
 	struct usb_interface *iface, *isoc_iface;
 	struct hci_usb *husb;
 	struct hci_dev *hdev;
 	int i, a, e, size, ifn, isoc_ifnum, isoc_alts;
 
-	BT_DBG("intf %p", intf);
+	BT_DBG("udev %p ifnum %d", udev, ifnum);
+
+	iface = &udev->actconfig->interface[0];
 
 	/* Check our black list */
 	if (usb_match_id(intf, ignore_ids))
@@ -679,6 +826,7 @@
 						bulk_out_ep[i] = ep;
 					break;
 
+#ifdef CONFIG_BT_USB_SCO
 				case USB_ENDPOINT_XFER_ISOC:
 					if (ep->desc.wMaxPacketSize < size)
 						break;
@@ -693,6 +841,7 @@
 					else
 						isoc_out_ep[i] = ep;
 					break;
+#endif
 				}
 			}
 		}
@@ -703,10 +852,12 @@
 		goto done;
 	}
 
+#ifdef CONFIG_BT_USB_SCO
 	if (!isoc_in_ep[1] || !isoc_out_ep[1]) {
 		BT_DBG("Isoc endpoints not found");
 		isoc_iface = NULL;
 	}
+#endif
 
 	if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
 		BT_ERR("Can't allocate: control structure");
@@ -716,35 +867,36 @@
 	memset(husb, 0, sizeof(struct hci_usb));
 
 	husb->udev = udev;
-	husb->bulk_out_ep = bulk_out_ep[0]->desc.bEndpointAddress;
-	husb->bulk_in_ep  = bulk_in_ep[0]->desc.bEndpointAddress;
-
-	husb->intr_ep = intr_in_ep[0]->desc.bEndpointAddress;
-	husb->intr_interval = intr_in_ep[0]->desc.bInterval;
+	husb->bulk_out_ep = bulk_out_ep[0];
+	husb->bulk_in_ep  = bulk_in_ep[0];
+	husb->intr_in_ep  = intr_in_ep[0];
 
+#ifdef CONFIG_BT_USB_SCO
 	if (isoc_iface) {
+		BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts);
 		if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
 			BT_ERR("Can't set isoc interface settings");
 			isoc_iface = NULL;
 		}
 		usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb);
 		husb->isoc_iface  = isoc_iface;
-
-		husb->isoc_in_ep  = isoc_in_ep[1]->desc.bEndpointAddress;
-		husb->isoc_out_ep = isoc_in_ep[1]->desc.bEndpointAddress;
+		husb->isoc_in_ep  = isoc_in_ep[isoc_ifnum];
+		husb->isoc_out_ep = isoc_out_ep[isoc_ifnum];
 	}
-
-	husb->completion_lock = RW_LOCK_UNLOCKED;
+#endif
 	
-	skb_queue_head_init(&husb->acl_q);
-	skb_queue_head_init(&husb->cmd_q);
-	skb_queue_head_init(&husb->pending_q);
-	skb_queue_head_init(&husb->completed_q);
+	husb->completion_lock = RW_LOCK_UNLOCKED;
+
+	for (i = 0; i < 4; i++) {	
+		skb_queue_head_init(&husb->transmit_q[i]);
+		_urb_queue_init(&husb->pending_q[i]);
+		_urb_queue_init(&husb->completed_q[i]);
+	}
 
 	/* Initialize and register HCI device */
 	hdev = &husb->hdev;
 
-	hdev->type = HCI_USB;
+	hdev->type  = HCI_USB;
 	hdev->driver_data = husb;
 
 	hdev->open  = hci_usb_open;
@@ -754,7 +906,7 @@
 	hdev->destruct = hci_usb_destruct;
 
 	hdev->owner = THIS_MODULE;
-	
+
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
 		goto probe_error;
@@ -773,13 +925,12 @@
 static void hci_usb_disconnect(struct usb_interface *intf)
 {
 	struct hci_usb *husb = usb_get_intfdata(intf);
-	struct hci_dev *hdev;
+	struct hci_dev *hdev = &husb->hdev;
 
 	if (!husb)
 		return;
 	usb_set_intfdata(intf, NULL);
 
-	hdev = &husb->hdev;
 	BT_DBG("%s", hdev->name);
 
 	hci_usb_close(hdev);
@@ -792,10 +943,10 @@
 }
 
 static struct usb_driver hci_usb_driver = {
-	.name       = "hci_usb",
-	.probe      = hci_usb_probe,
-	.disconnect = hci_usb_disconnect,
-	.id_table   = bluetooth_ids
+	.name       =  "hci_usb",
+	.probe      =  hci_usb_probe,
+	.disconnect =  hci_usb_disconnect,
+	.id_table   =  bluetooth_ids,
 };
 
 int hci_usb_init(void)
diff -urN linux-2.5.68-bk8/drivers/bluetooth/hci_usb.h linux-2.5.68-bk9/drivers/bluetooth/hci_usb.h
--- linux-2.5.68-bk8/drivers/bluetooth/hci_usb.h	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/drivers/bluetooth/hci_usb.h	2003-04-29 04:36:59.000000000 -0700
@@ -1,9 +1,10 @@
 /* 
-   BlueZ - Bluetooth protocol stack for Linux
+   HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
    Copyright (C) 2000-2001 Qualcomm Incorporated
-
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
+   Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
+
    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;
@@ -40,40 +41,96 @@
 #define HCI_MAX_BULK_TX     	4
 #define HCI_MAX_BULK_RX     	1
 
+#define HCI_MAX_ISOC_FRAMES     10
+
+struct _urb_queue {
+	struct list_head head;
+	spinlock_t       lock;
+};
+
+struct _urb {
+	struct list_head  list;
+	struct _urb_queue *queue;
+	int               type;
+	void              *priv;
+	struct urb        urb;
+};
+
+struct _urb *_urb_alloc(int isoc, int gfp);
+
+static inline void _urb_free(struct _urb *_urb)
+{
+	kfree(_urb);
+}
+
+static inline void _urb_queue_init(struct _urb_queue *q)
+{
+	INIT_LIST_HEAD(&q->head);
+	spin_lock_init(&q->lock);
+}
+
+static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb)
+{
+        unsigned long flags;
+        spin_lock_irqsave(&q->lock, flags);
+	list_add(&_urb->list, &q->head); _urb->queue = q;
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb)
+{
+        unsigned long flags;
+        spin_lock_irqsave(&q->lock, flags);
+	list_add_tail(&_urb->list, &q->head); _urb->queue = q;
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline void _urb_unlink(struct _urb *_urb)
+{
+	struct _urb_queue *q = _urb->queue;
+        unsigned long flags;
+	if (q) {
+        	spin_lock_irqsave(&q->lock, flags);
+		list_del(&_urb->list); _urb->queue = NULL;
+		spin_unlock_irqrestore(&q->lock, flags);
+	}
+}
+
+struct _urb *_urb_dequeue(struct _urb_queue *q);
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({                      \
+		        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+			        (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
 struct hci_usb {
 	struct hci_dev		hdev;
 
 	unsigned long		state;
 	
 	struct usb_device 	*udev;
-	struct usb_interface    *isoc_iface;
 	
-	__u8			bulk_out_ep;
-	__u8			bulk_in_ep;
-	__u8			isoc_out_ep;
-	__u8			isoc_in_ep;
-
-	__u8			intr_ep;
-	__u8			intr_interval;
-	struct urb		*intr_urb;
-	struct sk_buff		*intr_skb;
+	struct usb_host_endpoint	*bulk_in_ep;
+	struct usb_host_endpoint	*bulk_out_ep;
+	struct usb_host_endpoint	*intr_in_ep;
+
+	struct usb_interface            *isoc_iface;
+	struct usb_host_endpoint	*isoc_out_ep;
+	struct usb_host_endpoint	*isoc_in_ep;
+
+	struct sk_buff_head	transmit_q[4];
+	struct sk_buff		*reassembly[4]; // Reassembly buffers
 
 	rwlock_t		completion_lock;
-	
-	struct sk_buff_head	cmd_q;	     // TX Commands
-	struct sk_buff_head	acl_q;	     // TX ACLs
-	struct sk_buff_head	pending_q;   // Pending requests
-	struct sk_buff_head	completed_q; // Completed requests
-};
 
-struct hci_usb_scb {
-	struct urb *urb;
-	int    intr_len;
+	atomic_t		pending_tx[4];  // Number of pending requests 
+	struct _urb_queue	pending_q[4];   // Pending requests
+	struct _urb_queue	completed_q[4]; // Completed requests
 };
 
 /* States  */
 #define HCI_USB_TX_PROCESS	1
 #define HCI_USB_TX_WAKEUP	2
-#define HCI_USB_CTRL_TX		3
 
 #endif /* __KERNEL__ */
diff -urN linux-2.5.68-bk8/drivers/char/drm/drmP.h linux-2.5.68-bk9/drivers/char/drm/drmP.h
--- linux-2.5.68-bk8/drivers/char/drm/drmP.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drmP.h	2003-04-29 04:36:59.000000000 -0700
@@ -735,12 +735,6 @@
 extern int	     DRM(lock_free)(drm_device_t *dev,
 				    __volatile__ unsigned int *lock,
 				    unsigned int context);
-extern int	     DRM(finish)(struct inode *inode, struct file *filp,
-				 unsigned int cmd, unsigned long arg);
-extern int	     DRM(flush_unblock)(drm_device_t *dev, int context,
-					drm_lock_flags_t flags);
-extern int	     DRM(flush_block_and_flush)(drm_device_t *dev, int context,
-						drm_lock_flags_t flags);
 extern int           DRM(notifier)(void *priv);
 
 				/* Buffer management support (drm_bufs.h) */
diff -urN linux-2.5.68-bk8/drivers/char/drm/drm_bufs.h linux-2.5.68-bk9/drivers/char/drm/drm_bufs.h
--- linux-2.5.68-bk8/drivers/char/drm/drm_bufs.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drm_bufs.h	2003-04-29 04:36:59.000000000 -0700
@@ -145,7 +145,7 @@
 #ifdef __alpha__
 		map->offset += dev->hose->mem_space->start;
 #endif
-		map->offset = map->offset + dev->agp->base;
+		map->offset += dev->agp->base;
 		map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
 		break;
 #endif
@@ -154,7 +154,7 @@
 			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
 			return -EINVAL;
 		}
-		map->offset = map->offset + dev->sg->handle;
+		map->offset += dev->sg->handle;
 		break;
 
 	default:
@@ -680,9 +680,11 @@
 	/* No allocations failed, so now we can replace the orginal pagelist
 	 * with the new one.
 	 */
-	DRM(free)(dma->pagelist,
-		  dma->page_count * sizeof(*dma->pagelist),
-		  DRM_MEM_PAGES);
+	if (dma->page_count) {
+		DRM(free)(dma->pagelist,
+			  dma->page_count * sizeof(*dma->pagelist),
+			  DRM_MEM_PAGES);
+	}
 	dma->pagelist = temp_pagelist;
 
 	dma->buf_count += entry->buf_count;
diff -urN linux-2.5.68-bk8/drivers/char/drm/drm_dma.h linux-2.5.68-bk9/drivers/char/drm/drm_dma.h
--- linux-2.5.68-bk8/drivers/char/drm/drm_dma.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drm_dma.h	2003-04-29 04:36:59.000000000 -0700
@@ -193,6 +193,13 @@
 		return -EINVAL;
 
 	down( &dev->struct_sem );
+
+	/* Driver must have been initialized */
+	if ( !dev->dev_private ) {
+		up( &dev->struct_sem );
+		return -EINVAL;
+	}
+
 	if ( dev->irq ) {
 		up( &dev->struct_sem );
 		return -EBUSY;
diff -urN linux-2.5.68-bk8/drivers/char/drm/drm_drv.h linux-2.5.68-bk9/drivers/char/drm/drm_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/drm_drv.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drm_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -84,6 +84,9 @@
 #ifndef __HAVE_SG
 #define __HAVE_SG			0
 #endif
+#ifndef __HAVE_KERNEL_CTX_SWITCH
+#define __HAVE_KERNEL_CTX_SWITCH	0
+#endif
 #ifndef __HAVE_DRIVER_FOPS_READ
 #define __HAVE_DRIVER_FOPS_READ		0
 #endif
@@ -1013,6 +1016,12 @@
 			DRIVER_DMA_QUIESCENT();
 		}
 #endif
+#if __HAVE_KERNEL_CTX_SWITCH
+		if ( dev->last_context != lock.context ) {
+			DRM(context_switch)(dev, dev->last_context,
+					    lock.context);
+		}
+#endif
         }
 
         DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
@@ -1039,6 +1048,25 @@
 
 	atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 
+#if __HAVE_KERNEL_CTX_SWITCH
+	/* We no longer really hold it, but if we are the next
+	 * agent to request it then we should just be able to
+	 * take it immediately and not eat the ioctl.
+	 */
+	dev->lock.filp = 0;
+	{
+		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+		unsigned int old, new, prev, ctx;
+
+		ctx = lock.context;
+		do {
+			old  = *plock;
+			new  = ctx;
+			prev = cmpxchg(plock, old, new);
+		} while (prev != old);
+	}
+	wake_up_interruptible(&dev->lock.lock_queue);
+#else
 	DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
 			    DRM_KERNEL_CONTEXT );
 #if __HAVE_DMA_SCHEDULE
@@ -1053,6 +1081,7 @@
 			DRM_ERROR( "\n" );
 		}
 	}
+#endif /* !__HAVE_KERNEL_CTX_SWITCH */
 
 	unblock_all_signals();
 	return 0;
diff -urN linux-2.5.68-bk8/drivers/char/drm/drm_os_linux.h linux-2.5.68-bk9/drivers/char/drm/drm_os_linux.h
--- linux-2.5.68-bk8/drivers/char/drm/drm_os_linux.h	2003-04-19 19:50:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drm_os_linux.h	2003-04-29 04:36:59.000000000 -0700
@@ -11,8 +11,9 @@
 #define DRM_READ32(map, offset)		readl(((unsigned long)(map)->handle) + (offset))
 #define DRM_WRITE8(map, offset, val)	writeb(val, ((unsigned long)(map)->handle) + (offset))
 #define DRM_WRITE32(map, offset, val)	writel(val, ((unsigned long)(map)->handle) + (offset))
-#define DRM_READMEMORYBARRIER(map)	mb()
-#define DRM_WRITEMEMORYBARRIER(map)	wmb()
+#define DRM_READMEMORYBARRIER()		rmb()
+#define DRM_WRITEMEMORYBARRIER()	wmb()
+#define DRM_MEMORYBARRIER()		mb()
 #define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
 			drm_device_t	*dev	= priv->dev
 
diff -urN linux-2.5.68-bk8/drivers/char/drm/drm_proc.h linux-2.5.68-bk9/drivers/char/drm/drm_proc.h
--- linux-2.5.68-bk8/drivers/char/drm/drm_proc.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/drm_proc.h	2003-04-29 04:36:59.000000000 -0700
@@ -437,31 +437,6 @@
 			       pgprot & _PAGE_GLOBAL   ? 'g' : 'l' );
 #endif
 		DRM_PROC_PRINT("\n");
-#if 0
-		for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
-			pgd = pgd_offset(vma->vm_mm, i);
-			pmd = pmd_offset(pgd, i);
-			preempt_disable();
-			pte = pte_offset_map(pmd, i);
-			if (pte_present(*pte)) {
-				address = __pa(pte_page(*pte))
-					+ (i & (PAGE_SIZE-1));
-				DRM_PROC_PRINT("      0x%08lx -> 0x%08lx"
-					       " %c%c%c%c%c\n",
-					       i,
-					       address,
-					       pte_read(*pte)  ? 'r' : '-',
-					       pte_write(*pte) ? 'w' : '-',
-					       pte_exec(*pte)  ? 'x' : '-',
-					       pte_dirty(*pte) ? 'd' : '-',
-					       pte_young(*pte) ? 'a' : '-' );
-			} else {
-				DRM_PROC_PRINT("      0x%08lx\n", i);
-			}
-			pte_unmap(pte);
-			preempt_enable();
-		}
-#endif
 	}
 
 	if (len > request + offset) return request;
diff -urN linux-2.5.68-bk8/drivers/char/drm/gamma.h linux-2.5.68-bk9/drivers/char/drm/gamma.h
--- linux-2.5.68-bk8/drivers/char/drm/gamma.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/gamma.h	2003-04-29 04:36:59.000000000 -0700
@@ -63,6 +63,12 @@
 #define __HAVE_COUNTER9		_DRM_STAT_SPECIAL
 #define __HAVE_COUNTER10	_DRM_STAT_MISSED
 
+/* Driver customization:
+ */
+#define DRIVER_PRETAKEDOWN() do {					\
+	gamma_do_cleanup_dma( dev );					\
+} while (0)
+
 /* DMA customization:
  */
 #define __HAVE_DMA			1
diff -urN linux-2.5.68-bk8/drivers/char/drm/gamma_dma.c linux-2.5.68-bk9/drivers/char/drm/gamma_dma.c
--- linux-2.5.68-bk8/drivers/char/drm/gamma_dma.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/gamma_dma.c	2003-04-29 04:36:59.000000000 -0700
@@ -639,6 +639,14 @@
 {
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if ( dev->irq ) DRM(irq_uninstall)(dev);
+#endif
+
 	if ( dev->dev_private ) {
 		drm_gamma_private_t *dev_priv = dev->dev_private;
 
@@ -660,6 +668,8 @@
 	drm_device_t *dev = priv->dev;
 	drm_gamma_init_t init;
 
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
 	if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
 		return -EFAULT;
 
@@ -832,6 +842,8 @@
 void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
+	if (!dev_priv)
+		return;
 
 	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
 
diff -urN linux-2.5.68-bk8/drivers/char/drm/gamma_drv.h linux-2.5.68-bk9/drivers/char/drm/gamma_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/gamma_drv.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/gamma_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -49,6 +49,7 @@
 extern int gamma_dma_copy( struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg );
 
+extern int gamma_do_cleanup_dma( drm_device_t *dev );
 extern void gamma_dma_ready(drm_device_t *dev);
 extern void gamma_dma_quiescent_single(drm_device_t *dev);
 extern void gamma_dma_quiescent_dual(drm_device_t *dev);
@@ -60,6 +61,15 @@
 extern int  gamma_find_devices(void);
 extern int  gamma_found(void);
 
+/* Gamma-specific code pulled from drm_fops.h:
+ */
+extern int	     DRM(finish)(struct inode *inode, struct file *filp,
+				 unsigned int cmd, unsigned long arg);
+extern int	     DRM(flush_unblock)(drm_device_t *dev, int context,
+					drm_lock_flags_t flags);
+extern int	     DRM(flush_block_and_flush)(drm_device_t *dev, int context,
+						drm_lock_flags_t flags);
+
 /* Gamma-specific code pulled from drm_dma.h:
  */
 extern void	     DRM(clear_next_buffer)(drm_device_t *dev);
diff -urN linux-2.5.68-bk8/drivers/char/drm/i810.h linux-2.5.68-bk9/drivers/char/drm/i810.h
--- linux-2.5.68-bk8/drivers/char/drm/i810.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i810.h	2003-04-29 04:36:59.000000000 -0700
@@ -86,7 +86,11 @@
  */
 #define __HAVE_RELEASE		1
 #define DRIVER_RELEASE() do {						\
-	i810_reclaim_buffers( filp );				\
+	i810_reclaim_buffers( filp );					\
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do {					\
+	i810_dma_cleanup( dev );					\
 } while (0)
 
 /* DMA customization:
@@ -104,6 +108,7 @@
 /* Don't need an irq any more.  The template code will make sure that
  * a noop stub is generated for compatibility.
  */
+/* XXX: Add vblank support? */
 #define __HAVE_DMA_IRQ		0
 
 /* Buffer customization:
diff -urN linux-2.5.68-bk8/drivers/char/drm/i810_dma.c linux-2.5.68-bk9/drivers/char/drm/i810_dma.c
--- linux-2.5.68-bk8/drivers/char/drm/i810_dma.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i810_dma.c	2003-04-29 04:36:59.000000000 -0700
@@ -227,11 +227,19 @@
 	return retcode;
 }
 
-static int i810_dma_cleanup(drm_device_t *dev)
+int i810_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-	if(dev->dev_private) {
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq) DRM(irq_uninstall)(dev);
+#endif
+
+	if (dev->dev_private) {
 		int i;
 	   	drm_i810_private_t *dev_priv =
 	     		(drm_i810_private_t *) dev->dev_private;
diff -urN linux-2.5.68-bk8/drivers/char/drm/i810_drv.h linux-2.5.68-bk9/drivers/char/drm/i810_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/i810_drv.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i810_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -38,8 +38,6 @@
 	int currently_mapped;
 	void *virtual;
 	void *kernel_virtual;
-	int map_count;
-   	struct vm_area_struct *vma;
 } drm_i810_buf_priv_t;
 
 typedef struct _drm_i810_ring_buffer{
@@ -86,6 +84,7 @@
 			unsigned int cmd, unsigned long arg);
 extern int  i810_dma_init(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
+extern int  i810_dma_cleanup(drm_device_t *dev);
 extern int  i810_flush_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern void i810_reclaim_buffers(struct file *filp);
diff -urN linux-2.5.68-bk8/drivers/char/drm/i830.h linux-2.5.68-bk9/drivers/char/drm/i830.h
--- linux-2.5.68-bk8/drivers/char/drm/i830.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i830.h	2003-04-29 04:36:59.000000000 -0700
@@ -87,7 +87,11 @@
  */
 #define __HAVE_RELEASE		1
 #define DRIVER_RELEASE() do {						\
-	i830_reclaim_buffers( filp );				\
+	i830_reclaim_buffers( filp );					\
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do {					\
+	i830_dma_cleanup( dev );					\
 } while (0)
 
 /* DMA customization:
@@ -107,45 +111,17 @@
  * the card, but are subject to subtle interactions between bios,
  * hardware and the driver.
  */
+/* XXX: Add vblank support? */
 #define USE_IRQS 0
 
-
 #if USE_IRQS
 #define __HAVE_DMA_IRQ		1
 #define __HAVE_SHARED_IRQ	1
-
-#define DRIVER_PREINSTALL() do {			\
-	drm_i830_private_t *dev_priv =			\
-		(drm_i830_private_t *)dev->dev_private;	\
-							\
-   	I830_WRITE16( I830REG_HWSTAM, 0xffff );	\
-        I830_WRITE16( I830REG_INT_MASK_R, 0x0 );	\
-      	I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );	\
-} while (0)
-
-
-#define DRIVER_POSTINSTALL() do {				\
-	drm_i830_private_t *dev_priv =				\
-		(drm_i830_private_t *)dev->dev_private;		\
-   	I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );		\
-   	atomic_set(&dev_priv->irq_received, 0);			\
-   	atomic_set(&dev_priv->irq_emitted, 0);			\
-	init_waitqueue_head(&dev_priv->irq_queue);		\
-} while (0)
-
-
-/* This gets called too late to be useful: dev_priv has already been
- * freed.
- */
-#define DRIVER_UNINSTALL() do {					\
-} while (0)
-
 #else
 #define __HAVE_DMA_IRQ          0
 #endif
 
 
-
 /* Buffer customization:
  */
 
diff -urN linux-2.5.68-bk8/drivers/char/drm/i830_dma.c linux-2.5.68-bk9/drivers/char/drm/i830_dma.c
--- linux-2.5.68-bk8/drivers/char/drm/i830_dma.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i830_dma.c	2003-04-29 04:36:59.000000000 -0700
@@ -227,16 +227,24 @@
 	return retcode;
 }
 
-static int i830_dma_cleanup(drm_device_t *dev)
+int i830_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-	if(dev->dev_private) {
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq) DRM(irq_uninstall)(dev);
+#endif
+
+	if (dev->dev_private) {
 		int i;
 	   	drm_i830_private_t *dev_priv = 
 	     		(drm_i830_private_t *) dev->dev_private;
 	   
-	   	if(dev_priv->ring.virtual_start) {
+	   	if (dev_priv->ring.virtual_start) {
 		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
 					 dev_priv->ring.Size);
 		}
@@ -248,14 +256,6 @@
 		   	I830_WRITE(0x02080, 0x1ffff000);
 		}
 
-		/* Disable interrupts here because after dev_private
-		 * is freed, it's too late.
-		 */
-		if (dev->irq) {
-			I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
-			I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
-		}
-
 	   	DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), 
 			 DRM_MEM_DRIVER);
 	   	dev->dev_private = NULL;
diff -urN linux-2.5.68-bk8/drivers/char/drm/i830_drv.h linux-2.5.68-bk9/drivers/char/drm/i830_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/i830_drv.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i830_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -38,8 +38,6 @@
 	int currently_mapped;
 	void *virtual;
 	void *kernel_virtual;
-	int map_count;
-   	struct vm_area_struct *vma;
 } drm_i830_buf_priv_t;
 
 typedef struct _drm_i830_ring_buffer{
@@ -99,6 +97,7 @@
 			unsigned int cmd, unsigned long arg);
 extern int  i830_dma_init(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
+extern int  i830_dma_cleanup(drm_device_t *dev);
 extern int  i830_flush_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern void i830_reclaim_buffers(struct file *filp);
diff -urN linux-2.5.68-bk8/drivers/char/drm/i830_irq.c linux-2.5.68-bk9/drivers/char/drm/i830_irq.c
--- linux-2.5.68-bk8/drivers/char/drm/i830_irq.c	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/i830_irq.c	2003-04-29 04:36:59.000000000 -0700
@@ -40,12 +40,12 @@
 	drm_device_t	 *dev = (drm_device_t *)device;
       	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
    	u16 temp;
-   
+
       	temp = I830_READ16(I830REG_INT_IDENTITY_R);
-	printk("%s: %x\n", __FUNCTION__, temp);
-	
-   	if(temp == 0) 
-	   return;
+	DRM_DEBUG("%x\n", temp);
+
+   	if (temp == 0) 
+		return;
 
 	I830_WRITE16(I830REG_INT_IDENTITY_R, temp); 
 
@@ -175,3 +175,34 @@
 	return i830_wait_irq( dev, irqwait.irq_seq );
 }
 
+
+/* drm_dma.h hooks
+*/
+void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+	drm_i830_private_t *dev_priv =
+		(drm_i830_private_t *)dev->dev_private;
+
+	I830_WRITE16( I830REG_HWSTAM, 0xffff );
+	I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
+	I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+	atomic_set(&dev_priv->irq_received, 0);
+	atomic_set(&dev_priv->irq_emitted, 0);
+	init_waitqueue_head(&dev_priv->irq_queue);
+}
+
+void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+	drm_i830_private_t *dev_priv =
+		(drm_i830_private_t *)dev->dev_private;
+
+	I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
+}
+
+void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+	drm_i830_private_t *dev_priv =
+		(drm_i830_private_t *)dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
+	I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+}
diff -urN linux-2.5.68-bk8/drivers/char/drm/mga.h linux-2.5.68-bk9/drivers/char/drm/mga.h
--- linux-2.5.68-bk8/drivers/char/drm/mga.h	2003-04-19 19:48:46.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/mga.h	2003-04-29 04:36:59.000000000 -0700
@@ -72,7 +72,7 @@
 /* Driver customization:
  */
 #define DRIVER_PRETAKEDOWN() do {					\
-	if ( dev->dev_private ) mga_do_cleanup_dma( dev );		\
+	mga_do_cleanup_dma( dev );					\
 } while (0)
 
 /* DMA customization:
diff -urN linux-2.5.68-bk8/drivers/char/drm/mga_dma.c linux-2.5.68-bk9/drivers/char/drm/mga_dma.c
--- linux-2.5.68-bk8/drivers/char/drm/mga_dma.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/mga_dma.c	2003-04-29 04:36:59.000000000 -0700
@@ -639,6 +639,14 @@
 {
 	DRM_DEBUG( "\n" );
 
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if ( dev->irq ) DRM(irq_uninstall)(dev);
+#endif
+
 	if ( dev->dev_private ) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
 
@@ -666,6 +674,8 @@
 	DRM_DEVICE;
 	drm_mga_init_t init;
 
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
diff -urN linux-2.5.68-bk8/drivers/char/drm/mga_drv.h linux-2.5.68-bk9/drivers/char/drm/mga_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/mga_drv.h	2003-04-19 19:50:45.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/mga_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -131,7 +131,7 @@
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
 extern int mga_warp_init( drm_mga_private_t *dev_priv );
 
-#define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER(dev_priv->primary)
+#define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 
 #if defined(__linux__) && defined(__alpha__)
 #define MGA_BASE( reg )		((unsigned long)(dev_priv->mmio->handle))
@@ -142,12 +142,12 @@
 
 #define MGA_READ( reg )		(_MGA_READ((u32 *)MGA_ADDR(reg)))
 #define MGA_READ8( reg )	(_MGA_READ((u8 *)MGA_ADDR(reg)))
-#define MGA_WRITE( reg, val )	do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF( reg ) = val; } while (0)
-#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF8( reg ) = val; } while (0)
+#define MGA_WRITE( reg, val )	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
 
 static inline u32 _MGA_READ(u32 *addr)
 {
-	DRM_READMEMORYBARRIER(dev_priv->mmio);
+	DRM_MEMORYBARRIER();
 	return *(volatile u32 *)addr;
 }
 #else
diff -urN linux-2.5.68-bk8/drivers/char/drm/mga_irq.c linux-2.5.68-bk9/drivers/char/drm/mga_irq.c
--- linux-2.5.68-bk8/drivers/char/drm/mga_irq.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/mga_irq.c	2003-04-29 04:36:59.000000000 -0700
@@ -95,8 +95,9 @@
 void mga_driver_irq_uninstall( drm_device_t *dev ) {
   	drm_mga_private_t *dev_priv = 
 	   (drm_mga_private_t *)dev->dev_private;
-	if ( dev_priv ) {
-		/* Disable *all* interrupts */
-		MGA_WRITE( MGA_IEN, 0 );
-	}
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	MGA_WRITE( MGA_IEN, 0 );
 }
diff -urN linux-2.5.68-bk8/drivers/char/drm/r128.h linux-2.5.68-bk9/drivers/char/drm/r128.h
--- linux-2.5.68-bk8/drivers/char/drm/r128.h	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/r128.h	2003-04-29 04:36:59.000000000 -0700
@@ -85,7 +85,7 @@
 } while (0)
 
 #define DRIVER_PRETAKEDOWN() do {					\
-	if ( dev->dev_private ) r128_do_cleanup_cce( dev );		\
+	r128_do_cleanup_cce( dev );					\
 } while (0)
 
 /* DMA customization:
diff -urN linux-2.5.68-bk8/drivers/char/drm/r128_cce.c linux-2.5.68-bk9/drivers/char/drm/r128_cce.c
--- linux-2.5.68-bk8/drivers/char/drm/r128_cce.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/r128_cce.c	2003-04-29 04:36:59.000000000 -0700
@@ -613,6 +613,15 @@
 
 int r128_do_cleanup_cce( drm_device_t *dev )
 {
+
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if ( dev->irq ) DRM(irq_uninstall)(dev);
+#endif
+
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
@@ -649,6 +658,8 @@
 
 	DRM_DEBUG( "\n" );
 
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
diff -urN linux-2.5.68-bk8/drivers/char/drm/r128_drv.h linux-2.5.68-bk9/drivers/char/drm/r128_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/r128_drv.h	2003-04-19 19:51:21.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/r128_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -440,7 +440,7 @@
 #if defined(__powerpc__)
 #define r128_flush_write_combine()	(void) GET_RING_HEAD( &dev_priv->ring )
 #else
-#define r128_flush_write_combine()	DRM_WRITEMEMORYBARRIER(dev_priv->ring_rptr)
+#define r128_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 #endif
 
 
diff -urN linux-2.5.68-bk8/drivers/char/drm/r128_irq.c linux-2.5.68-bk9/drivers/char/drm/r128_irq.c
--- linux-2.5.68-bk8/drivers/char/drm/r128_irq.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/r128_irq.c	2003-04-29 04:36:59.000000000 -0700
@@ -95,8 +95,9 @@
 void r128_driver_irq_uninstall( drm_device_t *dev ) {
   	drm_r128_private_t *dev_priv = 
 	   (drm_r128_private_t *)dev->dev_private;
-	if ( dev_priv ) {
-		/* Disable *all* interrupts */
-		R128_WRITE( R128_GEN_INT_CNTL, 0 );
-	}
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	R128_WRITE( R128_GEN_INT_CNTL, 0 );
 }
diff -urN linux-2.5.68-bk8/drivers/char/drm/radeon_cp.c linux-2.5.68-bk9/drivers/char/drm/radeon_cp.c
--- linux-2.5.68-bk8/drivers/char/drm/radeon_cp.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/radeon_cp.c	2003-04-29 04:36:59.000000000 -0700
@@ -1266,6 +1266,14 @@
 {
 	DRM_DEBUG( "\n" );
 
+#if _HAVE_DMA_IRQ
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if ( dev->irq ) DRM(irq_uninstall)(dev);
+#endif
+
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1298,6 +1306,8 @@
 	DRM_DEVICE;
 	drm_radeon_init_t init;
 
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
diff -urN linux-2.5.68-bk8/drivers/char/drm/radeon_drv.h linux-2.5.68-bk9/drivers/char/drm/radeon_drv.h
--- linux-2.5.68-bk8/drivers/char/drm/radeon_drv.h	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/radeon_drv.h	2003-04-29 04:36:59.000000000 -0700
@@ -852,7 +852,7 @@
 
 #define COMMIT_RING() do {						\
 	/* Flush writes to ring */					\
-	DRM_READMEMORYBARRIER( dev_priv->mmio );			\
+	DRM_MEMORYBARRIER();						\
 	GET_RING_HEAD( dev_priv );					\
 	RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );		\
 	/* read from PCI bus to ensure correct posting */		\
diff -urN linux-2.5.68-bk8/drivers/char/drm/radeon_irq.c linux-2.5.68-bk9/drivers/char/drm/radeon_irq.c
--- linux-2.5.68-bk8/drivers/char/drm/radeon_irq.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/char/drm/radeon_irq.c	2003-04-29 04:36:59.000000000 -0700
@@ -250,8 +250,9 @@
 void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
 	drm_radeon_private_t *dev_priv =
 		(drm_radeon_private_t *)dev->dev_private;
-	if ( dev_priv ) {
-		/* Disable *all* interrupts */
-		RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
-	}
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
 }
diff -urN linux-2.5.68-bk8/drivers/eisa/Kconfig linux-2.5.68-bk9/drivers/eisa/Kconfig
--- linux-2.5.68-bk8/drivers/eisa/Kconfig	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/drivers/eisa/Kconfig	2003-04-29 04:37:03.000000000 -0700
@@ -1,6 +1,17 @@
 #
 # EISA configuration
 #
+config EISA_VLB_PRIMING
+	bool "Vesa Local Bus priming"
+	depends on X86_PC && EISA
+	default n
+	---help---
+	  Activate this option if your system contains a Vesa Local
+	  Bus (VLB) card that identify itself as an EISA card (such as
+	  the Adaptec AHA-284x).
+
+	  When in doubt, say N.
+
 config EISA_PCI_EISA
 	bool "Generic PCI/EISA bridge"
 	depends on PCI && EISA
@@ -12,9 +23,12 @@
 
 	  When in doubt, say Y.
 
+# Using EISA_VIRTUAL_ROOT on something other than an Alpha or
+# an X86_PC may lead to crashes...
+
 config EISA_VIRTUAL_ROOT
 	bool "EISA virtual root device"
-	depends on EISA
+	depends on EISA && (ALPHA || X86_PC)
 	default y
 	---help---
 	  Activate this option if your system only have EISA bus
diff -urN linux-2.5.68-bk8/drivers/eisa/Makefile linux-2.5.68-bk9/drivers/eisa/Makefile
--- linux-2.5.68-bk8/drivers/eisa/Makefile	2003-04-19 19:49:32.000000000 -0700
+++ linux-2.5.68-bk9/drivers/eisa/Makefile	2003-04-29 04:37:03.000000000 -0700
@@ -1,5 +1,8 @@
 # Makefile for the Linux device tree
 
+# Being anal sometimes saves a crash/reboot cycle... ;-)
+EXTRA_CFLAGS    := -Werror
+
 obj-$(CONFIG_EISA)	        += eisa-bus.o
 obj-${CONFIG_EISA_PCI_EISA}     += pci_eisa.o
 
diff -urN linux-2.5.68-bk8/drivers/eisa/eisa-bus.c linux-2.5.68-bk9/drivers/eisa/eisa-bus.c
--- linux-2.5.68-bk8/drivers/eisa/eisa-bus.c	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/drivers/eisa/eisa-bus.c	2003-04-29 04:37:03.000000000 -0700
@@ -56,13 +56,22 @@
         u16 rev;
 	int i;
 
-	sig[0] = inb (addr);
-
-	if (sig[0] & 0x80)
-                return NULL;
-
-	for (i = 1; i < 4; i++)
+	for (i = 0; i < 4; i++) {
+#ifdef CONFIG_EISA_VLB_PRIMING
+		/*
+		 * This ugly stuff is used to wake up VL-bus cards
+		 * (AHA-284x is the only known example), so we can
+		 * read the EISA id.
+		 *
+		 * Thankfully, this only exists on x86...
+		 */
+		outb(0x80 + i, addr);
+#endif
 		sig[i] = inb (addr + i);
+
+		if (!i && (sig[0] & 0x80))
+			return NULL;
+	}
 	
         sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
         sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
@@ -123,47 +132,28 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static void __init eisa_register_device (struct eisa_root_device *root,
-					 char *sig, int slot)
+static int __init eisa_register_device (struct eisa_root_device *root,
+					struct eisa_device *edev,
+					char *sig, int slot)
 {
-	struct eisa_device *edev;
-
-	if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL)))
-		return;
-
-	memset (edev, 0, sizeof (*edev));
-	memcpy (edev->id.sig, sig, 7);
+	memcpy (edev->id.sig, sig, EISA_SIG_LEN);
 	edev->slot = slot;
 	edev->base_addr = SLOT_ADDRESS (root, slot);
+	edev->dma_mask = 0xffffffff; /* Default DMA mask */
 	eisa_name_device (edev);
 	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
+	edev->dev.dma_mask = &edev->dma_mask;
 	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
 
-	/* Don't register resource for slot 0, since this will surely
-	 * fail... :-( */
+	edev->res.name  = edev->dev.name;
 
-	if (slot) {
-		edev->res.name  = edev->dev.name;
-		edev->res.start = edev->base_addr;
-		edev->res.end   = edev->res.start + 0xfff;
-		edev->res.flags = IORESOURCE_IO;
-
-		if (request_resource (root->res, &edev->res)) {
-			printk (KERN_WARNING \
-				"Cannot allocate resource for EISA slot %d\n",
-				slot);
-			kfree (edev);
-			return;
-		}
-	}
-	
-	if (device_register (&edev->dev)) {
-		kfree (edev);
-		return;
-	}
+	if (device_register (&edev->dev))
+		return -1;
 
 	device_create_file (&edev->dev, &dev_attr_signature);
+
+	return 0;
 }
 
 static int __init eisa_probe (struct eisa_root_device *root)
@@ -171,54 +161,106 @@
         int i, c;
         char *str;
         unsigned long sig_addr;
+	struct eisa_device *edev;
 
         printk (KERN_INFO "EISA: Probing bus %d at %s\n",
 		root->bus_nr, root->dev->name);
 	
         for (c = 0, i = 0; i <= root->slots; i++) {
-                sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
-                if ((str = decode_eisa_sig (sig_addr))) {
-			if (!i)
-				printk (KERN_INFO "EISA: Motherboard %s detected\n",
-					str);
-			else {
-				printk (KERN_INFO "EISA: slot %d : %s detected.\n",
-					i, str);
+		if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
+			printk (KERN_ERR "EISA: Out of memory for slot %d\n",
+				i);
+			continue;
+		}
+		
+		memset (edev, 0, sizeof (*edev));
 
-				c++;
-			}
+		/* Don't register resource for slot 0, since this is
+		 * very likely to fail... :-( Instead, grab the EISA
+		 * id, now we can display something in /proc/ioports.
+		 */
+
+		if (i) {
+			edev->res.name  = NULL;
+			edev->res.start = SLOT_ADDRESS (root, i);
+			edev->res.end   = edev->res.start + 0xfff;
+			edev->res.flags = IORESOURCE_IO;
+		} else {
+			edev->res.name  = NULL;
+			edev->res.start = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
+			edev->res.end   = edev->res.start + 3;
+			edev->res.flags = IORESOURCE_BUSY;
+		}
+	
+		if (request_resource (root->res, &edev->res)) {
+			printk (KERN_WARNING \
+				"Cannot allocate resource for EISA slot %d\n",
+				i);
+			kfree (edev);
+			continue;
+		}
+
+		sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
+
+                if (!(str = decode_eisa_sig (sig_addr))) {
+			release_resource (&edev->res);
+			kfree (edev);
+			continue;
+		}
+		
+		if (!i)
+			printk (KERN_INFO "EISA: Motherboard %s detected\n",
+				str);
+		else {
+			printk (KERN_INFO "EISA: slot %d : %s detected.\n",
+				i, str);
 
-			eisa_register_device (root, str, i);
-                }
+			c++;
+		}
+
+		if (eisa_register_device (root, edev, str, i)) {
+			printk (KERN_ERR "EISA: Failed to register %s\n", str);
+			release_resource (&edev->res);
+			kfree (edev);
+		}
         }
         printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
 
 	return 0;
 }
 
-
-static LIST_HEAD (eisa_root_head);
+static struct resource eisa_root_res = {
+	.name  = "EISA root resource",
+	.start = 0,
+	.end   = 0xffffffff,
+	.flags = IORESOURCE_IO,
+};
 
 static int eisa_bus_count;
 
-int eisa_root_register (struct eisa_root_device *root)
+int __init eisa_root_register (struct eisa_root_device *root)
 {
-	struct list_head *node;
-	struct eisa_root_device *tmp_root;
+	int err;
 
-	/* Check if this bus base address has been already
-	 * registered. This prevents the virtual root device from
-	 * registering after the real one has, for example... */
-	
-	list_for_each (node, &eisa_root_head) {
-		tmp_root = list_entry (node, struct eisa_root_device, node);
-		if (tmp_root->bus_base_addr == root->bus_base_addr)
-			return -1; /* Space already taken, buddy... */
-	}
+	/* Use our own resources to check if this bus base address has
+	 * been already registered. This prevents the virtual root
+	 * device from registering after the real one has, for
+	 * example... */
+	
+	root->eisa_root_res.name  = eisa_root_res.name;
+	root->eisa_root_res.start = root->res->start;
+	root->eisa_root_res.end   = root->res->end;
+	root->eisa_root_res.flags = IORESOURCE_BUSY;
+
+	if ((err = request_resource (&eisa_root_res, &root->eisa_root_res)))
+		return err;
 	
 	root->bus_nr = eisa_bus_count++;
-	list_add_tail (&root->node, &eisa_root_head);
-	return eisa_probe (root);
+
+	if ((err = eisa_probe (root)))
+		release_resource (&root->eisa_root_res);
+
+	return err;
 }
 
 static int __init eisa_init (void)
diff -urN linux-2.5.68-bk8/drivers/eisa/eisa.ids linux-2.5.68-bk9/drivers/eisa/eisa.ids
--- linux-2.5.68-bk8/drivers/eisa/eisa.ids	2003-04-19 19:48:46.000000000 -0700
+++ linux-2.5.68-bk9/drivers/eisa/eisa.ids	2003-04-29 04:37:03.000000000 -0700
@@ -162,6 +162,17 @@
 CPQ0501 "Compaq DESKPRO/M System Board"
 CPQ0509 "Compaq DESKPRO/M System Board with Audio"
 CPQ0511 "Compaq SYSTEMPRO/LT System Board"
+CPQ0521 "Compaq DESKPRO XL System Board"
+CPQ0531 "Compaq ProSignia 500 System Board"
+CPQ0541 "Compaq ProSignia 300 System Board"
+CPQ0551 "Compaq ProLiant 2500 Server"
+CPQ0552 "Compaq ProLiant 2500 System Board"
+CPQ0553 "Compaq ProLiant 1600 System Board"
+CPQ0559 "Compaq ProLiant 1500 System Board"
+CPQ0561 "Compaq ProLiant 3000 System Board"
+CPQ0571 "Compaq ProSignia 200 Server"
+CPQ0579 "Compaq ProLiant 800 Server"
+CPQ0589 "Compaq ProLiant 850R"
 CPQ0601 "Compaq ProSignia Server"
 CPQ0609 "Compaq ProSignia Server"
 CPQ0611 "Compaq ProSignia Server"
@@ -169,6 +180,30 @@
 CPQ0629 "Compaq ProSignia Server (ASSY # 3154)"
 CPQ0631 "Compaq ProLiant 1000 Server"
 CPQ0639 "Compaq ProLiant 1000 Server"
+CPQ0671 "Compaq ProSignia 200"
+CPQ0679 "Compaq ProLiant 1850R"
+CPQ0680 "Compaq ProLiant CL1850 System Board"
+CPQ0681 "ProLiant CL380"
+CPQ0685 "Compaq ProLiant DL360"
+CPQ0686 "Compaq ProSignia 780"
+CPQ0687 "Compaq ProSignia 740"
+CPQ0688 "Compaq ProLiant 800 System Board"
+CPQ0689 "Compaq ProLiant 1600 System Board"
+CPQ0690 "Compaq ProLiant ML370"
+CPQ0691 "Compaq ProLiant 800"
+CPQ0692 "Compaq ProLiant DL380"
+CPQ0701 "Compaq ProSignia VS"
+CPQ0709 "Compaq ProLiant 3000 System Board"
+CPQ0711 "Compaq ProSignia VS"
+CPQ0712 "Compaq ProLiant ML530"
+CPQ0714 "Compaq ProLiant ML570"
+CPQ0715 "Compaq ProLiant DL580"
+CPQ0718 "Compaq TaskSmart N2400"
+CPQ071D "Compaq TaskSmart C2500"
+CPQ0808 "Compaq ProLiant 5500"
+CPQ0809 "Compaq ProLiant 6500 System Board"
+CPQ0810 "Compaq ProLiant 6400R System Board"
+CPQ0811 "Compaq ProLiant 1500 System Board"
 CPQ1001 "Compaq Portable 486"
 CPQ1009 "Compaq Portable 486/66"
 CPQ1201 "Compaq DESKPRO 486/25"
@@ -178,6 +213,16 @@
 CPQ1501 "Compaq SYSTEMPRO/XL Server"
 CPQ1509 "Compaq ProLiant 4000 Server"
 CPQ1519 "Compaq ProLiant 2000 Server"
+CPQ1529 "Compaq ProLiant 4500 Server"
+CPQ1561 "Compaq ProLiant 5000 System Board"
+CPQ1563 "Compaq ProLiant 6000 System Board"
+CPQ1565 "Compaq ProLiant 6500 System Board"
+CPQ1601 "Compaq ProLiant 7000"
+CPQ1602 "Compaq ProLiant 6000"
+CPQ1603 "Compaq Standard Peripherals Board"
+CPQ1608 "Compaq ProLiant 8500"
+CPQ1609 "Compaq ProLiant 8000"
+CPQ1669 "Compaq ProLiant 7000 System Board"
 CPQ3001 "Compaq Advanced VGA"
 CPQ3011 "Compaq QVision 1024/E Video Controller"
 CPQ3021 "Compaq QVision 1024/I Video Controller"
@@ -189,27 +234,43 @@
 CPQ4002 "Compaq Intelligent Drive Array Controller-2"
 CPQ4010 "Compaq 32-Bit Intelligent Drive Array Expansion Controller"
 CPQ4020 "Compaq SMART Array Controller"
+CPQ4030 "Compaq SMART-2/E Array Controller"
 CPQ4300 "Compaq Advanced ESDI Fixed Disk Controller"
 CPQ4401 "Compaq Integrated SCSI-2 Options Port"
 CPQ4410 "Compaq Integrated 32-Bit Fast-SCSI-2 Controller"
 CPQ4411 "Compaq 32-Bit Fast-SCSI-2 Controller"
 CPQ4420 "Compaq 6260 SCSI-2 Controller"
+CPQ4430 "Compaq 32-Bit Fast-Wide SCSI-2/E Controller"
+CPQ4431 "Compaq 32-Bit Fast-Wide SCSI-2/E Controller"
 CPQ5000 "Compaq 386/33 System Processor Board used as Secondary"
+CPQ5251 "Compaq 5/133 System Processor Board-2MB"
+CPQ5253 "Compaq 5/166 System Processor Board-2MB"
+CPQ5255 "Compaq 5/133 System Processor Board-1MB"
+CPQ525D "Compaq 5/100 System Processor Board-1MB"
 CPQ5281 "Compaq 486/50 System Processor Board used as Secondary"
 CPQ5282 "Compaq 486/50 System Processor Board used as Secondary"
 CPQ5287 "Compaq 5/66 System Processor Board used as Secondary"
+CPQ528A "Compaq 5/100 System Processor Board w/ Transaction Blaster"
+CPQ528B "Compaq 5/100 System Processor Board"
 CPQ528F "Compaq 486DX2/66 System Processor Board used as Secondary"
+CPQ529B "Compaq 5/90 System Processor Board"
+CPQ529F "Compaq 5/133 System Processor Board"
+CPQ52A0 "Compaq System Processor"
 CPQ5900 "Compaq 486/33 System Processor Board used as Secondary"
 CPQ5A00 "Compaq 486/33 System Processor Board (ASSY # 002013) used as Secondary"
 CPQ5B00 "Compaq 486DX2/66 System Processor Board used as Secondary"
 CPQ5C00 "Compaq 486/33 System Processor Board used as Secondary"
 CPQ6000 "Compaq 32-Bit DualSpeed Token Ring Controller"
 CPQ6001 "Compaq 32-Bit DualSpeed Token Ring Controller"
-CPQ6100 "Compaq 32-Bit NetFlex Controller"
+CPQ6002 "Compaq NetFlex-2 TR"
+CPQ6100 "Compaq NetFlex ENET-TR"
 CPQ6101 "Compaq NetFlex-2 Controller"
 CPQ6200 "Compaq DualPort Ethernet Controller"
+CPQ6300 "Compaq NetFlex-2 DualPort TR"
 CPQ7000 "Compaq 32-Bit Server Manager/R Board"
 CPQ7001 "Compaq 32-Bit Server Manager/R Board"
+CPQ7100 "Compaq Remote Insight Board"
+CPQ7200 "Compaq StorageWorks Fibre Channel Host Bus Adapter/E"
 CPQ9004 "Compaq 386/33 Processor Board"
 CPQ9005 "Compaq 386/25 Processor Board"
 CPQ9013 "Compaq 486DX2/66 System Processor Board used as Primary"
@@ -232,16 +293,60 @@
 CPQ9045 "Compaq 5/60 Processor Board"
 CPQ9046 "Compaq 5/60 Processor Board"
 CPQ9047 "Compaq 5/60 Processor Board"
+CPQ9251 "Compaq 5/133 System Processor Board-2MB"
+CPQ9253 "Compaq 5/166 System Processor Board-2MB"
+CPQ9255 "Compaq 5/133 System Processor Board-1MB"
+CPQ925D "Compaq 5/100 System Processor Board-1MB"
+CPQ925F "ProLiant 2500 Dual Pentium Pro Processor Board"
+CPQ9267 "Compaq Pentium II Processor Board"
+CPQ9278 "Compaq Processor Board"
+CPQ9279 "Compaq Processor Board"
+CPQ9280 "Compaq Processor Board"
 CPQ9281 "Compaq 486/50 System Processor Board used as Primary"
 CPQ9282 "Compaq 486/50 System Processor Board used as Primary"
+CPQ9283 "Processor Modules"
+CPQ9285 "Processor Modules"
+CPQ9286 "Compaq Slot-1 Terminator Board"
 CPQ9287 "Compaq 5/66 System Processor Board used as Primary"
+CPQ928A "Compaq 5/100 System Processor Board w/ Transaction Blaster"
+CPQ928B "Compaq 5/100 System Processor Board"
 CPQ928F "Compaq 486DX2/66 System Processor Board used as Primary"
+CPQ929B "Compaq 5/90 System Processor Board"
+CPQ929F "Compaq 5/133 System Processor Board"
+CPQ92A0 "Compaq ProLiant 1500 Processor Board"
+CPQ92A4 "Compaq System Processor Board"
+CPQ92B0 "Compaq Processor Board"
+CPQ92B1 "Compaq FRC Processor Board"
+CPQ92B2 "Compaq Terminator Board"
+CPQ92B3 "6/200 FlexSMP Dual Processor Board"
+CPQ92B4 "Compaq Processor Board"
+CPQ92B5 "Compaq Terminator Board"
+CPQ92B6 "Compaq Processor Board"
+CPQ92B7 "Compaq Processor(s)"
+CPQ92B8 "Compaq Terminator Board"
+CPQ92B9 "Compaq Terminator Board"
+CPQ9351 "Compaq 5/133 System Processor Board-2MB"
+CPQ9353 "Compaq 5/166 System Processor Board-2MB"
+CPQ9355 "Compaq 5/133 System Processor Board-1MB"
+CPQ935D "Compaq 5/100 System Processor Board-1MB"
 CPQ9381 "Compaq 486/50 System Processor Board"
 CPQ9382 "Compaq 486/50 System Processor Board"
 CPQ9387 "Compaq 5/66 System Processor Board"
+CPQ938A "Compaq 5/100 System Processor Board w/ Transaction Blaster"
+CPQ938B "Compaq 5/100 System Processor Board"
+CPQ939B "Compaq 5/90 System Processor Board"
+CPQ939F "Compaq 5/133 System Processor Board"
+CPQ9451 "Compaq 5/133 System Processor Board-2MB"
+CPQ9453 "Compaq 5/166 System Processor Board-2MB"
+CPQ9455 "Compaq 5/133 System Processor Board-1MB"
+CPQ945D "Compaq 5/100 System Processor Board-1MB"
 CPQ9481 "Compaq 486/50 System Processor Board"
 CPQ9482 "Compaq 486/50 System Processor Board"
 CPQ9487 "Compaq 5/66 System Processor Board"
+CPQ948A "Compaq 5/100 System Processor Board w/ Transaction Blaster"
+CPQ948B "Compaq 5/100 System Processor Board"
+CPQ949B "Compaq 5/90 System Processor Board"
+CPQ949F "Compaq 5/133 System Processor Board"
 CPQ9901 "Compaq 486SX/16 Processor Board"
 CPQ9902 "Compaq 486SX/16 Processor Board"
 CPQ9903 "Compaq 486SX/25 Processor Board"
@@ -261,12 +366,21 @@
 CPQ9991 "Compaq 386/33 Desktop Processor Board"
 CPQ9999 "Compaq 486/33 System Processor Board used as Primary"
 CPQ999A "Compaq 486/33 Desktop Processor Board"
+CPQ9A83 "Compaq DESKPRO XL Processor Board"
+CPQ9AA1 "Compaq ProSignia 500 Processor Board"
+CPQ9AA2 "Compaq ProSignia 300 Processor Board"
 CPQA000 "Compaq Enhanced Option Slot Serial Board"
 CPQA010 "Compaq Enhanced Option Slot Modem Board"
+CPQA015 "Compaq Integrated Remote Console (IRC)"
 CPQA020 "Compaq Integrated CD Rom Adapter"
 CPQA030 "Compaq Integrated CD Rom Adapter"
+CPQA040 "Compaq Automatic Server Recovery (ASR)"
+CPQA045 "Compaq Integrated Management Display Information"
 CPQF000 "Compaq Fixed Disk Drive Feature"
 CPQF100 "Compaq Ethernet 16TP Controller"
+CPQF110 "Compaq Token Ring 16TR Controller"
+CPQF120 "Compaq NetFlex-3/E Controller"
+CPQF140 "Compaq NetFlex-3/E Controller"
 CPQFA0D "Compaq SYSTEMPRO 4-Socket System Memory Board"
 CPQFA0E "Compaq SYSTEMPRO 6-Socket System Memory Board"
 CPQFA0F "Compaq DESKPRO 486/25 System Memory Board"
@@ -274,8 +388,11 @@
 CPQFA1B "Compaq DESKPRO 486/50 System Memory Board"
 CPQFA1C "Compaq System Memory Expansion Board"
 CPQFA1D "Compaq SYSTEMPRO/XL Memory Expansion Board"
+CPQFA1E "Compaq Memory Expansion Board"
 CPQFB03 "Compaq Async/Parallel Printer Intf Assy 000990"
 CPQFB07 "Compaq DESKPRO 2400 Baud Modem"
+CPQFB09 "Compaq SpeedPaq 144/I Modem"
+CPQFB11 "Compaq Internal 28.8/33.6 Data+Fax Modem"
 CPQFC0B "Compaq Advanced Graphics 1024 Board"
 CPQFD08 "Compaq 135Mb, 150/250Mb Tape Adapter"
 CPQFD13 "Compaq 15MHz ESDI Fixed Disk Controller 001283"
diff -urN linux-2.5.68-bk8/drivers/ide/ide-disk.c linux-2.5.68-bk9/drivers/ide/ide-disk.c
--- linux-2.5.68-bk8/drivers/ide/ide-disk.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/ide/ide-disk.c	2003-04-29 04:37:03.000000000 -0700
@@ -72,8 +72,6 @@
 
 #include "legacy/pdc4030.h"
 
-static int driver_blocked;
-
 static inline u32 idedisk_read_24 (ide_drive_t *drive)
 {
 	u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
@@ -132,8 +130,24 @@
 	return 0;	/* lba_capacity value may be bad */
 }
 
+static int idedisk_start_tag(ide_drive_t *drive, struct request *rq)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	if (ata_pending_commands(drive) < drive->queue_depth)
+		ret = blk_queue_start_tag(&drive->queue, rq);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
+
 #ifndef CONFIG_IDE_TASKFILE_IO
 
+static int driver_blocked;
+
 /*
  * read_intr() is the handler for disk read/multread interrupts
  */
@@ -344,20 +358,6 @@
 	return DRIVER(drive)->error(drive, "multwrite_intr", stat);
 }
 
-static int idedisk_start_tag(ide_drive_t *drive, struct request *rq)
-{
-	unsigned long flags;
-	int ret = 1;
-
-	spin_lock_irqsave(&ide_lock, flags);
-
-	if (ata_pending_commands(drive) < drive->queue_depth)
-		ret = blk_queue_start_tag(&drive->queue, rq);
-
-	spin_unlock_irqrestore(&ide_lock, flags);
-	return ret;
-}
-
 /*
  * do_rw_disk() issues READ and WRITE commands to a disk,
  * using LBA if supported, or CHS otherwise, to address sectors.
@@ -744,7 +744,7 @@
 		args.tfRegister[IDE_FEATURE_OFFSET] = sectors;
 		args.tfRegister[IDE_NSECTOR_OFFSET] = rq->tag << 3;
 		args.hobRegister[IDE_FEATURE_OFFSET_HOB] = sectors >> 8;
-		args.hobRegister[IDE_NSECT_OFFSET_HOB] = 0;
+		args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = 0;
 	} else {
 		args.tfRegister[IDE_NSECTOR_OFFSET] = sectors;
 		args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = sectors >> 8;
diff -urN linux-2.5.68-bk8/drivers/ide/ide-taskfile.c linux-2.5.68-bk9/drivers/ide/ide-taskfile.c
--- linux-2.5.68-bk8/drivers/ide/ide-taskfile.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/ide/ide-taskfile.c	2003-04-29 04:37:03.000000000 -0700
@@ -189,15 +189,15 @@
 		case WIN_WRITEDMA_ONCE:
 		case WIN_WRITEDMA:
 		case WIN_WRITEDMA_EXT:
-			if (hwif->ide_dma_write(drive))
-				return ide_stopped;
+			if (!hwif->ide_dma_write(drive))
+				return ide_started;
 			break;
 		case WIN_READDMA_ONCE:
 		case WIN_READDMA:
 		case WIN_READDMA_EXT:
 		case WIN_IDENTIFY_DMA:
-			if (hwif->ide_dma_read(drive))
-				return ide_stopped;
+			if (!hwif->ide_dma_read(drive))
+				return ide_started;
 			break;
 		case WIN_READDMA_QUEUED:
 		case WIN_READDMA_QUEUED_EXT:
diff -urN linux-2.5.68-bk8/drivers/ide/legacy/hd98.c linux-2.5.68-bk9/drivers/ide/legacy/hd98.c
--- linux-2.5.68-bk8/drivers/ide/legacy/hd98.c	2003-04-29 04:36:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/ide/legacy/hd98.c	2003-04-29 04:37:03.000000000 -0700
@@ -46,8 +46,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#define MAJOR_NR HD_MAJOR
-#define DEVICE_NR(device) (minor(device)>>6)
 #include <linux/blk.h>
 
 #include "io_ports.h"
@@ -100,6 +98,9 @@
 #define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
 
 static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
+static struct request_queue hd_queue;
+
+#define CURRENT elv_next_request(&hd_queue)
 
 #define TIMEOUT_VALUE	(6*HZ)
 #define	HD_DELAY	0
@@ -115,26 +116,24 @@
 static void recal_intr(void);
 static void bad_rw_intr(void);
 
-static char recalibrate[MAX_HD];
-static char special_op[MAX_HD];
-
 static int reset;
 static int hd_error;
 
-#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
-
 /*
  *  This struct defines the HD's and their types.
  */
 struct hd_i_struct {
 	unsigned int head,sect,cyl,wpcom,lzone,ctl;
+	int unit;
+	int recalibrate;
+	int special_op;
 };
 	
 #ifdef HD_TYPE
-struct hd_i_struct hd_info[] = { HD_TYPE };
+static struct hd_i_struct hd_info[] = { HD_TYPE };
 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
 #else
-struct hd_i_struct hd_info[MAX_HD];
+static struct hd_i_struct hd_info[MAX_HD];
 static int NR_HD;
 #endif
 
@@ -195,11 +194,11 @@
 
 static void dump_status (const char *msg, unsigned int stat)
 {
-	char devc;
-
-	devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
+	char *name = CURRENT ?
+			CURRENT->rq_dev->bd_disk->disk_name :
+			"hd?";
 #ifdef VERBOSE_ERRORS
-	printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
+	printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
 	if (stat & BUSY_STAT)	printk("Busy ");
 	if (stat & READY_STAT)	printk("DriveReady ");
 	if (stat & WRERR_STAT)	printk("WriteFault ");
@@ -213,7 +212,7 @@
 		hd_error = 0;
 	} else {
 		hd_error = inb(HD_ERROR);
-		printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
+		printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff);
 		if (hd_error & BBD_ERR)		printk("BadSector ");
 		if (hd_error & ECC_ERR)		printk("UncorrectableError ");
 		if (hd_error & ID_ERR)		printk("SectorIdNotFound ");
@@ -230,12 +229,12 @@
 		printk("\n");
 	}
 #else
-	printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff);
+	printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff);
 	if ((stat & ERR_STAT) == 0) {
 		hd_error = 0;
 	} else {
 		hd_error = inb(HD_ERROR);
-		printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
+		printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff);
 	}
 #endif
 }
@@ -290,9 +289,13 @@
 	return 0;
 }
 
-static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
-		unsigned int head,unsigned int cyl,unsigned int cmd,
-		void (*intr_addr)(void))
+static void hd_out(struct hd_i_struct *disk,
+		   unsigned int nsect,
+		   unsigned int sect,
+		   unsigned int head,
+		   unsigned int cyl,
+		   unsigned int cmd,
+		   void (*intr_addr)(void))
 {
 	unsigned short port;
 
@@ -302,19 +305,19 @@
 #endif
 	if (reset)
 		return;
-	if (!controller_ready(drive, head)) {
+	if (!controller_ready(disk->unit, head)) {
 		reset = 1;
 		return;
 	}
 	SET_HANDLER(intr_addr);
-	outb(hd_info[drive].ctl,HD_CMD);
+	outb(disk->ctl,HD_CMD);
 	port=HD_DATA + 2;
-	outb(hd_info[drive].wpcom>>2, port); port += 2;
+	outb(disk->wpcom>>2, port); port += 2;
 	outb(nsect, port); port += 2;
 	outb(sect, port); port += 2;
 	outb(cyl, port); port += 2;
 	outb(cyl>>8, port); port += 2;
-	outb(0xA0|(drive<<4)|head, port); port += 2;
+	outb(0xA0|(disk->unit<<4)|head, port); port += 2;
 	outb(cmd, port);
 }
 
@@ -363,9 +366,10 @@
 			goto repeat;
 	}
 	if (++i < NR_HD) {
-		special_op[i] = recalibrate[i] = 1;
-		hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
-			hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
+		struct hd_i_struct *disk = &hd_info[i];
+		disk->special_op = disk->recalibrate = 1;
+		hd_out(disk, disk->sect, disk->sect, disk->head-1,
+			disk->cyl, WIN_SPECIFY, &reset_hd);
 		if (reset)
 			goto repeat;
 	} else
@@ -398,18 +402,19 @@
  */
 static void bad_rw_intr(void)
 {
-	int dev;
+	struct request *req = CURRENT;
+	struct hd_i_struct *disk;
 
-	if (!CURRENT)
+	if (!req)
 		return;
-	dev = DEVICE_NR(CURRENT->rq_dev);
-	if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
-		end_request(CURRENT, 0);
-		special_op[dev] = recalibrate[dev] = 1;
-	} else if (CURRENT->errors % RESET_FREQ == 0)
+	disk = req->rq_disk->private_data;
+	if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
+		end_request(req, 0);
+		disk->special_op = disk->recalibrate = 1;
+	} else if (req->errors % RESET_FREQ == 0)
 		reset = 1;
-	else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
-		special_op[dev] = recalibrate[dev] = 1;
+	else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0)
+		disk->special_op = disk->recalibrate = 1;
 	/* Otherwise just retry */
 }
 
@@ -427,6 +432,7 @@
 static void read_intr(void)
 {
 	int i, retries = 100000;
+	struct request *req;
 
 	do {
 		i = (unsigned) inb(HD_STATUS);
@@ -442,19 +448,20 @@
 	hd_request();
 	return;
 ok_to_read:
-	insw(HD_DATA,CURRENT->buffer,256);
-	CURRENT->sector++;
-	CURRENT->buffer += 512;
-	CURRENT->errors = 0;
-	i = --CURRENT->nr_sectors;
-	--CURRENT->current_nr_sectors;
+	req = CURRENT;
+	insw(HD_DATA,req->buffer,256);
+	req->sector++;
+	req->buffer += 512;
+	req->errors = 0;
+	i = --req->nr_sectors;
+	--req->current_nr_sectors;
 #ifdef DEBUG
-	printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n",
-		dev+'a', CURRENT->sector, CURRENT->nr_sectors,
-		(unsigned long) CURRENT->buffer+512);
+	printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
+		req->rq_disk->disk_name, req->sector, req->nr_sectors,
+		req->buffer+512);
 #endif
-	if (CURRENT->current_nr_sectors <= 0)
-		end_request(CURRENT, 1);
+	if (req->current_nr_sectors <= 0)
+		end_request(req, 1);
 	if (i > 0) {
 		SET_HANDLER(&read_intr);
 		return;
@@ -472,6 +479,7 @@
 {
 	int i;
 	int retries = 100000;
+	struct request *req = CURRENT;
 
 	do {
 		i = (unsigned) inb(HD_STATUS);
@@ -479,7 +487,7 @@
 			continue;
 		if (!OK_STATUS(i))
 			break;
-		if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
+		if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
 			goto ok_to_write;
 	} while (--retries > 0);
 	dump_status("write_intr", i);
@@ -487,15 +495,15 @@
 	hd_request();
 	return;
 ok_to_write:
-	CURRENT->sector++;
-	i = --CURRENT->nr_sectors;
-	--CURRENT->current_nr_sectors;
-	CURRENT->buffer += 512;
-	if (!i || (CURRENT->bio && !SUBSECTOR(i)))
-		end_request(CURRENT, 1);
+	req->sector++;
+	i = --req->nr_sectors;
+	--req->current_nr_sectors;
+	req->buffer += 512;
+	if (!i || (req->bio && req->current_nr_sectors < 1))
+		end_request(req, 1);
 	if (i > 0) {
 		SET_HANDLER(&write_intr);
-		outsw(HD_DATA,CURRENT->buffer,256);
+		outsw(HD_DATA,req->buffer,256);
 		local_irq_enable();
 	} else {
 #if (HD_DELAY > 0)
@@ -521,8 +529,6 @@
  */
 static void hd_times_out(unsigned long dummy)
 {
-	unsigned int dev;
-
 	do_hd = NULL;
 
 	if (!CURRENT)
@@ -531,11 +537,10 @@
 	disable_irq(HD_IRQ);
 	local_irq_enable();
 	reset = 1;
-	dev = DEVICE_NR(CURRENT->rq_dev);
-	printk("hd%c: timeout\n", dev+'a');
+	printk("%s: timeout\n", CURRENT->rq_disk->disk_name);
 	if (++CURRENT->errors >= MAX_ERRORS) {
 #ifdef DEBUG
-		printk("hd%c: too many errors\n", dev+'a');
+		printk("%s: too many errors\n", CURRENT->rq_disk->disk_name);
 #endif
 		end_request(CURRENT, 0);
 	}
@@ -544,18 +549,18 @@
 	enable_irq(HD_IRQ);
 }
 
-int do_special_op (unsigned int dev)
+int do_special_op(struct hd_i_struct *disk, struct request *req)
 {
-	if (recalibrate[dev]) {
-		recalibrate[dev] = 0;
-		hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+	if (disk->recalibrate) {
+		disk->recalibrate = 0;
+		hd_out(disk, disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
 		return reset;
 	}
-	if (hd_info[dev].head > 16) {
-		printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
-		end_request(CURRENT, 0);
+	if (disk->head > 16) {
+		printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
+		end_request(req, 0);
 	}
-	special_op[dev] = 0;
+	disk->special_op = 0;
 	return 1;
 }
 
@@ -571,7 +576,9 @@
  */
 static void hd_request(void)
 {
-	unsigned int dev, block, nsect, sec, track, head, cyl;
+	unsigned int block, nsect, sec, track, head, cyl;
+	struct hd_i_struct *disk;
+	struct request *req;
 
 	if (do_hd)
 		return;
@@ -583,62 +590,58 @@
 		do_hd = NULL;
 		return;
 	}
+	req = CURRENT;
 
 	if (reset) {
 		local_irq_disable();
 		reset_hd();
 		return;
 	}
-	dev = DEVICE_NR(CURRENT->rq_dev);
-	block = CURRENT->sector;
-	nsect = CURRENT->nr_sectors;
-	if (dev >= NR_HD) {
-		printk("hd: bad disk number: %d\n", dev);
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	if (block >= get_capacity(hd_gendisk[dev]) ||
-	    ((block+nsect) > get_capacity(hd_gendisk[dev]))) {
+	disk = req->rq_disk->private_data;
+	block = req->sector;
+	nsect = req->nr_sectors;
+	if (block >= get_capacity(req->rq_disk) ||
+	    ((block+nsect) > get_capacity(req->rq_disk))) {
 		printk("%s: bad access: block=%d, count=%d\n",
-			hd_gendisk[dev]->disk_name, block, nsect);
-		end_request(CURRENT, 0);
+			req->rq_disk->disk_name, block, nsect);
+		end_request(req, 0);
 		goto repeat;
 	}
 
-	if (special_op[dev]) {
-		if (do_special_op(dev))
+	if (disk->special_op) {
+		if (do_special_op(disk, req))
 			goto repeat;
 		return;
 	}
-	sec   = block % hd_info[dev].sect + 1;
-	track = block / hd_info[dev].sect;
-	head  = track % hd_info[dev].head;
-	cyl   = track / hd_info[dev].head;
+	sec   = block % disk->sect + 1;
+	track = block / disk->sect;
+	head  = track % disk->head;
+	cyl   = track / disk->head;
 #ifdef DEBUG
-	printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
-		dev+'a', (CURRENT->cmd == READ)?"read":"writ",
-		cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
+	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
+		req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+		cyl, head, sec, nsect, req->buffer);
 #endif
-	if(CURRENT->flags & REQ_CMD) {
-		switch (rq_data_dir(CURRENT)) {
+	if (req->flags & REQ_CMD) {
+		switch (rq_data_dir(req)) {
 		case READ:
-			hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
+			hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
 			if (reset)
 				goto repeat;
 			break;
 		case WRITE:
-			hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
+			hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 			if (reset)
 				goto repeat;
 			if (wait_DRQ()) {
 				bad_rw_intr();
 				goto repeat;
 			}
-			outsw(HD_DATA,CURRENT->buffer,256);
+			outsw(HD_DATA,req->buffer,256);
 			break;
 		default:
 			printk("unknown hd-command\n");
-			end_request(CURRENT, 0);
+			end_request(req, 0);
 			break;
 		}
 	}
@@ -654,34 +657,19 @@
 static int hd_ioctl(struct inode * inode, struct file * file,
 	unsigned int cmd, unsigned long arg)
 {
+	struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
-	int dev = DEVICE_NR(inode->i_rdev);
+	struct hd_geometry g; 
 
-	if (dev >= NR_HD)
+	if (cmd != HDIO_GETGEO)
 		return -EINVAL;
-	switch (cmd) {
-		case HDIO_GETGEO:
-		{
-			struct hd_geometry g; 
-			if (!loc)  return -EINVAL;
-			g.heads = hd_info[dev].head;
-			g.sectors = hd_info[dev].sect;
-			g.cylinders = hd_info[dev].cyl;
-			g.start = get_start_sect(inode->i_bdev);
-			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
-		}
-
-		default:
-			return -EINVAL;
-	}
-}
-
-static int hd_open(struct inode * inode, struct file * filp)
-{
-	int target =  DEVICE_NR(inode->i_rdev);
-	if (target >= NR_HD)
-		return -ENODEV;
-	return 0;
+	if (!loc)
+		return -EINVAL;
+	g.heads = disk->head;
+	g.sectors = disk->sect;
+	g.cylinders = disk->cyl;
+	g.start = get_start_sect(inode->i_bdev);
+	return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
 }
 
 /*
@@ -689,8 +677,6 @@
  * be forgotten about...
  */
 
-extern struct block_device_operations hd_fops;
-
 static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	void (*handler)(void) = do_hd;
@@ -704,7 +690,6 @@
 }
 
 static struct block_device_operations hd_fops = {
-	.open =		hd_open,
 	.ioctl =	hd_ioctl,
 };
 
@@ -721,15 +706,15 @@
 static int __init hd_init(void)
 {
 	int drive;
-	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+	if (register_blkdev(HD_MAJOR,"hd")) {
+		printk("hd: unable to get major %d for hard disk\n",HD_MAJOR);
 		return -1;
 	}
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
-	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
+	blk_init_queue(&hd_queue, do_hd_request, &hd_lock);
+	blk_queue_max_sectors(&hd_queue, 255);
 	init_timer(&device_timer);
 	device_timer.function = hd_times_out;
-	blk_queue_hardsect_size(QUEUE, 512);
+	blk_queue_hardsect_size(&hd_queue, 512);
 
 #ifdef __i386__
 	if (!NR_HD) {
@@ -768,24 +753,22 @@
 		goto out;
 
 	for (drive=0 ; drive < NR_HD ; drive++) {
-		struct gendisk *disk = alloc_disk();
+		struct gendisk *disk = alloc_disk(64);
+		struct hd_i_struct *p = &hd_info[drive];
 		if (!disk)
 			goto Enomem;
-		disk->major = MAJOR_NR;
+		disk->major = HD_MAJOR;
 		disk->first_minor = drive << 6;
-		disk->minor_shift = 6;
 		disk->fops = &hd_fops;
 		sprintf(disk->disk_name, "hd%c", 'a'+drive);
+		disk->private_data = p;
+		set_capacity(disk, p->head * p->sect * p->cyl);
+		disk->queue = &hd_queue;
+		p->unit = drive;
 		hd_gendisk[drive] = disk;
-	}
-	for (drive=0 ; drive < NR_HD ; drive++) {
-		sector_t size = hd_info[drive].head *
-			hd_info[drive].sect * hd_info[drive].cyl;
-		set_capacity(hd_gendisk[drive], size);
-		printk ("%s: %ldMB, CHS=%d/%d/%d\n",
-			hd_gendisk[drive]->disk_name,
-			size / 2048, hd_info[drive].cyl,
-			hd_info[drive].head, hd_info[drive].sect);
+		printk ("%s: %luMB, CHS=%d/%d/%d\n",
+			disk->disk_name, (unsigned long)get_capacity(disk)/2048,
+			p->cyl, p->head, p->sect);
 	}
 
 	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
@@ -849,11 +832,8 @@
 		goto out9;
 	}
 
-	for(drive=0; drive < NR_HD; drive++) {
-		struct hd_i_struct *p = hd_info + drive;
-		set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl);
+	for(drive=0; drive < NR_HD; drive++)
 		add_disk(hd_gendisk[drive]);
-	}
 	return 0;
 
 out9:
@@ -879,8 +859,8 @@
 	NR_HD = 0;
 out:
 	del_timer(&device_timer);
-	unregister_blkdev(MAJOR_NR,"hd");
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	unregister_blkdev(HD_MAJOR,"hd");
+	blk_cleanup_queue(&hd_queue);
 	return -1;
 Enomem:
 	while (drive--)
diff -urN linux-2.5.68-bk8/drivers/isdn/capi/capifs.c linux-2.5.68-bk9/drivers/isdn/capi/capifs.c
--- linux-2.5.68-bk8/drivers/isdn/capi/capifs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/isdn/capi/capifs.c	2003-04-29 04:37:04.000000000 -0700
@@ -153,39 +153,17 @@
 	.kill_sb	= kill_anon_super,
 };
 
-static spinlock_t entries_lock = SPIN_LOCK_UNLOCKED;
 static struct vfsmount *capifs_mnt;
-static int entry_count = 0;
+static int entry_count;
 
-static struct vfsmount *grab_instance(void)
+static int grab_instance(void)
 {
-	struct vfsmount *mnt = NULL;
-	spin_lock(&entries_lock);
-	if (!capifs_mnt) {
-		spin_unlock(&entries_lock);
-		mnt = kern_mount(&capifs_fs_type);
-		if (IS_ERR(mnt))
-			return NULL;
-		spin_lock(&entries_lock);
-		if (!capifs_mnt)
-			capifs_mnt = mnt;
-	}
-	mntget(capifs_mnt);
-	entry_count++;
-	spin_unlock(&entries_lock);
-	mntput(mnt);
-	return capifs_mnt;
+	return simple_pin_fs("capifs", &capifs_mnt, &entry_count);
 }
 
 static void drop_instance(void)
 {
-	struct vfsmount *mnt;
-	spin_lock(&entries_lock);
-	mnt = capifs_mnt;
-	if (!--entry_count)
-		capifs_mnt = NULL;
-	spin_unlock(&entries_lock);
-	mntput(mnt);
+	return simple_release_fs(&capifs_mnt, &entry_count);
 }
 
 static struct dentry *get_node(int type, int num)
@@ -207,7 +185,7 @@
 	struct dentry *dentry;
 	struct inode *inode;
 
-	if (!grab_instance())
+	if (grab_instance() < 0)
 		return;
 	sb = capifs_mnt->mnt_sb;
 	inode = new_inode(sb);
@@ -232,7 +210,7 @@
 
 void capifs_free_ncci(char type, unsigned int num)
 {
-	if (grab_instance()) {
+	if (grab_instance() == 0) {
 		struct dentry *dentry = get_node(type, num);
 		if (!IS_ERR(dentry)) {
 			struct inode *inode = dentry->d_inode;
diff -urN linux-2.5.68-bk8/drivers/macintosh/macio-adb.c linux-2.5.68-bk9/drivers/macintosh/macio-adb.c
--- linux-2.5.68-bk8/drivers/macintosh/macio-adb.c	2003-04-19 19:51:16.000000000 -0700
+++ linux-2.5.68-bk9/drivers/macintosh/macio-adb.c	2003-04-29 04:37:05.000000000 -0700
@@ -63,7 +63,7 @@
 
 static int macio_probe(void);
 static int macio_init(void);
-static void macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs);
 static int macio_send_request(struct adb_request *req, int sync);
 static int macio_adb_autopoll(int devs);
 static void macio_adb_poll(void);
@@ -198,7 +198,8 @@
 	return 0;
 }
 
-static void macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t macio_adb_interrupt(int irq, void *arg,
+				       struct pt_regs *regs)
 {
 	int i, n, err;
 	struct adb_request *req;
@@ -206,9 +207,11 @@
 	int ibuf_len = 0;
 	int complete = 0;
 	int autopoll = 0;
-	
+	int handled = 0;
+
 	spin_lock(&macio_lock);
 	if (in_8(&adb->intr.r) & TAG) {
+		handled = 1;
 		if ((req = current_req) != 0) {
 			/* put the current request in */
 			for (i = 0; i < req->nbytes; ++i)
@@ -229,6 +232,7 @@
 	}
 
 	if (in_8(&adb->intr.r) & DFB) {
+		handled = 1;
 		err = in_8(&adb->error.r);
 		if (current_req && current_req->sent) {
 			/* this is the response to a command */
@@ -266,6 +270,8 @@
 	}
 	if (ibuf_len)
 		adb_input(ibuf, ibuf_len, regs, autopoll);
+
+	return IRQ_RETVAL(handled);
 }
 
 static void macio_adb_poll(void)
diff -urN linux-2.5.68-bk8/drivers/macintosh/macserial.c linux-2.5.68-bk9/drivers/macintosh/macserial.c
--- linux-2.5.68-bk8/drivers/macintosh/macserial.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/macintosh/macserial.c	2003-04-29 04:37:05.000000000 -0700
@@ -154,8 +154,8 @@
 static int setup_scc(struct mac_serial * info);
 static void dbdma_reset(volatile struct dbdma_regs *dma);
 static void dbdma_flush(volatile struct dbdma_regs *dma);
-static void rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs);
-static void rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs);
 static void dma_init(struct mac_serial * info);
 static void rxdma_start(struct mac_serial * info, int current);
 static void rxdma_to_tty(struct mac_serial * info);
@@ -558,18 +558,19 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct mac_serial *info = (struct mac_serial *) dev_id;
 	unsigned char zs_intreg;
 	int shift;
 	unsigned long flags;
+	int handled = 0;
 
 	if (!(info->flags & ZILOG_INITIALIZED)) {
 		printk(KERN_WARNING "rs_interrupt: irq %d, port not "
 				    "initialized\n", irq);
 		disable_irq(irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	/* NOTE: The read register 3, which holds the irq status,
@@ -595,6 +596,7 @@
 
 		if ((zs_intreg & CHAN_IRQMASK) == 0)
 			break;
+		handled = 1;
 
 		if (zs_intreg & CHBRxIP) {
 			/* If we are doing DMA, we only ask for interrupts
@@ -610,30 +612,32 @@
 			status_handle(info);
 	}
 	spin_unlock_irqrestore(&info->lock, flags);
+	return IRQ_RETVAL(handled);
 }
 
 /* Transmit DMA interrupt - not used at present */
-static void rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
+	return IRQ_HANDLED;
 }
 
 /*
  * Receive DMA interrupt.
  */
-static void rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct mac_serial *info = (struct mac_serial *) dev_id;
 	volatile struct dbdma_cmd *cd;
 
 	if (!info->dma_initted)
-		return;
+		return IRQ_NONE;
 	spin_lock(&info->rx_dma_lock);
 	/* First, confirm that this interrupt is, indeed, coming */
 	/* from Rx DMA */
 	cd = info->rx_cmds[info->rx_cbuf] + 2;
 	if ((in_le16(&cd->xfer_status) & (RUN | ACTIVE)) != (RUN | ACTIVE)) {
 		spin_unlock(&info->rx_dma_lock);
-		return;
+		return IRQ_NONE;
 	}
 	if (info->rx_fbuf != RX_NO_FBUF) {
 		info->rx_cbuf = info->rx_fbuf;
@@ -643,6 +647,7 @@
 			info->rx_fbuf = RX_NO_FBUF;
 	}
 	spin_unlock(&info->rx_dma_lock);
+	return IRQ_HANDLED;
 }
 
 /*
@@ -2660,9 +2665,9 @@
 	callout_driver.proc_entry = 0;
 
 	if (tty_register_driver(&serial_driver))
-		panic("Couldn't register serial driver\n");
+		printk(KERN_ERR "Error: couldn't register serial driver\n");
 	if (tty_register_driver(&callout_driver))
-		panic("Couldn't register callout driver\n");
+		printk(KERN_ERR "Error: couldn't register callout driver\n");
 
 	for (channel = 0; channel < zs_channels_found; ++channel) {
 #ifdef CONFIG_KGDB
diff -urN linux-2.5.68-bk8/drivers/macintosh/via-cuda.c linux-2.5.68-bk9/drivers/macintosh/via-cuda.c
--- linux-2.5.68-bk8/drivers/macintosh/via-cuda.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/macintosh/via-cuda.c	2003-04-29 04:37:05.000000000 -0700
@@ -107,7 +107,7 @@
 
 static int cuda_init_via(void);
 static void cuda_start(void);
-static void cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
 static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
 void cuda_poll(void);
 static int cuda_write(struct adb_request *req);
@@ -441,7 +441,7 @@
     local_irq_restore(flags);
 }
 
-static void
+static irqreturn_t
 cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
     int status;
@@ -457,7 +457,7 @@
     out_8(&via[IFR], virq);   
     if ((virq & SR_INT) == 0) {
         spin_unlock(&cuda_lock);
-	return;
+	return IRQ_NONE;
     }
     
     status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
@@ -595,6 +595,7 @@
     }
     if (ibuf_len)
 	cuda_input(ibuf, ibuf_len, regs);
+    return IRQ_HANDLED;
 }
 
 static void
diff -urN linux-2.5.68-bk8/drivers/macintosh/via-pmu.c linux-2.5.68-bk9/drivers/macintosh/via-pmu.c
--- linux-2.5.68-bk8/drivers/macintosh/via-pmu.c	2003-04-19 19:50:48.000000000 -0700
+++ linux-2.5.68-bk9/drivers/macintosh/via-pmu.c	2003-04-29 04:37:05.000000000 -0700
@@ -180,8 +180,8 @@
 static int init_pmu(void);
 static int pmu_queue_request(struct adb_request *req);
 static void pmu_start(void);
-static void via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
-static void gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
 static int proc_get_info(char *page, char **start, off_t off,
 			  int count, int *eof, void *data);
 #ifdef CONFIG_PMAC_BACKLIGHT
@@ -1393,7 +1393,7 @@
 	return NULL;
 }
 
-static void __pmac
+static irqreturn_t __pmac
 via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
 	unsigned long flags;
@@ -1401,7 +1401,8 @@
 	int nloop = 0;
 	int int_data = -1;
 	struct adb_request *req = NULL;
-	
+	int handled = 0;
+
 	/* This is a bit brutal, we can probably do better */
 	spin_lock_irqsave(&pmu_lock, flags);
 	++disable_poll;
@@ -1410,6 +1411,7 @@
 		intr = in_8(&via[IFR]) & (SR_INT | CB1_INT);
 		if (intr == 0)
 			break;
+		handled = 1;
 		if (++nloop > 1000) {
 			printk(KERN_DEBUG "PMU: stuck in intr loop, "
 			       "intr=%x, ier=%x pmu_state=%d\n",
@@ -1473,15 +1475,19 @@
 		int_data = -1;
 		goto recheck;
 	}
+
+	return IRQ_RETVAL(handled);
 }
 
-static void __pmac
+static irqreturn_t __pmac
 gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
 	if ((in_8(gpio_reg + 0x9) & 0x02) == 0) {
 		adb_int_pending = 1;
 		via_pmu_interrupt(0, 0, 0);
+		return IRQ_HANDLED;
 	}
+	return IRQ_NONE;
 }
 
 #ifdef CONFIG_PMAC_BACKLIGHT
diff -urN linux-2.5.68-bk8/drivers/md/dm-ioctl.c linux-2.5.68-bk9/drivers/md/dm-ioctl.c
--- linux-2.5.68-bk8/drivers/md/dm-ioctl.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/md/dm-ioctl.c	2003-04-29 04:37:05.000000000 -0700
@@ -450,11 +450,11 @@
 	if (dm_suspended(md))
 		param->flags |= DM_SUSPEND_FLAG;
 
-	param->dev = MKDEV(disk->major, disk->first_minor);
-	bdev = bdget(param->dev);
+	bdev = bdget_disk(disk, 0);
 	if (!bdev)
 		return -ENXIO;
 
+	param->dev = bdev->bd_dev;
 	param->open_count = bdev->bd_openers;
 	bdput(bdev);
 
diff -urN linux-2.5.68-bk8/drivers/md/dm-table.c linux-2.5.68-bk9/drivers/md/dm-table.c
--- linux-2.5.68-bk8/drivers/md/dm-table.c	2003-04-19 19:51:13.000000000 -0700
+++ linux-2.5.68-bk9/drivers/md/dm-table.c	2003-04-29 04:37:05.000000000 -0700
@@ -345,26 +345,21 @@
 static int open_dev(struct dm_dev *d, dev_t dev)
 {
 	static char *_claim_ptr = "I belong to device-mapper";
+	struct block_device *bdev;
 
 	int r;
 
 	if (d->bdev)
 		BUG();
 
-	d->bdev = bdget(dev);
-	if (!d->bdev)
-		return -ENOMEM;
-
-	r = blkdev_get(d->bdev, d->mode, 0, BDEV_RAW);
+	bdev = open_by_devnum(dev, d->mode, BDEV_RAW);
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
+	r = bd_claim(bdev, _claim_ptr);
 	if (r)
-		return r;
-
-	r = bd_claim(d->bdev, _claim_ptr);
-	if (r) {
-		blkdev_put(d->bdev, BDEV_RAW);
-		d->bdev = NULL;
-	}
-
+		blkdev_put(bdev, BDEV_RAW);
+	else
+		d->bdev = bdev;
 	return r;
 }
 
diff -urN linux-2.5.68-bk8/drivers/md/md.c linux-2.5.68-bk9/drivers/md/md.c
--- linux-2.5.68-bk8/drivers/md/md.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/md/md.c	2003-04-29 04:37:05.000000000 -0700
@@ -1046,12 +1046,9 @@
 	int err = 0;
 	struct block_device *bdev;
 
-	bdev = bdget(dev);
-	if (!bdev)
-		return -ENOMEM;
-	err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW);
-	if (err)
-		return err;
+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE, BDEV_RAW);
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
 	err = bd_claim(bdev, rdev);
 	if (err) {
 		blkdev_put(bdev, BDEV_RAW);
@@ -1687,7 +1684,7 @@
 
 		del_timer_sync(&mddev->safemode_timer);
 
-		invalidate_device(mk_kdev(disk->major, disk->first_minor), 1);
+		invalidate_partition(disk, 0);
 
 		if (ro) {
 			err  = -ENXIO;
diff -urN linux-2.5.68-bk8/drivers/mtd/devices/blkmtd.c linux-2.5.68-bk9/drivers/mtd/devices/blkmtd.c
--- linux-2.5.68-bk8/drivers/mtd/devices/blkmtd.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/mtd/devices/blkmtd.c	2003-04-29 04:37:06.000000000 -0700
@@ -1049,17 +1049,10 @@
 /* Startup */
 static int __init init_blkmtd(void)
 {
-#ifdef MODULE
-  struct file *file = NULL;
-  struct inode *inode;
-#endif
-
-  int maj, min;
   int i, blocksize, blocksize_bits;
   loff_t size;
   int readonly = 0;
   int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
-  dev_t rdev;
   struct block_device *bdev;
   int err;
   int mode;
@@ -1092,48 +1085,24 @@
   mode = (readonly) ? O_RDONLY : O_RDWR;
 
 #ifdef MODULE
-
-  file = filp_open(device, mode, 0);
-  if(IS_ERR(file)) {
-    printk("blkmtd: error, can't open device %s\n", device);
-    DEBUG(2, "blkmtd: filp_open returned %ld\n", PTR_ERR(file));
-    return 1;
-  }
-  
-  /* determine is this is a block device and if so get its major and minor
-     numbers */
-  inode = file->f_dentry->d_inode;
-  if(!S_ISBLK(inode->i_mode)) {
-    printk("blkmtd: %s not a block device\n", device);
-    filp_close(file, NULL);
-    return 1;
-  }
-  rdev = inode->i_bdev->bd_dev;
-  filp_close(file, NULL);
+  bdev = open_bdev_excl(device, mode, BDEV_RAW, NULL);
 #else
-  rdev = name_to_dev_t(device);
+  bdev = open_by_devnum(name_to_dev_t(device), FMODE_READ, BDEV_RAW);
 #endif
 
-  maj = MAJOR(rdev);
-  min = MINOR(rdev);
-  DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", maj, min);
-
-  if(!rdev) {
-    printk("blkmtd: bad block device: `%s'\n", device);
+  if (IS_ERR(bdev)){
+    printk("blkmtd: error, can't open device %s\n", device);
+    DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
     return 1;
   }
 
-  if(maj == MTD_BLOCK_MAJOR) {
+  DEBUG(1, "blkmtd: devname = %s\n", bdevname(bdev, b));
+
+  if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
     printk("blkmtd: attempting to use an MTD device as a block device\n");
+    blkdev_put(bdev, BDEV_RAW);
     return 1;
   }
-  /* get the block device */
-  bdev = bdget(rdev);
-  err = blkdev_get(bdev, mode, 0, BDEV_RAW);
-  if (err)
-    return 1;
-
-  DEBUG(1, "blkmtd: devname = %s\n", bdevname(bdev, b));
   blocksize = BLOCK_SIZE;
 
   blocksize = bs ? bs : block_size(bdev);
diff -urN linux-2.5.68-bk8/drivers/mtd/maps/iq80321.c linux-2.5.68-bk9/drivers/mtd/maps/iq80321.c
--- linux-2.5.68-bk8/drivers/mtd/maps/iq80321.c	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/drivers/mtd/maps/iq80321.c	2003-04-29 04:37:06.000000000 -0700
@@ -67,17 +67,17 @@
 }
 
 static struct map_info iq80321_map = {
-	name	= "IQ80321 flash",
-	size	= WINDOW_SIZE,
-	buswidth	= BUSWIDTH,
-	read8	= iq80321_read8,
-	read16	= iq80321_read16,
-	read32	= iq80321_read32,
-	copy_from	= iq80321_copy_from,
-	write8	= iq80321_write8,
-	write16	= iq80321_write16,
-	write32	= iq80321_write32,
-	copy_to	= iq80321_copy_to
+	.name	= "IQ80321 flash",
+	.size	= WINDOW_SIZE,
+	.buswidth	= BUSWIDTH,
+	.read8	= iq80321_read8,
+	.read16	= iq80321_read16,
+	.read32	= iq80321_read32,
+	.copy_from	= iq80321_copy_from,
+	.write8	= iq80321_write8,
+	.write16	= iq80321_write16,
+	.write32	= iq80321_write32,
+	.copy_to	= iq80321_copy_to
 };
 
 static struct mtd_partition iq80321_partitions[4] = {
diff -urN linux-2.5.68-bk8/drivers/net/3c523.c linux-2.5.68-bk9/drivers/net/3c523.c
--- linux-2.5.68-bk8/drivers/net/3c523.c	2003-04-19 19:49:28.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/3c523.c	2003-04-29 04:37:06.000000000 -0700
@@ -179,7 +179,7 @@
       	dev->name,__LINE__); \
       elmc_id_reset586(); } } }
 
-static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
+static irqreturn_t elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
 static int elmc_open(struct net_device *dev);
 static int elmc_close(struct net_device *dev);
 static int elmc_send_packet(struct sk_buff *, struct net_device *);
@@ -876,7 +876,8 @@
  * Interrupt Handler ...
  */
 
-static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+static irqreturn_t
+elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	unsigned short stat;
@@ -884,7 +885,7 @@
 
 	if (dev == NULL) {
 		printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
-		return;
+		return IRQ_NONE;
 	} else if (!netif_running(dev)) {
 		/* The 3c523 has this habit of generating interrupts during the
 		   reset.  I'm not sure if the ni52 has this same problem, but it's
@@ -893,10 +894,10 @@
 		   might have missed a few. */
 
 		elmc_id_attn586();	/* ack inter. and disable any more */
-		return;
+		return IRQ_HANDLED;
 	} else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) {
 		/* wasn't this device */
-		return;
+		return IRQ_NONE;
 	}
 	/* reading ELMC_CTRL also clears the INT bit. */
 
@@ -943,6 +944,7 @@
 			break;
 		}
 	}
+	return IRQ_HANDLED;
 }
 
 /*******************************************************
diff -urN linux-2.5.68-bk8/drivers/net/3c527.c linux-2.5.68-bk9/drivers/net/3c527.c
--- linux-2.5.68-bk8/drivers/net/3c527.c	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/3c527.c	2003-04-29 04:37:06.000000000 -0700
@@ -213,7 +213,7 @@
 static int	mc32_open(struct net_device *dev);
 static void	mc32_timeout(struct net_device *dev);
 static int	mc32_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void	mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int	mc32_close(struct net_device *dev);
 static struct	net_device_stats *mc32_get_stats(struct net_device *dev);
 static void	mc32_set_multicast_list(struct net_device *dev);
@@ -1347,7 +1347,7 @@
  *
  */
 
-static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	struct mc32_local *lp;
@@ -1357,7 +1357,7 @@
 	
 	if (dev == NULL) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
-		return;
+		return IRQ_NONE;
 	}
  
 	ioaddr = dev->base_addr;
@@ -1461,7 +1461,7 @@
 	if(rx_event) 
 		mc32_rx_ring(dev);
 
-	return;
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/68360enet.c linux-2.5.68-bk9/drivers/net/68360enet.c
--- linux-2.5.68-bk8/drivers/net/68360enet.c	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/68360enet.c	2003-04-29 04:37:06.000000000 -0700
@@ -147,8 +147,7 @@
 static int scc_enet_open(struct net_device *dev);
 static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int scc_enet_rx(struct net_device *dev);
-/* static void scc_enet_interrupt(void *dev_id); */
-static void scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp);
+static irqreturn_t scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp);
 static int scc_enet_close(struct net_device *dev);
 /* static struct net_device_stats *scc_enet_get_stats(struct net_device *dev); */
 static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
@@ -316,8 +315,7 @@
 /* The interrupt handler.
  * This is called from the CPM handler, not the MPC core interrupt.
  */
-/* static void scc_enet_interrupt(void *dev_id) */
-static void scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp)
+static irqreturn_t scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp)
 {
 	struct	net_device *dev = (struct net_device *)dev_id;
 	volatile struct	scc_enet_private *cep;
@@ -454,7 +452,7 @@
 		printk("CPM ENET: BSY can't happen.\n");
 	}
 
-	return;
+	return IRQ_HANDLED;
 }
 
 /* During a receive, the cur_rx points to the current incoming buffer.
diff -urN linux-2.5.68-bk8/drivers/net/7990.c linux-2.5.68-bk9/drivers/net/7990.c
--- linux-2.5.68-bk8/drivers/net/7990.c	2003-04-19 19:50:30.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/7990.c	2003-04-29 04:37:06.000000000 -0700
@@ -397,7 +397,8 @@
         return 0;
 }
 
-static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t
+lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
         struct net_device *dev = (struct net_device *)dev_id;
         struct lance_private *lp = (struct lance_private *)dev->priv;
@@ -413,7 +414,7 @@
         
         if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
 		spin_lock (&lp->devlock);
-                return;                 /* been generated by the Lance. */
+                return IRQ_NONE;        /* been generated by the Lance. */
 	}
 
         /* Acknowledge all the interrupt sources ASAP */
@@ -451,6 +452,7 @@
         WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
 
 	spin_unlock (&lp->devlock);
+	return IRQ_HANDLED;
 }
 
 int lance_open (struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/8139cp.c linux-2.5.68-bk9/drivers/net/8139cp.c
--- linux-2.5.68-bk8/drivers/net/8139cp.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/8139cp.c	2003-04-29 04:37:06.000000000 -0700
@@ -1779,7 +1779,6 @@
 	long pciaddr;
 	unsigned int addr_len, i;
 	u8 pci_rev, cache_size;
-	u16 pci_command;
 	unsigned int board_type = (unsigned int) ent->driver_data;
 
 #ifndef MODULE
@@ -1937,12 +1936,8 @@
 	}
 
 	/* enable busmastering and memory-write-invalidate */
-	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-	if (!(pci_command & PCI_COMMAND_INVALIDATE)) {
-		pci_command |= PCI_COMMAND_INVALIDATE;
-		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
-	}
 	pci_set_master(pdev);
+	pci_set_mwi(pdev);
 
 	if (cp->wol_enabled) cp_set_d3_state (cp);
 
diff -urN linux-2.5.68-bk8/drivers/net/Kconfig linux-2.5.68-bk9/drivers/net/Kconfig
--- linux-2.5.68-bk8/drivers/net/Kconfig	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/Kconfig	2003-04-29 04:37:06.000000000 -0700
@@ -1980,8 +1980,8 @@
 	  as <file:Documentation/networking/net-modules.txt>.
 
 config E1000_NAPI
-	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
-	depends on E1000 && EXPERIMENTAL
+	bool "Use Rx Polling (NAPI)"
+	depends on E1000
 
 config MYRI_SBUS
 	tristate "MyriCOM Gigabit Ethernet support"
@@ -2085,6 +2085,50 @@
 
 endmenu
 
+#
+#	10 Gigabit Ethernet
+#
+
+menu "Ethernet (10000 Mbit)"
+	depends on NETDEVICES
+
+config IXGB
+	tristate "Intel(R) PRO/10GbE support"
+	depends on PCI
+	---help---
+	  This driver supports Intel(R) PRO/10GbE family of
+	  adapters, which includes:
+
+	  Controller  Adapter Name                           Board IDs
+	  ----------  ------------                           ---------
+	  82597EX     Intel(R) PRO/10GbE LR Server Adapter   A82505-xxx
+
+	  For more information on how to identify your adapter, go to the
+	  Adapter & Driver ID Guide at:
+
+	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
+
+	  For general information and support, go to the Intel support
+	  website at:
+
+	  <http://support.intel.com>
+
+	  More specific information on configuring the driver is in 
+	  <file:Documentation/networking/ixgb.txt>.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called ixgb.  If you want to compile it as a
+	  module, say M here and read <file:Documentation/modules.txt> as well
+	  as <file:Documentation/networking/net-modules.txt>.
+
+config IXGB_NAPI
+	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
+	depends on IXGB && EXPERIMENTAL
+
+endmenu
+
+
 config VETH
 	tristate "iSeries Virtual Ethernet driver support"
 	depends on NETDEVICES && PPC_ISERIES
diff -urN linux-2.5.68-bk8/drivers/net/Makefile linux-2.5.68-bk9/drivers/net/Makefile
--- linux-2.5.68-bk8/drivers/net/Makefile	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/Makefile	2003-04-29 04:37:06.000000000 -0700
@@ -10,6 +10,7 @@
 
 obj-$(CONFIG_E100) += e100/
 obj-$(CONFIG_E1000) += e1000/
+obj-$(CONFIG_IXGB) += ixgb/
 
 #
 # link order important here
diff -urN linux-2.5.68-bk8/drivers/net/a2065.c linux-2.5.68-bk9/drivers/net/a2065.c
--- linux-2.5.68-bk8/drivers/net/a2065.c	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/a2065.c	2003-04-29 04:37:06.000000000 -0700
@@ -429,7 +429,8 @@
 	return 0;
 }
 
-static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t
+lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev;
 	struct lance_private *lp;
@@ -445,7 +446,7 @@
 	csr0 = ll->rdp;
 
 	if (!(csr0 & LE_C0_INTR))	/* Check if any interrupt has */
-		return;			/* been generated by the Lance. */
+		return IRQ_NONE;	/* been generated by the Lance. */
 
 	/* Acknowledge all the interrupt sources ASAP */
 	ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
@@ -479,7 +480,7 @@
 	ll->rap = LE_CSR0;
 	ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
 					LE_C0_IDON|LE_C0_INEA;
-
+	return IRQ_HANDLED;
 }
 
 struct net_device *last_dev = 0;
diff -urN linux-2.5.68-bk8/drivers/net/am79c961a.c linux-2.5.68-bk9/drivers/net/am79c961a.c
--- linux-2.5.68-bk8/drivers/net/am79c961a.c	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/am79c961a.c	2003-04-29 04:37:06.000000000 -0700
@@ -40,7 +40,8 @@
 
 #include "am79c961a.h"
 
-static void am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
 
 static unsigned int net_debug = NET_DEBUG;
 
@@ -557,22 +558,30 @@
 	netif_wake_queue(dev);
 }
 
-static void
+static irqreturn_t
 am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	u_int status;
+	int handled = 0;
 
 	status = read_rreg(dev->base_addr, CSR0);
 	write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
 
-	if (status & CSR0_RINT)
+	if (status & CSR0_RINT) {
+		handled = 1;
 		am79c961_rx(dev, priv);
-	if (status & CSR0_TINT)
+	}
+	if (status & CSR0_TINT) {
+		handled = 1;
 		am79c961_tx(dev, priv);
-	if (status & CSR0_MISS)
+	}
+	if (status & CSR0_MISS) {
+		handled = 1;
 		priv->stats.rx_dropped ++;
+	}
+	return IRQ_RETVAL(handled);
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/appletalk/cops.c linux-2.5.68-bk9/drivers/net/appletalk/cops.c
--- linux-2.5.68-bk8/drivers/net/appletalk/cops.c	2003-04-19 19:49:31.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/appletalk/cops.c	2003-04-29 04:37:06.000000000 -0700
@@ -194,7 +194,7 @@
 static void cops_load (struct net_device *dev);
 static int  cops_nodeid (struct net_device *dev, int nodeid);
 
-static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
 static void cops_poll (unsigned long ltdev);
 static void cops_timeout(struct net_device *dev);
 static void cops_rx (struct net_device *dev);
@@ -710,7 +710,7 @@
  *      The typical workload of the driver:
  *      Handle the network interface interrupts.
  */
-static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
         struct net_device *dev = dev_id;
         struct cops_local *lp;
@@ -742,7 +742,7 @@
 		} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
 	}
 
-        return;
+        return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/appletalk/ltpc.c linux-2.5.68-bk9/drivers/net/appletalk/ltpc.c
--- linux-2.5.68-bk8/drivers/net/appletalk/ltpc.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/appletalk/ltpc.c	2003-04-29 04:37:06.000000000 -0700
@@ -789,13 +789,14 @@
 
 /* the handler for the board interrupt */
  
-static void ltpc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+static irqreturn_t
+ltpc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
 {
 	struct net_device *dev = dev_id;
 
 	if (dev==NULL) {
 		printk("ltpc_interrupt: unknown device.\n");
-		return;
+		return IRQ_NONE;
 	}
 
 	inb_p(dev->base_addr+6);  /* disable further interrupts from board */
@@ -804,7 +805,7 @@
  
 	/* idle re-enables interrupts from board */ 
 
-	return;
+	return IRQ_HANDLED;
 }
 
 /***
diff -urN linux-2.5.68-bk8/drivers/net/ariadne.c linux-2.5.68-bk9/drivers/net/ariadne.c
--- linux-2.5.68-bk8/drivers/net/ariadne.c	2003-04-19 19:50:06.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/ariadne.c	2003-04-29 04:37:06.000000000 -0700
@@ -127,7 +127,7 @@
 static void ariadne_tx_timeout(struct net_device *dev);
 static int ariadne_rx(struct net_device *dev);
 static void ariadne_reset(struct net_device *dev);
-static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t ariadne_interrupt(int irq, void *data, struct pt_regs *fp);
 static int ariadne_close(struct net_device *dev);
 static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
 #ifdef HAVE_MULTICAST
@@ -406,22 +406,23 @@
 }
 
 
-static void ariadne_interrupt(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t ariadne_interrupt(int irq, void *data, struct pt_regs *fp)
 {
     struct net_device *dev = (struct net_device *)data;
     volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
     struct ariadne_private *priv;
     int csr0, boguscnt;
+    int handled = 0;
 
     if (dev == NULL) {
 	printk("ariadne_interrupt(): irq for unknown device.\n");
-	return;
+	return IRQ_NONE;
     }
 
     lance->RAP = CSR0;			/* PCnet-ISA Controller Status */
 
     if (!(lance->RDP & INTR))		/* Check if any interrupt has been */
-	return;				/* generated by the board. */
+	return IRQ_NONE;		/* generated by the board. */
 
     priv = (struct ariadne_private *)dev->priv;
 
@@ -471,12 +472,15 @@
 	}
 #endif
 
-	if (csr0 & RINT)	/* Rx interrupt */
+	if (csr0 & RINT) {	/* Rx interrupt */
+	    handled = 1;
 	    ariadne_rx(dev);
+	}
 
 	if (csr0 & TINT) {	/* Tx-done interrupt */
 	    int dirty_tx = priv->dirty_tx;
 
+	    handled = 1;
 	    while (dirty_tx < priv->cur_tx) {
 		int entry = dirty_tx % TX_RING_SIZE;
 		int status = lowb(priv->tx_ring[entry]->TMD1);
@@ -532,11 +536,16 @@
 	}
 
 	/* Log misc errors. */
-	if (csr0 & BABL)
+	if (csr0 & BABL) {
+	    handled = 1;
 	    priv->stats.tx_errors++;	/* Tx babble. */
-	if (csr0 & MISS)
+	}
+	if (csr0 & MISS) {
+	    handled = 1;
 	    priv->stats.rx_errors++;	/* Missed a Rx frame. */
+	}
 	if (csr0 & MERR) {
+	    handled = 1;
 	    printk("%s: Bus master arbitration failure, status %4.4x.\n",
 		   dev->name, csr0);
 	    /* Restart the chip. */
@@ -553,7 +562,7 @@
 	printk("%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name, lance->RAP,
 	       lance->RDP);
 #endif
-    return;
+    return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/atarilance.c linux-2.5.68-bk9/drivers/net/atarilance.c
--- linux-2.5.68-bk8/drivers/net/atarilance.c	2003-04-19 19:48:55.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/atarilance.c	2003-04-29 04:37:06.000000000 -0700
@@ -344,7 +344,7 @@
 static int lance_open( struct net_device *dev );
 static void lance_init_ring( struct net_device *dev );
 static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
 static int lance_rx( struct net_device *dev );
 static int lance_close( struct net_device *dev );
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
@@ -860,16 +860,17 @@
 
 /* The LANCE interrupt handler. */
 
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	struct lance_ioreg	 *IO;
 	int csr0, boguscnt = 10;
+	int handled = 0;
 
 	if (dev == NULL) {
 		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
-		return;
+		return IRQ_NONE;
 	}
 
 	lp = (struct lance_private *)dev->priv;
@@ -880,6 +881,7 @@
 
 	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
 		   --boguscnt >= 0) {
+		handled = 1;
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
 									CSR0_TDMD | CSR0_INEA);
@@ -966,6 +968,7 @@
 				  dev->name, DREG ));
 
 	spin_unlock (&lp->devlock);
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/au1000_eth.c linux-2.5.68-bk9/drivers/net/au1000_eth.c
--- linux-2.5.68-bk8/drivers/net/au1000_eth.c	2003-04-19 19:49:52.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/au1000_eth.c	2003-04-29 04:37:07.000000000 -0700
@@ -73,7 +73,7 @@
 static int au1000_close(struct net_device *);
 static int au1000_tx(struct sk_buff *, struct net_device *);
 static int au1000_rx(struct net_device *);
-static void au1000_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
 static void au1000_tx_timeout(struct net_device *);
 static int au1000_set_config(struct net_device *dev, struct ifmap *map);
 static void set_rx_mode(struct net_device *);
@@ -1236,16 +1236,17 @@
 /*
  * Au1000 interrupt service routine.
  */
-void au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 
 	if (dev == NULL) {
 		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
-		return;
+		return IRQ_NONE;
 	}
 	au1000_tx_ack(dev);
 	au1000_rx(dev);
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/bagetlance.c linux-2.5.68-bk9/drivers/net/bagetlance.c
--- linux-2.5.68-bk8/drivers/net/bagetlance.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/bagetlance.c	2003-04-29 04:37:07.000000000 -0700
@@ -330,7 +330,7 @@
 static int lance_open( struct net_device *dev );
 static void lance_init_ring( struct net_device *dev );
 static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
 static int lance_rx( struct net_device *dev );
 static int lance_close( struct net_device *dev );
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
@@ -965,16 +965,17 @@
 
 /* The LANCE interrupt handler. */
 
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp;
 	struct lance_ioreg	 *IO;
 	int csr0, boguscnt = 10;
+	int handled = 0;
 
 	if (dev == NULL) {
 		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
-		return;
+		return IRQ_NONE;
 	}
 
 	lp = (struct lance_private *)dev->priv;
@@ -992,6 +993,7 @@
 
 	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
 		   --boguscnt >= 0) {
+		handled = 1;
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
 									CSR0_TDMD | CSR0_INEA);
@@ -1083,7 +1085,7 @@
 	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
 				  dev->name, DREG ));
 	dev->interrupt = 0;
-	return;
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/declance.c linux-2.5.68-bk9/drivers/net/declance.c
--- linux-2.5.68-bk8/drivers/net/declance.c	2003-04-19 19:49:59.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/declance.c	2003-04-29 04:37:07.000000000 -0700
@@ -709,7 +709,8 @@
 	spin_unlock(&lp->lock);
 }
 
-static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t
+lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -763,6 +764,7 @@
 
 	writereg(&ll->rdp, LE_C0_INEA);
 	writereg(&ll->rdp, LE_C0_INEA);
+	return IRQ_HANDLED;
 }
 
 struct net_device *last_dev = 0;
diff -urN linux-2.5.68-bk8/drivers/net/e1000/e1000.h linux-2.5.68-bk9/drivers/net/e1000/e1000.h
--- linux-2.5.68-bk8/drivers/net/e1000/e1000.h	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/e1000/e1000.h	2003-04-29 04:37:07.000000000 -0700
@@ -63,7 +63,9 @@
 #include <net/pkt_sched.h>
 #include <linux/list.h>
 #include <linux/reboot.h>
+#ifdef NETIF_F_TSO
 #include <net/checksum.h>
+#endif
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
diff -urN linux-2.5.68-bk8/drivers/net/e1000/e1000_main.c linux-2.5.68-bk9/drivers/net/e1000/e1000_main.c
--- linux-2.5.68-bk8/drivers/net/e1000/e1000_main.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/e1000/e1000_main.c	2003-04-29 04:37:07.000000000 -0700
@@ -61,7 +61,7 @@
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.0.43-k2";
+char e1000_driver_version[] = "5.0.43-k3";
 char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -455,9 +455,11 @@
 		netdev->features = NETIF_F_SG;
 	}
 
+#ifdef NETIF_F_TSO
 	if((adapter->hw.mac_type >= e1000_82544) &&
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
+#endif
 
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
@@ -1434,6 +1436,7 @@
 static inline boolean_t
 e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags)
 {
+#ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
 	int i;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
@@ -1477,6 +1480,7 @@
 
 		return TRUE;
 	}
+#endif
 
 	return FALSE;
 }
@@ -1520,7 +1524,9 @@
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	int len = skb->len, offset = 0, size, count = 0, i;
 
+#ifdef NETIF_F_TSO
 	int tso = skb_shinfo(skb)->tso_size;
+#endif
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	int f;
 	len -= skb->data_len;
@@ -1529,10 +1535,12 @@
 
 	while(len) {
 		size = min(len, E1000_MAX_DATA_PER_TXD);
+#ifdef NETIF_F_TSO
 		/* Workaround for premature desc write-backs
 		 * in TSO mode.  Append 4-byte sentinel desc */
 		if(tso && !nr_frags && size == len && size > 4)
 			size -= 4;
+#endif
 		tx_ring->buffer_info[i].length = size;
 		tx_ring->buffer_info[i].dma =
 			pci_map_single(adapter->pdev,
@@ -1556,10 +1564,12 @@
 
 		while(len) {
 			size = min(len, E1000_MAX_DATA_PER_TXD);
+#ifdef NETIF_F_TSO
 			/* Workaround for premature desc write-backs
 			 * in TSO mode.  Append 4-byte sentinel desc */
 			if(tso && f == (nr_frags-1) && size == len && size > 4)
 				size -= 4;
+#endif
 			tx_ring->buffer_info[i].length = size;
 			tx_ring->buffer_info[i].dma =
 				pci_map_page(adapter->pdev,
diff -urN linux-2.5.68-bk8/drivers/net/eth16i.c linux-2.5.68-bk9/drivers/net/eth16i.c
--- linux-2.5.68-bk8/drivers/net/eth16i.c	2003-04-19 19:50:42.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/eth16i.c	2003-04-29 04:37:07.000000000 -0700
@@ -412,7 +412,7 @@
 static int     eth16i_tx(struct sk_buff *skb, struct net_device *dev);
 static void    eth16i_rx(struct net_device *dev);
 static void    eth16i_timeout(struct net_device *dev);
-static void    eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void    eth16i_reset(struct net_device *dev);
 static void    eth16i_timeout(struct net_device *dev);
 static void    eth16i_skip_packet(struct net_device *dev);
@@ -1219,11 +1219,12 @@
 	} /* while */
 }
 
-static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct eth16i_local *lp;
 	int ioaddr = 0, status;
+	int handled = 0;
 
 	ioaddr = dev->base_addr;
 	lp = (struct eth16i_local *)dev->priv;
@@ -1237,6 +1238,9 @@
 	status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
 	outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
 
+	if (status)
+		handled = 1;
+
 	if(eth16i_debug > 3)
 		printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
 
@@ -1314,7 +1318,7 @@
 	
 	spin_unlock(&lp->lock);
 	
-	return;
+	return IRQ_RETVAL(handled);
 }
 
 static void eth16i_skip_packet(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/ewrk3.c linux-2.5.68-bk9/drivers/net/ewrk3.c
--- linux-2.5.68-bk8/drivers/net/ewrk3.c	2003-04-19 19:51:13.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/ewrk3.c	2003-04-29 04:37:07.000000000 -0700
@@ -300,7 +300,7 @@
  */
 static int ewrk3_open(struct net_device *dev);
 static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int ewrk3_close(struct net_device *dev);
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -896,7 +896,7 @@
 /*
    ** The EWRK3 interrupt handler.
  */
-static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct ewrk3_private *lp;
@@ -945,6 +945,7 @@
 	outb(cr, EWRK3_CR);
 	ENABLE_IRQs;
 	spin_unlock(&lp->hw_lock);
+	return IRQ_HANDLED;
 }
 
 /* Called with lp->hw_lock held */
diff -urN linux-2.5.68-bk8/drivers/net/gt96100eth.c linux-2.5.68-bk9/drivers/net/gt96100eth.c
--- linux-2.5.68-bk8/drivers/net/gt96100eth.c	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/gt96100eth.c	2003-04-29 04:37:07.000000000 -0700
@@ -108,7 +108,7 @@
 static int gt96100_close(struct net_device *dev);
 static int gt96100_tx(struct sk_buff *skb, struct net_device *dev);
 static int gt96100_rx(struct net_device *dev, u32 status);
-static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void gt96100_tx_timeout(struct net_device *dev);
 static void gt96100_set_rx_mode(struct net_device *dev);
 static struct net_device_stats* gt96100_get_stats(struct net_device *dev);
@@ -1392,16 +1392,17 @@
 }
 
 
-static void
+static irqreturn_t
 gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	u32 status;
-    
+    	int handled = 0;
+
 	if (dev == NULL) {
 		err("%s: null dev ptr\n", __FUNCTION__);
-		return;
+		return IRQ_NONE;
 	}
 
 	dbg(3, "%s: entry, icr=%x\n", __FUNCTION__,
@@ -1420,7 +1421,9 @@
 		if ((status & icrEtherIntSum) == 0 &&
 		    !(status & (icrTxBufferLow|icrTxBufferHigh|icrRxBuffer)))
 			break;
-	
+
+		handled = 1;
+
 		if (status & icrMIIPhySTC) {
 			u32 psr = GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS);
 			if (gp->last_psr != psr) {
@@ -1487,6 +1490,7 @@
 	    GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE));
 
 	spin_unlock(&gp->lock);
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/hamradio/baycom_ser_fdx.c linux-2.5.68-bk9/drivers/net/hamradio/baycom_ser_fdx.c
--- linux-2.5.68-bk8/drivers/net/hamradio/baycom_ser_fdx.c	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/hamradio/baycom_ser_fdx.c	2003-04-29 04:37:07.000000000 -0700
@@ -279,7 +279,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
@@ -288,10 +288,10 @@
 	unsigned int txcount = 0;
 
 	if (!bc || bc->hdrv.magic != HDLCDRV_MAGIC)
-		return;
+		return IRQ_NONE;
 	/* fast way out for shared irq */
 	if ((iir = inb(IIR(dev->base_addr))) & 1) 	
-		return;
+		return IRQ_NONE;
 	/* get current time */
 	do_gettimeofday(&tv);
 	msr = inb(MSR(dev->base_addr));
@@ -362,6 +362,7 @@
 	hdlcdrv_transmitter(dev, &bc->hdrv);
 	hdlcdrv_receiver(dev, &bc->hdrv);
 	local_irq_disable();
+	return IRQ_HANDLED;
 }
 
 /* --------------------------------------------------------------------- */
diff -urN linux-2.5.68-bk8/drivers/net/hamradio/baycom_ser_hdx.c linux-2.5.68-bk9/drivers/net/hamradio/baycom_ser_hdx.c
--- linux-2.5.68-bk8/drivers/net/hamradio/baycom_ser_hdx.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/hamradio/baycom_ser_hdx.c	2003-04-29 04:37:07.000000000 -0700
@@ -373,17 +373,17 @@
 
 /* --------------------------------------------------------------------- */
 
-static void ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct baycom_state *bc = (struct baycom_state *)dev->priv;
 	unsigned char iir;
 
 	if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
-		return;
+		return IRQ_NONE;
 	/* fast way out */
 	if ((iir = inb(IIR(dev->base_addr))) & 1)
-		return;
+		return IRQ_NONE;
 	baycom_int_freq(bc);
 	do {
 		switch (iir & 6) {
@@ -423,6 +423,7 @@
 	hdlcdrv_transmitter(dev, &bc->hdrv);
 	hdlcdrv_receiver(dev, &bc->hdrv);
 	local_irq_disable();
+	return IRQ_HANDLED;
 }
 
 /* --------------------------------------------------------------------- */
diff -urN linux-2.5.68-bk8/drivers/net/hamradio/dmascc.c linux-2.5.68-bk9/drivers/net/hamradio/dmascc.c
--- linux-2.5.68-bk8/drivers/net/hamradio/dmascc.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/hamradio/dmascc.c	2003-04-29 04:37:07.000000000 -0700
@@ -266,7 +266,7 @@
 static struct net_device_stats *scc_get_stats(struct net_device *dev);
 static int scc_set_mac_address(struct net_device *dev, void *sa);
 
-static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
 static inline void z8530_isr(struct scc_info *info);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
@@ -949,7 +949,7 @@
 }
 
 
-static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
   struct scc_info *info = dev_id;
 
   spin_lock(info->priv[0].register_lock);
@@ -981,6 +981,7 @@
     }
   } else z8530_isr(info);
   spin_unlock(info->priv[0].register_lock);
+  return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/hamradio/yam.c linux-2.5.68-bk9/drivers/net/hamradio/yam.c
--- linux-2.5.68-bk8/drivers/net/hamradio/yam.c	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/hamradio/yam.c	2003-04-29 04:37:07.000000000 -0700
@@ -714,7 +714,7 @@
 * ISR routine
 ************************************************************************************/
 
-static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev;
 	struct yam_port *yp;
@@ -758,6 +758,7 @@
 			}
 		}
 	}
+	return IRQ_HANDLED;
 }
 
 static int yam_net_get_info(char *buffer, char **start, off_t offset, int length)
diff -urN linux-2.5.68-bk8/drivers/net/ibmlana.c linux-2.5.68-bk9/drivers/net/ibmlana.c
--- linux-2.5.68-bk8/drivers/net/ibmlana.c	2003-04-19 19:48:55.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/ibmlana.c	2003-04-29 04:37:07.000000000 -0700
@@ -701,14 +701,14 @@
 
 /* general interrupt entry */
 
-static void irq_handler(int irq, void *device, struct pt_regs *regs)
+static irqreturn_t irq_handler(int irq, void *device, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) device;
 	u16 ival;
 
 	/* in case we're not meant... */
 	if (!(inb(dev->base_addr + BCMREG) & BCMREG_IPEND))
-		return;
+		return IRQ_NONE;
 
 	/* loop through the interrupt bits until everything is clear */
 	while (1) {
@@ -732,6 +732,7 @@
 		}
 		break;
 	}
+	return IRQ_HANDLED;
 }
 
 /* ------------------------------------------------------------------------
diff -urN linux-2.5.68-bk8/drivers/net/ioc3-eth.c linux-2.5.68-bk9/drivers/net/ioc3-eth.c
--- linux-2.5.68-bk8/drivers/net/ioc3-eth.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/ioc3-eth.c	2003-04-29 04:37:07.000000000 -0700
@@ -681,7 +681,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread.  */
-static void ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
+static irqreturn_t ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)_dev;
 	struct ioc3_private *ip = dev->priv;
@@ -707,6 +707,7 @@
 
 		eisr = ioc3->eisr & enabled;
 	}
+	return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/isa-skeleton.c linux-2.5.68-bk9/drivers/net/isa-skeleton.c
--- linux-2.5.68-bk8/drivers/net/isa-skeleton.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/isa-skeleton.c	2003-04-29 04:37:07.000000000 -0700
@@ -109,7 +109,7 @@
 static int	netcard_probe1(struct net_device *dev, int ioaddr);
 static int	net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void	net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void	net_rx(struct net_device *dev);
 static int	net_close(struct net_device *dev);
 static struct	net_device_stats *net_get_stats(struct net_device *dev);
@@ -470,17 +470,22 @@
  * The typical workload of the driver:
  * Handle the network interface interrupts.
  */
-static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *np;
 	int ioaddr, status;
+	int handled = 0;
 
 	ioaddr = dev->base_addr;
 
 	np = (struct net_local *)dev->priv;
 	status = inw(ioaddr + 0);
 
+	if (status == 0)
+		goto out;
+	handled = 1;
+
 	if (status & RX_INTR) {
 		/* Got a packet(s). */
 		net_rx(dev);
@@ -497,6 +502,8 @@
 		/* Increment the appropriate 'localstats' field. */
 		np->stats.tx_window_errors++;
 	}
+out:
+	return IRQ_RETVAL(handled);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/Makefile linux-2.5.68-bk9/drivers/net/ixgb/Makefile
--- linux-2.5.68-bk8/drivers/net/ixgb/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/Makefile	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,35 @@
+################################################################################
+#
+# 
+# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# 
+# 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., 59 
+# Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# 
+# The full GNU General Public License is included in this distribution in the
+# file called LICENSE.
+# 
+# Contact Information:
+# Linux NICS <linux.nics@intel.com>
+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+#
+################################################################################
+
+#
+# Makefile for the Intel(R) PRO/10GbE driver
+#
+
+obj-$(CONFIG_IXGB) += ixgb.o
+
+ixgb-objs := ixgb_main.o ixgb_hw.o ixgb_ee.o ixgb_ethtool.o ixgb_param.o
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb.h linux-2.5.68-bk9/drivers/net/ixgb/ixgb.h
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb.h	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,185 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#ifndef _IXGB_H_
+#define _IXGB_H_
+
+#include <linux/stddef.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/pagemap.h>
+#include <linux/bitops.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <net/pkt_sched.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/reboot.h>
+#ifdef NETIF_F_TSO
+#include <net/checksum.h>
+#endif
+
+/* ethtool support */
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+struct ixgb_adapter;
+
+#define BAR_0           0
+#define BAR_1           1
+#define BAR_5           5
+#define PCI_DMA_64BIT   0xffffffffffffffffULL
+#define PCI_DMA_32BIT   0x00000000ffffffffULL
+
+#include "ixgb_hw.h"
+#include "ixgb_ee.h"
+#include "ixgb_ids.h"
+
+#if _DEBUG_DRIVER_
+#define IXGB_DBG(args...) printk(KERN_DEBUG "ixgb: " args)
+#else
+#define IXGB_DBG(args...)
+#endif
+
+#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+
+/* Supported Rx Buffer Sizes */
+#define IXGB_RXBUFFER_2048  2048
+#define IXGB_RXBUFFER_4096  4096
+#define IXGB_RXBUFFER_8192  8192
+#define IXGB_RXBUFFER_16384 16384
+
+/* How many Tx Descriptors do we need to call netif_wake_queue? */
+#define IXGB_TX_QUEUE_WAKE 16
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define IXGB_RX_BUFFER_WRITE    16
+
+/* only works for sizes that are powers of 2 */
+#define IXGB_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
+
+/* wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer */
+struct ixgb_buffer {
+	struct sk_buff *skb;
+	uint64_t dma;
+	unsigned long length;
+	unsigned long time_stamp;
+};
+
+struct ixgb_desc_ring {
+	/* pointer to the descriptor ring memory  */
+	void *desc;
+	/* physical address of the descriptor ring  */
+	dma_addr_t dma;
+	/* length of descriptor ring in bytes  */
+	unsigned int size;
+	/* number of descriptors in the ring  */
+	unsigned int count;
+	/* next descriptor to associate a buffer with  */
+	unsigned int next_to_use;
+	/* next descriptor to check for DD status bit  */
+	unsigned int next_to_clean;
+	/* array of buffer information structs  */
+	struct ixgb_buffer *buffer_info;
+};
+
+#define IXGB_DESC_UNUSED(R) \
+((((R)->next_to_clean + (R)->count) - ((R)->next_to_use + 1)) % ((R)->count))
+
+#define IXGB_GET_DESC(R, i, type)       (&(((struct type *)((R).desc))[i]))
+#define IXGB_RX_DESC(R, i)              IXGB_GET_DESC(R, i, ixgb_rx_desc)
+#define IXGB_TX_DESC(R, i)              IXGB_GET_DESC(R, i, ixgb_tx_desc)
+#define IXGB_CONTEXT_DESC(R, i)         IXGB_GET_DESC(R, i, ixgb_context_desc)
+
+/* board specific private data structure */
+
+struct ixgb_adapter {
+	struct timer_list watchdog_timer;
+	struct vlan_group *vlgrp;
+	char *id_string;
+	u32 bd_number;
+	u32 rx_buffer_len;
+	u32 part_num;
+	u16 link_speed;
+	u16 link_duplex;
+	atomic_t irq_sem;
+	struct work_struct tx_timeout_task;
+
+#ifdef ETHTOOL_PHYS_ID
+	struct timer_list blink_timer;
+	unsigned long led_status;
+#endif
+#ifdef _INTERNAL_LOOPBACK_DRIVER_
+	struct ixgb_desc_ring diag_tx_ring;
+	struct ixgb_desc_ring diag_rx_ring;
+#endif
+	/* TX */
+	struct ixgb_desc_ring tx_ring;
+	unsigned long timeo_start;
+	u32 tx_cmd_type;
+	int max_data_per_txd;
+	uint64_t hw_csum_tx_good;
+	uint64_t hw_csum_tx_error;
+	boolean_t tx_csum;
+	u32 tx_int_delay;
+	boolean_t tx_int_delay_enable;
+
+	/* RX */
+	struct ixgb_desc_ring rx_ring;
+	uint64_t hw_csum_rx_error;
+	uint64_t hw_csum_rx_good;
+	u32 rx_int_delay;
+	boolean_t raidc;
+	boolean_t rx_csum;
+
+	/* OS defined structs */
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+
+	/* structs defined in ixgb_hw.h */
+	struct ixgb_hw hw;
+	struct ixgb_hw_stats stats;
+	u32 pci_state[16];
+	char ifname[IFNAMSIZ];
+};
+
+#endif				/* _IXGB_H_ */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ee.c linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ee.c
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ee.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ee.c	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,749 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#include "ixgb_hw.h"
+#include "ixgb_ee.h"
+/* Local prototypes */
+static u16 ixgb_shift_in_bits(struct ixgb_hw *hw);
+
+static void ixgb_shift_out_bits(struct ixgb_hw *hw,
+				u16 data, u16 count);
+static void ixgb_standby_eeprom(struct ixgb_hw *hw);
+
+static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
+
+static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+
+/******************************************************************************
+ * Raises the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+ixgb_raise_clock(struct ixgb_hw *hw, u32 * eecd_reg)
+{
+	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
+	 *  wait 50 microseconds.
+	 */
+	*eecd_reg = *eecd_reg | IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Lowers the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+ixgb_lower_clock(struct ixgb_hw *hw, u32 * eecd_reg)
+{
+	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then 
+	 * wait 50 microseconds. 
+	 */
+	*eecd_reg = *eecd_reg & ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Shift data bits out to the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * data - data to send to the EEPROM
+ * count - number of bits to shift out
+ *****************************************************************************/
+static void
+ixgb_shift_out_bits(struct ixgb_hw *hw, u16 data, u16 count)
+{
+	u32 eecd_reg;
+	u32 mask;
+
+	/* We need to shift "count" bits out to the EEPROM. So, value in the
+	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
+	 * In order to do this, "data" must be broken down into bits. 
+	 */
+	mask = 0x01 << (count - 1);
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+	eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
+	do {
+		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
+		 * and then raising and then lowering the clock (the SK bit controls
+		 * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
+		 * by setting "DI" to "0" and then raising and then lowering the clock.
+		 */
+		eecd_reg &= ~IXGB_EECD_DI;
+
+		if (data & mask)
+			eecd_reg |= IXGB_EECD_DI;
+
+		IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+		udelay(50);
+
+		ixgb_raise_clock(hw, &eecd_reg);
+		ixgb_lower_clock(hw, &eecd_reg);
+
+		mask = mask >> 1;
+
+	} while (mask);
+
+	/* We leave the "DI" bit set to "0" when we leave this routine. */
+	eecd_reg &= ~IXGB_EECD_DI;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	return;
+}
+
+/******************************************************************************
+ * Shift data bits in from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static u16
+ixgb_shift_in_bits(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+	u32 i;
+	u16 data;
+
+	/* In order to read a register from the EEPROM, we need to shift 16 bits 
+	 * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+	 * the EEPROM (setting the SK bit), and then reading the value of the "DO"
+	 * bit.  During this "shifting in" process the "DI" bit should always be 
+	 * clear..
+	 */
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
+	data = 0;
+
+	for (i = 0; i < 16; i++) {
+		data = data << 1;
+		ixgb_raise_clock(hw, &eecd_reg);
+
+		eecd_reg = IXGB_READ_REG(hw, EECD);
+
+		eecd_reg &= ~(IXGB_EECD_DI);
+		if (eecd_reg & IXGB_EECD_DO)
+			data |= 1;
+
+		ixgb_lower_clock(hw, &eecd_reg);
+	}
+
+	return data;
+}
+
+/******************************************************************************
+ * Prepares EEPROM for access
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This 
+ * function should be called before issuing a command to the EEPROM.
+ *****************************************************************************/
+static void
+ixgb_setup_eeprom(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Clear SK and DI  */
+	eecd_reg &= ~(IXGB_EECD_SK | IXGB_EECD_DI);
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+	/*  Set CS  */
+	eecd_reg |= IXGB_EECD_CS;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	return;
+}
+
+/******************************************************************************
+ * Returns EEPROM to a "standby" state
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_standby_eeprom(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Deselct EEPROM  */
+	eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_SK);
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Clock high  */
+	eecd_reg |= IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Select EEPROM  */
+	eecd_reg |= IXGB_EECD_CS;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Clock low  */
+	eecd_reg &= ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Raises then lowers the EEPROM's clock pin
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_clock_eeprom(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Rising edge of clock  */
+	eecd_reg |= IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Falling edge of clock  */
+	eecd_reg &= ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Terminates a command by lowering the EEPROM's chip select pin
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_DI);
+
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+	ixgb_clock_eeprom(hw);
+	return;
+}
+
+/******************************************************************************
+ * Waits for the EEPROM to finish the current command.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * The command is done when the EEPROM's data out pin goes high.
+ * 
+ * Returns:
+ *      TRUE: EEPROM data pin is high before timeout.
+ *      FALSE:  Time expired.
+ *****************************************************************************/
+static boolean_t
+ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+{
+	u32 eecd_reg;
+	u32 i;
+
+	/* Toggle the CS line.  This in effect tells to EEPROM to actually execute 
+	 * the command in question.
+	 */
+	ixgb_standby_eeprom(hw);
+
+	/* Now read DO repeatedly until is high (equal to '1').  The EEEPROM will
+	 * signal that the command has been completed by raising the DO signal.
+	 * If DO does not go high in 10 milliseconds, then error out.
+	 */
+	for (i = 0; i < 200; i++) {
+		eecd_reg = IXGB_READ_REG(hw, EECD);
+
+		if (eecd_reg & IXGB_EECD_DO)
+			return (TRUE);
+
+		udelay(50);
+	}
+	ASSERT(0);
+	return (FALSE);
+}
+
+/******************************************************************************
+ * Verifies that the EEPROM has a valid checksum
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Reads the first 64 16 bit words of the EEPROM and sums the values read.
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *
+ * Returns:
+ *  TRUE: Checksum is valid
+ *  FALSE: Checksum is not valid.
+ *****************************************************************************/
+boolean_t
+ixgb_validate_eeprom_checksum(struct ixgb_hw * hw)
+{
+	u16 checksum = 0;
+	u16 i;
+
+	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+		checksum += ixgb_read_eeprom(hw, i);
+
+	if (checksum == (u16) EEPROM_SUM)
+		return (TRUE);
+	else
+		return (FALSE);
+}
+
+/******************************************************************************
+ * Calculates the EEPROM checksum and writes it to the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ *****************************************************************************/
+void
+ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+{
+	u16 checksum = 0;
+	u16 i;
+
+	for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
+		checksum += ixgb_read_eeprom(hw, i);
+
+	checksum = (u16) EEPROM_SUM - checksum;
+
+	ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum);
+	return;
+}
+
+/******************************************************************************
+ * Writes a 16 bit word to a given offset in the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * reg - offset within the EEPROM to be written to
+ * data - 16 bit word to be writen to the EEPROM
+ *
+ * If ixgb_update_eeprom_checksum is not called after this function, the 
+ * EEPROM will most likely contain an invalid checksum.
+ *
+ *****************************************************************************/
+void
+ixgb_write_eeprom(struct ixgb_hw *hw, u16 offset, u16 data)
+{
+	/*  Prepare the EEPROM for writing  */
+	ixgb_setup_eeprom(hw);
+
+	/*  Send the 9-bit EWEN (write enable) command to the EEPROM (5-bit opcode
+	 *  plus 4-bit dummy).  This puts the EEPROM into write/erase mode. 
+	 */
+	ixgb_shift_out_bits(hw, EEPROM_EWEN_OPCODE, 5);
+	ixgb_shift_out_bits(hw, 0, 4);
+
+	/*  Prepare the EEPROM  */
+	ixgb_standby_eeprom(hw);
+
+	/*  Send the Write command (3-bit opcode + 6-bit addr)  */
+	ixgb_shift_out_bits(hw, EEPROM_WRITE_OPCODE, 3);
+	ixgb_shift_out_bits(hw, offset, 6);
+
+	/*  Send the data  */
+	ixgb_shift_out_bits(hw, data, 16);
+
+	ixgb_wait_eeprom_command(hw);
+
+	/*  Recover from write  */
+	ixgb_standby_eeprom(hw);
+
+	/* Send the 9-bit EWDS (write disable) command to the EEPROM (5-bit
+	 * opcode plus 4-bit dummy).  This takes the EEPROM out of write/erase
+	 * mode.
+	 */
+	ixgb_shift_out_bits(hw, EEPROM_EWDS_OPCODE, 5);
+	ixgb_shift_out_bits(hw, 0, 4);
+
+	/*  Done with writing  */
+	ixgb_cleanup_eeprom(hw);
+
+	return;
+}
+
+/******************************************************************************
+ * Reads a 16 bit word from the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of 16 bit word in the EEPROM to read
+ *
+ * Returns:
+ *  The 16-bit value read from the eeprom
+ *****************************************************************************/
+u16
+ixgb_read_eeprom(struct ixgb_hw * hw, u16 offset)
+{
+	u16 data;
+
+	/*  Prepare the EEPROM for reading  */
+	ixgb_setup_eeprom(hw);
+
+	/*  Send the READ command (opcode + addr)  */
+	ixgb_shift_out_bits(hw, EEPROM_READ_OPCODE, 3);
+	/* 
+	 * We have a 64 word EEPROM, there are 6 address bits
+	 */
+	ixgb_shift_out_bits(hw, offset, 6);
+
+	/*  Read the data  */
+	data = ixgb_shift_in_bits(hw);
+
+	/*  End this read operation  */
+	ixgb_standby_eeprom(hw);
+
+	return (data);
+}
+
+/******************************************************************************
+ * Reads eeprom and stores data in shared structure.
+ * Validates eeprom checksum and eeprom signature.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns:
+ *      TRUE: if eeprom read is successful
+ *      FALSE: otherwise.
+ *****************************************************************************/
+boolean_t
+ixgb_get_eeprom_data(struct ixgb_hw * hw)
+{
+	u16 i;
+	u16 checksum = 0;
+	struct ixgb_ee_map_type *ee_map;
+
+	DEBUGFUNC("ixgb_get_eeprom_data");
+
+	ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
+
+	DEBUGOUT("ixgb_ee: Reading eeprom data\n");
+	for (i = 0; i < IXGB_EEPROM_SIZE; i++) {
+		u16 ee_data;
+		ee_data = ixgb_read_eeprom(hw, i);
+		checksum += ee_data;
+		hw->eeprom[i] = le16_to_cpu(ee_data);
+	}
+
+	if (checksum != (u16) EEPROM_SUM) {
+		DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+		return (FALSE);
+	}
+
+	if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
+	    != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+		DEBUGOUT("ixgb_ee: Signature invalid.\n");
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+/******************************************************************************
+ * Local function to check if the eeprom signature is good
+ * If the eeprom signature is good, calls ixgb)get_eeprom_data.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns:
+ *      TRUE: eeprom signature was good and the eeprom read was successful
+ *      FALSE: otherwise.
+ ******************************************************************************/
+static boolean_t
+ixgb_check_and_get_eeprom_data(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
+	    == le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+		return (TRUE);
+	} else {
+		return ixgb_get_eeprom_data(hw);
+	}
+}
+
+/******************************************************************************
+ * return the mac address from EEPROM
+ *
+ * hw       - Struct containing variables accessed by shared code 
+ * mac_addr - Ethernet Address if EEPROM contents are valid, 0 otherwise
+ *
+ * Returns: None.
+ ******************************************************************************/
+void
+ixgb_get_ee_mac_addr(struct ixgb_hw *hw, u8 * mac_addr)
+{
+	int i;
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	DEBUGFUNC("ixgb_get_ee_mac_addr");
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE) {
+		for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
+			mac_addr[i] = ee_map->mac_addr[i];
+			DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
+		}
+	}
+}
+
+/******************************************************************************
+ * return the compatibility flags from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          compatibility flags if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_compatibility(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->compatibility);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Printed Board Assembly number from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          PBA number if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u32
+ixgb_get_ee_pba_number(struct ixgb_hw * hw)
+{
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
+			| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG]) << 16));
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Initialization Control Word 1 from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->init_ctrl_reg_1);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Initialization Control Word 2 from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->init_ctrl_reg_2);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Subsystem Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          Subsystem Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_subsystem_id(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->subsystem_id);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Sub Vendor Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          Sub Vendor Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_subvendor_id(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->subvendor_id);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Device Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          Device Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_device_id(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->device_id);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Vendor Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          Device Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_vendor_id(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->vendor_id);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the Software Defined Pins Register from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          SDP Register if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u16
+ixgb_get_ee_swdpins_reg(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->swdpins_reg);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the D3 Power Management Bits from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u8
+ixgb_get_ee_d3_power(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->d3_power);
+
+	return (0);
+}
+
+/******************************************************************************
+ * return the D0 Power Management Bits from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Returns: 
+ *          D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+u8
+ixgb_get_ee_d0_power(struct ixgb_hw * hw)
+{
+	struct ixgb_ee_map_type *ee_map =
+	    (struct ixgb_ee_map_type *) hw->eeprom;
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (ee_map->d0_power);
+
+	return (0);
+}
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ee.h linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ee.h
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ee.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ee.h	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,104 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#ifndef _IXGB_EE_H_
+#define _IXGB_EE_H_
+
+#define IXGB_EEPROM_SIZE    64	/* Size in words */
+
+#define IXGB_ETH_LENGTH_OF_ADDRESS   6
+
+/* EEPROM Commands */
+#define EEPROM_READ_OPCODE  0x6		/* EERPOM read opcode */
+#define EEPROM_WRITE_OPCODE 0x5		/* EERPOM write opcode */
+#define EEPROM_ERASE_OPCODE 0x7		/* EERPOM erase opcode */
+#define EEPROM_EWEN_OPCODE  0x13	/* EERPOM erase/write enable */
+#define EEPROM_EWDS_OPCODE  0x10	/* EERPOM erast/write disable */
+
+/* EEPROM MAP (Word Offsets) */
+#define EEPROM_IA_1_2_REG        0x0000
+#define EEPROM_IA_3_4_REG        0x0001
+#define EEPROM_IA_5_6_REG        0x0002
+#define EEPROM_COMPATIBILITY_REG 0x0003
+#define EEPROM_PBA_1_2_REG       0x0008
+#define EEPROM_PBA_3_4_REG       0x0009
+#define EEPROM_INIT_CONTROL1_REG 0x000A
+#define EEPROM_SUBSYS_ID_REG     0x000B
+#define EEPROM_SUBVEND_ID_REG    0x000C
+#define EEPROM_DEVICE_ID_REG     0x000D
+#define EEPROM_VENDOR_ID_REG     0x000E
+#define EEPROM_INIT_CONTROL2_REG 0x000F
+#define EEPROM_SWDPINS_REG       0x0020
+#define EEPROM_CIRCUIT_CTRL_REG  0x0021
+#define EEPROM_D0_D3_POWER_REG   0x0022
+#define EEPROM_FLASH_VERSION     0x0032
+#define EEPROM_CHECKSUM_REG      0x003F
+
+/* Mask bits for fields in Word 0x0a of the EEPROM */
+
+#define EEPROM_ICW1_SIGNATURE_MASK  0xC000
+#define EEPROM_ICW1_SIGNATURE_VALID 0x4000
+
+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
+#define EEPROM_SUM 0xBABA
+
+/* EEPROM Map Sizes (Byte Counts) */
+#define PBA_SIZE 4
+
+/* EEPROM Map defines (WORD OFFSETS)*/
+
+/* EEPROM structure */
+struct ixgb_ee_map_type {
+	u8 mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
+	u16 compatibility;
+	u16 reserved1[4];
+	u32 pba_number;
+	u16 init_ctrl_reg_1;
+	u16 subsystem_id;
+	u16 subvendor_id;
+	u16 device_id;
+	u16 vendor_id;
+	u16 init_ctrl_reg_2;
+	u16 oem_reserved[16];
+	u16 swdpins_reg;
+	u16 circuit_ctrl_reg;
+	u8 d3_power;
+	u8 d0_power;
+	u16 reserved2[28];
+	u16 checksum;
+};
+
+/* EEPROM Functions */
+u16 ixgb_read_eeprom(struct ixgb_hw *hw, u16 reg);
+
+boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
+
+void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
+
+void ixgb_write_eeprom(struct ixgb_hw *hw, u16 reg, u16 data);
+
+#endif				/* IXGB_EE_H */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ethtool.c linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ethtool.c
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ethtool.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ethtool.c	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,555 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+/* ethtool support for ixgb */
+
+#include "ixgb.h"
+
+#include <asm/uaccess.h>
+
+extern char ixgb_driver_name[];
+extern char ixgb_driver_version[];
+
+extern int ixgb_up(struct ixgb_adapter *adapter);
+extern int ixgb_down(struct ixgb_adapter *adapter);
+
+/**
+ * ixgb_ethtool_ioctl - Ethtool Ioctl Support
+ * @netdev: net device structure
+ * @ifr: interface request structure
+ **/
+
+static inline int
+ixgb_eeprom_size(struct ixgb_hw *hw)
+{
+	/* return size in bytes */
+	return (IXGB_EEPROM_SIZE << 1);
+}
+
+#define SUPPORTED_10000baseT_Full (1 << 11)
+#define SPEED_10000 10000
+
+static void
+ixgb_ethtool_gset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd)
+{
+	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+	ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_EXTERNAL;
+
+	if (netif_carrier_ok(adapter->netdev)) {
+		ecmd->speed = 10000;
+		ecmd->duplex = DUPLEX_FULL;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_DISABLE;
+}
+
+static int
+ixgb_ethtool_sset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd)
+{
+	if (ecmd->autoneg == AUTONEG_ENABLE ||
+	    ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
+		return -EINVAL;
+	else {
+		ixgb_down(adapter);
+		ixgb_up(adapter);
+	}
+
+	return 0;
+}
+
+#if 0
+static int
+ixgb_ethtool_promiscuous(struct ixgb_adapter *adapter,
+			 struct ethtool_pmode *pmode)
+{
+	u32 rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+	pmode->rctl_old = rctl;
+	if (pmode->upe)
+		rctl |= IXGB_RCTL_UPE;
+	else
+		rctl &= ~IXGB_RCTL_UPE;
+
+	if (pmode->mpe)
+		rctl |= IXGB_RCTL_MPE;
+	else
+		rctl &= ~IXGB_RCTL_MPE;
+
+	IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+
+	pmode->rctl_new = IXGB_READ_REG(&adapter->hw, RCTL);
+
+	return 0;
+}
+#endif
+
+#define IXGB_REG_DUMP_LEN  136*sizeof(u32)
+static void
+ixgb_ethtool_gdrvinfo(struct ixgb_adapter *adapter,
+		      struct ethtool_drvinfo *drvinfo)
+{
+	strncpy(drvinfo->driver, ixgb_driver_name, 32);
+	strncpy(drvinfo->version, ixgb_driver_version, 32);
+	strncpy(drvinfo->fw_version, "", 32);
+	strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
+#ifdef ETHTOOL_GREGS
+	drvinfo->regdump_len = IXGB_REG_DUMP_LEN;
+#endif				/* ETHTOOL_GREGS */
+	drvinfo->eedump_len = ixgb_eeprom_size(&adapter->hw);
+}
+
+#ifdef  ETHTOOL_GREGS
+#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
+static void
+ixgb_ethtool_gregs(struct ixgb_adapter *adapter,
+		   struct ethtool_regs *regs, u8 * regs_buff)
+{
+	struct ixgb_hw *hw = &adapter->hw;
+	u32 *reg = (u32 *) regs_buff;
+	u32 *reg_start = reg;
+	u8 i;
+
+	regs->version =
+	    (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
+
+	/* General Registers */
+	*reg++ = IXGB_READ_REG(hw, CTRL0);	/*   0 */
+	*reg++ = IXGB_READ_REG(hw, CTRL1);	/*   1 */
+	*reg++ = IXGB_READ_REG(hw, STATUS);	/*   2 */
+	*reg++ = IXGB_READ_REG(hw, EECD);	/*   3 */
+	*reg++ = IXGB_READ_REG(hw, MFS);	/*   4 */
+
+	/* Interrupt */
+	*reg++ = IXGB_READ_REG(hw, ICR);	/*   5 */
+	*reg++ = IXGB_READ_REG(hw, ICS);	/*   6 */
+	*reg++ = IXGB_READ_REG(hw, IMS);	/*   7 */
+	*reg++ = IXGB_READ_REG(hw, IMC);	/*   8 */
+
+	/* Receive */
+	*reg++ = IXGB_READ_REG(hw, RCTL);	/*   9 */
+	*reg++ = IXGB_READ_REG(hw, FCRTL);	/*  10 */
+	*reg++ = IXGB_READ_REG(hw, FCRTH);	/*  11 */
+	*reg++ = IXGB_READ_REG(hw, RDBAL);	/*  12 */
+	*reg++ = IXGB_READ_REG(hw, RDBAH);	/*  13 */
+	*reg++ = IXGB_READ_REG(hw, RDLEN);	/*  14 */
+	*reg++ = IXGB_READ_REG(hw, RDH);	/*  15 */
+	*reg++ = IXGB_READ_REG(hw, RDT);	/*  16 */
+	*reg++ = IXGB_READ_REG(hw, RDTR);	/*  17 */
+	*reg++ = IXGB_READ_REG(hw, RXDCTL);	/*  18 */
+	*reg++ = IXGB_READ_REG(hw, RAIDC);	/*  19 */
+	*reg++ = IXGB_READ_REG(hw, RXCSUM);	/*  20 */
+
+	for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
+		*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1));	/*21,...,51 */
+		*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1));	/*22,...,52 */
+	}
+
+	/* Transmit */
+	*reg++ = IXGB_READ_REG(hw, TCTL);	/*  53 */
+	*reg++ = IXGB_READ_REG(hw, TDBAL);	/*  54 */
+	*reg++ = IXGB_READ_REG(hw, TDBAH);	/*  55 */
+	*reg++ = IXGB_READ_REG(hw, TDLEN);	/*  56 */
+	*reg++ = IXGB_READ_REG(hw, TDH);	/*  57 */
+	*reg++ = IXGB_READ_REG(hw, TDT);	/*  58 */
+	*reg++ = IXGB_READ_REG(hw, TIDV);	/*  59 */
+	*reg++ = IXGB_READ_REG(hw, TXDCTL);	/*  60 */
+	*reg++ = IXGB_READ_REG(hw, TSPMT);	/*  61 */
+	*reg++ = IXGB_READ_REG(hw, PAP);	/*  62 */
+
+	/* Physical */
+	*reg++ = IXGB_READ_REG(hw, PCSC1);	/*  63 */
+	*reg++ = IXGB_READ_REG(hw, PCSC2);	/*  64 */
+	*reg++ = IXGB_READ_REG(hw, PCSS1);	/*  65 */
+	*reg++ = IXGB_READ_REG(hw, PCSS2);	/*  66 */
+	*reg++ = IXGB_READ_REG(hw, XPCSS);	/*  67 */
+	*reg++ = IXGB_READ_REG(hw, UCCR);	/*  68 */
+	*reg++ = IXGB_READ_REG(hw, XPCSTC);	/*  69 */
+	*reg++ = IXGB_READ_REG(hw, MACA);	/*  70 */
+	*reg++ = IXGB_READ_REG(hw, APAE);	/*  71 */
+	*reg++ = IXGB_READ_REG(hw, ARD);	/*  72 */
+	*reg++ = IXGB_READ_REG(hw, AIS);	/*  73 */
+	*reg++ = IXGB_READ_REG(hw, MSCA);	/*  74 */
+	*reg++ = IXGB_READ_REG(hw, MSRWD);	/*  75 */
+
+#if 0
+	/* Wake-up */
+	reg[IXGB_WUFC] = IXGB_READ_REG(hw, WUFC);
+	reg[IXGB_WUS] = IXGB_READ_REG(hw, WUS);
+	reg[IXGB_FFLT] = IXGB_READ_REG(hw, FFLT);
+	reg[IXGB_FFMT] = IXGB_READ_REG(hw, FFMT);
+	reg[IXGB_FTVT] = IXGB_READ_REG(hw, FTVT);
+#endif
+
+	/* Statistics */
+	*reg++ = IXGB_GET_STAT(adapter, tprl);	/*  76 */
+	*reg++ = IXGB_GET_STAT(adapter, tprh);	/*  77 */
+	*reg++ = IXGB_GET_STAT(adapter, gprcl);	/*  78 */
+	*reg++ = IXGB_GET_STAT(adapter, gprch);	/*  79 */
+	*reg++ = IXGB_GET_STAT(adapter, bprcl);	/*  80 */
+	*reg++ = IXGB_GET_STAT(adapter, bprch);	/*  81 */
+	*reg++ = IXGB_GET_STAT(adapter, mprcl);	/*  82 */
+	*reg++ = IXGB_GET_STAT(adapter, mprch);	/*  83 */
+	*reg++ = IXGB_GET_STAT(adapter, uprcl);	/*  84 */
+	*reg++ = IXGB_GET_STAT(adapter, uprch);	/*  85 */
+	*reg++ = IXGB_GET_STAT(adapter, vprcl);	/*  86 */
+	*reg++ = IXGB_GET_STAT(adapter, vprch);	/*  87 */
+	*reg++ = IXGB_GET_STAT(adapter, jprcl);	/*  88 */
+	*reg++ = IXGB_GET_STAT(adapter, jprch);	/*  89 */
+	*reg++ = IXGB_GET_STAT(adapter, gorcl);	/*  90 */
+	*reg++ = IXGB_GET_STAT(adapter, gorch);	/*  91 */
+	*reg++ = IXGB_GET_STAT(adapter, torl);	/*  92 */
+	*reg++ = IXGB_GET_STAT(adapter, torh);	/*  93 */
+	*reg++ = IXGB_GET_STAT(adapter, rnbc);	/*  94 */
+	*reg++ = IXGB_GET_STAT(adapter, ruc);	/*  95 */
+	*reg++ = IXGB_GET_STAT(adapter, roc);	/*  96 */
+	*reg++ = IXGB_GET_STAT(adapter, rlec);	/*  97 */
+	*reg++ = IXGB_GET_STAT(adapter, crcerrs);	/*  98 */
+	*reg++ = IXGB_GET_STAT(adapter, icbc);	/*  99 */
+	*reg++ = IXGB_GET_STAT(adapter, ecbc);	/* 100 */
+	*reg++ = IXGB_GET_STAT(adapter, mpc);	/* 101 */
+	*reg++ = IXGB_GET_STAT(adapter, tptl);	/* 102 */
+	*reg++ = IXGB_GET_STAT(adapter, tpth);	/* 103 */
+	*reg++ = IXGB_GET_STAT(adapter, gptcl);	/* 104 */
+	*reg++ = IXGB_GET_STAT(adapter, gptch);	/* 105 */
+	*reg++ = IXGB_GET_STAT(adapter, bptcl);	/* 106 */
+	*reg++ = IXGB_GET_STAT(adapter, bptch);	/* 107 */
+	*reg++ = IXGB_GET_STAT(adapter, mptcl);	/* 108 */
+	*reg++ = IXGB_GET_STAT(adapter, mptch);	/* 109 */
+	*reg++ = IXGB_GET_STAT(adapter, uptcl);	/* 110 */
+	*reg++ = IXGB_GET_STAT(adapter, uptch);	/* 111 */
+	*reg++ = IXGB_GET_STAT(adapter, vptcl);	/* 112 */
+	*reg++ = IXGB_GET_STAT(adapter, vptch);	/* 113 */
+	*reg++ = IXGB_GET_STAT(adapter, jptcl);	/* 114 */
+	*reg++ = IXGB_GET_STAT(adapter, jptch);	/* 115 */
+	*reg++ = IXGB_GET_STAT(adapter, gotcl);	/* 116 */
+	*reg++ = IXGB_GET_STAT(adapter, gotch);	/* 117 */
+	*reg++ = IXGB_GET_STAT(adapter, totl);	/* 118 */
+	*reg++ = IXGB_GET_STAT(adapter, toth);	/* 119 */
+	*reg++ = IXGB_GET_STAT(adapter, dc);	/* 120 */
+	*reg++ = IXGB_GET_STAT(adapter, plt64c);	/* 121 */
+	*reg++ = IXGB_GET_STAT(adapter, tsctc);	/* 122 */
+	*reg++ = IXGB_GET_STAT(adapter, tsctfc);	/* 123 */
+	*reg++ = IXGB_GET_STAT(adapter, ibic);	/* 124 */
+	*reg++ = IXGB_GET_STAT(adapter, rfc);	/* 125 */
+	*reg++ = IXGB_GET_STAT(adapter, lfc);	/* 126 */
+	*reg++ = IXGB_GET_STAT(adapter, pfrc);	/* 127 */
+	*reg++ = IXGB_GET_STAT(adapter, pftc);	/* 128 */
+	*reg++ = IXGB_GET_STAT(adapter, mcfrc);	/* 129 */
+	*reg++ = IXGB_GET_STAT(adapter, mcftc);	/* 130 */
+	*reg++ = IXGB_GET_STAT(adapter, xonrxc);	/* 131 */
+	*reg++ = IXGB_GET_STAT(adapter, xontxc);	/* 132 */
+	*reg++ = IXGB_GET_STAT(adapter, xoffrxc);	/* 133 */
+	*reg++ = IXGB_GET_STAT(adapter, xofftxc);	/* 134 */
+	*reg++ = IXGB_GET_STAT(adapter, rjc);	/* 135 */
+
+#if 0
+#endif
+	regs->len = (reg - reg_start) * sizeof (u32);
+}
+#endif				/* ETHTOOL_GREGS */
+
+static int
+ixgb_ethtool_geeprom(struct ixgb_adapter *adapter,
+		     struct ethtool_eeprom *eeprom, u16 * eeprom_buff)
+{
+	struct ixgb_hw *hw = &adapter->hw;
+	int i, max_len, first_word, last_word;
+	IXGB_DBG("ixgb_ethtool_geeprom\n");
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+	max_len = ixgb_eeprom_size(hw);
+
+	/* use our function to read the eeprom and update our cache */
+	ixgb_get_eeprom_data(hw);
+
+	if (eeprom->offset > eeprom->offset + eeprom->len)
+		return -EINVAL;
+
+	if ((eeprom->offset + eeprom->len) > max_len)
+		eeprom->len = (max_len - eeprom->offset);
+
+	first_word = eeprom->offset >> 1;
+	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+	for (i = 0; i <= (last_word - first_word); i++) {
+		eeprom_buff[i] = hw->eeprom[first_word + i];
+	}
+
+	return 0;
+}
+static int
+ixgb_ethtool_seeprom(struct ixgb_adapter *adapter,
+		     struct ethtool_eeprom *eeprom, void *user_data)
+{
+	struct ixgb_hw *hw = &adapter->hw;
+	u16 eeprom_buff[256];
+	int i, max_len, first_word, last_word;
+	void *ptr;
+
+	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+		return -EFAULT;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	max_len = ixgb_eeprom_size(hw);
+
+	if (eeprom->offset > eeprom->offset + eeprom->len)
+		return -EINVAL;
+
+	if ((eeprom->offset + eeprom->len) > max_len)
+		eeprom->len = (max_len - eeprom->offset);
+
+	first_word = eeprom->offset >> 1;
+	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+	ptr = (void *) eeprom_buff;
+
+	if (eeprom->offset & 1) {
+		/* need read/modify/write of first changed EEPROM word */
+		/* only the second byte of the word is being modified */
+		eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
+		ptr++;
+	}
+	if ((eeprom->offset + eeprom->len) & 1) {
+		/* need read/modify/write of last changed EEPROM word */
+		/* only the first byte of the word is being modified */
+		eeprom_buff[last_word - first_word]
+		    = ixgb_read_eeprom(hw, last_word);
+	}
+	if (copy_from_user(ptr, user_data, eeprom->len))
+		return -EFAULT;
+
+	for (i = 0; i <= (last_word - first_word); i++)
+		ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
+
+	/* Update the checksum over the first part of the EEPROM if needed */
+	if (first_word <= EEPROM_CHECKSUM_REG)
+		ixgb_update_eeprom_checksum(hw);
+
+	return 0;
+}
+
+#ifdef  ETHTOOL_PHYS_ID
+
+/* toggle LED 4 times per second = 2 "blinks" per second */
+#define IXGB_ID_INTERVAL    (HZ/4)
+
+/* bit defines for adapter->led_status */
+#define IXGB_LED_ON     0
+
+static void
+ixgb_led_blink_callback(unsigned long data)
+{
+	struct ixgb_adapter *adapter = (struct ixgb_adapter *) data;
+
+	if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
+		ixgb_led_off(&adapter->hw);
+	else
+		ixgb_led_on(&adapter->hw);
+
+	mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);
+}
+
+static int
+ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id)
+{
+	if (!adapter->blink_timer.function) {
+		init_timer(&adapter->blink_timer);
+		adapter->blink_timer.function = ixgb_led_blink_callback;
+		adapter->blink_timer.data = (unsigned long) adapter;
+	}
+
+	mod_timer(&adapter->blink_timer, jiffies);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (id->data)
+		schedule_timeout(id->data * HZ);
+	else
+		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+
+	del_timer_sync(&adapter->blink_timer);
+	ixgb_led_off(&adapter->hw);
+	clear_bit(IXGB_LED_ON, &adapter->led_status);
+
+	return 0;
+}
+#endif				/* ETHTOOL_PHYS_ID */
+
+int
+ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	void *addr = ifr->ifr_data;
+	u32 cmd;
+
+	if (get_user(cmd, (u32 *) addr))
+		return -EFAULT;
+
+	switch (cmd) {
+#if 0
+	case ETHTOOL_PROMISCUOUS:{
+			struct ethtool_pmode pmode;
+
+			if (copy_from_user(&pmode, addr, sizeof (pmode)))
+				return -EFAULT;
+
+			ixgb_ethtool_promiscuous(adapter, &pmode);
+
+			if (copy_to_user(addr, &pmode, sizeof (pmode)))
+				return -EFAULT;
+
+			return 0;
+		}
+	case ETHTOOL_DOWN_UP:
+		ixgb_down(netdev->priv);
+		ixgb_up(netdev->priv);
+		return 0;
+#endif
+	case ETHTOOL_GSET:{
+			struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+
+			ixgb_ethtool_gset(adapter, &ecmd);
+			if (copy_to_user(addr, &ecmd, sizeof (ecmd)))
+				return -EFAULT;
+			return 0;
+		}
+	case ETHTOOL_SSET:{
+			struct ethtool_cmd ecmd;
+
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			if (copy_from_user(&ecmd, addr, sizeof (ecmd)))
+				return -EFAULT;
+			return ixgb_ethtool_sset(adapter, &ecmd);
+		}
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO };
+
+			ixgb_ethtool_gdrvinfo(adapter, &drvinfo);
+			if (copy_to_user(addr, &drvinfo, sizeof (drvinfo)))
+				return -EFAULT;
+			return 0;
+		}
+#if defined(ETHTOOL_GREGS) && defined(ETHTOOL_GEEPROM)
+	case ETHTOOL_GREGS:{
+			struct ethtool_regs regs = { ETHTOOL_GREGS };
+			u8 regs_buff[IXGB_REG_DUMP_LEN];
+
+			ixgb_ethtool_gregs(adapter, &regs, regs_buff);
+
+			if (copy_to_user(addr, &regs, sizeof (regs)))
+				return -EFAULT;
+
+			addr += offsetof(struct ethtool_regs, data);
+
+			if (copy_to_user(addr, regs_buff, regs.len))
+				return -EFAULT;
+			return 0;
+		}
+#endif				/* ETHTOOL_GREGS */
+	case ETHTOOL_NWAY_RST:{
+			IXGB_DBG("ETHTOOL_NWAY_RST\n");
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+
+			ixgb_down(adapter);
+			ixgb_up(adapter);
+
+			return 0;
+		}
+#ifdef  ETHTOOL_PHYS_ID
+	case ETHTOOL_PHYS_ID:{
+			struct ethtool_value id;
+
+			IXGB_DBG("ETHTOOL_PHYS_ID\n");
+			if (copy_from_user(&id, addr, sizeof (id)))
+				return -EFAULT;
+			return ixgb_ethtool_led_blink(adapter, &id);
+		}
+#endif				/* ETHTOOL_PHYS_ID */
+	case ETHTOOL_GLINK:{
+			struct ethtool_value link = { ETHTOOL_GLINK };
+
+			IXGB_DBG("ETHTOOL_GLINK\n");
+			link.data = netif_carrier_ok(netdev);
+			if (copy_to_user(addr, &link, sizeof (link)))
+				return -EFAULT;
+			return 0;
+		}
+
+	case ETHTOOL_GEEPROM:{
+			struct ethtool_eeprom eeprom = { ETHTOOL_GEEPROM };
+			u16 eeprom_buff[IXGB_EEPROM_SIZE];
+			void *ptr;
+			int err;
+
+			IXGB_DBG("ETHTOOL_GEEPROM\n");
+			if (copy_from_user(&eeprom, addr, sizeof (eeprom)))
+				return -EFAULT;
+
+			if ((err =
+			     ixgb_ethtool_geeprom(adapter, &eeprom,
+						  eeprom_buff)) < 0)
+				return err;
+
+			if (copy_to_user(addr, &eeprom, sizeof (eeprom)))
+				return -EFAULT;
+
+			addr += offsetof(struct ethtool_eeprom, data);
+
+			ptr = ((void *) eeprom_buff) + (eeprom.offset & 1);
+			if (copy_to_user(addr, ptr, eeprom.len))
+				return -EFAULT;
+			return 0;
+		}
+	case ETHTOOL_SEEPROM:{
+			struct ethtool_eeprom eeprom;
+
+			IXGB_DBG("ETHTOOL_SEEPROM\n");
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+
+			if (copy_from_user(&eeprom, addr, sizeof (eeprom)))
+				return -EFAULT;
+
+			addr += offsetof(struct ethtool_eeprom, data);
+			return ixgb_ethtool_seeprom(adapter, &eeprom, addr);
+		}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_hw.c linux-2.5.68-bk9/drivers/net/ixgb/ixgb_hw.c
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_hw.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_hw.c	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,1055 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+/* ixgb_hw.c
+ * Shared functions for accessing and configuring the adapter
+ */
+
+#include "ixgb_hw.h"
+#include "ixgb_ids.h"
+
+/*  Local function prototypes */
+
+static u32 ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr);
+
+static void ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value);
+
+static void ixgb_get_bus_info(struct ixgb_hw *hw);
+
+boolean_t mac_addr_valid(u8 * mac_addr);
+
+static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
+
+static void ixgb_optics_reset(struct ixgb_hw *hw);
+
+u32 ixgb_mac_reset(struct ixgb_hw *hw);
+
+u32
+ixgb_mac_reset(struct ixgb_hw *hw)
+{
+	u32 ctrl_reg;
+
+	/* Setup up hardware to known state with RESET.  */
+	ctrl_reg = IXGB_CTRL0_RST | IXGB_CTRL0_SDP3_DIR |	/* All pins are Output=1 */
+	    IXGB_CTRL0_SDP2_DIR | IXGB_CTRL0_SDP1_DIR | IXGB_CTRL0_SDP0_DIR | IXGB_CTRL0_SDP3 |	/* Initial value 1101   */
+	    IXGB_CTRL0_SDP2 | IXGB_CTRL0_SDP0;
+#ifdef HP_ZX1
+	outl(IXGB_CTRL0, hw->io_base);
+	outl(ctrl_reg, hw->io_base + 4);
+#else
+	IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
+#endif
+
+	/* Delay a few ms just to allow the reset to complete */
+	msec_delay(IXGB_DELAY_AFTER_RESET);
+	ctrl_reg = IXGB_READ_REG(hw, CTRL0);
+#if DBG
+	/* Make sure the self-clearing global reset bit did self clear */
+	ASSERT(!(ctrl_reg & IXGB_CTRL0_RST));
+#endif
+
+	ixgb_optics_reset(hw);
+	return ctrl_reg;
+}
+
+/******************************************************************************
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+boolean_t
+ixgb_adapter_stop(struct ixgb_hw * hw)
+{
+	u32 ctrl_reg;
+	u32 icr_reg;
+
+	DEBUGFUNC("ixgb_adapter_stop");
+
+	/* If we are stopped or resetting exit gracefully and wait to be
+	 * started again before accessing the hardware.
+	 */
+	if (hw->adapter_stopped) {
+		DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+		return FALSE;
+	}
+
+	/* Set the Adapter Stopped flag so other driver functions stop
+	 * touching the Hardware.
+	 */
+	hw->adapter_stopped = TRUE;
+
+	/* Clear interrupt mask to stop board from generating interrupts */
+	DEBUGOUT("Masking off all interrupts\n");
+	IXGB_WRITE_REG(hw, IMC, 0xFFFFFFFF);
+
+	/* Disable the Transmit and Receive units.  Then delay to allow
+	 * any pending transactions to complete before we hit the MAC with
+	 * the global reset.
+	 */
+	IXGB_WRITE_REG(hw, RCTL, IXGB_READ_REG(hw, RCTL) & ~IXGB_RCTL_RXEN);
+	IXGB_WRITE_REG(hw, TCTL, IXGB_READ_REG(hw, TCTL) & ~IXGB_TCTL_TXEN);
+	msec_delay(IXGB_DELAY_BEFORE_RESET);
+
+	/* Issue a global reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA, and link units.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	DEBUGOUT("Issuing a global reset to MAC\n");
+
+	ctrl_reg = ixgb_mac_reset(hw);
+
+	/* Clear interrupt mask to stop board from generating interrupts */
+	DEBUGOUT("Masking off all interrupts\n");
+	IXGB_WRITE_REG(hw, IMC, 0xffffffff);
+
+	/* Clear any pending interrupt events. */
+	icr_reg = IXGB_READ_REG(hw, ICR);
+
+	return (ctrl_reg & IXGB_CTRL0_RST);
+}
+
+/******************************************************************************
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * 
+ * Resets the controller.  
+ * Reads and validates the EEPROM.
+ * Initializes the receive address registers.
+ * Initializes the multicast table.
+ * Clears all on-chip counters. 
+ * Calls routine to setup flow control settings. 
+ * Leaves the transmit and receive units disabled and uninitialized.
+ * 
+ * Returns:
+ *      TRUE if successful, 
+ *      FALSE if unrecoverable problems were encountered.
+ *****************************************************************************/
+boolean_t
+ixgb_init_hw(struct ixgb_hw * hw)
+{
+	u32 i;
+	u32 ctrl_reg;
+	boolean_t status;
+
+	DEBUGFUNC("ixgb_init_hw");
+
+	/* Issue a global reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA, and link units.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	DEBUGOUT("Issuing a global reset to MAC\n");
+
+	ctrl_reg = ixgb_mac_reset(hw);
+
+	DEBUGOUT("Issuing an EE reset to MAC\n");
+#ifdef HP_ZX1
+	outl(IXGB_CTRL1, hw->io_base);
+	outl(IXGB_CTRL1_EE_RST, hw->io_base + 4);
+#else
+	IXGB_WRITE_REG(hw, CTRL1, IXGB_CTRL1_EE_RST);
+#endif
+
+	/* Delay a few ms just to allow the reset to complete */
+	msec_delay(IXGB_DELAY_AFTER_EE_RESET);
+
+	if (ixgb_get_eeprom_data(hw) == FALSE) {
+		return (FALSE);
+	}
+
+	/* Setup the receive addresses. 
+	 * Receive Address Registers (RARs 0 - 15).
+	 */
+	ixgb_init_rx_addrs(hw);
+
+	/* 
+	 * Check that a valid MAC address has been set.
+	 * If it is not valid, we fail hardware init.
+	 */
+	if (!mac_addr_valid(hw->curr_mac_addr)) {
+		DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+		return (FALSE);
+	}
+
+	/* tell the routines in this file they can access hardware again */
+	hw->adapter_stopped = FALSE;
+
+	/* Fill in the bus_info structure */
+	ixgb_get_bus_info(hw);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < IXGB_MC_TBL_SIZE; i++)
+		IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
+
+	/* Zero out the VLAN Filter Table Array */
+	ixgb_clear_vfta(hw);
+
+	/* Zero all of the hardware counters */
+	ixgb_clear_hw_cntrs(hw);
+
+	/* Call a subroutine to setup flow control. */
+	status = ixgb_setup_fc(hw);
+
+	/* check-for-link in case lane deskew is locked */
+	ixgb_check_for_link(hw);
+
+	return (status);
+}
+
+/******************************************************************************
+ * Initializes receive address filters.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Places the MAC address in receive address register 0 and clears the rest
+ * of the receive addresss registers. Clears the multicast table. Assumes
+ * the receiver is in reset when the routine is called.
+ *****************************************************************************/
+void
+ixgb_init_rx_addrs(struct ixgb_hw *hw)
+{
+	u32 i;
+
+	DEBUGFUNC("ixgb_init_rx_addrs");
+
+	/* 
+	 * If the current mac address is valid, assume it is a software override
+	 * to the permanent address.
+	 * Otherwise, use the permanent address from the eeprom.
+	 */
+	if (!mac_addr_valid(hw->curr_mac_addr)) {
+
+		/* Get the MAC address from the eeprom for later reference */
+		ixgb_get_ee_mac_addr(hw, hw->curr_mac_addr);
+
+		DEBUGOUT3(" Keeping Permanent MAC Addr =%.2X %.2X %.2X ",
+			  hw->curr_mac_addr[0],
+			  hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
+		DEBUGOUT3("%.2X %.2X %.2X\n",
+			  hw->curr_mac_addr[3],
+			  hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+	} else {
+
+		/* Setup the receive address. */
+		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
+		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
+			  hw->curr_mac_addr[0],
+			  hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
+		DEBUGOUT3("%.2X %.2X %.2X\n",
+			  hw->curr_mac_addr[3],
+			  hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+
+		ixgb_rar_set(hw, hw->curr_mac_addr, 0);
+	}
+
+	/* Zero out the other 15 receive addresses. */
+	DEBUGOUT("Clearing RAR[1-15]\n");
+	for (i = 1; i < IXGB_RAR_ENTRIES; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+	}
+
+	return;
+}
+
+/******************************************************************************
+ * Updates the MAC's list of multicast addresses.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr_list - the list of new multicast addresses
+ * mc_addr_count - number of addresses
+ * pad - number of bytes between addresses in the list
+ *
+ * The given list replaces any existing list. Clears the last 15 receive
+ * address registers and the multicast table. Uses receive address registers
+ * for the first 15 multicast addresses, and hashes the rest into the 
+ * multicast table.
+ *****************************************************************************/
+void
+ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+			 u8 * mc_addr_list,
+			 u32 mc_addr_count, u32 pad)
+{
+	u32 hash_value;
+	u32 i;
+	u32 rar_used_count = 1;	/* RAR[0] is used for our MAC address */
+
+	DEBUGFUNC("ixgb_mc_addr_list_update");
+
+	/* Set the new number of MC addresses that we are being requested to use. */
+	hw->num_mc_addrs = mc_addr_count;
+
+	/* Clear RAR[1-15] */
+	DEBUGOUT(" Clearing RAR[1-15]\n");
+	for (i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+	}
+
+	/* Clear the MTA */
+	DEBUGOUT(" Clearing MTA\n");
+	for (i = 0; i < IXGB_MC_TBL_SIZE; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
+	}
+
+	/* Add the new addresses */
+	for (i = 0; i < mc_addr_count; i++) {
+		DEBUGOUT(" Adding the multicast addresses:\n");
+		DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       1],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       2],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       3],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       4],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       5]);
+
+		/* Place this multicast address in the RAR if there is room, *
+		 * else put it in the MTA            
+		 */
+		if (rar_used_count < IXGB_RAR_ENTRIES) {
+			ixgb_rar_set(hw,
+				     mc_addr_list +
+				     (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
+				     rar_used_count);
+			DEBUGOUT1("Added a multicast address to RAR[%d]\n", i);
+			rar_used_count++;
+		} else {
+			hash_value = ixgb_hash_mc_addr(hw,
+						       mc_addr_list +
+						       (i *
+							(IXGB_ETH_LENGTH_OF_ADDRESS
+							 + pad)));
+
+			DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
+
+			ixgb_mta_set(hw, hash_value);
+		}
+	}
+
+	DEBUGOUT("MC Update Complete\n");
+	return;
+}
+
+/******************************************************************************
+ * Hashes an address to determine its location in the multicast table
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash 
+ *
+ * Returns:
+ *      The hash value
+ *****************************************************************************/
+static u32
+ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr)
+{
+	u32 hash_value = 0;
+
+	DEBUGFUNC("ixgb_hash_mc_addr");
+
+	/* The portion of the address that is used for the hash table is
+	 * determined by the mc_filter_type setting.  
+	 */
+	switch (hw->mc_filter_type) {
+		/* [0] [1] [2] [3] [4] [5]
+		 * 01  AA  00  12  34  56
+		 * LSB                 MSB - According to H/W docs */
+	case 0:
+		/* [47:36] i.e. 0x563 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+		break;
+	case 1:		/* [46:35] i.e. 0xAC6 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+		break;
+	case 2:		/* [45:34] i.e. 0x5D8 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+		break;
+	case 3:		/* [43:32] i.e. 0x634 for above example address */
+		hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+		break;
+	default:
+		/* Invalid mc_filter_type, what should we do? */
+		DEBUGOUT("MC filter type param set incorrectly\n");
+		ASSERT(0);
+		break;
+	}
+
+	hash_value &= 0xFFF;
+	return (hash_value);
+}
+
+/******************************************************************************
+ * Sets the bit in the multicast table corresponding to the hash value.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ *****************************************************************************/
+static void
+ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta_reg;
+
+	/* The MTA is a register array of 128 32-bit registers.  
+	 * It is treated like an array of 4096 bits.  We want to set 
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the 
+	 * upper 7 bits of the hash value and the bit within that 
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 5) & 0x7F;
+	hash_bit = hash_value & 0x1F;
+
+	mta_reg = IXGB_READ_REG_ARRAY(hw, MTA, hash_reg);
+
+	mta_reg |= (1 << hash_bit);
+
+	IXGB_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta_reg);
+
+	return;
+}
+
+/******************************************************************************
+ * Puts an ethernet address into a receive address register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * addr - Address to put into receive address register
+ * index - Receive address register to write
+ *****************************************************************************/
+void
+ixgb_rar_set(struct ixgb_hw *hw, u8 * addr, u32 index)
+{
+	u32 rar_low, rar_high;
+
+	DEBUGFUNC("ixgb_rar_set");
+
+	/* HW expects these in little endian so we reverse the byte order
+	 * from network order (big endian) to little endian              
+	 */
+	rar_low = ((u32) addr[0] |
+		   ((u32) addr[1] << 8) |
+		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+	rar_high = ((u32) addr[4] |
+		    ((u32) addr[5] << 8) | IXGB_RAH_AV);
+
+	IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+	IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
+	return;
+}
+
+/******************************************************************************
+ * Writes a value to the specified offset in the VLAN filter table.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - Offset in VLAN filer table to write
+ * value - Value to write into VLAN filter table
+ *****************************************************************************/
+void
+ixgb_write_vfta(struct ixgb_hw *hw, u32 offset, u32 value)
+{
+	IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+	return;
+}
+
+/******************************************************************************
+ * Clears the VLAN filer table
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_clear_vfta(struct ixgb_hw *hw)
+{
+	u32 offset;
+
+	for (offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+		IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+	return;
+}
+
+/******************************************************************************
+ * Configures the flow control settings based on SW configuration.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+
+boolean_t
+ixgb_setup_fc(struct ixgb_hw * hw)
+{
+	u32 ctrl_reg;
+	u32 pap_reg = 0;	/* by default, assume no pause time */
+	boolean_t status = TRUE;
+
+	DEBUGFUNC("ixgb_setup_fc");
+
+	/* Get the current control reg 0 settings */
+	ctrl_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* Clear the Receive Pause Enable and Transmit Pause Enable bits */
+	ctrl_reg &= ~(IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
+
+	/* The possible values of the "flow_control" parameter are:
+	 *      0:  Flow control is completely disabled
+	 *      1:  Rx flow control is enabled (we can receive pause frames
+	 *          but not send pause frames).
+	 *      2:  Tx flow control is enabled (we can send pause frames
+	 *          but we do not support receiving pause frames).
+	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
+	 *  other:  Invalid.
+	 */
+	switch (hw->fc.type) {
+	case ixgb_fc_none:	/* 0 */
+		break;
+	case ixgb_fc_rx_pause:	/* 1 */
+		/* RX Flow control is enabled, and TX Flow control is
+		 * disabled.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_RPE);
+		break;
+	case ixgb_fc_tx_pause:	/* 2 */
+		/* TX Flow control is enabled, and RX Flow control is
+		 * disabled, by a software over-ride.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_TPE);
+		pap_reg = hw->fc.pause_time;
+		break;
+	case ixgb_fc_full:	/* 3 */
+		/* Flow control (both RX and TX) is enabled by a software
+		 * over-ride.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
+		pap_reg = hw->fc.pause_time;
+		break;
+	default:
+		/* We should never get here.  The value should be 0-3. */
+		DEBUGOUT("Flow control param set incorrectly\n");
+		ASSERT(0);
+		break;
+	}
+
+	/* Write the new settings */
+	IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
+
+	if (pap_reg != 0) {
+		IXGB_WRITE_REG(hw, PAP, pap_reg);
+	}
+
+	/* Set the flow control receive threshold registers.  Normally,
+	 * these registers will be set to a default threshold that may be
+	 * adjusted later by the driver's runtime code.  However, if the
+	 * ability to transmit pause frames in not enabled, then these
+	 * registers will be set to 0. 
+	 */
+	if (!(hw->fc.type & ixgb_fc_tx_pause)) {
+		IXGB_WRITE_REG(hw, FCRTL, 0);
+		IXGB_WRITE_REG(hw, FCRTH, 0);
+	} else {
+		/* We need to set up the Receive Threshold high and low water
+		 * marks as well as (optionally) enabling the transmission of XON frames.
+		 */
+		if (hw->fc.send_xon) {
+			IXGB_WRITE_REG(hw, FCRTL,
+				       (hw->fc.low_water | IXGB_FCRTL_XONE));
+		} else {
+			IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);
+		}
+		IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);
+	}
+	return (status);
+}
+
+/******************************************************************************
+ * Reads a word from a device over the Management Data Interface (MDI) bus.
+ * This interface is used to manage Physical layer devices.
+ *
+ * hw          - Struct containing variables accessed by hw code
+ * reg_address - Offset of device register being read.
+ * phy_address - Address of device on MDI.
+ *
+ * Returns:  Data word (16 bits) from MDI device.
+ *
+ * This routine uses the new protocol MDI Single Command and Address Operation.
+ * This requires that first an address cycle command is sent, followed by a
+ * read command.
+ *****************************************************************************/
+u16
+ixgb_read_phy_reg(struct ixgb_hw * hw,
+		  u32 reg_address,
+		  u32 phy_address, u32 device_type)
+{
+	u32 i;
+	u32 data;
+	u32 command = 0;
+
+	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+
+	/* Setup and write the address cycle command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the address cycle completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** This may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for (i = 0; i < 10; i++) {
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Address cycle complete, setup and write the read command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_READ | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the read command completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** The read may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for (i = 0; i < 10; i++) {
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Operation is complete, get the data from the MDIO Read/Write Data
+	 * register and return. 
+	 */
+	data = IXGB_READ_REG(hw, MSRWD);
+	data >>= IXGB_MSRWD_READ_DATA_SHIFT;
+	return ((u16) data);
+}
+
+/******************************************************************************
+ * Writes a word to a device over the Management Data Interface (MDI) bus.
+ * This interface is used to manage Physical layer devices.
+ *
+ * hw          - Struct containing variables accessed by hw code
+ * reg_address - Offset of device register being read.
+ * phy_address - Address of device on MDI.
+ * device_type - Also known as the Device ID or DID.
+ * data        - 16-bit value to be written
+ *
+ * Returns:  void.
+ *
+ * This routine uses the new protocol MDI Single Command and Address Operation.
+ * This requires that first an address cycle command is sent, followed by a
+ * write command.
+ *****************************************************************************/
+void
+ixgb_write_phy_reg(struct ixgb_hw *hw,
+		   u32 reg_address,
+		   u32 phy_address, u32 device_type, u16 data)
+{
+	u32 i;
+	u32 command = 0;
+
+	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+
+	/* Put the data in the MDIO Read/Write Data register */
+	IXGB_WRITE_REG(hw, MSRWD, (u32) data);
+
+	/* Setup and write the address cycle command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the address cycle completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** This may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for (i = 0; i < 10; i++) {
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Address cycle complete, setup and write the write command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the read command completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** The write may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for (i = 0; i < 10; i++) {
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Operation is complete, return. */
+}
+
+/******************************************************************************
+ * Checks to see if the link status of the hardware has changed.
+ *
+ * hw - Struct containing variables accessed by hw code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+void
+ixgb_check_for_link(struct ixgb_hw *hw)
+{
+	u32 status_reg;
+	u32 xpcss_reg;
+
+	DEBUGFUNC("ixgb_check_for_link");
+
+	xpcss_reg = IXGB_READ_REG(hw, XPCSS);
+	status_reg = IXGB_READ_REG(hw, STATUS);
+
+	if ((xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+	    (status_reg & IXGB_STATUS_LU)) {
+		hw->link_up = TRUE;
+	} else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+		   (status_reg & IXGB_STATUS_LU)) {
+		DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
+		hw->link_up = ixgb_link_reset(hw);
+	} else {
+		hw->link_up = ixgb_link_reset(hw);
+	}
+
+	/*  Anything else for 10 Gig?? */
+}
+
+boolean_t
+ixgb_check_for_bad_link(struct ixgb_hw *hw)
+{
+	u32 newLFC, newRFC;
+	boolean_t bad_link_returncode = FALSE;
+
+	/* check for a bad reset that may have occured
+	 * the indication is that the RFC / LFC registers may be incrementing
+	 * continually. Do a full adapter reset to recover
+	 */
+	newLFC = IXGB_READ_REG(hw, LFC);
+	newRFC = IXGB_READ_REG(hw, RFC);
+	if ((hw->lastLFC + 250 < newLFC) || (hw->lastRFC + 250 < newRFC)) {
+		DEBUGOUT("BAD LINK! too many LFC/RFC since last check\n");
+		bad_link_returncode = TRUE;
+	}
+	hw->lastLFC = newLFC;
+	hw->lastRFC = newRFC;
+	return bad_link_returncode;
+}
+
+/******************************************************************************
+ * Clears all hardware statistics counters. 
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+{
+	volatile u32 temp_reg;
+
+	DEBUGFUNC("ixgb_clear_hw_cntrs");
+
+	/* if we are stopped or resetting exit gracefully */
+	if (hw->adapter_stopped) {
+		DEBUGOUT("Exiting because the adapter is stopped!!!\n");
+		return;
+	}
+
+	temp_reg = IXGB_READ_REG(hw, TPRL);
+	temp_reg = IXGB_READ_REG(hw, TPRH);
+	temp_reg = IXGB_READ_REG(hw, GPRCL);
+	temp_reg = IXGB_READ_REG(hw, GPRCH);
+	temp_reg = IXGB_READ_REG(hw, BPRCL);
+	temp_reg = IXGB_READ_REG(hw, BPRCH);
+	temp_reg = IXGB_READ_REG(hw, MPRCL);
+	temp_reg = IXGB_READ_REG(hw, MPRCH);
+	temp_reg = IXGB_READ_REG(hw, UPRCL);
+	temp_reg = IXGB_READ_REG(hw, UPRCH);
+	temp_reg = IXGB_READ_REG(hw, VPRCL);
+	temp_reg = IXGB_READ_REG(hw, VPRCH);
+	temp_reg = IXGB_READ_REG(hw, JPRCL);
+	temp_reg = IXGB_READ_REG(hw, JPRCH);
+	temp_reg = IXGB_READ_REG(hw, GORCL);
+	temp_reg = IXGB_READ_REG(hw, GORCH);
+	temp_reg = IXGB_READ_REG(hw, TORL);
+	temp_reg = IXGB_READ_REG(hw, TORH);
+	temp_reg = IXGB_READ_REG(hw, RNBC);
+	temp_reg = IXGB_READ_REG(hw, RUC);
+	temp_reg = IXGB_READ_REG(hw, ROC);
+	temp_reg = IXGB_READ_REG(hw, RLEC);
+	temp_reg = IXGB_READ_REG(hw, CRCERRS);
+	temp_reg = IXGB_READ_REG(hw, ICBC);
+	temp_reg = IXGB_READ_REG(hw, ECBC);
+	temp_reg = IXGB_READ_REG(hw, MPC);
+	temp_reg = IXGB_READ_REG(hw, TPTL);
+	temp_reg = IXGB_READ_REG(hw, TPTH);
+	temp_reg = IXGB_READ_REG(hw, GPTCL);
+	temp_reg = IXGB_READ_REG(hw, GPTCH);
+	temp_reg = IXGB_READ_REG(hw, BPTCL);
+	temp_reg = IXGB_READ_REG(hw, BPTCH);
+	temp_reg = IXGB_READ_REG(hw, MPTCL);
+	temp_reg = IXGB_READ_REG(hw, MPTCH);
+	temp_reg = IXGB_READ_REG(hw, UPTCL);
+	temp_reg = IXGB_READ_REG(hw, UPTCH);
+	temp_reg = IXGB_READ_REG(hw, VPTCL);
+	temp_reg = IXGB_READ_REG(hw, VPTCH);
+	temp_reg = IXGB_READ_REG(hw, JPTCL);
+	temp_reg = IXGB_READ_REG(hw, JPTCH);
+	temp_reg = IXGB_READ_REG(hw, GOTCL);
+	temp_reg = IXGB_READ_REG(hw, GOTCH);
+	temp_reg = IXGB_READ_REG(hw, TOTL);
+	temp_reg = IXGB_READ_REG(hw, TOTH);
+	temp_reg = IXGB_READ_REG(hw, DC);
+	temp_reg = IXGB_READ_REG(hw, PLT64C);
+	temp_reg = IXGB_READ_REG(hw, TSCTC);
+	temp_reg = IXGB_READ_REG(hw, TSCTFC);
+	temp_reg = IXGB_READ_REG(hw, IBIC);
+	temp_reg = IXGB_READ_REG(hw, RFC);
+	temp_reg = IXGB_READ_REG(hw, LFC);
+	temp_reg = IXGB_READ_REG(hw, PFRC);
+	temp_reg = IXGB_READ_REG(hw, PFTC);
+	temp_reg = IXGB_READ_REG(hw, MCFRC);
+	temp_reg = IXGB_READ_REG(hw, MCFTC);
+	temp_reg = IXGB_READ_REG(hw, XONRXC);
+	temp_reg = IXGB_READ_REG(hw, XONTXC);
+	temp_reg = IXGB_READ_REG(hw, XOFFRXC);
+	temp_reg = IXGB_READ_REG(hw, XOFFTXC);
+	temp_reg = IXGB_READ_REG(hw, RJC);
+	return;
+}
+
+/******************************************************************************
+ * Turns on the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_led_on(struct ixgb_hw *hw)
+{
+	u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* To turn on the LED, clear software-definable pin 0 (SDP0). */
+	ctrl0_reg &= ~IXGB_CTRL0_SDP0;
+	IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
+	return;
+}
+
+/******************************************************************************
+ * Turns off the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_led_off(struct ixgb_hw *hw)
+{
+	u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* To turn off the LED, set software-definable pin 0 (SDP0). */
+	ctrl0_reg |= IXGB_CTRL0_SDP0;
+	IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
+	return;
+}
+
+/******************************************************************************
+ * Gets the current PCI bus type, speed, and width of the hardware
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_get_bus_info(struct ixgb_hw *hw)
+{
+	u32 status_reg;
+
+	status_reg = IXGB_READ_REG(hw, STATUS);
+
+	hw->bus.type = (status_reg & IXGB_STATUS_PCIX_MODE) ?
+	    ixgb_bus_type_pcix : ixgb_bus_type_pci;
+
+	if (hw->bus.type == ixgb_bus_type_pci) {
+		hw->bus.speed = (status_reg & IXGB_STATUS_PCI_SPD) ?
+		    ixgb_bus_speed_66 : ixgb_bus_speed_33;
+	} else {
+		switch (status_reg & IXGB_STATUS_PCIX_SPD_MASK) {
+		case IXGB_STATUS_PCIX_SPD_66:
+			hw->bus.speed = ixgb_bus_speed_66;
+			break;
+		case IXGB_STATUS_PCIX_SPD_100:
+			hw->bus.speed = ixgb_bus_speed_100;
+			break;
+		case IXGB_STATUS_PCIX_SPD_133:
+			hw->bus.speed = ixgb_bus_speed_133;
+			break;
+		default:
+			hw->bus.speed = ixgb_bus_speed_reserved;
+			break;
+		}
+	}
+
+	hw->bus.width = (status_reg & IXGB_STATUS_BUS64) ?
+	    ixgb_bus_width_64 : ixgb_bus_width_32;
+
+	return;
+}
+
+/******************************************************************************
+ * Tests a MAC address to ensure it is a valid Individual Address
+ *
+ * mac_addr - pointer to MAC address. 
+ *
+ *****************************************************************************/
+boolean_t
+mac_addr_valid(u8 * mac_addr)
+{
+	boolean_t is_valid = TRUE;
+	DEBUGFUNC("mac_addr_valid");
+
+	/* Make sure it is not a multicast address */
+	if (IS_MULTICAST(mac_addr)) {
+		DEBUGOUT("MAC address is multicast\n");
+		is_valid = FALSE;
+	}
+	/* Not a broadcast address */
+	else if (IS_BROADCAST(mac_addr)) {
+		DEBUGOUT("MAC address is broadcast\n");
+		is_valid = FALSE;
+	}
+	/* Reject the zero address */
+	else if (mac_addr[0] == 0 &&
+		 mac_addr[1] == 0 &&
+		 mac_addr[2] == 0 &&
+		 mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
+		DEBUGOUT("MAC address is all zeros\n");
+		is_valid = FALSE;
+	}
+	return (is_valid);
+}
+
+/******************************************************************************
+ * Resets the 10GbE link.  Waits the settle time and returns the state of 
+ * the link.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+boolean_t
+ixgb_link_reset(struct ixgb_hw * hw)
+{
+	boolean_t link_status = FALSE;
+	u8 wait_retries = MAX_RESET_ITERATIONS;
+	u8 lrst_retries = MAX_RESET_ITERATIONS;
+
+	do {
+		IXGB_WRITE_REG(hw, CTRL0,
+			       IXGB_READ_REG(hw, CTRL0) | IXGB_CTRL0_LRST);
+
+		do {
+			udelay(IXGB_DELAY_USECS_AFTER_LINK_RESET);
+			link_status =
+			    ((IXGB_READ_REG(hw, STATUS) & IXGB_STATUS_LU)
+			     && (IXGB_READ_REG(hw, XPCSS) &
+				 IXGB_XPCSS_ALIGN_STATUS)) ? TRUE : FALSE;
+		} while (!link_status && --wait_retries);
+	} while (!link_status && --lrst_retries);
+
+	return link_status;
+}
+
+/******************************************************************************
+ * Resets the 10GbE optics module.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_optics_reset(struct ixgb_hw *hw)
+{
+	u16 mdio_reg;
+
+	ixgb_write_phy_reg(hw,
+			   TXN17401_PMA_PMD_CR1,
+			   IXGB_PHY_ADDRESS,
+			   TXN17401_PMA_PMD_DID, TXN17401_PMA_PMD_CR1_RESET);
+	mdio_reg = ixgb_read_phy_reg(hw,
+				     TXN17401_PMA_PMD_CR1,
+				     IXGB_PHY_ADDRESS, TXN17401_PMA_PMD_DID);
+}
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_hw.h linux-2.5.68-bk9/drivers/net/ixgb/ixgb_hw.h
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_hw.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_hw.h	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,625 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#ifndef _IXGB_HW_H_
+#define _IXGB_HW_H_
+
+#include "ixgb_osdep.h"
+
+/* Enums */
+typedef enum {
+	ixgb_mac_unknown = 0,
+	ixgb_82597,
+	ixgb_num_macs
+} ixgb_mac_type;
+
+/* Media Types */
+typedef enum {
+	ixgb_media_type_unknown = 0,
+	ixgb_media_type_fiber = 1,
+	ixgb_num_media_types
+} ixgb_media_type;
+
+/* Flow Control Settings */
+typedef enum {
+	ixgb_fc_none = 0,
+	ixgb_fc_rx_pause = 1,
+	ixgb_fc_tx_pause = 2,
+	ixgb_fc_full = 3,
+	ixgb_fc_default = 0xFF
+} ixgb_fc_type;
+
+/* PCI bus types */
+typedef enum {
+	ixgb_bus_type_unknown = 0,
+	ixgb_bus_type_pci,
+	ixgb_bus_type_pcix
+} ixgb_bus_type;
+
+/* PCI bus speeds */
+typedef enum {
+	ixgb_bus_speed_unknown = 0,
+	ixgb_bus_speed_33,
+	ixgb_bus_speed_66,
+	ixgb_bus_speed_100,
+	ixgb_bus_speed_133,
+	ixgb_bus_speed_reserved
+} ixgb_bus_speed;
+
+/* PCI bus widths */
+typedef enum {
+	ixgb_bus_width_unknown = 0,
+	ixgb_bus_width_32,
+	ixgb_bus_width_64
+} ixgb_bus_width;
+
+#define IXGB_ETH_LENGTH_OF_ADDRESS   6
+
+#define IXGB_EEPROM_SIZE    64	/* Size in words */
+
+#define SPEED_10000  10000
+#define FULL_DUPLEX  2
+
+#define IXGB_DELAY_BEFORE_RESET        10	/* allow 10ms after idling rx/tx units      */
+#define IXGB_DELAY_AFTER_RESET          1	/* allow 1ms after the reset                */
+#define IXGB_DELAY_AFTER_EE_RESET      10	/* allow 10ms after the EEPROM reset        */
+
+#define IXGB_DELAY_USECS_AFTER_LINK_RESET    13	/* allow 13 microseconds after the reset    */
+					   /* NOTE: this is MICROSECONDS               */
+#define MAX_RESET_ITERATIONS            8	/* number of iterations to get things right */
+
+/* General Registers */
+#define IXGB_CTRL0   0x00000	/* Device Control Register 0 - RW */
+#define IXGB_CTRL1   0x00008	/* Device Control Register 1 - RW */
+#define IXGB_STATUS  0x00010	/* Device Status Register - RO */
+#define IXGB_EECD    0x00018	/* EEPROM/Flash Control/Data Register - RW */
+#define IXGB_MFS     0x00020	/* Maximum Frame Size - RW */
+
+/* Interrupt */
+#define IXGB_ICR     0x00080	/* Interrupt Cause Read - R/clr */
+#define IXGB_ICS     0x00088	/* Interrupt Cause Set - RW */
+#define IXGB_IMS     0x00090	/* Interrupt Mask Set/Read - RW */
+#define IXGB_IMC     0x00098	/* Interrupt Mask Clear - WO */
+
+/* Receive */
+#define IXGB_RCTL    0x00100	/* RX Control - RW */
+#define IXGB_FCRTL   0x00108	/* Flow Control Receive Threshold Low - RW */
+#define IXGB_FCRTH   0x00110	/* Flow Control Receive Threshold High - RW */
+#define IXGB_RDBAL   0x00118	/* RX Descriptor Base Low - RW */
+#define IXGB_RDBAH   0x0011C	/* RX Descriptor Base High - RW */
+#define IXGB_RDLEN   0x00120	/* RX Descriptor Length - RW */
+#define IXGB_RDH     0x00128	/* RX Descriptor Head - RW */
+#define IXGB_RDT     0x00130	/* RX Descriptor Tail - RW */
+#define IXGB_RDTR    0x00138	/* RX Delay Timer Ring - RW */
+#define IXGB_RXDCTL  0x00140	/* Receive Descriptor Control - RW */
+#define IXGB_RAIDC   0x00148	/* Receive Adaptive Interrupt Delay Control - RW */
+#define IXGB_RXCSUM  0x00158	/* Receive Checksum Control - RW */
+#define IXGB_RA      0x00180	/* Receive Address Array Base - RW */
+#define IXGB_RAL     0x00180	/* Receive Address Low [0:15] - RW */
+#define IXGB_RAH     0x00184	/* Receive Address High [0:15] - RW */
+#define IXGB_MTA     0x00200	/* Multicast Table Array [0:127] - RW */
+#define IXGB_VFTA    0x00400	/* VLAN Filter Table Array [0:127] - RW */
+#define IXGB_REQ_RX_DESCRIPTOR_MULTIPLE 8
+
+/* Transmit */
+#define IXGB_TCTL    0x00600	/* TX Control - RW */
+#define IXGB_TDBAL   0x00608	/* TX Descriptor Base Low - RW */
+#define IXGB_TDBAH   0x0060C	/* TX Descriptor Base High - RW */
+#define IXGB_TDLEN   0x00610	/* TX Descriptor Length - RW */
+#define IXGB_TDH     0x00618	/* TX Descriptor Head - RW */
+#define IXGB_TDT     0x00620	/* TX Descriptor Tail - RW */
+#define IXGB_TIDV    0x00628	/* TX Interrupt Delay Value - RW */
+#define IXGB_TXDCTL  0x00630	/* Transmit Descriptor Control - RW */
+#define IXGB_TSPMT   0x00638	/* TCP Segmentation PAD & Min Threshold - RW */
+#define IXGB_PAP     0x00640	/* Pause and Pace - RW */
+#define IXGB_REQ_TX_DESCRIPTOR_MULTIPLE 8
+
+/* Physical */
+#define IXGB_PCSC1   0x00700	/* PCS Control 1 - RW */
+#define IXGB_PCSC2   0x00708	/* PCS Control 2 - RW */
+#define IXGB_PCSS1   0x00710	/* PCS Status 1 - RO */
+#define IXGB_PCSS2   0x00718	/* PCS Status 2 - RO */
+#define IXGB_XPCSS   0x00720	/* 10GBASE-X PCS Status (or XGXS Lane Status) - RO */
+#define IXGB_UCCR    0x00728	/* Unilink Circuit Control Register */
+#define IXGB_XPCSTC  0x00730	/* 10GBASE-X PCS Test Control */
+#define IXGB_MACA    0x00738	/* MDI Autoscan Command and Address - RW */
+#define IXGB_APAE    0x00740	/* Autoscan PHY Address Enable - RW */
+#define IXGB_ARD     0x00748	/* Autoscan Read Data - RO */
+#define IXGB_AIS     0x00750	/* Autoscan Interrupt Status - RO */
+#define IXGB_MSCA    0x00758	/* MDI Single Command and Address - RW */
+#define IXGB_MSRWD   0x00760	/* MDI Single Read and Write Data - RW, RO */
+
+/* Wake-up */
+#define IXGB_WUFC    0x00808	/* Wake Up Filter Control - RW */
+#define IXGB_WUS     0x00810	/* Wake Up Status - RO */
+#define IXGB_FFLT    0x01000	/* Flexible Filter Length Table - RW */
+#define IXGB_FFMT    0x01020	/* Flexible Filter Mask Table - RW */
+#define IXGB_FTVT    0x01420	/* Flexible Filter Value Table - RW */
+
+/* Statistics */
+#define IXGB_TPRL    0x02000	/* Total Packets Received (Low) */
+#define IXGB_TPRH    0x02004	/* Total Packets Received (High) */
+#define IXGB_GPRCL   0x02008	/* Good Packets Received Count (Low) */
+#define IXGB_GPRCH   0x0200C	/* Good Packets Received Count (High) */
+#define IXGB_BPRCL   0x02010	/* Broadcast Packets Received Count (Low) */
+#define IXGB_BPRCH   0x02014	/* Broadcast Packets Received Count (High) */
+#define IXGB_MPRCL   0x02018	/* Multicast Packets Received Count (Low) */
+#define IXGB_MPRCH   0x0201C	/* Multicast Packets Received Count (High) */
+#define IXGB_UPRCL   0x02020	/* Unicast Packets Received Count (Low) */
+#define IXGB_UPRCH   0x02024	/* Unicast Packets Received Count (High) */
+#define IXGB_VPRCL   0x02028	/* VLAN Packets Received Count (Low) */
+#define IXGB_VPRCH   0x0202C	/* VLAN Packets Received Count (High) */
+#define IXGB_JPRCL   0x02030	/* Jumbo Packets Received Count (Low) */
+#define IXGB_JPRCH   0x02034	/* Jumbo Packets Received Count (High) */
+#define IXGB_GORCL   0x02038	/* Good Octets Received Count (Low) */
+#define IXGB_GORCH   0x0203C	/* Good Octets Received Count (High) */
+#define IXGB_TORL    0x02040	/* Total Octets Received (Low) */
+#define IXGB_TORH    0x02044	/* Total Octets Received (High) */
+#define IXGB_RNBC    0x02048	/* Receive No Buffers Count */
+#define IXGB_RUC     0x02050	/* Receive Undersize Count */
+#define IXGB_ROC     0x02058	/* Receive Oversize Count */
+#define IXGB_RLEC    0x02060	/* Receive Length Error Count */
+#define IXGB_CRCERRS 0x02068	/* CRC Error Count */
+#define IXGB_ICBC    0x02070	/* Illegal control byte in mid-packet Count */
+#define IXGB_ECBC    0x02078	/* Error Control byte in mid-packet Count */
+#define IXGB_MPC     0x02080	/* Missed Packets Count */
+#define IXGB_TPTL    0x02100	/* Total Packets Transmitted (Low) */
+#define IXGB_TPTH    0x02104	/* Total Packets Transmitted (High) */
+#define IXGB_GPTCL   0x02108	/* Good Packets Transmitted Count (Low) */
+#define IXGB_GPTCH   0x0210C	/* Good Packets Transmitted Count (High) */
+#define IXGB_BPTCL   0x02110	/* Broadcast Packets Transmitted Count (Low) */
+#define IXGB_BPTCH   0x02114	/* Broadcast Packets Transmitted Count (High) */
+#define IXGB_MPTCL   0x02118	/* Multicast Packets Transmitted Count (Low) */
+#define IXGB_MPTCH   0x0211C	/* Multicast Packets Transmitted Count (High) */
+#define IXGB_UPTCL   0x02120	/* Unicast Packets Transmitted Count (Low) */
+#define IXGB_UPTCH   0x02124	/* Unicast Packets Transmitted Count (High) */
+#define IXGB_VPTCL   0x02128	/* VLAN Packets Transmitted Count (Low) */
+#define IXGB_VPTCH   0x0212C	/* VLAN Packets Transmitted Count (High) */
+#define IXGB_JPTCL   0x02130	/* Jumbo Packets Transmitted Count (Low) */
+#define IXGB_JPTCH   0x02134	/* Jumbo Packets Transmitted Count (High) */
+#define IXGB_GOTCL   0x02138	/* Good Octets Transmitted Count (Low) */
+#define IXGB_GOTCH   0x0213C	/* Good Octets Transmitted Count (High) */
+#define IXGB_TOTL    0x02140	/* Total Octets Transmitted Count (Low) */
+#define IXGB_TOTH    0x02144	/* Total Octets Transmitted Count (High) */
+#define IXGB_DC      0x02148	/* Defer Count */
+#define IXGB_PLT64C  0x02150	/* Packet Transmitted was less than 64 bytes Count */
+#define IXGB_TSCTC   0x02170	/* TCP Segmentation Context Transmitted Count */
+#define IXGB_TSCTFC  0x02178	/* TCP Segmentation Context Tx Fail Count */
+#define IXGB_IBIC    0x02180	/* Illegal byte during Idle stream count */
+#define IXGB_RFC     0x02188	/* Remote Fault Count */
+#define IXGB_LFC     0x02190	/* Local Fault Count */
+#define IXGB_PFRC    0x02198	/* Pause Frame Receive Count */
+#define IXGB_PFTC    0x021A0	/* Pause Frame Transmit Count */
+#define IXGB_MCFRC   0x021A8	/* MAC Control Frames (non-Pause) Received Count */
+#define IXGB_MCFTC   0x021B0	/* MAC Control Frames (non-Pause) Transmitted Count */
+#define IXGB_XONRXC  0x021B8	/* XON Received Count */
+#define IXGB_XONTXC  0x021C0	/* XON Transmitted Count */
+#define IXGB_XOFFRXC 0x021C8	/* XOFF Received Count */
+#define IXGB_XOFFTXC 0x021D0	/* XOFF Transmitted Count */
+#define IXGB_RJC     0x021D8	/* Receive Jabber Count */
+
+/* CTRL0 Bit Masks */
+#define IXGB_CTRL0_LRST     0x00000008
+#define IXGB_CTRL0_JFE      0x00000010
+#define IXGB_CTRL0_SDP0     0x00040000
+#define IXGB_CTRL0_SDP1     0x00080000
+#define IXGB_CTRL0_SDP2     0x00100000
+#define IXGB_CTRL0_SDP3     0x00200000
+#define IXGB_CTRL0_SDP0_DIR 0x00400000
+#define IXGB_CTRL0_SDP1_DIR 0x00800000
+#define IXGB_CTRL0_SDP2_DIR 0x01000000
+#define IXGB_CTRL0_SDP3_DIR 0x02000000
+#define IXGB_CTRL0_RST      0x04000000
+#define IXGB_CTRL0_RPE      0x08000000
+#define IXGB_CTRL0_TPE      0x10000000
+#define IXGB_CTRL0_VME      0x40000000
+
+/* CTRL1 Bit Masks */
+
+#define IXGB_CTRL1_EE_RST      0x00002000
+
+/* STATUS Bit Masks */
+#define IXGB_STATUS_LU            0x00000002
+
+#define IXGB_STATUS_TXOFF         0x00000010
+
+#define IXGB_STATUS_PCI_SPD       0x00000800
+#define IXGB_STATUS_BUS64         0x00001000
+#define IXGB_STATUS_PCIX_MODE     0x00002000
+#define IXGB_STATUS_PCIX_SPD_MASK 0x0000C000
+#define IXGB_STATUS_PCIX_SPD_66   0x00000000
+#define IXGB_STATUS_PCIX_SPD_100  0x00004000
+#define IXGB_STATUS_PCIX_SPD_133  0x00008000
+
+/* EECD Bit Masks */
+#define IXGB_EECD_SK       0x00000001
+#define IXGB_EECD_CS       0x00000002
+#define IXGB_EECD_DI       0x00000004
+#define IXGB_EECD_DO       0x00000008
+
+/* MFS */
+#define IXGB_MFS_SHIFT 16
+
+/* Interrupt Register Bit Masks (used for ICR, ICS, IMS, and IMC) */
+#define IXGB_INT_TXDW     0x00000001
+#define IXGB_INT_LSC      0x00000004
+#define IXGB_INT_RXSEQ    0x00000008
+#define IXGB_INT_RXDMT0   0x00000010
+#define IXGB_INT_RXO      0x00000040
+#define IXGB_INT_RXT0     0x00000080
+
+/* RCTL Bit Masks */
+#define IXGB_RCTL_RXEN        0x00000002
+#define IXGB_RCTL_UPE         0x00000008
+#define IXGB_RCTL_MPE         0x00000010
+#define IXGB_RCTL_RDMTS_1_2   0x00000000
+#define IXGB_RCTL_MO_SHIFT    12
+#define IXGB_RCTL_BAM         0x00008000
+#define IXGB_RCTL_BSIZE_2048  0x00000000
+#define IXGB_RCTL_BSIZE_4096  0x00010000
+#define IXGB_RCTL_BSIZE_8192  0x00020000
+#define IXGB_RCTL_BSIZE_16384 0x00030000
+#define IXGB_RCTL_VFE         0x00040000
+#define IXGB_RCTL_CFIEN       0x00080000
+#define IXGB_RCTL_CFI         0x00100000
+#define IXGB_RCTL_CFF         0x00800000
+#define IXGB_RCTL_SECRC       0x04000000
+
+/* FCRTL Bit Masks */
+#define IXGB_FCRTL_XONE       0x80000000
+
+/* RXDCTL Bit Masks */
+#define IXGB_RXDCTL_PTHRESH_SHIFT 0
+#define IXGB_RXDCTL_HTHRESH_SHIFT 9
+#define IXGB_RXDCTL_WTHRESH_SHIFT 18
+
+/* RAIDC Bit Masks */
+#define IXGB_RAIDC_DELAY_SHIFT   11
+#define IXGB_RAIDC_POLL_SHIFT    20
+#define IXGB_RAIDC_RXT_GATE      0x40000000
+#define IXGB_RAIDC_EN            0x80000000
+
+/* RXCSUM Bit Masks */
+#define IXGB_RXCSUM_TUOFL 0x00000200
+
+/* RAH Bit Masks */
+#define IXGB_RAH_AV        0x80000000
+
+/* TCTL Bit Masks */
+#define IXGB_TCTL_TCE  0x00000001
+#define IXGB_TCTL_TXEN 0x00000002
+#define IXGB_TCTL_TPDE 0x00000004
+
+/* TXDCTL Bit Masks */
+#define IXGB_TXDCTL_HTHRESH_SHIFT 8
+
+/* TSPMT Bit Masks */
+
+/* PAP Bit Masks */
+
+/* PCSC1 Bit Masks */
+
+/* PCSC2 Bit Masks */
+
+/* PCSS1 Bit Masks */
+
+/* PCSS2 Bit Masks */
+
+/* XPCSS Bit Masks */
+#define IXGB_XPCSS_ALIGN_STATUS 0x00001000
+
+/* XPCSTC Bit Masks */
+
+/* MSCA bit Masks */
+/* New Protocol Address */
+#define IXGB_MSCA_NP_ADDR_SHIFT     0
+/* Either Device Type or Register Address,depending on ST_CODE */
+#define IXGB_MSCA_DEV_TYPE_SHIFT    16
+#define IXGB_MSCA_PHY_ADDR_SHIFT    21
+#define IXGB_MSCA_ADDR_CYCLE        0x00000000
+#define IXGB_MSCA_WRITE             0x04000000
+#define IXGB_MSCA_READ              0x08000000
+/* Initiate command, self-clearing when command completes */
+#define IXGB_MSCA_MDI_COMMAND       0x40000000
+/*MDI In Progress Enable. */
+
+/* MSRWD bit masks */
+#define IXGB_MSRWD_READ_DATA_SHIFT  16
+
+/* Definitions for the TXN17401 devices on the MDIO bus. */
+#define IXGB_PHY_ADDRESS             0x0	/* Single PHY, multiple "Devices" */
+
+/* Five bit Device IDs */
+#define TXN17401_PMA_PMD_DID    0x01
+#define TXN17401_PCS_DID        0x03
+#define TXN17401_XGXS_DID       0x04
+
+/* PMA/PMD registers and bit definitions. */
+/* Note: This is a very limited set of definitions,      */
+/* only implemented features are defined.                */
+#define TXN17401_PMA_PMD_CR1        0x0000
+
+#define TXN17401_PMA_PMD_CR1_RESET  0x8000
+
+struct ixgb_rx_desc {
+	uint64_t buff_addr;
+	u16 length;
+	u16 reserved;
+	u8 status;
+	u8 errors;
+	u16 special;
+};
+
+#define IXGB_RX_DESC_STATUS_DD    0x01
+#define IXGB_RX_DESC_STATUS_EOP   0x02
+#define IXGB_RX_DESC_STATUS_IXSM  0x04
+#define IXGB_RX_DESC_STATUS_VP    0x08
+#define IXGB_RX_DESC_STATUS_TCPCS 0x20
+
+#define IXGB_RX_DESC_ERRORS_CE   0x01
+#define IXGB_RX_DESC_ERRORS_SE   0x02
+#define IXGB_RX_DESC_ERRORS_P    0x08
+#define IXGB_RX_DESC_ERRORS_TCPE 0x20
+#define IXGB_RX_DESC_ERRORS_RXE  0x80
+
+#define IXGB_RX_DESC_SPECIAL_VLAN_MASK  0x0FFF	/* VLAN ID is in lower 12 bits */
+
+struct ixgb_tx_desc {
+	uint64_t buff_addr;
+	u32 cmd_type_len;
+	u8 status;
+	u8 popts;
+	u16 vlan;
+};
+
+#define IXGB_TX_DESC_CMD_EOP        0x01000000
+#define IXGB_TX_DESC_CMD_TSE        0x04000000
+#define IXGB_TX_DESC_CMD_RS         0x08000000
+#define IXGB_TX_DESC_CMD_VLE        0x40000000
+#define IXGB_TX_DESC_CMD_IDE        0x80000000
+
+#define IXGB_TX_DESC_TYPE           0x00100000
+
+#define IXGB_TX_DESC_STATUS_DD  0x01
+
+#define IXGB_TX_DESC_POPTS_IXSM 0x01
+#define IXGB_TX_DESC_POPTS_TXSM 0x02
+
+struct ixgb_context_desc {
+	u8 ipcss;
+	u8 ipcso;
+	u16 ipcse;
+	u8 tucss;
+	u8 tucso;
+	u16 tucse;
+	u32 cmd_type_len;
+	u8 status;
+	u8 hdr_len;
+	u16 mss;
+};
+
+#define IXGB_CONTEXT_DESC_CMD_TCP 0x01000000
+#define IXGB_CONTEXT_DESC_CMD_IP  0x02000000
+#define IXGB_CONTEXT_DESC_CMD_TSE 0x04000000
+#define IXGB_CONTEXT_DESC_CMD_RS  0x08000000
+#define IXGB_CONTEXT_DESC_CMD_IDE 0x80000000
+
+#define IXGB_CONTEXT_DESC_TYPE 0x00000000
+
+/* Filters */
+#define IXGB_RAR_ENTRIES          16	/* Number of entries in Rx Address array */
+#define IXGB_MC_TBL_SIZE          128	/* Multicast Filter Table (4096 bits) */
+#define IXGB_VLAN_FILTER_TBL_SIZE 128	/* VLAN Filter Table (4096 bits) */
+
+#define ENET_HEADER_SIZE            14
+#define ENET_FCS_LENGTH             4
+#define IXGB_MAX_NUM_MULTICAST_ADDRESSES    128
+#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS    60
+#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS    1514
+#define IXGB_MAX_JUMBO_FRAME_SIZE       0x3F00
+
+/* Phy Addresses */
+
+/*
+ * This is a little-endian specific check.
+ */
+#define IS_MULTICAST(Address) \
+    (boolean_t)(((u8 *)(Address))[0] & ((u8)0x01))
+
+/*
+ * Check whether an address is broadcast.
+ */
+#define IS_BROADCAST(Address)               \
+    ((((u8 *)(Address))[0] == ((u8)0xff)) && (((u8 *)(Address))[1] == ((u8)0xff)))
+
+/* Flow control parameters */
+struct ixgb_fc {
+	u32 high_water;	/* Flow Control High-water          */
+	u32 low_water;	/* Flow Control Low-water           */
+	u16 pause_time;	/* Flow Control Pause timer         */
+	boolean_t send_xon;	/* Flow control send XON            */
+	ixgb_fc_type type;	/* Type of flow control             */
+};
+
+/* The historical defaults for the flow control values are given below. */
+
+/* Phy definitions */
+#define IXGB_MAX_PHY_REG_ADDRESS    0xFFFF
+#define IXGB_MAX_PHY_ADDRESS        31
+#define IXGB_MAX_PHY_DEV_TYPE       31
+
+/* Bus parameters */
+struct ixgb_bus {
+	ixgb_bus_speed speed;
+	ixgb_bus_width width;
+	ixgb_bus_type type;
+};
+
+struct ixgb_hw {
+	u8 *hw_addr;	/* Base Address of the hardware     */
+	void *back;		/* Pointer to OS-dependent struct   */
+	struct ixgb_fc fc;	/* Flow control parameters          */
+	struct ixgb_bus bus;	/* Bus parameters                   */
+	u32 phy_id;	/* Phy Identifier                   */
+	u32 phy_addr;	/* XGMII address of Phy             */
+	ixgb_mac_type mac_type;	/* Identifier for MAC controller    */
+	u32 max_frame_size;	/* Maximum frame size supported     */
+	u32 mc_filter_type;	/* Multicast filter hash type       */
+	u32 num_mc_addrs;	/* Number of current Multicast addrs */
+	u8 curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];	/* Individual address currently programmed in MAC */
+	u32 num_tx_desc;	/* Number of Transmit descriptors   */
+	u32 num_rx_desc;	/* Number of Receive descriptors    */
+	u32 rx_buffer_size;	/* Size of Receive buffer           */
+	boolean_t link_up;	/* TRUE if link is valid            */
+	boolean_t adapter_stopped;	/* State of adapter                 */
+	u16 device_id;	/* device id from PCI configuration space */
+	u16 vendor_id;	/* vendor id from PCI configuration space */
+	u16 subsystem_vendor_id;	/* subsystem vendor id from PCI configuration space */
+	u16 subsystem_id;	/* subsystem id from PCI configuration space */
+	u16 eeprom[IXGB_EEPROM_SIZE];	/* EEPROM contents read at init time  */
+	uint64_t io_base;	/* Our I/O mapped location */
+	u32 lastLFC;
+	u32 lastRFC;
+};
+
+struct ixgb_hw_stats {
+	uint64_t tprl;
+	uint64_t tprh;
+	uint64_t gprcl;
+	uint64_t gprch;
+	uint64_t bprcl;
+	uint64_t bprch;
+	uint64_t mprcl;
+	uint64_t mprch;
+	uint64_t uprcl;
+	uint64_t uprch;
+	uint64_t vprcl;
+	uint64_t vprch;
+	uint64_t jprcl;
+	uint64_t jprch;
+	uint64_t gorcl;
+	uint64_t gorch;
+	uint64_t torl;
+	uint64_t torh;
+	uint64_t rnbc;
+	uint64_t ruc;
+	uint64_t roc;
+	uint64_t rlec;
+	uint64_t crcerrs;
+	uint64_t icbc;
+	uint64_t ecbc;
+	uint64_t mpc;
+	uint64_t tptl;
+	uint64_t tpth;
+	uint64_t gptcl;
+	uint64_t gptch;
+	uint64_t bptcl;
+	uint64_t bptch;
+	uint64_t mptcl;
+	uint64_t mptch;
+	uint64_t uptcl;
+	uint64_t uptch;
+	uint64_t vptcl;
+	uint64_t vptch;
+	uint64_t jptcl;
+	uint64_t jptch;
+	uint64_t gotcl;
+	uint64_t gotch;
+	uint64_t totl;
+	uint64_t toth;
+	uint64_t dc;
+	uint64_t plt64c;
+	uint64_t tsctc;
+	uint64_t tsctfc;
+	uint64_t ibic;
+	uint64_t rfc;
+	uint64_t lfc;
+	uint64_t pfrc;
+	uint64_t pftc;
+	uint64_t mcfrc;
+	uint64_t mcftc;
+	uint64_t xonrxc;
+	uint64_t xontxc;
+	uint64_t xoffrxc;
+	uint64_t xofftxc;
+	uint64_t rjc;
+};
+
+/* Function Prototypes */
+extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw);
+extern boolean_t ixgb_init_hw(struct ixgb_hw *hw);
+extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw);
+extern void ixgb_init_rx_addrs(struct ixgb_hw *hw);
+extern void ixgb_check_for_link(struct ixgb_hw *hw);
+extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
+extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
+extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw);
+extern boolean_t mac_addr_valid(u8 * mac_addr);
+
+extern u16 ixgb_read_phy_reg(struct ixgb_hw *hw,
+				  u32 reg_addr,
+				  u32 phy_addr, u32 device_type);
+
+extern void ixgb_write_phy_reg(struct ixgb_hw *hw,
+			       u32 reg_addr,
+			       u32 phy_addr,
+			       u32 device_type, u16 data);
+
+extern void ixgb_rar_set(struct ixgb_hw *hw, u8 * addr, u32 index);
+
+/* Filters (multicast, vlan, receive) */
+extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+				     u8 * mc_addr_list,
+				     u32 mc_addr_count, u32 pad);
+
+/* Vfta functions */
+extern void ixgb_write_vfta(struct ixgb_hw *hw,
+			    u32 offset, u32 value);
+
+extern void ixgb_clear_vfta(struct ixgb_hw *hw);
+
+/* Access functions to eeprom data */
+void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, u8 * mac_addr);
+u16 ixgb_get_ee_compatibility(struct ixgb_hw *hw);
+u32 ixgb_get_ee_pba_number(struct ixgb_hw *hw);
+u16 ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
+u16 ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
+u16 ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
+u16 ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
+u16 ixgb_get_ee_device_id(struct ixgb_hw *hw);
+u16 ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
+u16 ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
+u8 ixgb_get_ee_d3_power(struct ixgb_hw *hw);
+u8 ixgb_get_ee_d0_power(struct ixgb_hw *hw);
+boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
+
+/* Everything else */
+void ixgb_led_on(struct ixgb_hw *hw);
+void ixgb_led_off(struct ixgb_hw *hw);
+void ixgb_write_pci_cfg(struct ixgb_hw *hw, u32 reg, u16 * value);
+
+#endif				/* _IXGB_HW_H_ */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ids.h linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ids.h
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_ids.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_ids.h	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,44 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#ifndef _IXGB_IDS_H_
+#define _IXGB_IDS_H_
+
+/**********************************************************************
+** The Device and Vendor IDs for 10 Gigabit MACs
+**********************************************************************/
+
+#define INTEL_VENDOR_ID         0x8086
+#define INTEL_SUBVENDOR_ID      0x8086
+
+#define IXGB_DEVICE_ID_82597EX 	0x1048
+#define IXGB_SUBDEVICE_ID_A11F  0xA11F	/* Adapter-OEM-1310nm-Fiber */
+#define IXGB_SUBDEVICE_ID_A01F	0xA01F	/* Adapter-Retail-1310nm-Fiber */
+
+#endif				/* #ifndef _IXGB_IDS_H_ */
+
+/* End of File */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_main.c linux-2.5.68-bk9/drivers/net/ixgb/ixgb_main.c
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_main.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_main.c	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,2350 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#define __IXGB_MAIN__
+
+#include "ixgb.h"
+
+char ixgb_driver_name[] = "ixgb";
+char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
+char ixgb_driver_version[] = "1.0.47-k1jg";
+char ixgb_copyright[] = "Copyright (c) 2001-2003 Intel Corporation.";
+
+/* ixgb_pci_tbl - PCI Device ID Table
+ *
+ * For selecting devices to load on private driver_data field (last one) 
+ * stores an index into ixgb_strings.
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, String Index }
+ */
+static struct pci_device_id ixgb_pci_tbl[] __devinitdata = {
+	/* Intel(R) PRO/10GbE Network Connection */
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
+	 INTEL_SUBVENDOR_ID, IXGB_SUBDEVICE_ID_A11F, 0, 0, 0},
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
+	 INTEL_SUBVENDOR_ID, IXGB_SUBDEVICE_ID_A01F, 0, 0, 0},
+	/* Generic */
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+	/* required last entry */
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
+
+static char *ixgb_strings[] = {
+	"Intel(R) PRO/10GbE Network Connection"
+};
+
+/* Local Function Prototypes */
+
+int ixgb_up(struct ixgb_adapter *adapter);
+void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+void ixgb_reset(struct ixgb_adapter *adapter);
+
+static int ixgb_init_module(void);
+static void ixgb_exit_module(void);
+static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void ixgb_remove(struct pci_dev *pdev);
+static void ixgb_sw_init(struct ixgb_adapter *adapter);
+static int ixgb_open(struct net_device *netdev);
+static int ixgb_close(struct net_device *netdev);
+static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+static void ixgb_configure_tx(struct ixgb_adapter *adapter);
+static void ixgb_configure_rx(struct ixgb_adapter *adapter);
+static void ixgb_setup_rctl(struct ixgb_adapter *adapter);
+static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);
+static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);
+static void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+static void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+static void ixgb_set_multi(struct net_device *netdev);
+static void ixgb_watchdog(unsigned long data);
+static inline boolean_t ixgb_tso(struct ixgb_adapter *adapter,
+				 struct sk_buff *skb);
+static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+static void ixgb_tx_timeout(struct net_device *netdev);
+static void ixgb_tx_timeout_task(struct net_device *netdev);
+static void ixgb_vlan_rx_register(struct net_device *netdev,
+				  struct vlan_group *grp);
+static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
+static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
+static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
+static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
+static int ixgb_set_mac(struct net_device *netdev, void *p);
+static void ixgb_update_stats(struct ixgb_adapter *adapter);
+static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
+static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
+static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
+static void ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+#ifdef CONFIG_IXGB_NAPI
+static int ixgb_poll(struct net_device *netdev, int *budget);
+#else
+static void ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+#endif
+static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
+				    struct ixgb_rx_desc *rx_desc,
+				    struct sk_buff *skb);
+static int ixgb_notify_reboot(struct notifier_block *, unsigned long event,
+			      void *ptr);
+static int ixgb_suspend(struct pci_dev *pdev, u32 state);
+
+struct notifier_block ixgb_notifier_reboot = {
+	.notifier_call	= ixgb_notify_reboot,
+	.next		= NULL,
+	.priority	= 0
+};
+
+/* Exported from other modules */
+
+extern void ixgb_check_options(struct ixgb_adapter *adapter);
+extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
+
+static struct pci_driver ixgb_driver = {
+	.name		= ixgb_driver_name,
+	.id_table	= ixgb_pci_tbl,
+	.probe		= ixgb_probe,
+	.remove		= __devexit_p(ixgb_remove),
+	/* Power Managment Hooks */
+	.suspend	= NULL,
+	.resume		= NULL
+};
+
+MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
+MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
+MODULE_LICENSE("GPL");
+
+/* some defines for controlling descriptor fetches in h/w */
+#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
+#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is 
+					   pushed this many descriptors from head */
+#define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 */
+
+/**
+ * ixgb_init_module - Driver Registration Routine.
+ *
+ * ixgb_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+
+static int __init
+ixgb_init_module(void)
+{
+	int ret;
+	IXGB_DBG("ixgb_init_module\n");
+
+	printk(KERN_INFO "%s - version %s\n", ixgb_driver_string,
+	       ixgb_driver_version);
+	printk(KERN_INFO "%s\n", ixgb_copyright);
+#ifdef CONFIG_IXGB_NAPI
+	printk(KERN_INFO "NAPI Enabled\n");
+#endif
+	ret = pci_module_init(&ixgb_driver);
+	if (ret >= 0) {
+		register_reboot_notifier(&ixgb_notifier_reboot);
+	}
+	return ret;
+}
+
+module_init(ixgb_init_module);
+
+/**
+ * ixgb_exit_module - Driver Exit Cleanup Routine.
+ *
+ * ixgb_exit_module is called just before the driver is removed
+ * from memory.
+ **/
+
+static void __exit
+ixgb_exit_module(void)
+{
+
+	IXGB_DBG("ixgb_exit_module\n");
+	unregister_reboot_notifier(&ixgb_notifier_reboot);
+	pci_unregister_driver(&ixgb_driver);
+}
+
+module_exit(ixgb_exit_module);
+
+/**
+ * ixgb_up - Driver ifconfig UP routine.
+ *
+ * ixgb_up is called to initialize and bring online an interface.
+ * @param adapter board private structure
+ **/
+
+int
+ixgb_up(struct ixgb_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	IXGB_DBG("ixgb_up\n");
+
+	if (request_irq(netdev->irq, &ixgb_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
+			netdev->name, netdev)) {
+		IXGB_DBG("%s: request_irq failed\n", netdev->name);
+		return -1;
+	}
+	/* disable interrupts and get the hardware into a known state */
+	IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+
+	/* hardware was reset in probe/down, we need to reload some things */
+	ixgb_set_multi(netdev);
+	ixgb_restore_vlan(adapter);
+
+	ixgb_configure_tx(adapter);
+	ixgb_setup_rctl(adapter);
+	ixgb_configure_rx(adapter);
+	ixgb_alloc_rx_buffers(adapter);
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+	ixgb_irq_enable(adapter);
+
+	IXGB_DBG("ixgb_up: RAH_0 is <%x>\n", IXGB_READ_REG(&adapter->hw, RAH));
+	IXGB_DBG("ixgb_up: RDBAL is <%x>\n",
+		 IXGB_READ_REG(&adapter->hw, RDBAL));
+	return 0;
+}
+
+/**
+ * ixgb_down - Driver ifconfig DOWN routine.
+ *
+ * ixgb_down is called to uninitialize and take offline an interface.
+ * @param adapter board private structure
+ * @param kill_watchdog
+ **/
+void
+ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	IXGB_DBG("ixgb_down\n");
+
+	ixgb_irq_disable(adapter);
+	free_irq(netdev->irq, netdev);
+	if (kill_watchdog)
+		del_timer_sync(&adapter->watchdog_timer);
+	adapter->link_speed = 0;
+	adapter->link_duplex = 0;
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	ixgb_reset(adapter);
+
+	ixgb_clean_tx_ring(adapter);
+	ixgb_clean_rx_ring(adapter);
+}
+
+/**
+ * ixgb_reset - hardware reset.
+ *
+ * ixgb_reset is called to initialize hardware to a known state.
+ * @param adapter board private structure
+ **/
+void
+ixgb_reset(struct ixgb_adapter *adapter)
+{
+	IXGB_DBG("ixgb_reset\n");
+
+	ixgb_adapter_stop(&adapter->hw);
+	if (!ixgb_init_hw(&adapter->hw))
+		IXGB_DBG("ixgb_init_hw failed.\n");
+}
+
+/**
+ * ixgb_probe - Device Initialization Routine.
+ * @param pdev PCI device information struct
+ * @param ent entry in ixgb_pci_table
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int __devinit
+ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *netdev = NULL;
+	struct ixgb_adapter *adapter;
+	static int cards_found = 0;
+	unsigned long mmio_start;
+	int mmio_len;
+	int pci_using_dac;
+	int i;
+
+	IXGB_DBG("ixgb_probe\n");
+
+	if ((i = pci_enable_device(pdev))) {
+		IXGB_ERR("pci_enable_device failed\n");
+		return i;
+	}
+
+	if (!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
+		pci_using_dac = 1;
+	} else {
+		if ((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
+			IXGB_ERR("No usable DMA configuration, aborting\n");
+			return i;
+		}
+		pci_using_dac = 0;
+	}
+
+	if ((i = pci_request_regions(pdev, ixgb_driver_name))) {
+		IXGB_ERR("Failed to reserve PCI I/O and Memory resources.\n");
+		return i;
+	}
+
+	pci_set_master(pdev);
+
+	/* alloc_etherdev clears the memory for us */
+	netdev = alloc_etherdev(sizeof (struct ixgb_adapter));
+	if (!netdev) {
+		IXGB_ERR("Unable to allocate net_device struct\n");
+		goto err_alloc_etherdev;
+	}
+
+	SET_MODULE_OWNER(netdev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev->priv;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.back = adapter;
+
+	mmio_start = pci_resource_start(pdev, BAR_0);
+	mmio_len = pci_resource_len(pdev, BAR_0);
+
+	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+	if (!adapter->hw.hw_addr)
+		goto err_ioremap;
+
+	for (i = BAR_1; i <= BAR_5; i++) {
+		if (pci_resource_len(pdev, i) == 0)
+			continue;
+		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+			adapter->hw.io_base = pci_resource_start(pdev, i);
+			break;
+		}
+	}
+	IXGB_DBG("mmio_start<%lx> hw_addr<%p>\n", mmio_start,
+		 adapter->hw.hw_addr);
+
+	netdev->open = &ixgb_open;
+	netdev->stop = &ixgb_close;
+	netdev->hard_start_xmit = &ixgb_xmit_frame;
+	netdev->get_stats = &ixgb_get_stats;
+	netdev->set_multicast_list = &ixgb_set_multi;
+	netdev->set_mac_address = &ixgb_set_mac;
+	netdev->change_mtu = &ixgb_change_mtu;
+	netdev->do_ioctl = &ixgb_ioctl;
+	netdev->tx_timeout = &ixgb_tx_timeout;
+	netdev->watchdog_timeo = HZ;
+#ifdef CONFIG_IXGB_NAPI
+	netdev->poll = &ixgb_poll;
+	netdev->weight = 64;
+#endif
+	netdev->vlan_rx_register = ixgb_vlan_rx_register;
+	netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
+	netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;
+
+	netdev->irq = pdev->irq;
+	netdev->mem_start = mmio_start;
+	netdev->mem_end = mmio_start + mmio_len;
+	netdev->base_addr = adapter->hw.io_base;
+
+	adapter->bd_number = cards_found;
+	adapter->id_string = ixgb_strings[ent->driver_data];
+	adapter->link_speed = 0;
+	adapter->link_duplex = 0;
+
+	/* setup the private structure */
+	ixgb_sw_init(adapter);
+
+	netdev->features = NETIF_F_SG |
+	    NETIF_F_HW_CSUM |
+	    NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+#ifdef NETIF_F_TSO
+	netdev->features |= NETIF_F_TSO;
+#endif
+
+	if (pci_using_dac)
+		netdev->features |= NETIF_F_HIGHDMA;
+
+	/* make sure the EEPROM is good */
+
+	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+		IXGB_DBG("Invalid EEPROM checksum.\n");
+		goto err_eeprom;
+	}
+
+	ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		IXGB_DBG("Invalid MAC address in EEPROM.\n");
+		goto err_eeprom;
+	}
+
+	adapter->max_data_per_txd = IXGB_MAX_JUMBO_FRAME_SIZE;
+	adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);
+
+	init_timer(&adapter->watchdog_timer);
+	adapter->watchdog_timer.function = &ixgb_watchdog;
+	adapter->watchdog_timer.data = (unsigned long) adapter;
+
+	INIT_WORK(&adapter->tx_timeout_task,
+		  (void (*)(void *)) ixgb_tx_timeout_task, netdev);
+
+	register_netdev(netdev);
+	memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
+	adapter->ifname[IFNAMSIZ - 1] = 0;
+
+	/* we're going to reset, so assume we have no link for now */
+
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
+	ixgb_check_options(adapter);
+
+	/* reset the hardware with the new settings */
+	ixgb_reset(adapter);
+
+	cards_found++;
+	return 0;
+
+      err_eeprom:
+	iounmap(adapter->hw.hw_addr);
+      err_ioremap:
+	pci_release_regions(pdev);
+	kfree(netdev);
+      err_alloc_etherdev:
+	return -ENOMEM;
+}
+
+/**
+ * ixgb_remove - Device Removal Routine.
+ * @param pdev PCI device information struct
+ *
+ * ixgb_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+
+static void __devexit
+ixgb_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	IXGB_DBG("ixgb_remove\n");
+
+	unregister_netdev(netdev);
+
+#ifdef ETHTOOL_IDENTIFY
+	ixgb_identify_stop(adapter);
+#endif
+
+	iounmap((void *) adapter->hw.hw_addr);
+	pci_release_regions(pdev);
+
+	kfree(netdev);
+}
+
+/**
+ * ixgb_sw_init - Initialize general software structures (struct ixgb_adapter).
+ * @param adapter board private structure to initialize
+ *
+ * ixgb_sw_init initializes the adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ **/
+
+static void __devinit
+ixgb_sw_init(struct ixgb_adapter *adapter)
+{
+	struct ixgb_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+
+	IXGB_DBG("ixgb_sw_init\n");
+
+	/* PCI config space info */
+
+	/* FIXME: do not store, instead directly use struct pci_dev
+	 * where needed
+	 */
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+
+	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
+
+	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
+	if (hw->device_id == IXGB_DEVICE_ID_82597EX)
+		hw->mac_type = ixgb_82597;
+	else {
+		/* should never have loaded on this device */
+		printk(KERN_ERR "ixgb: unsupported device id\n");
+	}
+
+	/* enable flow control to be programmed */
+	hw->fc.send_xon = 1;
+
+	atomic_set(&adapter->irq_sem, 1);
+}
+
+/**
+ * ixgb_open - Called when a network interface is made active.
+ * @param netdev network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ **/
+
+static int
+ixgb_open(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	IXGB_DBG("ixgb_open\n");
+
+	/* allocate transmit descriptors */
+
+	if (ixgb_setup_tx_resources(adapter)) {
+		IXGB_DBG("ixgb_open: failed ixgb_setup_tx_resources.\n");
+		goto err_setup_tx;
+	}
+
+	/* allocate receive descriptors and buffers */
+
+	if (ixgb_setup_rx_resources(adapter)) {
+		IXGB_DBG("ixgb_open: failed ixgb_setup_rx_resources.\n");
+		goto err_setup_rx;
+	}
+	if (ixgb_up(adapter))
+		goto err_up;
+
+	return 0;
+
+      err_up:
+	ixgb_free_rx_resources(adapter);
+      err_setup_rx:
+	ixgb_free_tx_resources(adapter);
+      err_setup_tx:
+	ixgb_reset(adapter);
+	return -EBUSY;
+}
+
+/**
+ * ixgb_close - Disables a network interface.
+ * @param netdev network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ **/
+
+static int
+ixgb_close(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	IXGB_DBG("ixgb_close\n");
+
+	ixgb_down(adapter, TRUE);
+
+	ixgb_free_tx_resources(adapter);
+	ixgb_free_rx_resources(adapter);
+
+	return 0;
+}
+
+/**
+ * ixgb_setup_tx_resources - allocate Tx resources (Descriptors).
+ * @param adapter board private structure
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+static int
+ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+	int size;
+
+	IXGB_DBG("ixgb_setup_tx_resources\n");
+
+	size = sizeof (struct ixgb_buffer) * txdr->count;
+	txdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	if (!txdr->buffer_info) {
+		return -ENOMEM;
+	}
+	memset(txdr->buffer_info, 0, size);
+
+	/* round up to nearest 4K */
+	txdr->size = txdr->count * sizeof (struct ixgb_tx_desc);
+	IXGB_ROUNDUP(txdr->size, 4096);
+
+	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+	if (!txdr->desc) {
+		kfree(txdr->buffer_info);
+		return -ENOMEM;
+	}
+	memset(txdr->desc, 0, txdr->size);
+
+	IXGB_DBG("txdr->desc <%p>\n", txdr->desc);
+	IXGB_DBG("txdr->next_to_use = <%p>\n", &txdr->next_to_use);
+	IXGB_DBG("txdr->next_to_clean = <%p>\n", &txdr->next_to_clean);
+
+	txdr->next_to_use = 0;
+	txdr->next_to_clean = 0;
+
+	return 0;
+}
+
+/**
+ * ixgb_configure_tx - Configure 82597 Transmit Unit after Reset.
+ * @adapter board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_tx(struct ixgb_adapter *adapter)
+{
+	u32 tctl;
+	u32 tdlen = adapter->tx_ring.count * sizeof (struct ixgb_tx_desc);
+	uint64_t tdba = adapter->tx_ring.dma;
+	struct ixgb_hw *hw = &adapter->hw;
+
+	IXGB_DBG("ixgb_configure_tx\n");
+
+	/* Setup the Base and Length of the Tx Descriptor Ring 
+	 * tx_ring.dma can be either a 32 or 64 bit value 
+	 */
+
+	IXGB_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+	IXGB_WRITE_REG(hw, TDBAH, (tdba >> 32));
+
+	IXGB_WRITE_REG(hw, TDLEN, tdlen);
+
+	/* Setup the HW Tx Head and Tail descriptor pointers */
+
+	IXGB_WRITE_REG(hw, TDH, 0);
+	IXGB_WRITE_REG(hw, TDT, 0);
+
+	/* don't set up txdctl, it induces performance problems if
+	 * configured incorrectly
+	 txdctl  = TXDCTL_PTHRESH_DEFAULT; // prefetch txds below this threshold
+	 txdctl |= (TXDCTL_HTHRESH_DEFAULT // only prefetch if there are this many ready
+	 << IXGB_TXDCTL_HTHRESH_SHIFT);
+	 IXGB_WRITE_REG (hw, TXDCTL, txdctl);
+	 */
+
+	/* Set the Tx Interrupt Delay register */
+
+	IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+
+	/* Program the Transmit Control Register */
+
+	tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
+	IXGB_WRITE_REG(hw, TCTL, tctl);
+
+	/* Setup Transmit Descriptor Settings for this adapter */
+	adapter->tx_cmd_type =
+	    IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS
+	    | (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
+}
+
+/**
+ * ixgb_setup_rx_resources - allocate Rx resources (Descriptors).
+ * @param adapter board private structure
+ * 
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+	int size;
+
+	IXGB_DBG("ixgb_setup_rx_resources.\n");
+
+	size = sizeof (struct ixgb_buffer) * rxdr->count;
+	rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	if (!rxdr->buffer_info) {
+		return -ENOMEM;
+	}
+	memset(rxdr->buffer_info, 0, size);
+
+	/* Round up to nearest 4K */
+	rxdr->size = rxdr->count * sizeof (struct ixgb_rx_desc);
+	IXGB_ROUNDUP(rxdr->size, 4096);
+
+	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+
+	if (!rxdr->desc) {
+		IXGB_DBG("pci_alloc_consistent failed.\n");
+		kfree(rxdr->buffer_info);
+		return -ENOMEM;
+	}
+	memset(rxdr->desc, 0, rxdr->size);
+
+	IXGB_DBG("rxdr->desc <%p>\n", rxdr->desc);
+	IXGB_DBG("rxdr->next_to_use = <%p>\n", &rxdr->next_to_use);
+	IXGB_DBG("rxdr->next_to_clean = <%p>\n", &rxdr->next_to_clean);
+
+	rxdr->next_to_use = 0;
+	rxdr->next_to_clean = 0;
+
+	return 0;
+}
+
+/**
+ * ixgb_setup_rctl - configure the receive control register.
+ * @param adapter Board private structure
+ **/
+
+static void
+ixgb_setup_rctl(struct ixgb_adapter *adapter)
+{
+	u32 rctl;
+
+	rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+	IXGB_DBG("ixgb_setup_rctl\n");
+
+	rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
+
+	rctl |=
+	    IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
+	    IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
+	    (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
+
+	rctl |= IXGB_RCTL_SECRC;
+
+	switch (adapter->rx_buffer_len) {
+	case IXGB_RXBUFFER_2048:
+	default:
+		rctl |= IXGB_RCTL_BSIZE_2048;
+		break;
+	case IXGB_RXBUFFER_4096:
+		rctl |= IXGB_RCTL_BSIZE_4096;
+		break;
+	case IXGB_RXBUFFER_8192:
+		rctl |= IXGB_RCTL_BSIZE_8192;
+		break;
+	case IXGB_RXBUFFER_16384:
+		rctl |= IXGB_RCTL_BSIZE_16384;
+		break;
+	}
+	IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_configure_rx - Configure 82597 Receive Unit after Reset.
+ * @param adapter board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_rx(struct ixgb_adapter *adapter)
+{
+	uint64_t rdba = adapter->rx_ring.dma;
+	u32 rdlen = adapter->rx_ring.count * sizeof (struct ixgb_rx_desc);
+	struct ixgb_hw *hw = &adapter->hw;
+	u32 rctl;
+	u32 rxcsum;
+
+	IXGB_DBG("ixgb_configure_rx\n");
+
+	/* make sure receives are disabled while setting up the descriptors */
+	rctl = IXGB_READ_REG(hw, RCTL);
+	IXGB_WRITE_REG(hw, RCTL, rctl & ~IXGB_RCTL_RXEN);
+
+	/* set the Receive Delay Timer Register */
+	IXGB_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+
+	/* Setup the Base and Length of the Rx Descriptor Ring */
+	IXGB_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+	IXGB_WRITE_REG(hw, RDBAH, (rdba >> 32));
+
+	IXGB_WRITE_REG(hw, RDLEN, rdlen);
+
+	/* Setup the HW Rx Head and Tail Descriptor Pointers */
+	IXGB_WRITE_REG(hw, RDH, 0);
+	IXGB_WRITE_REG(hw, RDT, 0);
+
+	{
+		u32 rxdctl;
+		/* burst 16 or burst when RXT0 */
+		rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
+		    | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
+		    | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+		IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
+	}
+
+	if (adapter->raidc) {
+		u32 raidc;
+		u8 poll_threshold;
+
+		/* Poll every rx_int_delay period, if RBD exists
+		 * Receive Backlog Detection is set to <threshold> 
+		 * Rx Descriptors
+		 * max is 0x3F == set to poll when 504 RxDesc left 
+		 * min is 0 */
+
+		/* polling times are 1 == 0.8192us
+		   2 == 1.6384us
+		   3 == 3.2768us etc
+		   ...
+		   511 == 418 us
+		 */
+#define IXGB_RAIDC_POLL_DEFAULT 122	/* set to poll every ~100 us under load 
+					   also known as 10000 interrupts / sec */
+
+		/* divide this by 2^3 (8) to get a register size count */
+		poll_threshold = ((adapter->rx_ring.count - 1) >> 3);
+		/* poll at half of that size */
+		poll_threshold >>= 1;
+		/* make sure its not bigger than our max */
+		poll_threshold &= 0x3F;
+
+		raidc = IXGB_RAIDC_EN |	/* turn on raidc style moderation */
+		    IXGB_RAIDC_RXT_GATE |	/* don't interrupt with rxt0 while
+						   in RBD mode (polling) */
+		    (IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
+		    /* this sets the regular "min interrupt delay" */
+		    (adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
+		    poll_threshold;
+
+		IXGB_WRITE_REG(hw, RAIDC, raidc);
+	}
+
+	/* Enable Receive Checksum Offload for TCP and UDP */
+	if (adapter->rx_csum == TRUE) {
+		rxcsum = IXGB_READ_REG(hw, RXCSUM);
+		rxcsum |= IXGB_RXCSUM_TUOFL;
+		IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
+	}
+
+	/* Enable Receives */
+
+	IXGB_WRITE_REG(hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_free_tx_resources - Free Tx Resources.
+ * @param adapter board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+static void
+ixgb_free_tx_resources(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	IXGB_DBG("ixgb_free_tx_resources\n");
+
+	ixgb_clean_tx_ring(adapter);
+
+	kfree(adapter->tx_ring.buffer_info);
+	adapter->tx_ring.buffer_info = NULL;
+
+	pci_free_consistent(pdev, adapter->tx_ring.size, adapter->tx_ring.desc,
+			    adapter->tx_ring.dma);
+
+	adapter->tx_ring.desc = NULL;
+}
+
+/**
+ * ixgb_clean_tx_ring - Free Tx Buffers.
+ * @param adapter board private structure
+ **/
+
+static void
+ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	int i;
+
+	IXGB_DBG("ixgb_clean_tx_ring\n");
+
+	/* Free all the Tx ring sk_buffs */
+
+	for (i = 0; i < adapter->tx_ring.count; i++) {
+		if (adapter->tx_ring.buffer_info[i].skb) {
+
+			pci_unmap_page(pdev,
+				       adapter->tx_ring.buffer_info[i].dma,
+				       adapter->tx_ring.buffer_info[i].length,
+				       PCI_DMA_TODEVICE);
+
+			dev_kfree_skb(adapter->tx_ring.buffer_info[i].skb);
+
+			adapter->tx_ring.buffer_info[i].skb = NULL;
+		}
+	}
+
+	size = sizeof (struct ixgb_buffer) * adapter->tx_ring.count;
+	memset(adapter->tx_ring.buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+
+	memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size);
+
+	adapter->tx_ring.next_to_use = 0;
+	adapter->tx_ring.next_to_clean = 0;
+
+	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
+	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
+}
+
+/**
+ * ixgb_free_rx_resources - Free Rx Resources.
+ * @param adapter board private structure
+ *
+ * Free all receive software resources
+ **/
+
+static void
+ixgb_free_rx_resources(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	IXGB_DBG("ixgb_free_rx_resources\n");
+
+	ixgb_clean_rx_ring(adapter);
+
+	kfree(adapter->rx_ring.buffer_info);
+	adapter->rx_ring.buffer_info = NULL;
+
+	pci_free_consistent(pdev, adapter->rx_ring.size,
+			    adapter->rx_ring.desc, adapter->rx_ring.dma);
+
+	adapter->rx_ring.desc = NULL;
+}
+
+/**
+ * ixgb_clean_rx_ring - Free Rx Buffers.
+ * @param adapter board private structure
+ **/
+
+static void
+ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	int i;
+
+	IXGB_DBG("ixgb_free_rx_ring\n");
+
+	/* Free all the Rx ring sk_buffs */
+
+	for (i = 0; i < adapter->rx_ring.count; i++) {
+		if (adapter->rx_ring.buffer_info[i].skb) {
+
+			pci_unmap_single(pdev,
+					 adapter->rx_ring.buffer_info[i].dma,
+					 adapter->rx_ring.buffer_info[i].length,
+					 PCI_DMA_FROMDEVICE);
+
+			dev_kfree_skb(adapter->rx_ring.buffer_info[i].skb);
+
+			adapter->rx_ring.buffer_info[i].skb = NULL;
+		}
+	}
+
+	size = sizeof (struct ixgb_buffer) * adapter->rx_ring.count;
+	memset(adapter->rx_ring.buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+
+	memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size);
+
+	adapter->rx_ring.next_to_clean = 0;
+	adapter->rx_ring.next_to_use = 0;
+
+	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
+	IXGB_WRITE_REG(&adapter->hw, RDT, 0);
+}
+
+/**
+ * ixgb_set_multi - Multicast and Promiscuous mode set.
+ * @param netdev network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * resposible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ **/
+
+void
+ixgb_set_multi(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	u32 rctl;
+	int i;
+	struct dev_mc_list *mc_ptr;
+
+	IXGB_DBG("ixgb_set_multi <%x>\n", netdev->flags);
+
+	/* Check for Promiscuous and All Multicast modes */
+
+	rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+	if (netdev->flags & IFF_PROMISC) {
+		rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		rctl |= IXGB_RCTL_MPE;
+		rctl &= ~IXGB_RCTL_UPE;
+	} else {
+		rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+	}
+
+	if (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
+		rctl |= IXGB_RCTL_MPE;
+		IXGB_WRITE_REG(hw, RCTL, rctl);
+	} else {
+		u8 mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];
+
+		IXGB_WRITE_REG(hw, RCTL, rctl);
+
+		for (i = 0, mc_ptr = netdev->mc_list; mc_ptr;
+		     i++, mc_ptr = mc_ptr->next)
+			memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
+			       mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+
+		ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);
+	}
+}
+
+/**
+ * ixgb_watchdog - Timer Call-back.
+ * @param data pointer to adapter cast into an unsigned long
+ **/
+
+void
+ixgb_watchdog(unsigned long data)
+{
+	struct ixgb_adapter *adapter = (struct ixgb_adapter *) data;
+	struct net_device *netdev = adapter->netdev;
+
+	ixgb_check_for_link(&adapter->hw);
+
+	if (ixgb_check_for_bad_link(&adapter->hw)) {
+		/* force the reset path */
+		netif_stop_queue(netdev);
+	}
+
+	if (adapter->hw.link_up) {
+		if (!netif_carrier_ok(netdev)) {
+			printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
+			       netdev->name, 10000, "Full Duplex");
+			adapter->link_speed = 10000;
+			adapter->link_duplex = FULL_DUPLEX;
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	} else {
+		if (netif_carrier_ok(netdev)) {
+			printk(KERN_INFO "ixgb: %s NIC Link is Down\n",
+			       netdev->name);
+			adapter->link_speed = 0;
+			adapter->link_duplex = 0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+
+			ixgb_down(adapter, FALSE);
+			ixgb_up(adapter);
+		}
+	}
+
+	ixgb_update_stats(adapter);
+
+	/* Early detection of hung controller */
+	{
+		struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+		int i = txdr->next_to_clean;
+
+		if (txdr->buffer_info[i].dma &&
+		    time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
+		    !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
+		{
+			IXGB_DBG
+			    ("ixgb: %s Hung controller? Watchdog stopping queue\n",
+			     netdev->name);
+			netif_stop_queue(netdev);
+		}
+	}
+
+	/* generate an interrupt to force clean up of any stragglers */
+	IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+#define IXGB_TX_FLAGS_CSUM	0x00000001
+#define IXGB_TX_FLAGS_VLAN	0x00000002
+#define IXGB_TX_FLAGS_TSO	0x00000004
+
+/** Transmit Segmentation offload setup.
+ * ixgb_tso - (Large Send) setup where the initial descriptor is prepared
+ * @param adapter adapter specific information
+ * @param skb the skb we are trying to set up for segmentation
+ **/
+
+static inline boolean_t
+ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+{
+#ifdef NETIF_F_TSO
+	struct ixgb_context_desc *context_desc;
+	int i;
+	u8 ipcss, ipcso, tucss, tucso, hdr_len;
+	u16 ipcse, tucse, mss;
+
+	if (likely(skb_shinfo(skb)->tso_size)) {
+		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		mss = skb_shinfo(skb)->tso_size;
+		skb->nh.iph->tot_len = 0;
+		skb->nh.iph->check = 0;
+		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
+						      skb->nh.iph->daddr,
+						      0, IPPROTO_TCP, 0);
+		ipcss = skb->nh.raw - skb->data;
+		ipcso = (void *) &(skb->nh.iph->check) - (void *) skb->data;
+		ipcse = skb->h.raw - skb->data - 1;
+		tucss = skb->h.raw - skb->data;
+		tucso = (void *) &(skb->h.th->check) - (void *) skb->data;
+		tucse = 0;
+
+		i = adapter->tx_ring.next_to_use;
+		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+
+		context_desc->ipcss = ipcss;
+		context_desc->ipcso = ipcso;
+		context_desc->ipcse = cpu_to_le16(ipcse);
+		context_desc->tucss = tucss;
+		context_desc->tucso = tucso;
+		context_desc->tucse = cpu_to_le16(tucse);
+		context_desc->mss = cpu_to_le16(mss);
+		context_desc->hdr_len = hdr_len;
+		context_desc->status = 0;
+		context_desc->cmd_type_len = cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
+							 |
+							 IXGB_CONTEXT_DESC_CMD_TSE
+							 |
+							 IXGB_CONTEXT_DESC_CMD_IP
+							 |
+							 IXGB_CONTEXT_DESC_CMD_TCP
+							 |
+							 IXGB_CONTEXT_DESC_CMD_RS
+							 |
+							 IXGB_CONTEXT_DESC_CMD_IDE
+							 | (skb->len -
+							    (hdr_len)));
+
+		i = (i + 1) % adapter->tx_ring.count;
+		adapter->tx_ring.next_to_use = i;
+
+		return TRUE;
+	}
+#endif
+	return FALSE;
+}
+
+/**
+ * ixgb_tx_csum - prepare context descriptor for checksum offload.
+ *
+ * ixgb_tx_csum is called to prepare for checksumming a packet in hw.
+ * @param adapter board private structure
+ * @param skb structure containing data to send
+ **/
+static inline boolean_t
+ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+{
+	struct ixgb_context_desc *context_desc;
+	int i;
+	u8 css, cso;
+
+	if (likely(skb->ip_summed == CHECKSUM_HW)) {
+		css = skb->h.raw - skb->data;
+		cso = (skb->h.raw + skb->csum) - skb->data;
+		i = adapter->tx_ring.next_to_use;
+		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+
+		context_desc->tucss = css;
+		context_desc->tucso = cso;
+		context_desc->tucse = 0;
+		/* zero out any previously existing data in one instruction */
+		*(u32 *) & (context_desc->ipcss) = 0;
+		context_desc->status = 0;
+		context_desc->hdr_len = 0;
+		context_desc->mss = 0;
+		context_desc->cmd_type_len =
+		    cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
+				| IXGB_TX_DESC_CMD_RS | IXGB_TX_DESC_CMD_IDE);
+
+		i = (i + 1) % adapter->tx_ring.count;
+		adapter->tx_ring.next_to_use = i;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * ixgb_tx_map - private function for mapping send data to hardware addresses.
+ *
+ * @param adapter board private structure
+ * @param skb structure containing data to send
+ **/
+
+static inline int
+ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	int len, offset, count, size, i;
+
+	int f;
+	len = skb->len - skb->data_len;
+
+	i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count;
+	count = 0;
+
+	offset = 0;
+
+	while (len) {
+		i = (i + 1) % tx_ring->count;
+		size = min(len, adapter->max_data_per_txd);
+		tx_ring->buffer_info[i].length = size;
+		tx_ring->buffer_info[i].dma =
+		    pci_map_single(adapter->pdev, skb->data + offset, size,
+				   PCI_DMA_TODEVICE);
+
+		tx_ring->buffer_info[i].time_stamp = jiffies;
+
+		len -= size;
+		offset += size;
+		count++;
+	}
+
+	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
+		struct skb_frag_struct *frag;
+
+		frag = &skb_shinfo(skb)->frags[f];
+		len = frag->size;
+		offset = 0;
+
+		while (len) {
+			i = (i + 1) % tx_ring->count;
+			size = min(len, adapter->max_data_per_txd);
+			tx_ring->buffer_info[i].length = size;
+			tx_ring->buffer_info[i].dma =
+			    pci_map_page(adapter->pdev, frag->page,
+					 frag->page_offset + offset, size,
+					 PCI_DMA_TODEVICE);
+
+			tx_ring->buffer_info[i].time_stamp = jiffies;
+			len -= size;
+			offset += size;
+			count++;
+		}
+	}
+	tx_ring->buffer_info[i].skb = skb;
+
+	return count;
+}
+
+/**
+ * ixgb_tx_queue - private function to start transmit on hardware.
+ *
+ * @param adapter board private structure
+ * @param count number of tx_descriptors to initialize (consume)
+ * @param vlan_id the vlan tag to insert (if necessary)
+ * @param tx_flags special handling for this transmit, if any
+ **/
+
+static inline void
+ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
+	      int tx_flags)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct ixgb_tx_desc *tx_desc = NULL;
+	u32 cmd_type_len = adapter->tx_cmd_type;
+	u8 status = 0;
+	u8 popts = 0;
+	int i;
+
+	if (tx_flags & IXGB_TX_FLAGS_TSO) {
+		cmd_type_len |= IXGB_TX_DESC_CMD_TSE;
+		popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);
+	}
+
+	if (tx_flags & IXGB_TX_FLAGS_CSUM)
+		popts |= IXGB_TX_DESC_POPTS_TXSM;
+
+	if (tx_flags & IXGB_TX_FLAGS_VLAN) {
+		cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
+	}
+
+	i = tx_ring->next_to_use;
+
+	while (count--) {
+		tx_desc = IXGB_TX_DESC(*tx_ring, i);
+		tx_desc->buff_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
+		tx_desc->cmd_type_len =
+		    cpu_to_le32(cmd_type_len | tx_ring->buffer_info[i].length);
+		tx_desc->status = status;
+		tx_desc->popts = popts;
+		tx_desc->vlan = cpu_to_le16(vlan_id);
+
+		i = (i + 1) % tx_ring->count;
+	}
+
+	tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP);
+
+	/* Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64). */
+	wmb();
+
+	tx_ring->next_to_use = i;
+	IXGB_WRITE_REG(&adapter->hw, TDT, i);
+}
+
+#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0))
+
+/**
+ * ixgb_xmit_frame - hard_start_xmit linked function, transmit entry point.
+ *
+ * ixgb_xmit_frame is called to send an skb on the wire.
+ * @param skb contains data to send
+ * @param netdev network interface device structure 
+ **/
+
+static int
+ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	int vlan_id = 0;
+	int tx_flags = 0, count;
+	int f;
+
+	count =
+	    TXD_USE_COUNT(skb->len - skb->data_len, adapter->max_data_per_txd);
+
+	if (count == 0) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+				       adapter->max_data_per_txd);
+#ifdef NETIF_F_TSO
+	if ((skb_shinfo(skb)->tso_size) || (skb->ip_summed == CHECKSUM_HW))
+		count++;
+#else
+	if (skb->ip_summed == CHECKSUM_HW)
+		count++;
+#endif
+
+	if (unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < count)) {
+		netif_stop_queue(netdev);
+		return 1;
+	}
+
+	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+		tx_flags |= IXGB_TX_FLAGS_VLAN;
+		vlan_id = vlan_tx_tag_get(skb);
+	}
+
+	if (ixgb_tso(adapter, skb))
+		tx_flags |= IXGB_TX_FLAGS_TSO;
+	else if (ixgb_tx_csum(adapter, skb))
+		tx_flags |= IXGB_TX_FLAGS_CSUM;
+
+	count = ixgb_tx_map(adapter, skb);
+	ixgb_tx_queue(adapter, count, vlan_id, tx_flags);
+	netdev->trans_start = jiffies;
+
+	return 0;
+}
+
+/**
+ * ixgb_tx_timeout - Respond to a Tx Hang by resetting the adapter.
+ * @param netdev network interface device structure
+ **/
+
+static void
+ixgb_tx_timeout(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	IXGB_DBG("ixgb_tx_timeout\n");
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
+}
+
+/**
+ * ixgb_tx_timeout_task - worker function to reset hardware and dump queues.
+ * This function is pointed to by adapter->tx_timeout_task
+ *
+ * @param netdev network interface device structure 
+ **/
+
+static void
+ixgb_tx_timeout_task(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	IXGB_DBG("ixgb_tx_timeout_task\n");
+
+	netif_device_detach(netdev);
+	ixgb_down(adapter, TRUE);
+	ixgb_up(adapter);
+	netif_device_attach(netdev);
+}
+
+/**
+ * ixgb_get_stats - Get System Network Statistics.
+ * @param netdev network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ **/
+
+static struct net_device_stats *
+ixgb_get_stats(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	return &adapter->net_stats;
+}
+
+/**
+ * ixgb_change_mtu - Change the Maximum Transfer Unit.
+ * @param netdev network interface device structure
+ * @param new_mtu new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	u32 old_mtu = adapter->rx_buffer_len;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
+	IXGB_DBG("ixgb_change_mtu\n");
+
+	if ((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+	    || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
+		IXGB_ERR("Invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	if ((max_frame <=
+	     IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+	    || (max_frame <= IXGB_RXBUFFER_2048)) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
+
+	} else if (max_frame <= IXGB_RXBUFFER_4096) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
+
+	} else if (max_frame <= IXGB_RXBUFFER_8192) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
+
+	} else {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
+	}
+
+	if (old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+
+		ixgb_down(adapter, TRUE);
+		ixgb_up(adapter);
+	}
+
+	if (adapter->hw.max_frame_size != max_frame) {
+		struct ixgb_hw *hw = &adapter->hw;
+
+		adapter->hw.max_frame_size = max_frame;
+
+		IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
+
+		if (hw->max_frame_size >
+		    IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+			u32 ctrl0 = IXGB_READ_REG(hw, CTRL0);
+
+			if (!(ctrl0 & IXGB_CTRL0_JFE)) {
+				ctrl0 |= IXGB_CTRL0_JFE;
+				IXGB_WRITE_REG(hw, CTRL0, ctrl0);
+			}
+		}
+
+		printk(KERN_ERR "%s: ixgb_change_mtu MFS is set to <%x>\n",
+		       adapter->netdev->name,
+		       (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT));
+	}
+
+	netdev->mtu = new_mtu;
+
+	return 0;
+}
+
+/**
+ * ixgb_set_mac - Change the Ethernet Address of the NIC.
+ * @param netdev network interface device structure
+ * @param p pointer to an address structure
+ * 
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_set_mac(struct net_device *netdev, void *p)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct sockaddr *addr = (struct sockaddr *) p;
+
+	IXGB_DBG("ixgb_set_mac\n");
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+	ixgb_rar_set(&adapter->hw, addr->sa_data, 0);
+
+	return 0;
+}
+
+/**
+ * ixgb_update_stats - Update the board statistics counters.
+ * @param adapter board private structure
+ **/
+
+static void
+ixgb_update_stats(struct ixgb_adapter *adapter)
+{
+	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
+	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
+	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
+	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
+	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
+	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
+	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
+	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
+	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
+	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
+	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
+	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
+	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
+	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
+	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
+	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
+	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
+	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
+	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
+	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
+	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
+	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
+	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
+	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
+	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
+	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
+	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
+	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
+	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
+	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
+	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
+	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
+	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
+	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
+	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
+	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
+	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
+	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
+	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
+	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
+	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
+	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
+	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
+	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
+	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
+	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
+	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
+	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
+	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
+	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
+	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
+	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
+	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
+	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
+	adapter->stats.mcftc += IXGB_READ_REG(&adapter->hw, MCFTC);
+	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
+	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
+	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
+	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
+	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
+
+	/* Fill out the OS statistics structure */
+
+	adapter->net_stats.rx_packets = adapter->stats.gprcl;
+	adapter->net_stats.tx_packets = adapter->stats.gptcl;
+	adapter->net_stats.rx_bytes = adapter->stats.gorcl;
+	adapter->net_stats.tx_bytes = adapter->stats.gotcl;
+	adapter->net_stats.multicast = adapter->stats.mprcl;
+	adapter->net_stats.collisions = 0;
+
+	/* ignore RLEC as it reports errors for padded (<64bytes) frames
+	 * with a length in the type/len field */
+	adapter->net_stats.rx_errors =
+	    /* adapter->stats.rnbc + */ adapter->stats.crcerrs +
+	    adapter->stats.ruc +
+	    adapter->stats.roc /*+ adapter->stats.rlec */  +
+	    adapter->stats.icbc +
+	    adapter->stats.ecbc + adapter->stats.mpc;
+
+	adapter->net_stats.rx_dropped = adapter->stats.mpc;
+
+	/* see above
+	 * adapter->net_stats.rx_length_errors = adapter->stats.rlec;
+	 */
+
+	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
+	adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
+	adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
+	adapter->net_stats.rx_over_errors = adapter->stats.mpc;
+
+	adapter->net_stats.tx_errors = 0;
+	adapter->net_stats.rx_frame_errors = 0;
+	adapter->net_stats.tx_aborted_errors = 0;
+	adapter->net_stats.tx_carrier_errors = 0;
+	adapter->net_stats.tx_fifo_errors = 0;
+	adapter->net_stats.tx_heartbeat_errors = 0;
+	adapter->net_stats.tx_window_errors = 0;
+}
+
+/**
+ * ixgb_irq_disable - Mask off interrupt generation on the NIC
+ * @param adapter board private structure
+ **/
+
+static inline void
+ixgb_irq_disable(struct ixgb_adapter *adapter)
+{
+	IXGB_DBG("ixgb_irq_disable\n");
+
+	atomic_inc(&adapter->irq_sem);
+	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+	synchronize_irq(adapter->netdev->irq);
+}
+
+/**
+ * ixgb_irq_enable - Enable default interrupt generation settings.
+ * @param adapter board private structure
+ **/
+
+static inline void
+ixgb_irq_enable(struct ixgb_adapter *adapter)
+{
+	IXGB_DBG("ixgb_irq_enable\n");
+
+	if (atomic_dec_and_test(&adapter->irq_sem)) {
+		IXGB_WRITE_REG(&adapter->hw, IMS,
+			       IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+			       IXGB_INT_RXO | IXGB_INT_LSC);
+	}
+}
+
+#define IXGB_MAX_INTR 10
+/**
+ * ixgb_intr - Interrupt Handler.
+ * @param irq interrupt number
+ * @param data pointer to a network interface device structure
+ * @param regs CPU registers structure
+ **/
+
+static irqreturn_t
+ixgb_intr(int irq, void *data, struct pt_regs *regs)
+{
+	struct net_device *netdev = (struct net_device *) data;
+	struct ixgb_adapter *adapter = netdev->priv;
+#ifdef CONFIG_IXGB_NAPI
+	if (netif_rx_schedule_prep(netdev)) {
+		ixgb_irq_disable(adapter);
+		__netif_rx_schedule(netdev);
+	}
+
+	return IRQ_HANDLED; /* FIXME: check for shared interrupts */
+#else
+	struct ixgb_hw *hw = &adapter->hw;
+	u32 icr;
+	uint i = IXGB_MAX_INTR;
+	boolean_t rxdmt0 = FALSE;
+	int handled = 0;
+
+	while (i && (icr = IXGB_READ_REG(hw, ICR))) {
+		handled = 1;
+
+		if (icr & IXGB_INT_RXDMT0)
+			rxdmt0 = TRUE;
+
+		if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+			mod_timer(&adapter->watchdog_timer, jiffies);
+		}
+
+		/* adapter->generate_int = 0; */
+		ixgb_clean_rx_irq(adapter);
+		ixgb_clean_tx_irq(adapter);
+
+		i--;
+	}
+
+	/* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
+	 * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
+	 */
+	if (rxdmt0 && adapter->raidc) {
+		/* ready the timer by writing the clear reg */
+		IXGB_WRITE_REG(hw, IMC, IXGB_INT_RXDMT0);
+		/* now restart it, h/w will decide if its necessary */
+		IXGB_WRITE_REG(hw, IMS, IXGB_INT_RXDMT0);
+	}
+
+	return IRQ_RETVAL(handled);
+#endif				// NAPI else
+}
+
+#ifdef CONFIG_IXGB_NAPI
+static int
+ixgb_process_intr(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	u32 icr;
+	int i = IXGB_MAX_INTR;
+	int hasReceived = 0;
+
+	while (i && (icr = IXGB_READ_REG(&adapter->hw, ICR))) {
+		if (icr & IXGB_INT_RXT0)
+			hasReceived = 1;
+
+		if (!(icr & ~(IXGB_INT_RXT0)))
+			break;
+
+		if (icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
+			mod_timer(&adapter->watchdog_timer, jiffies);
+		}
+
+		ixgb_clean_tx_irq(adapter);
+		i--;
+	}
+
+	return hasReceived;
+}
+
+#endif
+/**
+ * ixgb_clean_tx_irq - Reclaim resources after transmit completes.
+ * @param adapter board private structure
+ **/
+
+static void
+ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	int i = adapter->tx_ring.next_to_clean;
+	struct ixgb_tx_desc *tx_desc = IXGB_TX_DESC(*tx_ring, i);
+	while ((tx_desc->status & IXGB_TX_DESC_STATUS_DD)) {
+		if (tx_desc->popts
+		    & (IXGB_TX_DESC_POPTS_TXSM | IXGB_TX_DESC_POPTS_IXSM))
+			adapter->hw_csum_tx_good++;
+
+		if (tx_ring->buffer_info[i].dma) {
+			pci_unmap_page(pdev, tx_ring->buffer_info[i].dma,
+				       tx_ring->buffer_info[i].length,
+				       PCI_DMA_TODEVICE);
+			tx_ring->buffer_info[i].dma = 0;
+		}
+
+		if (tx_ring->buffer_info[i].skb) {
+			dev_kfree_skb_any(tx_ring->buffer_info[i].skb);
+			tx_ring->buffer_info[i].skb = NULL;
+		}
+
+		*(u32 *) & (tx_desc->status) = 0;
+
+		i = (i + 1) % tx_ring->count;
+		tx_desc = IXGB_TX_DESC(*tx_ring, i);
+	}
+
+	tx_ring->next_to_clean = i;
+
+	if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+	    (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
+
+		netif_wake_queue(netdev);
+	}
+}
+
+#ifdef CONFIG_IXGB_NAPI
+static int
+ixgb_poll(struct net_device *netdev, int *budget)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_rx_desc *rx_desc;
+	struct sk_buff *skb;
+	u32 length;
+	int i;
+	int received = 0;
+	int rx_work_limit = *budget;
+
+	if (rx_work_limit > netdev->quota)
+		rx_work_limit = netdev->quota;
+
+	ixgb_process_intr(netdev);
+
+	i = rx_ring->next_to_clean;
+	rx_desc = IXGB_RX_DESC(*rx_ring, i);
+
+	while ((rx_desc->status & IXGB_RX_DESC_STATUS_DD)) {
+		if (--rx_work_limit < 0)
+			goto not_done;
+
+		pci_unmap_single(pdev,
+				 rx_ring->buffer_info[i].dma,
+				 rx_ring->buffer_info[i].length,
+				 PCI_DMA_FROMDEVICE);
+
+		skb = rx_ring->buffer_info[i].skb;
+		length = le16_to_cpu(rx_desc->length);
+
+		if (!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP)) {
+
+			/* All receives must fit into a single buffer */
+
+			IXGB_DBG("Receive packet consumed multiple buffers\n");
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			rx_ring->buffer_info[i].skb = NULL;
+
+			i = (i + 1) % rx_ring->count;
+
+			rx_desc = IXGB_RX_DESC(*rx_ring, i);
+			continue;
+		}
+
+		if (rx_desc->
+		    errors & (IXGB_RX_DESC_ERRORS_CE | IXGB_RX_DESC_ERRORS_SE |
+			      IXGB_RX_DESC_ERRORS_P | IXGB_RX_DESC_ERRORS_RXE))
+		{
+
+			IXGB_DBG("Receive Errors Reported by Hardware-%x.\n",
+				 rx_desc->errors);
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			rx_ring->buffer_info[i].skb = NULL;
+			i = (i + 1) % rx_ring->count;
+			rx_desc = IXGB_RX_DESC(*rx_ring, i);
+			continue;
+		}
+
+		/* Good Receive */
+		skb_put(skb, length);
+
+		/* Receive Checksum Offload */
+		ixgb_rx_checksum(adapter, rx_desc, skb);
+
+		skb->protocol = eth_type_trans(skb, netdev);
+		if (adapter->vlgrp
+		    && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+			vlan_hwaccel_rx(skb, adapter->vlgrp,
+					(rx_desc->
+					 special &
+					 IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+		} else {
+			netif_receive_skb(skb);
+		}
+		netdev->last_rx = jiffies;
+
+		rx_desc->status = 0;
+		rx_ring->buffer_info[i].skb = NULL;
+
+		i = (i + 1) % rx_ring->count;
+
+		rx_desc = IXGB_RX_DESC(*rx_ring, i);
+		received++;
+	}
+
+	if (!received)
+		received = 1;
+
+	ixgb_alloc_rx_buffers(adapter);
+
+	rx_ring->next_to_clean = i;
+	netdev->quota -= received;
+	*budget -= received;
+
+	netif_rx_complete(netdev);
+
+	/* NOTE: RAIDC will be automatically restarted by this enable */
+	ixgb_irq_enable(adapter);
+	return 0;
+
+      not_done:
+
+	ixgb_alloc_rx_buffers(adapter);
+
+	rx_ring->next_to_clean = i;
+	netdev->quota -= received;
+	*budget -= received;
+
+	return 1;
+}
+#else
+/**
+ * ixgb_clean_rx_irq - Send received data up the network stack.
+ * @param adapter board private structure
+ **/
+
+static void
+ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_rx_desc *rx_desc;
+	struct sk_buff *skb;
+	u32 length;
+	int i;
+
+	i = rx_ring->next_to_clean;
+	rx_desc = IXGB_RX_DESC(*rx_ring, i);
+
+	while ((rx_desc->status & IXGB_RX_DESC_STATUS_DD)) {
+		pci_unmap_single(pdev, rx_ring->buffer_info[i].dma,
+				 rx_ring->buffer_info[i].length,
+				 PCI_DMA_FROMDEVICE);
+
+		skb = rx_ring->buffer_info[i].skb;
+		length = le16_to_cpu(rx_desc->length);
+
+		if (unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+
+			/* All receives must fit into a single buffer */
+
+			IXGB_DBG("Receive packet consumed multiple buffers "
+				 "length<%x>\n", length);
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			rx_ring->buffer_info[i].skb = NULL;
+			i = (i + 1) % rx_ring->count;
+			rx_desc = IXGB_RX_DESC(*rx_ring, i);
+			continue;
+		}
+
+		if (unlikely(rx_desc->errors
+			     & (IXGB_RX_DESC_ERRORS_CE | IXGB_RX_DESC_ERRORS_SE
+				| IXGB_RX_DESC_ERRORS_P |
+				IXGB_RX_DESC_ERRORS_RXE))) {
+
+			IXGB_DBG("Receive Errors Reported by Hardware-%x.\n",
+				 rx_desc->errors);
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			rx_ring->buffer_info[i].skb = NULL;
+			i = (i + 1) % rx_ring->count;
+			rx_desc = IXGB_RX_DESC(*rx_ring, i);
+			continue;
+		}
+
+		/* Good Receive */
+		skb_put(skb, length);
+
+		/* Receive Checksum Offload */
+		ixgb_rx_checksum(adapter, rx_desc, skb);
+
+		skb->protocol = eth_type_trans(skb, netdev);
+		if (adapter->vlgrp
+		    && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+			vlan_hwaccel_rx(skb, adapter->vlgrp,
+					(rx_desc->
+					 special &
+					 IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+		} else {
+			netif_rx(skb);
+		}
+
+		netdev->last_rx = jiffies;
+
+		rx_desc->status = 0;
+
+		rx_ring->buffer_info[i].skb = NULL;
+		i = (i + 1) % rx_ring->count;
+
+		rx_desc = IXGB_RX_DESC(*rx_ring, i);
+	}			/* while */
+
+	rx_ring->next_to_clean = i;
+
+	ixgb_alloc_rx_buffers(adapter);
+}
+#endif
+
+/**
+ * ixgb_alloc_rx_buffers - Replace used receive buffers.
+ * @param adapter address of board private structure
+ **/
+
+static void
+ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_rx_desc *rx_desc;
+	struct sk_buff *skb;
+	int reserve_len;
+	int i;
+	int num_group_tail_writes;
+	long cleancount;
+
+	reserve_len = 2;
+
+	i = rx_ring->next_to_use;
+	cleancount = IXGB_DESC_UNUSED(rx_ring);
+
+	/* lessen this to 4 if we're
+	 * in the midst of raidc and rbd is occuring
+	 * because we don't want to delay returning buffers when low
+	 */
+	num_group_tail_writes = adapter->raidc ? 4 : IXGB_RX_BUFFER_WRITE;
+
+	/* leave one descriptor unused */
+	while (--cleancount > 0) {
+		rx_desc = IXGB_RX_DESC(*rx_ring, i);
+
+		/* allocate a new one */
+		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
+
+		if (unlikely(!skb)) {
+			/* better luck next time around */
+			IXGB_DBG("Could not allocate SKB\n");
+			break;
+		}
+		/* Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		skb_reserve(skb, reserve_len);
+
+		skb->dev = netdev;
+
+		rx_ring->buffer_info[i].skb = skb;
+		rx_ring->buffer_info[i].length = adapter->rx_buffer_len;
+		rx_ring->buffer_info[i].dma =
+		    pci_map_single(pdev, skb->data, adapter->rx_buffer_len,
+				   PCI_DMA_FROMDEVICE);
+
+		rx_desc->buff_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
+
+		if (!(i % num_group_tail_writes)) {
+			/* Force memory writes to complete before letting h/w
+			 * know there are new descriptors to fetch.  (Only
+			 * applicable for weak-ordered memory model archs,
+			 * such as IA-64). */
+			wmb();
+			/* move tail */
+			IXGB_WRITE_REG(&adapter->hw, RDT, i);
+		}
+		i = (i + 1) % rx_ring->count;
+	}
+
+	rx_ring->next_to_use = i;
+}
+
+/**
+ * ixgb_ioctl - perform a command - e.g: ethtool:get_driver_info.
+ * @param netdev network interface device structure
+ * @param ifr data to be used/filled in by the ioctl command
+ * @param cmd ioctl command to execute
+ **/
+
+int
+ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return ixgb_ethtool_ioctl(netdev, ifr);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+/**
+ * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
+ * 
+ * @param netdev network interface device structure
+ * @param grp indicates to enable or disable tagging/stripping
+ **/
+
+static void
+ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	u32 ctrl, rctl;
+
+	ixgb_irq_disable(adapter);
+	adapter->vlgrp = grp;
+
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+		ctrl |= IXGB_CTRL0_VME;
+		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
+
+		/* enable VLAN receive filtering */
+		rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+		rctl |= IXGB_RCTL_VFE;
+		rctl &= ~IXGB_RCTL_CFIEN;
+		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+		ctrl &= ~IXGB_CTRL0_VME;
+		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
+
+		/* disable VLAN filtering */
+		rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+		rctl &= ~IXGB_RCTL_VFE;
+		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+	}
+
+	ixgb_irq_enable(adapter);
+}
+
+/**
+ * ixgb_vlan_rx_add_vid - adds a vlan id to be tagged/stripped in packet data.
+ * @param netdev network interface device structure
+ * @param vid the vlan to be added
+ **/
+
+static void
+ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	u32 vfta, index;
+
+	/* add VID to filter table */
+
+	index = (vid >> 5) & 0x7F;
+	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta |= (1 << (vid & 0x1F));
+	ixgb_write_vfta(&adapter->hw, index, vfta);
+}
+
+/**
+ * ixgb_vlan_rx_kill_vid - removes a vlan id from tag/strip tables.
+ * @param netdev network interface device structure
+ * @param vid the vlan to be deleted
+ **/
+
+static void
+ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	u32 vfta, index;
+
+	ixgb_irq_disable(adapter);
+
+	if (adapter->vlgrp)
+		adapter->vlgrp->vlan_devices[vid] = NULL;
+
+	ixgb_irq_enable(adapter);
+
+	/* remove VID from filter table */
+
+	index = (vid >> 5) & 0x7F;
+	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta &= ~(1 << (vid & 0x1F));
+	ixgb_write_vfta(&adapter->hw, index, vfta);
+}
+
+/**
+ * ixgb_restore_vlan - restores vlan settings after adapter reset.
+ * @param adapter the address of the board private structure
+ **/
+static void
+ixgb_restore_vlan(struct ixgb_adapter *adapter)
+{
+	ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+
+	if (adapter->vlgrp) {
+		u16 vid;
+		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+			if (!adapter->vlgrp->vlan_devices[vid])
+				continue;
+			ixgb_vlan_rx_add_vid(adapter->netdev, vid);
+		}
+	}
+}
+
+/**
+ * ixgb_rx_checksum - Receive Checksum Offload for 82597.
+ * @param adapter board private structure
+ * @param rx_desc receive descriptor
+ * @param skb socket buffer with received data
+ **/
+
+static inline void
+ixgb_rx_checksum(struct ixgb_adapter *adapter,
+		 struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
+{
+	/* Ignore Checksum bit is set OR 
+	 * TCP Checksum has not been calculated 
+	 */
+	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+	    (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return;
+	}
+
+	/* At this point we know the hardware did the TCP checksum 
+	 * now look at the TCP checksum error bit
+	 */
+	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_rx_error++;
+	} else {
+		/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_rx_good++;
+	}
+}
+
+/**
+ * ixgb_write_pci_cfg - write PCI configuration space.
+ * @param hw board specific data structure
+ * @param reg PCI configuration space register to write to
+ * @param value Value to be written to reg
+ **/
+
+void
+ixgb_write_pci_cfg(struct ixgb_hw *hw, u32 reg, u16 * value)
+{
+	struct ixgb_adapter *adapter = (struct ixgb_adapter *) hw->back;
+
+	pci_write_config_word(adapter->pdev, reg, *value);
+}
+
+/**
+ * ixgb_notify_reboot - handles OS notification of reboot event.
+ * @param nb notifier block, unused
+ * @param event Event being passed to driver to act upon
+ * @param p A pointer to our net device
+ **/
+static int
+ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
+{
+	struct pci_dev *pdev = NULL;
+
+	switch (event) {
+	case SYS_DOWN:
+	case SYS_HALT:
+	case SYS_POWER_OFF:
+		pci_for_each_dev(pdev) {
+			if (pci_dev_driver(pdev) == &ixgb_driver)
+				ixgb_suspend(pdev, 3);
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+/**
+ * ixgb_suspend - driver suspend function called from notify.
+ * @param pdev pci driver structure used for passing to
+ * @param state power state to enter 
+ **/
+static int
+ixgb_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		ixgb_down(adapter, TRUE);
+
+	pci_save_state(pdev, adapter->pci_state);
+
+	state = (state > 0) ? 3 : 0;
+	pci_set_power_state(pdev, state);
+	msec_delay(200);
+
+	return 0;
+}
+
+/* ixgb_main.c */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_osdep.h linux-2.5.68-bk9/drivers/net/ixgb/ixgb_osdep.h
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_osdep.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_osdep.h	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,84 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+/* glue for the OS independant part of ixgb 
+ * includes register access macros
+ */
+
+#ifndef IXGB_OSDEP_H
+#define IXGB_OSDEP_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+/* FIXME: eliminate me */
+#define msec_delay(x)	do { if(in_interrupt()) { \
+	                	mdelay(x); \
+			} else { \
+				set_current_state(TASK_UNINTERRUPTIBLE); \
+				schedule_timeout((x * HZ)/1000); \
+			} } while(0)
+
+typedef enum {
+	FALSE = 0,
+	TRUE = 1
+} boolean_t;
+
+#define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
+
+#if DBG
+#define ASSERT(x)	if(!(x)) BUG()
+#define DEBUGOUT(S)		printk(KERN_ERR S "\n")
+#define DEBUGOUT1(S, A...)	printk(KERN_ERR S "\n", A)
+#else
+#define ASSERT(x)
+#define DEBUGOUT(S)
+#define DEBUGOUT1(S, A...)
+#endif
+
+#define DEBUGOUT2 DEBUGOUT1
+#define DEBUGOUT3 DEBUGOUT1
+#define DEBUGOUT7 DEBUGOUT1
+#define DEBUGFUNC(F)        DEBUGOUT(F)
+
+#define IXGB_WRITE_REG(a, reg, value) ( \
+    writel((value), ((a)->hw_addr + IXGB_##reg)))
+
+#define IXGB_READ_REG(a, reg) ( \
+    readl((a)->hw_addr + IXGB_##reg))
+
+#define IXGB_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+    writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
+
+#define IXGB_READ_REG_ARRAY(a, reg, offset) ( \
+    readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
+
+#endif				/* IXGB_OSDEP_H */
diff -urN linux-2.5.68-bk8/drivers/net/ixgb/ixgb_param.c linux-2.5.68-bk9/drivers/net/ixgb/ixgb_param.c
--- linux-2.5.68-bk8/drivers/net/ixgb/ixgb_param.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/drivers/net/ixgb/ixgb_param.c	2003-04-29 04:37:07.000000000 -0700
@@ -0,0 +1,502 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+  
+  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., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*******************************************************************************/
+
+#include "ixgb.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define IXGB_MAX_NIC			 8
+
+#define OPTION_UNSET			-1
+#define OPTION_DISABLED			 0
+#define OPTION_ENABLED			 1
+
+/* Module Parameters are always initialized to -1, so that the driver
+ * can tell the difference between no user specified value or the
+ * user asking for the default value.
+ * The true default values are loaded in when ixgb_check_options is called.
+ *
+ * This is a GCC extension to ANSI C.
+ * See the item "Labeled Elements in Initializers" in the section
+ * "Extensions to the C Language Family" of the GCC documentation.
+ */
+
+#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+
+#define IXGB_PARAM(X, S) \
+static const int __devinitdata X[IXGB_MAX_NIC + 1] = IXGB_PARAM_INIT; \
+MODULE_PARM(X, "1-" __MODULE_STRING(IXGB_MAX_NIC) "i"); \
+MODULE_PARM_DESC(X, S);
+
+/* Transmit Descriptor Count
+ *
+ * Valid Range: 64-4096
+ *
+ * Default Value: 256
+ */
+
+IXGB_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+/* Receive Descriptor Count
+ *
+ * Valid Range: 64-4096
+ *
+ * Default Value: 1024
+ */
+
+IXGB_PARAM(RxDescriptors, "Number of receive descriptors");
+
+/* User Specified Flow Control Override
+ *
+ * Valid Range: 0-3
+ *  - 0 - No Flow Control
+ *  - 1 - Rx only, respond to PAUSE frames but do not generate them
+ *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
+ *  - 3 - Full Flow Control Support
+ *
+ * Default Value: Read flow control settings from the EEPROM
+ */
+
+IXGB_PARAM(FlowControl, "Flow Control setting");
+
+/* XsumRX - Receive Checksum Offload Enable/Disable
+ *
+ * Valid Range: 0, 1
+ *  - 0 - disables all checksum offload
+ *  - 1 - enables receive IP/TCP/UDP checksum offload
+ *        on 82597 based NICs
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
+
+/* XsumTX - Transmit Checksum Offload Enable/Disable
+ *
+ * Valid Range: 0, 1
+ *  - 0 - disables all checksum offload
+ *  - 1 - enables transmmit IP/TCP/UDP checksum offload
+ *        on 82597 based NICs
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(XsumTX, "Disable or enable Transmit Checksum offload");
+
+/* Receive Interrupt Delay in units of 0.8192 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 72
+ */
+
+IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");
+
+/* Receive Interrupt Moderation enable (uses RxIntDelay too)
+ *
+ * Valid Range: 0,1
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(RAIDC, "Disable or enable Receive Interrupt Moderation");
+
+/* Receive Flow control high threshold (when we send a pause frame)
+ * (FCRTH)
+ *
+ * Valid Range: 1,536 - 262,136 (0x600 - 0x3FFF8, 8 byte granularity)
+ *
+ * Default Value: 196,608 (0x30000)
+ */
+
+IXGB_PARAM(RxFCHighThresh, "Receive Flow Control High Threshold");
+
+/* Receive Flow control low threshold (when we send a resume frame)
+ * (FCRTL)
+ *
+ * Valid Range: 64 - 262,136 (0x40 - 0x3FFF8, 8 byte granularity)
+ *              must be less than high threshold by at least 8 bytes
+ *
+ * Default Value:  163,840 (0x28000)
+ */
+
+IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");
+
+/* Flow control request timeout (how long to pause the link partner's tx)
+ * (PAP 15:0)
+ *
+ * Valid Range: 1 - 65535 
+ *
+ * Default Value:  256 (0x100)
+ */
+
+IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
+
+/* Transmit Interrupt Delay in units of 0.8192 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 32
+ */
+
+IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+
+/* Interrupt Delay Enable
+ *
+ * Valid Range: 0, 1
+ *
+ *  - 0 - disables transmit interrupt delay
+ *  - 1 - enables transmmit interrupt delay
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
+
+#define DEFAULT_TXD			    256
+#define MAX_TXD				   4096
+#define MIN_TXD				     64
+#define DEFAULT_RXD			   1024
+#define MAX_RXD				   4096
+#define MIN_RXD				     64
+#define DEFAULT_TIDV			     32
+#define MAX_TIDV		         0xFFFF
+#define MIN_TIDV			      0
+#define DEFAULT_RDTR			     72
+#define MAX_RDTR			 0xFFFF
+#define MIN_RDTR			      0
+#define XSUMRX_DEFAULT		 OPTION_ENABLED
+#define FLOW_CONTROL_FULL	   ixgb_fc_full
+#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
+#define DEFAULT_FCRTL	    		0x28000
+#define DEFAULT_FCRTH			0x30000
+#define MIN_FCRTL			      0
+#define MAX_FCRTL			0x3FFE8
+#define MIN_FCRTH			      8
+#define MAX_FCRTH			0x3FFF0
+#define DEFAULT_FCPAUSE		 	  0x100
+#define MIN_FCPAUSE			      1
+#define MAX_FCPAUSE			 0xffff
+
+struct ixgb_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int def;
+	union {
+		struct {	/* range option information */
+			int min;
+			int max;
+		} r;
+		struct {	/* list option information */
+			int nr;
+			struct ixgb_opt_list {
+				int i;
+				char *str;
+			} *p;
+		} l;
+	} arg;
+};
+
+static int __devinit
+ixgb_validate_option(int *value, struct ixgb_option *opt)
+{
+	if (*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			printk(KERN_INFO "%s Enabled\n", opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			printk(KERN_INFO "%s Disabled\n", opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
+			return 0;
+		}
+		break;
+	case list_option:
+		{
+			int i;
+			struct ixgb_opt_list *ent;
+
+			for (i = 0; i < opt->arg.l.nr; i++) {
+				ent = &opt->arg.l.p[i];
+				if (*value == ent->i) {
+					if (ent->str[0] != '\0')
+						printk(KERN_INFO "%s",
+						       ent->str);
+					return 0;
+				}
+			}
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	printk(KERN_INFO "Invalid %s specified (%i) %s\n", opt->name, *value,
+	       opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+#define LIST_LEN(l) (sizeof(l) / sizeof(l[0]))
+
+/**
+ * ixgb_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line paramters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ **/
+
+void __devinit
+ixgb_check_options(struct ixgb_adapter *adapter)
+{
+	int board = adapter->bd_number;
+
+	IXGB_DBG("ixgb_check_options\n");
+
+	if (board >= IXGB_MAX_NIC) {
+		printk(KERN_NOTICE "Warning: no configuration for board #%i\n",
+		       board);
+		printk(KERN_NOTICE "Using defaults for all values\n");
+		board = IXGB_MAX_NIC;
+	}
+
+	{			/* Transmit Descriptor Count */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Transmit Descriptors",
+			.err = "using default of " __MODULE_STRING(DEFAULT_TXD),
+			.def = DEFAULT_TXD,
+			.arg = {.r = {.min = MIN_TXD,.max = MAX_TXD}}
+		};
+		struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+		tx_ring->count = TxDescriptors[board];
+		ixgb_validate_option(&tx_ring->count, &opt);
+		IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+	}
+
+	{			/* Receive Descriptor Count */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Receive Descriptors",
+			.err = "using default of " __MODULE_STRING(DEFAULT_RXD),
+			.def = DEFAULT_RXD,
+			.arg = {.r = {.min = MIN_RXD,.max = MAX_RXD}}
+		};
+		struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+
+		rx_ring->count = RxDescriptors[board];
+		ixgb_validate_option(&rx_ring->count, &opt);
+		IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+	}
+
+	{			/* Receive Checksum Offload Enable */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Receive Checksum Offload",
+			.err = "defaulting to Enabled",
+			.def = OPTION_ENABLED,
+		};
+		int rx_csum = XsumRX[board];
+
+		ixgb_validate_option(&rx_csum, &opt);
+		adapter->rx_csum = rx_csum;
+	}
+
+	{			/* Transmit Checksum Offload Enable */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Transmit Checksum Offload",
+			.err = "defaulting to Enabled",
+			.def = OPTION_ENABLED,
+		};
+		int tx_csum = XsumTX[board];
+
+		ixgb_validate_option(&tx_csum, &opt);
+		adapter->tx_csum = tx_csum;
+	}
+
+	{			/* Flow Control */
+		struct ixgb_opt_list fc_list[] = {
+			{ixgb_fc_none, "Flow Control Disabled\n"},
+			{ixgb_fc_rx_pause, "Flow Control Receive Only\n"},
+			{ixgb_fc_tx_pause, "Flow Control Transmit Only\n"},
+			{ixgb_fc_full, "Flow Control Enabled\n"},
+			{ixgb_fc_default, "Flow Control Hardware Default\n"}
+		};
+
+		struct ixgb_option opt = {
+			.type = list_option,
+			.name = "Flow Control",
+			.err = "reading default settings from EEPROM",
+			.def = ixgb_fc_full,
+			.arg = {.l = {.nr = LIST_LEN(fc_list),.p = fc_list}}
+		};
+
+		int fc = FlowControl[board];
+
+		ixgb_validate_option(&fc, &opt);
+		adapter->hw.fc.type = fc;
+	}
+	{			/* Receive Flow Control High Threshold */
+		struct ixgb_option fcrth = {
+			.type = range_option,
+			.name = "Rx Flow Control High Threshold",
+			.err =
+			    "using default of " __MODULE_STRING(DEFAULT_FCRTH),
+			.def = DEFAULT_FCRTH,
+			.arg = {.r = {.min = MIN_FCRTH,.max = MAX_FCRTH}}
+		};
+
+		adapter->hw.fc.high_water = RxFCHighThresh[board];
+		ixgb_validate_option(&adapter->hw.fc.high_water, &fcrth);
+		if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
+			printk(KERN_INFO
+			       "Ignoring RxFCHighThresh when no RxFC\n");
+	}
+	{			/* Receive Flow Control Low Threshold */
+		struct ixgb_option fcrtl = {
+			.type = range_option,
+			.name = "Rx Flow Control Low Threshold",
+			.err =
+			    "using default of " __MODULE_STRING(DEFAULT_FCRTL),
+			.def = DEFAULT_FCRTL,
+			.arg = {.r = {.min = MIN_FCRTL,.max = MAX_FCRTL}}
+		};
+
+		adapter->hw.fc.low_water = RxFCLowThresh[board];
+		ixgb_validate_option(&adapter->hw.fc.low_water, &fcrtl);
+		if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
+			printk(KERN_INFO
+			       "Ignoring RxFCLowThresh when no RxFC\n");
+	}
+	{			/* Flow Control Pause Time Request */
+		struct ixgb_option fcpap = {
+			.type = range_option,
+			.name = "Flow Control Pause Time Request",
+			.err =
+			    "using default of "
+			    __MODULE_STRING(DEFAULT_FCPAUSE),
+			.def = DEFAULT_FCPAUSE,
+			.arg = {.r = {.min = MIN_FCPAUSE,.max = MAX_FCPAUSE}}
+		};
+
+		int pause_time = FCReqTimeout[board];
+
+		ixgb_validate_option(&pause_time, &fcpap);
+		if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
+			printk(KERN_INFO
+			       "Ignoring FCReqTimeout when no RxFC\n");
+		adapter->hw.fc.pause_time = pause_time;
+	}
+	/* high low and spacing check for rx flow control thresholds */
+	if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
+		/* high must be greater than low */
+		if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
+			/* set defaults */
+			printk(KERN_INFO
+			       "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
+			       "Using Defaults\n");
+			adapter->hw.fc.high_water = DEFAULT_FCRTH;
+			adapter->hw.fc.low_water = DEFAULT_FCRTL;
+		}
+	}
+	{			/* Receive Interrupt Delay */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Receive Interrupt Delay",
+			.err =
+			    "using default of " __MODULE_STRING(DEFAULT_RDTR),
+			.def = DEFAULT_RDTR,
+			.arg = {.r = {.min = MIN_RDTR,.max = MAX_RDTR}}
+		};
+
+		adapter->rx_int_delay = RxIntDelay[board];
+		ixgb_validate_option(&adapter->rx_int_delay, &opt);
+	}
+	{			/* Receive Interrupt Moderation */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Advanced Receive Interrupt Moderation",
+			.err = "defaulting to Enabled",
+			.def = OPTION_ENABLED,
+		};
+		int raidc = RAIDC[board];
+
+		ixgb_validate_option(&raidc, &opt);
+		adapter->raidc = raidc;
+	}
+
+	{			/* Transmit Interrupt Delay */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Transmit Interrupt Delay",
+			.err =
+			    "using default of " __MODULE_STRING(DEFAULT_TIDV),
+			.def = DEFAULT_TIDV,
+			.arg = {.r = {.min = MIN_TIDV,.max = MAX_TIDV}}
+		};
+
+		adapter->tx_int_delay = TxIntDelay[board];
+		ixgb_validate_option(&adapter->tx_int_delay, &opt);
+	}
+
+	{			/* Transmit Interrupt Delay Enable */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Tx Interrupt Delay Enable",
+			.err = "defaulting to Enabled",
+			.def = OPTION_ENABLED,
+		};
+		int ide = IntDelayEnable[board];
+
+		ixgb_validate_option(&ide, &opt);
+		adapter->tx_int_delay_enable = ide;
+	}
+}
diff -urN linux-2.5.68-bk8/drivers/net/lasi_82596.c linux-2.5.68-bk9/drivers/net/lasi_82596.c
--- linux-2.5.68-bk8/drivers/net/lasi_82596.c	2003-04-19 19:48:51.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/lasi_82596.c	2003-04-29 04:37:07.000000000 -0700
@@ -405,7 +405,7 @@
 
 static int i596_open(struct net_device *dev);
 static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int i596_close(struct net_device *dev);
 static struct net_device_stats *i596_get_stats(struct net_device *dev);
 static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
@@ -1244,7 +1244,7 @@
 }
 
 
-static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct i596_private *lp;
@@ -1252,7 +1252,7 @@
 
 	if (dev == NULL) {
 		printk("i596_interrupt(): irq %d for unknown device.\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	lp = (struct i596_private *) dev->priv;
@@ -1270,7 +1270,7 @@
 	if (!ack_cmd) {
 		DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
 		spin_unlock (&lp->lock);
-		return;
+		return IRQ_NONE;
 	}
 
 	if ((status & 0x8000) || (status & 0x2000)) {
@@ -1396,7 +1396,7 @@
 	DEB(DEB_INTS,printk("%s: exiting interrupt.\n", dev->name));
 
 	spin_unlock (&lp->lock);
-	return;
+	return IRQ_HANDLED;
 }
 
 static int i596_close(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/mac89x0.c linux-2.5.68-bk9/drivers/net/mac89x0.c
--- linux-2.5.68-bk8/drivers/net/mac89x0.c	2003-04-19 19:49:33.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/mac89x0.c	2003-04-29 04:37:07.000000000 -0700
@@ -129,7 +129,7 @@
 #endif
 static int net_open(struct net_device *dev);
 static int	net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void set_multicast_list(struct net_device *dev);
 static void net_rx(struct net_device *dev);
 static int net_close(struct net_device *dev);
@@ -424,7 +424,7 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
@@ -432,7 +432,7 @@
 
 	if (dev == NULL) {
 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 	if (dev->interrupt)
 		printk("%s: Re-entering the interrupt handler.\n", dev->name);
@@ -491,7 +491,7 @@
 		}
 	}
 	dev->interrupt = 0;
-	return;
+	return IRQ_HANDLED;
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
diff -urN linux-2.5.68-bk8/drivers/net/pci-skeleton.c linux-2.5.68-bk9/drivers/net/pci-skeleton.c
--- linux-2.5.68-bk8/drivers/net/pci-skeleton.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pci-skeleton.c	2003-04-29 04:37:07.000000000 -0700
@@ -505,7 +505,7 @@
 static void netdrv_init_ring (struct net_device *dev);
 static int netdrv_start_xmit (struct sk_buff *skb,
 			       struct net_device *dev);
-static void netdrv_interrupt (int irq, void *dev_instance,
+static irqreturn_t netdrv_interrupt (int irq, void *dev_instance,
 			       struct pt_regs *regs);
 static int netdrv_close (struct net_device *dev);
 static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
@@ -1665,7 +1665,7 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void netdrv_interrupt (int irq, void *dev_instance,
+static irqreturn_t netdrv_interrupt (int irq, void *dev_instance,
 			       struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
@@ -1673,6 +1673,7 @@
 	int boguscnt = max_interrupt_work;
 	void *ioaddr = tp->mmio_addr;
 	int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
+	int handled = 0;
 
 	spin_lock (&tp->lock);
 
@@ -1683,6 +1684,7 @@
 		if (status == 0xFFFF)
 			break;
 
+		handled = 1;
 		/* Acknowledge all of the current interrupt sources ASAP */
 		NETDRV_W16_F (IntrStatus, status);
 
@@ -1724,6 +1726,7 @@
 
 	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
 		 dev->name, NETDRV_R16 (IntrStatus));
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/3c574_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/3c574_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/3c574_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/3c574_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -247,7 +247,7 @@
 static void media_check(unsigned long arg);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev, int worklimit);
@@ -947,15 +947,16 @@
 }
 
 /* The EL3 interrupt handler. */
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct el3_private *lp = dev_id;
 	struct net_device *dev = &lp->dev;
 	ioaddr_t ioaddr, status;
 	int work_budget = max_interrupt_work;
+	int handled = 0;
 
 	if (!netif_device_present(dev))
-		return;
+		return IRQ_NONE;
 	ioaddr = dev->base_addr;
 
 	DEBUG(3, "%s: interrupt, status %4.4x.\n",
@@ -971,6 +972,8 @@
 			break;
 		}
 
+		handled = 1;
+
 		if (status & RxComplete)
 			work_budget = el3_rx(dev, work_budget);
 
@@ -1029,7 +1032,7 @@
 		  dev->name, inw(ioaddr + EL3_STATUS));
 		  
 	spin_unlock(&lp->window_lock);
-	return;
+	return IRQ_RETVAL(handled);
 }
 
 /*
@@ -1336,37 +1339,26 @@
 	return 0;
 }
 
-static int __init init_3c574_cs(void)
-{
-	servinfo_t serv;
+static struct pcmcia_driver tc574_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "3c574_cs",
+	},
+	.attach		= tc574_attach,
+	.detach		= tc574_detach,
+};
 
-	DEBUG(0, "%s\n", version);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "3c574_cs: Card Services release "
-			   "does not match!\n");
-		return -1;
-	}
-	register_pccard_driver(&dev_info, &tc574_attach, &tc574_detach);
-	return 0;
+static int __init init_tc574(void)
+{
+	return pcmcia_register_driver(&tc574_driver);
 }
 
-static void __exit exit_3c574_cs(void)
+static void __exit exit_tc574(void)
 {
-	DEBUG(0, "3c574_cs: unloading\n");
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&tc574_driver);
 	while (dev_list != NULL)
 		tc574_detach(dev_list);
 }
 
-module_init(init_3c574_cs);
-module_exit(exit_3c574_cs);
-
-/*
- * Local variables:
- *  compile-command: "make 3c574_cs.o"
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
+module_init(init_tc574);
+module_exit(exit_tc574);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/3c589_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/3c589_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/3c589_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/3c589_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -1151,28 +1151,26 @@
     return 0;
 }
 
-/*====================================================================*/
+static struct pcmcia_driver tc589_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "3c589_cs",
+	},
+	.attach		= tc589_attach,
+	.detach		= tc589_detach,
+};
 
-static int __init init_3c589_cs(void)
+static int __init init_tc589(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_ERR "3c589_cs: Card Services release does not match!\n");
-	return -1;
-    }
-    register_pccard_driver(&dev_info, &tc589_attach, &tc589_detach);
-    return 0;
+	return pcmcia_register_driver(&tc589_driver);
 }
 
-static void __exit exit_3c589_cs(void)
+static void __exit exit_tc589(void)
 {
-    DEBUG(0, "3c589_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	tc589_detach(dev_list);
+	pcmcia_unregister_driver(&tc589_driver);
+	while (dev_list != NULL)
+		tc589_detach(dev_list);
 }
 
-module_init(init_3c589_cs);
-module_exit(exit_3c589_cs);
+module_init(init_tc589);
+module_exit(exit_tc589);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/axnet_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/axnet_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/axnet_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/axnet_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -930,28 +930,25 @@
     outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
 }
 
-/*====================================================================*/
+static struct pcmcia_driver axnet_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "axnet_cs",
+	},
+	.attach		= axnet_attach,
+	.detach		= axnet_detach,
+};
 
 static int __init init_axnet_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "axnet_cs: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &axnet_attach, &axnet_detach);
-    return 0;
+	return pcmcia_register_driver(&axnet_cs_driver);
 }
 
 static void __exit exit_axnet_cs(void)
 {
-    DEBUG(0, "axnet_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	axnet_detach(dev_list);
+	pcmcia_unregister_driver(&axnet_cs_driver);
+	while (dev_list != NULL)
+		axnet_detach(dev_list);
 }
 
 module_init(init_axnet_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/com20020_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/com20020_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/com20020_cs.c	2003-04-19 19:49:26.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/com20020_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -567,29 +567,26 @@
 } /* com20020_event */
 
 
-/*====================================================================*/
+
+static struct pcmcia_driver com20020_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "com20020_cs",
+	},
+	.attach		= com20020_attach,
+	.detach		= com20020_detach,
+};
 
 static int __init init_com20020_cs(void)
 {
-    servinfo_t serv;
-
-    DEBUG(0, "%s\n", VERSION);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "com20020_cs: Card Services release "
-	       "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &com20020_attach, &com20020_detach);
-    return 0;
+	return pcmcia_register_driver(&com20020_cs_driver);
 }
 
 static void __exit exit_com20020_cs(void)
 {
-    DEBUG(0, "com20020_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-        com20020_detach(dev_list);
+	pcmcia_unregister_driver(&com20020_cs_driver);
+	while (dev_list != NULL)
+		com20020_detach(dev_list);
 }
 
 module_init(init_com20020_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/fmvj18x_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/fmvj18x_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/fmvj18x_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -829,28 +829,25 @@
     return 0;
 } /* fmvj18x_event */
 
-/*====================================================================*/
+static struct pcmcia_driver fmvj18x_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "fmvj18x_cs",
+	},
+	.attach		= fmvj18x_attach,
+	.detach		= fmvj18x_detach,
+};
 
 static int __init init_fmvj18x_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_NOTICE "fmvj18x: Card Services release "
-	       "does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach);
-    return 0;
+	return pcmcia_register_driver(&fmvj18x_cs_driver);
 }
 
 static void __exit exit_fmvj18x_cs(void)
 {
-    DEBUG(0, "fmvj18x_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	fmvj18x_detach(dev_list);
+	pcmcia_unregister_driver(&fmvj18x_cs_driver);
+	while (dev_list != NULL)
+		fmvj18x_detach(dev_list);
 }
 
 module_init(init_fmvj18x_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/ibmtr_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/ibmtr_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/ibmtr_cs.c	2003-04-19 19:49:52.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/ibmtr_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -585,28 +585,25 @@
     return;
 }
 
-/*====================================================================*/
+static struct pcmcia_driver ibmtr_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "ibmtr_cs",
+	},
+	.attach		= ibmtr_attach,
+	.detach		= ibmtr_detach,
+};
 
 static int __init init_ibmtr_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-        printk(KERN_NOTICE "ibmtr_cs: Card Services release "
-	       "does not match!\n");
-        return -1;
-    }
-    register_pccard_driver(&dev_info, &ibmtr_attach, &ibmtr_detach);
-    return 0;
+	return pcmcia_register_driver(&ibmtr_cs_driver);
 }
 
 static void __exit exit_ibmtr_cs(void)
 {
-    DEBUG(0, "ibmtr_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-        ibmtr_detach(dev_list);
+	pcmcia_unregister_driver(&ibmtr_cs_driver);
+	while (dev_list != NULL)
+		ibmtr_detach(dev_list);
 }
 
 module_init(init_ibmtr_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/nmclan_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/nmclan_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/nmclan_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/nmclan_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -1741,33 +1741,25 @@
 
 } /* set_multicast_list */
 
-/* ----------------------------------------------------------------------------
-init_nmclan_cs
----------------------------------------------------------------------------- */
+static struct pcmcia_driver nmclan_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "nmclan_cs",
+	},
+	.attach		= nmclan_attach,
+	.detach		= nmclan_detach,
+};
 
 static int __init init_nmclan_cs(void)
 {
-  servinfo_t serv;
-  DEBUG(0, "%s\n", version);
-  CardServices(GetCardServicesInfo, &serv);
-  if (serv.Revision != CS_RELEASE_CODE) {
-    printk(KERN_NOTICE "nmclan_cs: Card Services release does not match!\n");
-    return -1;
-  }
-  register_pccard_driver(&dev_info, &nmclan_attach, &nmclan_detach);
-  return 0;
+	return pcmcia_register_driver(&nmclan_cs_driver);
 }
 
-/* ----------------------------------------------------------------------------
-exit_nmclan_cs
----------------------------------------------------------------------------- */
-
 static void __exit exit_nmclan_cs(void)
 {
-    DEBUG(0, "nmclan_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	nmclan_detach(dev_list);
+	pcmcia_unregister_driver(&nmclan_cs_driver);
+	while (dev_list != NULL)
+		nmclan_detach(dev_list);
 }
 
 module_init(init_nmclan_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/smc91c92_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/smc91c92_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/smc91c92_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/smc91c92_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -2265,29 +2265,25 @@
     return rc;
 }
 
-
-/*====================================================================*/
+static struct pcmcia_driver smc91c92_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "smc91c92_cs",
+	},
+	.attach		= smc91c92_attach,
+	.detach		= smc91c92_detach,
+};
 
 static int __init init_smc91c92_cs(void)
 {
-    servinfo_t serv;
-    DEBUG(0, "%s\n", version);
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KERN_ERR
-	       "smc91c92_cs: Card Services release does not match!\n");
-	return -EINVAL;
-    }
-    register_pccard_driver(&dev_info, &smc91c92_attach, &smc91c92_detach);
-    return 0;
+	return pcmcia_register_driver(&smc91c92_cs_driver);
 }
 
 static void __exit exit_smc91c92_cs(void)
 {
-    DEBUG(0, "smc91c92_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list != NULL)
-	smc91c92_detach(dev_list);
+	pcmcia_unregister_driver(&smc91c92_cs_driver);
+	while (dev_list != NULL)
+		smc91c92_detach(dev_list);
 }
 
 module_init(init_smc91c92_cs);
diff -urN linux-2.5.68-bk8/drivers/net/pcmcia/xirc2ps_cs.c linux-2.5.68-bk9/drivers/net/pcmcia/xirc2ps_cs.c
--- linux-2.5.68-bk8/drivers/net/pcmcia/xirc2ps_cs.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/pcmcia/xirc2ps_cs.c	2003-04-29 04:37:07.000000000 -0700
@@ -2069,35 +2069,32 @@
     return 0;
 }
 
+static struct pcmcia_driver xirc2ps_cs_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "xirc2ps_cs",
+	},
+	.attach		= xirc2ps_attach,
+	.detach		= xirc2ps_detach,
+};
+
 static int __init
 init_xirc2ps_cs(void)
 {
-    servinfo_t serv;
-
-    printk(KERN_INFO "%s\n", version);
-    if (lockup_hack)
-	printk(KINF_XIRC "lockup hack is enabled\n");
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk(KNOT_XIRC "Card Services release does not match!\n");
-	return -1;
-    }
-    DEBUG(0, "pc_debug=%d\n", pc_debug);
-    register_pccard_driver(&dev_info, &xirc2ps_attach, &xirc2ps_detach);
-    return 0;
+	return pcmcia_register_driver(&xirc2ps_cs_driver);
 }
 
 static void __exit
 exit_xirc2ps_cs(void)
 {
-    DEBUG(0, "unloading\n");
-    unregister_pccard_driver(&dev_info);
-    while (dev_list) {
-	if (dev_list->state & DEV_CONFIG)
-	    xirc2ps_release((u_long)dev_list);
-	if (dev_list)	/* xirc2ps_release() might already have detached... */
-	    xirc2ps_detach(dev_list);
-    }
+	pcmcia_unregister_driver(&xirc2ps_cs_driver);
+
+	while (dev_list) {
+		if (dev_list->state & DEV_CONFIG)
+			xirc2ps_release((u_long)dev_list);
+		if (dev_list)	/* xirc2ps_release() might already have detached... */
+			xirc2ps_detach(dev_list);
+	}
 }
 
 module_init(init_xirc2ps_cs);
diff -urN linux-2.5.68-bk8/drivers/net/rrunner.c linux-2.5.68-bk9/drivers/net/rrunner.c
--- linux-2.5.68-bk8/drivers/net/rrunner.c	2003-04-19 19:48:55.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/rrunner.c	2003-04-29 04:37:07.000000000 -0700
@@ -1045,7 +1045,7 @@
 }
 
 
-static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
+static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
@@ -1056,7 +1056,7 @@
 	regs = rrpriv->regs;
 
 	if (!(readl(&regs->HostCtrl) & RR_INT))
-		return;
+		return IRQ_NONE;
 
 	spin_lock(&rrpriv->lock);
 
@@ -1127,6 +1127,7 @@
 	wmb();
 
 	spin_unlock(&rrpriv->lock);
+	return IRQ_HANDLED;
 }
 
 static void rr_timer(unsigned long data)
diff -urN linux-2.5.68-bk8/drivers/net/rrunner.h linux-2.5.68-bk9/drivers/net/rrunner.h
--- linux-2.5.68-bk8/drivers/net/rrunner.h	2003-04-19 19:50:07.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/rrunner.h	2003-04-29 04:37:07.000000000 -0700
@@ -1,7 +1,8 @@
 #ifndef _RRUNNER_H_
 #define _RRUNNER_H_
 
-#include<linux/config.h>
+#include <linux/config.h>
+#include <linux/interrupt.h>
 
 #if ((BITS_PER_LONG != 32) && (BITS_PER_LONG != 64))
 #error "BITS_PER_LONG not defined or not valid"
@@ -830,7 +831,7 @@
  */
 static int rr_init(struct net_device *dev);
 static int rr_init1(struct net_device *dev);
-static void rr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 static int rr_open(struct net_device *dev);
 static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev);
diff -urN linux-2.5.68-bk8/drivers/net/saa9730.c linux-2.5.68-bk9/drivers/net/saa9730.c
--- linux-2.5.68-bk8/drivers/net/saa9730.c	2003-04-19 19:49:56.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/saa9730.c	2003-04-29 04:37:07.000000000 -0700
@@ -745,7 +745,7 @@
 	return 0;
 }
 
-static void lan_saa9730_interrupt(const int irq, void *dev_id,
+static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id,
 				  struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
@@ -773,7 +773,7 @@
 	/* Enable the EVM LAN interrupt. */
 	evm_saa9730_unblock_lan_int(lp);
 
-	return;
+	return IRQ_HANDLED;
 }
 
 static int lan_saa9730_open_fail(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/sb1000.c linux-2.5.68-bk9/drivers/net/sb1000.c
--- linux-2.5.68-bk8/drivers/net/sb1000.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sb1000.c	2003-04-29 04:37:07.000000000 -0700
@@ -84,7 +84,7 @@
 static int sb1000_open(struct net_device *dev);
 static int sb1000_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
 static int sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats *sb1000_stats(struct net_device *dev);
 static int sb1000_close(struct net_device *dev);
 
@@ -1112,7 +1112,7 @@
 }
 
 /* SB1000 interrupt handler. */
-static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	char *name;
 	unsigned char st;
@@ -1127,7 +1127,7 @@
 	if (dev == NULL) {
 		printk(KERN_ERR "sb1000_interrupt(): irq %d for unknown device.\n",
 			irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	ioaddr[0] = dev->base_addr;
@@ -1138,7 +1138,7 @@
 	/* is it a good interrupt? */
 	st = inb(ioaddr[1] + 6);
 	if (!(st & 0x08 && st & 0x20)) {
-		return;
+		return IRQ_NONE;
 	}
 
 	if (sb1000_debug > 3)
@@ -1169,7 +1169,7 @@
 		lp->rx_error_count = 0;
 	}
 
-	return;
+	return IRQ_HANDLED;
 }
 
 static struct net_device_stats *sb1000_stats(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/sb1250-mac.c linux-2.5.68-bk9/drivers/net/sb1250-mac.c
--- linux-2.5.68-bk8/drivers/net/sb1250-mac.c	2003-04-19 19:51:07.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sb1250-mac.c	2003-04-29 04:37:07.000000000 -0700
@@ -281,7 +281,7 @@
 static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);
 /*static void sbmac_init_and_start(struct sbmac_softc *sc);*/
 static uint64_t sbmac_addr2reg(unsigned char *ptr);
-static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
+static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
 static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
 static void sbmac_setmulti(struct sbmac_softc *sc);
 static int sbmac_init(struct net_device *dev);
@@ -1891,7 +1891,8 @@
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv);
 	uint64_t isr;
-	
+	int handled = 0;
+
 	for (;;) {
 		
 		/*
@@ -1900,8 +1901,9 @@
 		
 		isr = SBMAC_READCSR(sc->sbm_isr);
 		
-		if (isr == 0) break;
-		
+		if (isr == 0)
+			break;
+		handled = 1;
 		/*
 		 * Transmits on channel 0
 		 */
@@ -1918,7 +1920,7 @@
 			sbdma_rx_process(sc,&(sc->sbm_rxdma));
 		}
 	}
-	
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/sgiseeq.c linux-2.5.68-bk9/drivers/net/sgiseeq.c
--- linux-2.5.68-bk8/drivers/net/sgiseeq.c	2003-04-19 19:51:07.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sgiseeq.c	2003-04-29 04:37:07.000000000 -0700
@@ -416,7 +416,7 @@
 	}
 }
 
-static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
@@ -436,6 +436,7 @@
 	if ((TX_BUFFS_AVAIL(sp) > 0) && netif_queue_stopped(dev)) {
 		netif_wake_queue(dev);
 	}
+	return IRQ_HANDLED;
 }
 
 static int sgiseeq_open(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/sk_g16.c linux-2.5.68-bk9/drivers/net/sk_g16.c
--- linux-2.5.68-bk8/drivers/net/sk_g16.c	2003-04-19 19:51:23.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sk_g16.c	2003-04-29 04:37:07.000000000 -0700
@@ -478,7 +478,7 @@
 static void  SK_timeout(struct net_device *dev);
 static int   SK_open(struct net_device *dev);
 static int   SK_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void  SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void  SK_rxintr(struct net_device *dev);
 static void  SK_txintr(struct net_device *dev);
 static int   SK_close(struct net_device *dev);
@@ -1337,7 +1337,7 @@
  *     YY/MM/DD  uid  Description
 -*/
 
-static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
     int csr0;
     struct net_device *dev = dev_id;
@@ -1386,6 +1386,7 @@
     SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */
 
     spin_unlock (&SK_lock);
+    return IRQ_HANDLED;
 } /* End of SK_interrupt() */ 
 
 
diff -urN linux-2.5.68-bk8/drivers/net/sk_mca.c linux-2.5.68-bk9/drivers/net/sk_mca.c
--- linux-2.5.68-bk8/drivers/net/sk_mca.c	2003-04-19 19:50:06.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sk_mca.c	2003-04-29 04:37:07.000000000 -0700
@@ -754,7 +754,7 @@
 
 /* general interrupt entry */
 
-static void irq_handler(int irq, void *device, struct pt_regs *regs)
+static irqreturn_t irq_handler(int irq, void *device, struct pt_regs *regs)
 {
 	struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) device;
 	u16 csr0val;
@@ -766,7 +766,7 @@
 	/* in case we're not meant... */
 
 	if ((csr0val & CSR0_INTR) == 0)
-		return;
+		return IRQ_NONE;
 
 #if (LINUX_VERSION_CODE >= 0x02032a)
 #if 0
@@ -805,6 +805,7 @@
 #else
 	dev->interrupt = 0;
 #endif
+	return IRQ_HANDLED;
 }
 
 /* ------------------------------------------------------------------------
diff -urN linux-2.5.68-bk8/drivers/net/skfp/skfddi.c linux-2.5.68-bk9/drivers/net/skfp/skfddi.c
--- linux-2.5.68-bk8/drivers/net/skfp/skfddi.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/skfp/skfddi.c	2003-04-29 04:37:07.000000000 -0700
@@ -118,7 +118,7 @@
 static int skfp_driver_init(struct net_device *dev);
 static int skfp_open(struct net_device *dev);
 static int skfp_close(struct net_device *dev);
-static void skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);
 static void skfp_ctl_set_multicast_list(struct net_device *dev);
 static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
@@ -896,7 +896,7 @@
  *   Interrupts are disabled, then reenabled at the adapter.
  */
 
-void skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct s_smc *smc;	/* private board structure pointer */
@@ -905,7 +905,7 @@
 
 	if (dev == NULL) {
 		printk("%s: irq %d for unknown device\n", dev->name, irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	smc = (struct s_smc *) dev->priv;
@@ -913,12 +913,12 @@
 	// IRQs enabled or disabled ?
 	if (inpd(ADDR(B0_IMSK)) == 0) {
 		// IRQs are disabled: must be shared interrupt
-		return;
+		return IRQ_NONE;
 	}
 	// Note: At this point, IRQs are enabled.
 	if ((inpd(ISR_A) & smc->hw.is_imask) == 0) {	// IRQ?
 		// Adapter did not issue an IRQ: must be shared interrupt
-		return;
+		return IRQ_NONE;
 	}
 	CLI_FBI();		// Disable IRQs from our adapter.
 	spin_lock(&bp->DriverLock);
@@ -933,7 +933,7 @@
 	spin_unlock(&bp->DriverLock);
 	STI_FBI();		// Enable IRQs from our adapter.
 
-	return;
+	return IRQ_HANDLED;
 }				// skfp_interrupt
 
 
diff -urN linux-2.5.68-bk8/drivers/net/sonic.c linux-2.5.68-bk9/drivers/net/sonic.c
--- linux-2.5.68-bk8/drivers/net/sonic.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sonic.c	2003-04-29 04:37:07.000000000 -0700
@@ -170,7 +170,7 @@
  * The typical workload of the driver:
  * Handle the network interface interrupts.
  */
-static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	unsigned int base_addr = dev->base_addr;
@@ -179,7 +179,7 @@
 
 	if (dev == NULL) {
 		printk("sonic_interrupt: irq %d for unknown device.\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	lp = (struct sonic_local *) dev->priv;
@@ -286,6 +286,7 @@
 	 * clear interrupt bits and return
 	 */
 	SONIC_WRITE(SONIC_ISR, status);
+	return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/sonic.h linux-2.5.68-bk9/drivers/net/sonic.h
--- linux-2.5.68-bk8/drivers/net/sonic.h	2003-04-19 19:48:48.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sonic.h	2003-04-29 04:37:07.000000000 -0700
@@ -469,7 +469,7 @@
 
 static int sonic_open(struct net_device *dev);
 static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void sonic_rx(struct net_device *dev);
 static int sonic_close(struct net_device *dev);
 static struct net_device_stats *sonic_get_stats(struct net_device *dev);
diff -urN linux-2.5.68-bk8/drivers/net/sun3_82586.c linux-2.5.68-bk9/drivers/net/sun3_82586.c
--- linux-2.5.68-bk8/drivers/net/sun3_82586.c	2003-04-19 19:49:52.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/sun3_82586.c	2003-04-29 04:37:07.000000000 -0700
@@ -119,7 +119,7 @@
      DELAY_16(); DELAY_16(); } }
 
 static int     sun3_82586_probe1(struct net_device *dev,int ioaddr);
-static void    sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
+static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
 static int     sun3_82586_open(struct net_device *dev);
 static int     sun3_82586_close(struct net_device *dev);
 static int     sun3_82586_send_packet(struct sk_buff *,struct net_device *);
@@ -665,7 +665,7 @@
  * Interrupt Handler ...
  */
 
-static void sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
+static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
 {
 	struct net_device *dev = dev_id;
 	unsigned short stat;
@@ -674,7 +674,7 @@
 
 	if (!dev) {
 		printk ("sun3_82586-interrupt: irq %d for unknown device.\n",irq);
-		return;
+		return IRQ_NONE;
 	}
 	p = (struct priv *) dev->priv;
 
@@ -733,6 +733,7 @@
 
 	if(debuglevel > 1)
 		printk("i");
+	return IRQ_HANDLED;
 }
 
 /*******************************************************
diff -urN linux-2.5.68-bk8/drivers/net/tc35815.c linux-2.5.68-bk9/drivers/net/tc35815.c
--- linux-2.5.68-bk8/drivers/net/tc35815.c	2003-04-19 19:48:46.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tc35815.c	2003-04-29 04:37:08.000000000 -0700
@@ -451,7 +451,7 @@
 static int	tc35815_open(struct net_device *dev);
 static int	tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void     tc35815_tx_timeout(struct net_device *dev);
-static void	tc35815_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tc35815_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void	tc35815_rx(struct net_device *dev);
 static void	tc35815_txdone(struct net_device *dev);
 static int	tc35815_close(struct net_device *dev);
@@ -1036,16 +1036,17 @@
  * The typical workload of the driver:
  *   Handle the network interface interrupts.
  */
-static void tc35815_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t tc35815_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	struct tc35815_regs *tr;
 	struct tc35815_local *lp;
 	int status, boguscount = 0;
+	int handled = 0;
 
 	if (dev == NULL) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	tr = (struct tc35815_regs*)dev->base_addr;
@@ -1055,6 +1056,7 @@
 		status = tc_readl(&tr->Int_Src);
 		if (status == 0)
 			break;
+		handled = 1;
 		tc_writel(status, &tr->Int_Src);	/* write to clear */
 
 		/* Fatal errors... */
@@ -1097,7 +1099,7 @@
 		}
 	} while (++boguscount < 20) ;
 
-	return;
+	return IRQ_RETVAL(handled);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
diff -urN linux-2.5.68-bk8/drivers/net/tokenring/3c359.c linux-2.5.68-bk9/drivers/net/tokenring/3c359.c
--- linux-2.5.68-bk8/drivers/net/tokenring/3c359.c	2003-04-19 19:51:13.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tokenring/3c359.c	2003-04-29 04:37:08.000000000 -0700
@@ -131,7 +131,7 @@
 static void xl_dn_comp(struct net_device *dev); 
 static int xl_close(struct net_device *dev);
 static void xl_set_rx_mode(struct net_device *dev);
-static void xl_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats * xl_get_stats(struct net_device *dev);
 static int xl_set_mac_address(struct net_device *dev, void *addr) ; 
 static void xl_arb_cmd(struct net_device *dev);
@@ -1027,7 +1027,7 @@
 	return  ; 
 }
 
-static void xl_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
 	struct net_device *dev = (struct net_device *)dev_id;
  	struct xl_private *xl_priv =(struct xl_private *)dev->priv;
@@ -1036,13 +1036,13 @@
 
 	if (!dev) { 
 		printk(KERN_WARNING "Device structure dead, aaahhhh !\n") ;
-		return ; 
+		return IRQ_NONE; 
 	}
 
 	intstatus = readw(xl_mmio + MMIO_INTSTATUS) ;  
 
 	if (!(intstatus & 1)) /* We didn't generate the interrupt */
-		return ; 
+		return IRQ_NONE;
 
 	spin_lock(&xl_priv->xl_lock) ; 
 
@@ -1074,7 +1074,7 @@
 				xl_reset(dev) ; 
 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
 				spin_unlock(&xl_priv->xl_lock) ; 
-				return ; 
+				return IRQ_HANDLED;
 			} /* Host Error */
 
 			if (intstatus & SRBRINT ) {  /* Srbc interrupt */
@@ -1134,7 +1134,7 @@
 				xl_reset(dev) ; 
 				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
 				spin_unlock(&xl_priv->xl_lock) ; 
-				return ; 
+				return IRQ_HANDLED;
 			}
 		} else { 
 			printk(KERN_WARNING "%s: Received Unknown interrupt : %04x \n", dev->name, intstatus) ;
@@ -1147,7 +1147,8 @@
 	writel( SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
 	writel( SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
 
-	spin_unlock(&xl_priv->xl_lock) ; 
+	spin_unlock(&xl_priv->xl_lock) ;
+	return IRQ_HANDLED;
 }	
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/tokenring/ibmtr.c linux-2.5.68-bk9/drivers/net/tokenring/ibmtr.c
--- linux-2.5.68-bk8/drivers/net/tokenring/ibmtr.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tokenring/ibmtr.c	2003-04-29 04:37:08.000000000 -0700
@@ -198,7 +198,7 @@
 static void 	tok_set_multicast_list(struct net_device *dev);
 static int 	tok_send_packet(struct sk_buff *skb, struct net_device *dev);
 static int 	tok_close(struct net_device *dev);
-void 		tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void 	initial_tok_int(struct net_device *dev);
 static void 	tr_tx(struct net_device *dev);
 static void 	tr_rx(struct net_device *dev);
@@ -1166,7 +1166,7 @@
 
 /******************************************************************************/
 
-void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned char status;
 	/*  unsigned char status_even ; */
@@ -1182,7 +1182,7 @@
 #endif
 	ti = (struct tok_info *) dev->priv;
 	if (ti->sram_virt & 1)
-		return;         /* PCMCIA card extraction flag */
+		return IRQ_NONE;         /* PCMCIA card extraction flag */
 	spin_lock(&(ti->lock));
 #ifdef ENABLE_PAGING
 	save_srpr = readb(ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
@@ -1202,7 +1202,7 @@
                 writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
 #endif
                 spin_unlock(&(ti->lock));
-                return;
+                return IRQ_HANDLED;
         }
 	/*  Begin interrupt handler HERE inline to avoid the extra
 	    levels of logic and call depth for the original solution. */
@@ -1241,7 +1241,7 @@
 		outb(0, dev->base_addr + ADAPTRESET);
 		ibmtr_reset_timer(&(ti->tr_timer), dev);/*BMS try to reopen*/
 		spin_unlock(&(ti->lock));
-		return;
+		return IRQ_HANDLED;
 	}
 	if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)
 		& (TCR_INT | ERR_INT | ACCESS_INT)) {
@@ -1256,7 +1256,7 @@
                 writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
 #endif
                 spin_unlock(&(ti->lock));
-                return;
+                return IRQ_HANDLED;
         }
 	if (status & SRB_RESP_INT) {	/* SRB response */
 		SET_PAGE(ti->srb_page);
@@ -1487,6 +1487,7 @@
 #endif
 	writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
 	spin_unlock(&(ti->lock));
+	return IRQ_HANDLED;
 }				/*tok_interrupt */
 
 /*****************************************************************************/
diff -urN linux-2.5.68-bk8/drivers/net/tokenring/madgemc.c linux-2.5.68-bk9/drivers/net/tokenring/madgemc.c
--- linux-2.5.68-bk8/drivers/net/tokenring/madgemc.c	2003-04-19 19:51:10.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tokenring/madgemc.c	2003-04-29 04:37:08.000000000 -0700
@@ -77,7 +77,7 @@
 static void madgemc_setsifsel(struct net_device *dev, int val);
 static void madgemc_setint(struct net_device *dev, int val);
 
-static void madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 /*
  * These work around paging, however they don't guarentee you're on the
@@ -457,14 +457,14 @@
  * exhausted all contiguous interrupts.
  *
  */
-static void madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int pending,reg1;
 	struct net_device *dev;
 
 	if (!dev_id) {
 		printk("madgemc_interrupt: was not passed a dev_id!\n");
-		return;
+		return IRQ_NONE;
 	}
 
 	dev = (struct net_device *)dev_id;
@@ -472,7 +472,7 @@
 	/* Make sure its really us. -- the Madge way */
 	pending = inb(dev->base_addr + MC_CONTROL_REG0);
 	if (!(pending & MC_CONTROL_REG0_SINTR))
-		return; /* not our interrupt */
+		return IRQ_NONE; /* not our interrupt */
 
 	/*
 	 * Since we're level-triggered, we may miss the rising edge
@@ -496,10 +496,10 @@
 			pending = SIFREADW(SIFSTS); /* restart - the SIF way */
 
 		} else
-			return; 
+			return IRQ_HANDLED; 
 	} while (1);
 
-	return; /* not reachable */
+	return IRQ_HANDLED; /* not reachable */
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/tokenring/olympic.c linux-2.5.68-bk9/drivers/net/tokenring/olympic.c
--- linux-2.5.68-bk8/drivers/net/tokenring/olympic.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tokenring/olympic.c	2003-04-29 04:37:08.000000000 -0700
@@ -185,7 +185,7 @@
 static int olympic_close(struct net_device *dev);
 static void olympic_set_rx_mode(struct net_device *dev);
 static void olympic_freemem(struct net_device *dev) ;  
-static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static struct net_device_stats * olympic_get_stats(struct net_device *dev);
 static int olympic_set_mac_address(struct net_device *dev, void *addr) ; 
 static void olympic_arb_cmd(struct net_device *dev);
@@ -910,7 +910,7 @@
 	return ; 
 }
  
-static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
 	struct net_device *dev= (struct net_device *)dev_id;
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
@@ -925,7 +925,7 @@
 	 */ 
 	sisr=readl(olympic_mmio+SISR) ; 
 	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
-		return ;
+		return IRQ_NONE;
 	sisr=readl(olympic_mmio+SISR_RR) ;  /* Read & Reset sisr */ 
 
 	spin_lock(&olympic_priv->olympic_lock);
@@ -937,7 +937,7 @@
 		free_irq(dev->irq, dev) ;
 		dev->stop = NULL ;  
 		spin_unlock(&olympic_priv->olympic_lock) ; 
-		return ;
+		return IRQ_NONE;
 	} 
 		
 	if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK |  
@@ -954,7 +954,7 @@
 			free_irq(dev->irq, dev) ;
 			dev->stop = NULL ;  
 			spin_unlock(&olympic_priv->olympic_lock) ; 
-			return ;
+			return IRQ_HANDLED;
 		} /* SISR_ERR */
 
 		if(sisr & SISR_SRB_REPLY) {
@@ -999,7 +999,7 @@
 			free_irq(dev->irq, dev) ;
 			dev->stop = NULL ;  
 			spin_unlock(&olympic_priv->olympic_lock) ; 
-			return ; 
+			return IRQ_HANDLED; 
 		} /* SISR_ADAPTER_CHECK */
 	
 		if (sisr & SISR_ASB_FREE) {
@@ -1032,6 +1032,7 @@
 	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
 	
 	spin_unlock(&olympic_priv->olympic_lock) ; 
+	return IRQ_HANDLED;
 }	
 
 static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
diff -urN linux-2.5.68-bk8/drivers/net/tokenring/smctr.c linux-2.5.68-bk9/drivers/net/tokenring/smctr.c
--- linux-2.5.68-bk8/drivers/net/tokenring/smctr.c	2003-04-19 19:49:30.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/tokenring/smctr.c	2003-04-29 04:37:08.000000000 -0700
@@ -151,7 +151,7 @@
 static int smctr_init_tx_bdbs(struct net_device *dev);
 static int smctr_init_tx_fcbs(struct net_device *dev);
 static int smctr_internal_self_test(struct net_device *dev);
-static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int smctr_issue_enable_int_cmd(struct net_device *dev,
         __u16 interrupt_enable_mask);
 static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
@@ -2002,7 +2002,7 @@
 /*
  * The typical workload of the driver: Handle the network interface interrupts.
  */
-static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         struct net_device *dev = dev_id;
         struct net_local *tp;
@@ -2015,7 +2015,7 @@
         if(dev == NULL)
         {
                 printk(KERN_CRIT "%s: irq %d for unknown device.\n", dev->name, irq);
-                return;
+                return IRQ_NONE;
         }
 
         ioaddr = dev->base_addr;
@@ -2023,7 +2023,7 @@
         
 
         if(tp->status == NOT_INITIALIZED)
-                return;
+                return IRQ_NONE;
 
         spin_lock(&tp->lock);
         
@@ -2047,7 +2047,7 @@
                 {
                         smctr_disable_16bit(dev);
 		        spin_unlock(&tp->lock);
-                        return;
+                        return IRQ_HANDLED;
                 }
 
                 err = HARDWARE_FAILED;
@@ -2486,7 +2486,7 @@
         smctr_enable_bic_int(dev);
         spin_unlock(&tp->lock);
 
-        return;
+        return IRQ_HANDLED;
 }
 
 static int smctr_issue_enable_int_cmd(struct net_device *dev,
diff -urN linux-2.5.68-bk8/drivers/net/wan/comx-hw-comx.c linux-2.5.68-bk9/drivers/net/wan/comx-hw-comx.c
--- linux-2.5.68-bk8/drivers/net/wan/comx-hw-comx.c	2003-04-19 19:48:51.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/comx-hw-comx.c	2003-04-29 04:37:08.000000000 -0700
@@ -96,7 +96,7 @@
 extern struct comx_hardware comx_hw;
 extern struct comx_hardware cmx_hw;
 
-static void COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 static void COMX_board_on(struct net_device *dev)
 {
@@ -335,7 +335,7 @@
 
 
 
-static void COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct comx_channel *ch = dev->priv;
@@ -348,7 +348,7 @@
 
 	if (dev == NULL) {
 		printk(KERN_ERR "COMX_interrupt: irq %d for unknown device\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	jiffs = jiffies;
@@ -445,6 +445,7 @@
 	}
 
 	ch->HW_release_board(dev, interrupted);
+	return IRQ_HANDLED;
 }
 
 static int COMX_open(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/wan/comx-hw-mixcom.c linux-2.5.68-bk9/drivers/net/wan/comx-hw-mixcom.c
--- linux-2.5.68-bk8/drivers/net/wan/comx-hw-mixcom.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/comx-hw-mixcom.c	2003-04-29 04:37:08.000000000 -0700
@@ -412,7 +412,7 @@
 }
 
 
-static void MIXCOM_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t MIXCOM_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long flags;
 	struct net_device *dev = (struct net_device *)dev_id;
@@ -422,7 +422,7 @@
 
 	if (dev==NULL) {
 		printk(KERN_ERR "comx_interrupt: irq %d for unknown device\n",irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	ch = dev->priv; 
@@ -480,7 +480,7 @@
 	}
 
 	restore_flags(flags);
-	return;
+	return IRQ_HANDLED;
 }
 
 static int MIXCOM_open(struct net_device *dev)
diff -urN linux-2.5.68-bk8/drivers/net/wan/comx-hw-munich.c linux-2.5.68-bk9/drivers/net/wan/comx-hw-munich.c
--- linux-2.5.68-bk8/drivers/net/wan/comx-hw-munich.c	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/comx-hw-munich.c	2003-04-29 04:37:08.000000000 -0700
@@ -1029,7 +1029,7 @@
  * Called by the Linux kernel.
  * BEWARE! The interrupts are enabled on the call!
  */
-static void MUNICH_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t MUNICH_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct sk_buff *skb;
     int length;
@@ -1386,7 +1386,7 @@
 	board->stat_pri_races_missed++;
     if (race_stat & STAT_PTI)
 	board->stat_pti_races_missed++;
-    return;
+    return IRQ_HANDLED;
 }
 
 /* 
diff -urN linux-2.5.68-bk8/drivers/net/wan/cosa.c linux-2.5.68-bk9/drivers/net/wan/cosa.c
--- linux-2.5.68-bk8/drivers/net/wan/cosa.c	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/cosa.c	2003-04-29 04:37:08.000000000 -0700
@@ -343,7 +343,7 @@
 static void put_driver_status_nolock(struct cosa_data *cosa);
 
 /* Interrupt handling */
-static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
+static irqreturn_t cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
 
 /* I/O ops debugging */
 #ifdef DEBUG_IO
@@ -1983,7 +1983,7 @@
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
 
-static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
+static irqreturn_t cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
 {
 	unsigned status;
 	int count = 0;
@@ -2023,6 +2023,7 @@
 	else
 		printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
 #endif
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/wan/cycx_main.c linux-2.5.68-bk9/drivers/net/wan/cycx_main.c
--- linux-2.5.68-bk8/drivers/net/wan/cycx_main.c	2003-04-19 19:49:28.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/cycx_main.c	2003-04-29 04:37:08.000000000 -0700
@@ -75,7 +75,7 @@
 static int ioctl (wan_device_t *wandev, unsigned cmd, unsigned long arg);
 
 /* Miscellaneous functions */
-static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t cycx_isr (int irq, void *dev_id, struct pt_regs *regs);
 
 /* Global Data
  * Note: All data must be explicitly initialized!!!
@@ -316,7 +316,7 @@
  * o acknowledge Cyclom 2X hardware interrupt.
  * o call protocol-specific interrupt service routine, if any.
  */
-static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
 {
 	cycx_t *card = (cycx_t *)dev_id;
 
@@ -331,7 +331,8 @@
 
 	if (card->isr)
 		card->isr(card);
-out:	return;
+	return IRQ_HANDLED;
+out:	return IRQ_NONE;
 }
 
 /*
diff -urN linux-2.5.68-bk8/drivers/net/wan/dscc4.c linux-2.5.68-bk9/drivers/net/wan/dscc4.c
--- linux-2.5.68-bk8/drivers/net/wan/dscc4.c	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/dscc4.c	2003-04-29 04:37:08.000000000 -0700
@@ -337,7 +337,7 @@
 static void dscc4_release_ring(struct dscc4_dev_priv *);
 static void dscc4_timer(unsigned long);
 static void dscc4_tx_timeout(struct net_device *);
-static void dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
+static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
 static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
 static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
@@ -1315,14 +1315,14 @@
 	return ret;
 }
 
-static void dscc4_irq(int irq, void *token, struct pt_regs *ptregs)
+static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs)
 {
 	struct dscc4_dev_priv *root = token;
 	struct dscc4_pci_priv *priv;
 	struct net_device *dev;
 	u32 ioaddr, state;
 	unsigned long flags;
-	int i;
+	int i, handled = 1;
 
 	priv = root->pci_priv;
 	dev = hdlc_to_dev(&root->hdlc);
@@ -1332,8 +1332,10 @@
 	ioaddr = dev->base_addr;
 
 	state = readl(ioaddr + GSTAR);
-	if (!state)
+	if (!state) {
+		handled = 0;
 		goto out;
+	}
 	writel(state, ioaddr + GSTAR);
 
 	if (state & Arf) {
@@ -1366,6 +1368,7 @@
 	}
 out:
 	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_RETVAL(handled);
 }
 
 static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
diff -urN linux-2.5.68-bk8/drivers/net/wan/farsync.c linux-2.5.68-bk9/drivers/net/wan/farsync.c
--- linux-2.5.68-bk8/drivers/net/wan/farsync.c	2003-04-29 04:36:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/farsync.c	2003-04-29 04:37:08.000000000 -0700
@@ -614,7 +614,7 @@
 
 /*      Control signal change interrupt event
  */
-static void
+static irqreturn_t
 fst_intr_ctlchg ( struct fst_card_info *card, struct fst_port_info *port )
 {
         int signals;
@@ -637,6 +637,7 @@
                         netif_carrier_off ( port_to_dev ( port ));
                 }
         }
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/wan/pc300_drv.c linux-2.5.68-bk9/drivers/net/wan/pc300_drv.c
--- linux-2.5.68-bk8/drivers/net/wan/pc300_drv.c	2003-04-19 19:51:11.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/pc300_drv.c	2003-04-29 04:37:08.000000000 -0700
@@ -285,7 +285,7 @@
 static void rx_dma_buf_init(pc300_t *, int);
 static void tx_dma_buf_check(pc300_t *, int);
 static void rx_dma_buf_check(pc300_t *, int);
-static void cpc_intr(int, void *, struct pt_regs *);
+static irqreturn_t cpc_intr(int, void *, struct pt_regs *);
 static struct net_device_stats *cpc_get_stats(struct net_device *);
 static int clock_rate_calc(uclong, uclong, int *);
 static uclong detect_ram(pc300_t *);
@@ -2366,7 +2366,7 @@
 	}
 }
 
-static void cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	pc300_t *card;
 	volatile ucchar plx_status;
@@ -2375,14 +2375,14 @@
 #ifdef PC300_DEBUG_INTR
 		printk("cpc_intr: spurious intr %d\n", irq);
 #endif
-		return;		/* spurious intr */
+		return IRQ_NONE;		/* spurious intr */
 	}
 
 	if (card->hw.rambase == 0) {
 #ifdef PC300_DEBUG_INTR
 		printk("cpc_intr: spurious intr2 %d\n", irq);
 #endif
-		return;		/* spurious intr */
+		return IRQ_NONE;		/* spurious intr */
 	}
 
 	switch (card->hw.type) {
@@ -2403,6 +2403,7 @@
 			}
 			break;
 	}
+	return IRQ_HANDLED;
 }
 
 void cpc_sca_status(pc300_t * card, int ch)
diff -urN linux-2.5.68-bk8/drivers/net/wan/sbni.c linux-2.5.68-bk9/drivers/net/wan/sbni.c
--- linux-2.5.68-bk8/drivers/net/wan/sbni.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/sbni.c	2003-04-29 04:37:08.000000000 -0700
@@ -119,7 +119,7 @@
 static struct net_device_stats  *sbni_get_stats( struct net_device * );
 static void  set_multicast_list( struct net_device * );
 
-static void  sbni_interrupt( int, void *, struct pt_regs * );
+static irqreturn_t sbni_interrupt( int, void *, struct pt_regs * );
 static void  handle_channel( struct net_device * );
 static int   recv_frame( struct net_device * );
 static void  send_frame( struct net_device * );
@@ -469,7 +469,7 @@
  * this board to be "master".
  */ 
 
-static void
+static irqreturn_t
 sbni_interrupt( int  irq,  void  *dev_id,  struct pt_regs  *regs )
 {
 	struct net_device	  *dev = (struct net_device *) dev_id;
@@ -494,6 +494,7 @@
 	if( nl->second )
 		spin_unlock( &((struct net_local *)nl->second->priv)->lock );
 	spin_unlock( &nl->lock );
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.68-bk8/drivers/net/wan/sdla.c linux-2.5.68-bk9/drivers/net/wan/sdla.c
--- linux-2.5.68-bk8/drivers/net/wan/sdla.c	2003-04-19 19:51:20.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/sdla.c	2003-04-29 04:37:08.000000000 -0700
@@ -856,7 +856,7 @@
 	restore_flags(flags);
 }
 
-static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device     *dev;
 	struct frad_local *flp;
@@ -867,7 +867,7 @@
 	if (dev == NULL)
 	{
 		printk(KERN_WARNING "sdla_isr(): irq %d for unknown device.\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	flp = dev->priv;
@@ -875,7 +875,7 @@
 	if (!flp->initialized)
 	{
 		printk(KERN_WARNING "%s: irq %d for uninitialized device.\n", dev->name, irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);
@@ -910,6 +910,7 @@
 	/* this clears the byte, informing the Z80 we're done */
 	byte = 0;
 	sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
+	return IRQ_HANDLED;
 }
 
 static void sdla_poll(unsigned long device)
diff -urN linux-2.5.68-bk8/drivers/net/wan/sdlamain.c linux-2.5.68-bk9/drivers/net/wan/sdlamain.c
--- linux-2.5.68-bk8/drivers/net/wan/sdlamain.c	2003-04-19 19:50:32.000000000 -0700
+++ linux-2.5.68-bk9/drivers/net/wan/sdlamain.c	2003-04-29 04:37:08.000000000 -0700
@@ -193,7 +193,7 @@
 static int ioctl_exec	(sdla_t* card, sdla_exec_t* u_exec, int);
 
 /* Miscellaneous functions */
-STATIC void sdla_isr	(int irq, void* dev_id, struct pt_regs *regs);
+STATIC irqreturn_t sdla_isr	(int irq, void* dev_id, struct pt_regs *regs);
 static void release_hw  (sdla_t *card);
 static void run_wanpipe_tq (unsigned long);
 
@@ -1034,9 +1034,10 @@
  * o acknowledge SDLA hardware interrupt.
  * o call protocol-specific interrupt service routine, if any.
  */
-STATIC void sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
+STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
 {
 #define	card	((sdla_t*)dev_id)
+	int handled = 0;
 
 	if(card->hw.type == SDLA_S514) {	/* handle interrrupt on S514 */
                 u32 int_status;
@@ -1051,7 +1052,7 @@
 			/* check if the interrupt is for this device */
  			if(!((unsigned char)int_status &
 				(IRQ_CPU_A | IRQ_CPU_B)))
-                	        return;
+                	        return IRQ_HANDLED;
 
 			/* if the IRQ is for both CPUs on the same adapter, */
 			/* then alter the interrupt status so as to handle */
@@ -1083,7 +1084,7 @@
 			/* exit if the interrupt is for another CPU on the */
 			/* same IRQ */
 			if(!card_found_for_IRQ)
-				return;
+				return IRQ_HANDLED;
 
        	 		if (!card || 
 			   (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){
@@ -1093,7 +1094,7 @@
 					printk(KERN_INFO
 						"IRQ for unconfigured adapter\n");
 					S514_intack(&card->hw, int_status);
-					return;
+					return IRQ_HANDLED;
        			}
 
 	        	if (card->in_isr) {
@@ -1101,7 +1102,7 @@
 					"%s: interrupt re-entrancy on IRQ %d\n",
                        			card->devname, card->wandev.irq);
 				S514_intack(&card->hw, int_status);
- 				return;
+ 				return IRQ_HANDLED;
        			}
 
 			spin_lock(&card->wandev.lock);
@@ -1121,20 +1122,20 @@
 			/* handle a maximum of two interrupts (one for each */
 			/* CPU on the adapter) before returning */  
 			if((++ IRQ_count) == 2)
-				return;
+				return IRQ_HANDLED;
 		}
 	}
 
 	else {			/* handle interrupt on S508 adapter */
 
 		if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))
-			return;
+			return IRQ_HANDLED;
 
 		if (card->in_isr) {
 			printk(KERN_INFO
 				"%s: interrupt re-entrancy on IRQ %d!\n",
 				card->devname, card->wandev.irq);
-			return;
+			return IRQ_HANDLED;
 		}
 
 		spin_lock(&card->wandev.lock);
@@ -1152,7 +1153,7 @@
 		spin_unlock(&card->wandev.lock);
 
 	}
-                
+        return IRQ_HANDLED;
 #undef	card
 }
 
diff -urN linux-2.5.68-bk8/drivers/pci/pci.ids linux-2.5.68-bk9/drivers/pci/pci.ids
--- linux-2.5.68-bk8/drivers/pci/pci.ids	2003-04-19 19:49:51.000000000 -0700
+++ linux-2.5.68-bk9/drivers/pci/pci.ids	2003-04-29 04:37:08.000000000 -0700
@@ -6207,6 +6207,9 @@
 	103e  82801BD PRO/100 VM (MOB) Ethernet Controller
 	1040  536EP Data Fax Modem
 		16be 1040  V.9X DSP Data Fax Modem
+	1048  82597EX 10GbE Ethernet Controller
+		8086 a01f  PRO/10GbE LR Server Adapter
+		8086 a11f  PRO/10GbE LR Server Adapter
 	1059  82551QM Ethernet Controller
 	1130  82815 815 Chipset Host Bridge and Memory Controller Hub
 		1025 1016  Travelmate 612 TX
diff -urN linux-2.5.68-bk8/drivers/usb/core/inode.c linux-2.5.68-bk9/drivers/usb/core/inode.c
--- linux-2.5.68-bk8/drivers/usb/core/inode.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/drivers/usb/core/inode.c	2003-04-29 04:37:10.000000000 -0700
@@ -45,7 +45,6 @@
 static struct inode_operations usbfs_dir_inode_operations;
 static struct vfsmount *usbdevfs_mount;
 static struct vfsmount *usbfs_mount;
-static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
 static int usbdevfs_mount_count;	/* = 0 */
 static int usbfs_mount_count;	/* = 0 */
 
@@ -514,69 +513,20 @@
 };
 
 /* --------------------------------------------------------------------- */
-static int get_mount (struct file_system_type *fs_type, struct vfsmount **mount, int *mount_count)
-{
-	struct vfsmount *mnt;
-
-	spin_lock (&mount_lock);
-	if (*mount) {
-		mntget(*mount);
-		++(*mount_count);
-		spin_unlock (&mount_lock);
-		goto go_ahead;
-	}
-
-	spin_unlock (&mount_lock);
-	mnt = kern_mount (fs_type);
-	if (IS_ERR(mnt)) {
-		err ("could not mount the fs...erroring out!\n");
-		return -ENODEV;
-	}
-	spin_lock (&mount_lock);
-	if (!*mount) {
-		*mount = mnt;
-		++(*mount_count);
-		spin_unlock (&mount_lock);
-		goto go_ahead;
-	}
-	mntget(*mount);
-	++(*mount_count);
-	spin_unlock (&mount_lock);
-	mntput(mnt);
-
-go_ahead:
-	dbg("mount_count = %d", *mount_count);
-	return 0;
-}
-
-static void put_mount (struct vfsmount **mount, int *mount_count)
-{
-	struct vfsmount *mnt;
-
-	spin_lock (&mount_lock);
-	mnt = *mount;
-	--(*mount_count);
-	if (!(*mount_count))
-		*mount = NULL;
-
-	spin_unlock (&mount_lock);
-	mntput(mnt);
-	dbg("mount_count = %d", *mount_count);
-}
 
 static int create_special_files (void)
 {
 	struct dentry *parent;
-	int retval = 0;
+	int retval;
 
 	/* create the devices special file */
-	retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount, &usbdevfs_mount_count);
+	retval = simple_pin_fs("usbdevfs", &usbdevfs_mount, &usbdevfs_mount_count);
 	if (retval) {
 		err ("Unable to get usbdevfs mount");
 		goto exit;
 	}
 
-	retval = get_mount (&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
+	retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count);
 	if (retval) {
 		err ("Unable to get usbfs mount");
 		goto error_clean_usbdevfs_mount;
@@ -611,10 +561,10 @@
 	devices_usbfs_dentry = NULL;
 
 error_clean_mounts:
-	put_mount (&usbfs_mount, &usbfs_mount_count);
+	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
 
 error_clean_usbdevfs_mount:
-	put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
+	simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
 
 exit:
 	return retval;
@@ -628,8 +578,8 @@
 		fs_remove_file (devices_usbfs_dentry);
 	devices_usbdevfs_dentry = NULL;
 	devices_usbfs_dentry = NULL;
-	put_mount (&usbdevfs_mount, &usbdevfs_mount_count);
-	put_mount (&usbfs_mount, &usbfs_mount_count);
+	simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count);
+	simple_release_fs(&usbfs_mount, &usbfs_mount_count);
 }
 
 void usbfs_update_special (void)
diff -urN linux-2.5.68-bk8/drivers/video/cyber2000fb.c linux-2.5.68-bk9/drivers/video/cyber2000fb.c
--- linux-2.5.68-bk8/drivers/video/cyber2000fb.c	2003-04-29 04:36:53.000000000 -0700
+++ linux-2.5.68-bk9/drivers/video/cyber2000fb.c	2003-04-29 04:37:10.000000000 -0700
@@ -55,6 +55,10 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#ifdef __arm__
+#include <asm/mach-types.h>
+#endif
+
 #include "cyber2000fb.h"
 
 struct cfb_info {
diff -urN linux-2.5.68-bk8/fs/binfmt_misc.c linux-2.5.68-bk9/fs/binfmt_misc.c
--- linux-2.5.68-bk8/fs/binfmt_misc.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/fs/binfmt_misc.c	2003-04-29 04:37:10.000000000 -0700
@@ -53,7 +53,7 @@
 
 static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
 static struct vfsmount *bm_mnt;
-static int entry_count = 0;
+static int entry_count;
 
 /* 
  * Check if we support the binfmt
@@ -399,19 +399,7 @@
 
 static void bm_clear_inode(struct inode *inode)
 {
-	Node *e = inode->u.generic_ip;
-
-	if (e) {
-		struct vfsmount *mnt;
-		write_lock(&entries_lock);
-		list_del(&e->list);
-		mnt = bm_mnt;
-		if (!--entry_count)
-			bm_mnt = NULL;
-		write_unlock(&entries_lock);
-		kfree(e);
-		mntput(mnt);
-	}
+	kfree(inode->u.generic_ip);
 }
 
 static void kill_node(Node *e)
@@ -430,6 +418,7 @@
 		dentry->d_inode->i_nlink--;
 		d_drop(dentry);
 		dput(dentry);
+		simple_release_fs(&bm_mnt, &entry_count);
 	}
 }
 
@@ -498,8 +487,6 @@
 	.write		= bm_entry_write,
 };
 
-static struct file_system_type bm_fs_type;
-
 /* /register */
 
 static ssize_t bm_register_write(struct file *file, const char *buffer,
@@ -507,7 +494,6 @@
 {
 	Node *e;
 	struct inode *inode;
-	struct vfsmount *mnt = NULL;
 	struct dentry *root, *dentry;
 	struct super_block *sb = file->f_vfsmnt->mnt_sb;
 	int err = 0;
@@ -534,32 +520,22 @@
 	if (!inode)
 		goto out2;
 
-	write_lock(&entries_lock);
-	if (!bm_mnt) {
-		write_unlock(&entries_lock);
-		mnt = kern_mount(&bm_fs_type);
-		if (IS_ERR(mnt)) {
-			err = PTR_ERR(mnt);
-			iput(inode);
-			inode = NULL;
-			goto out2;
-		}
-		write_lock(&entries_lock);
-		if (!bm_mnt)
-			bm_mnt = mnt;
+	err = simple_pin_fs("binfmt_misc", &bm_mnt, &entry_count);
+	if (err) {
+		iput(inode);
+		inode = NULL;
+		goto out2;
 	}
-	mntget(bm_mnt);
-	entry_count++;
 
 	e->dentry = dget(dentry);
 	inode->u.generic_ip = e;
 	inode->i_fop = &bm_entry_operations;
-	d_instantiate(dentry, inode);
 
+	write_lock(&entries_lock);
+	d_instantiate(dentry, inode);
 	list_add(&e->list, &entries);
 	write_unlock(&entries_lock);
 
-	mntput(mnt);
 	err = 0;
 out2:
 	dput(dentry);
@@ -630,64 +606,20 @@
 
 static struct super_operations s_ops = {
 	.statfs		= simple_statfs,
-	.drop_inode	= generic_delete_inode,
 	.clear_inode	= bm_clear_inode,
 };
 
 static int bm_fill_super(struct super_block * sb, void * data, int silent)
 {
-	struct qstr names[2] = {{.name = "status"}, {.name = "register"}};
-	struct inode * inode;
-	struct dentry * dentry[3];
-	int i;
-
-	for (i=0; i<sizeof(names)/sizeof(names[0]); i++) {
-		names[i].len = strlen(names[i].name);
-		names[i].hash = full_name_hash(names[i].name, names[i].len);
-	}
-
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = 0x42494e4d;
-	sb->s_op = &s_ops;
-
-	inode = bm_get_inode(sb, S_IFDIR | 0755);
-	if (!inode)
-		return -ENOMEM;
-	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
-	dentry[0] = d_alloc_root(inode);
-	if (!dentry[0]) {
-		iput(inode);
-		return -ENOMEM;
-	}
-	dentry[1] = d_alloc(dentry[0], &names[0]);
-	if (!dentry[1])
-		goto out1;
-	dentry[2] = d_alloc(dentry[0], &names[1]);
-	if (!dentry[2])
-		goto out2;
-	inode = bm_get_inode(sb, S_IFREG | 0644);
-	if (!inode)
-		goto out3;
-	inode->i_fop = &bm_status_operations;
-	d_add(dentry[1], inode);
-	inode = bm_get_inode(sb, S_IFREG | 0400);
-	if (!inode)
-		goto out3;
-	inode->i_fop = &bm_register_operations;
-	d_add(dentry[2], inode);
-
-	sb->s_root = dentry[0];
-	return 0;
-
-out3:
-	dput(dentry[2]);
-out2:
-	dput(dentry[1]);
-out1:
-	dput(dentry[0]);
-	return -ENOMEM;
+	static struct tree_descr bm_files[] = {
+		[1] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
+		[2] = {"register", &bm_register_operations, S_IWUSR},
+		/* last one */ {""}
+	};
+	int err = simple_fill_super(sb, 0x42494e4d, bm_files);
+	if (!err)
+		sb->s_op = &s_ops;
+	return err;
 }
 
 static struct super_block *bm_get_sb(struct file_system_type *fs_type,
diff -urN linux-2.5.68-bk8/fs/block_dev.c linux-2.5.68-bk9/fs/block_dev.c
--- linux-2.5.68-bk8/fs/block_dev.c	2003-04-29 04:36:53.000000000 -0700
+++ linux-2.5.68-bk9/fs/block_dev.c	2003-04-29 04:37:10.000000000 -0700
@@ -437,6 +437,23 @@
 }
 
 /*
+ * Tries to open block device by device number.  Use it ONLY if you
+ * really do not have anything better - i.e. when you are behind a
+ * truly sucky interface and all you are given is a device number.  _Never_
+ * to be used for internal purposes.  If you ever need it - reconsider
+ * your API.
+ */
+struct block_device *open_by_devnum(dev_t dev, unsigned mode, int kind)
+{
+	struct block_device *bdev = bdget(dev);
+	int err = -ENOMEM;
+	int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY;
+	if (bdev)
+		err = blkdev_get(bdev, mode, flags, kind);
+	return err ? ERR_PTR(err) : bdev;
+}
+
+/*
  * This routine checks whether a removable media has been changed,
  * and invalidates all buffer-cache-entries in that case. This
  * is a relatively slow routine, so we have to try to minimize using
@@ -518,7 +535,7 @@
 		} else {
 			struct hd_struct *p;
 			struct block_device *whole;
-			whole = bdget(MKDEV(disk->major, disk->first_minor));
+			whole = bdget_disk(disk, 0);
 			ret = -ENOMEM;
 			if (!whole)
 				goto out_first;
diff -urN linux-2.5.68-bk8/fs/ext3/super.c linux-2.5.68-bk9/fs/ext3/super.c
--- linux-2.5.68-bk8/fs/ext3/super.c	2003-04-19 19:50:47.000000000 -0700
+++ linux-2.5.68-bk9/fs/ext3/super.c	2003-04-29 04:37:10.000000000 -0700
@@ -384,20 +384,16 @@
 static struct block_device *ext3_blkdev_get(dev_t dev)
 {
 	struct block_device *bdev;
-	int err = -ENODEV;
 	char b[BDEVNAME_SIZE];
 
-	bdev = bdget(dev);
-	if (bdev == NULL)
-		goto fail;
-	err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
-	if (err < 0)
+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE, BDEV_FS);
+	if (IS_ERR(bdev))
 		goto fail;
 	return bdev;
 
 fail:
-	printk(KERN_ERR "EXT3: failed to open journal device %s: %d\n",
-			__bdevname(dev, b), err);
+	printk(KERN_ERR "EXT3: failed to open journal device %s: %ld\n",
+			__bdevname(dev, b), PTR_ERR(bdev));
 	return NULL;
 }
 
diff -urN linux-2.5.68-bk8/fs/inode.c linux-2.5.68-bk9/fs/inode.c
--- linux-2.5.68-bk8/fs/inode.c	2003-04-29 04:36:53.000000000 -0700
+++ linux-2.5.68-bk9/fs/inode.c	2003-04-29 04:37:10.000000000 -0700
@@ -365,16 +365,6 @@
 	return res;
 }
 
-int invalidate_device(kdev_t dev, int do_sync)
-{
-	int res = 0;
-	struct block_device *bdev = bdget(kdev_t_to_nr(dev));
-	if (bdev)
-		res = __invalidate_device(bdev, do_sync);
-	bdput(bdev);
-	return res;
-}
-
 static int can_unuse(struct inode *inode)
 {
 	if (inode->i_state)
diff -urN linux-2.5.68-bk8/fs/jfs/jfs_logmgr.c linux-2.5.68-bk9/fs/jfs/jfs_logmgr.c
--- linux-2.5.68-bk8/fs/jfs/jfs_logmgr.c	2003-04-19 19:49:32.000000000 -0700
+++ linux-2.5.68-bk9/fs/jfs/jfs_logmgr.c	2003-04-29 04:37:11.000000000 -0700
@@ -1105,13 +1105,10 @@
 	 */
       externalLog:
 
-	if (!(bdev = bdget(JFS_SBI(sb)->logdev))) {
-		rc = ENODEV;
-		goto free;
-	}
-
-	if ((rc = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS))) {
-		rc = -rc;
+	bdev = open_by_devnum(JFS_SBI(sb)->logdev,
+					FMODE_READ|FMODE_WRITE, BDEV_FS);
+	if (IS_ERR(bdev)) {
+		rc = -PTR_ERR(bdev);
 		goto free;
 	}
 
diff -urN linux-2.5.68-bk8/fs/libfs.c linux-2.5.68-bk9/fs/libfs.c
--- linux-2.5.68-bk8/fs/libfs.c	2003-04-19 19:48:48.000000000 -0700
+++ linux-2.5.68-bk9/fs/libfs.c	2003-04-29 04:37:11.000000000 -0700
@@ -4,8 +4,11 @@
  */
 
 #include <linux/pagemap.h>
+#include <linux/mount.h>
 #include <linux/vfs.h>
 
+extern struct vfsmount *do_kern_mount(const char *, int, char *, void *);
+
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		   struct kstat *stat)
 {
@@ -332,3 +335,94 @@
 	set_page_dirty(page);
 	return 0;
 }
+
+int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+{
+	static struct super_operations s_ops = {statfs:simple_statfs};
+	struct inode *inode;
+	struct dentry *root;
+	struct dentry *dentry;
+	int i;
+
+	s->s_blocksize = PAGE_CACHE_SIZE;
+	s->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	s->s_magic = magic;
+	s->s_op = &s_ops;
+
+	inode = new_inode(s);
+	if (!inode)
+		return -ENOMEM;
+	inode->i_mode = S_IFDIR | 0755;
+	inode->i_uid = inode->i_gid = 0;
+	inode->i_blksize = PAGE_CACHE_SIZE;
+	inode->i_blocks = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_op = &simple_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+	root = d_alloc_root(inode);
+	if (!root) {
+		iput(inode);
+		return -ENOMEM;
+	}
+	for (i = 0; !files->name || files->name[0]; i++, files++) {
+		struct qstr name;
+		if (!files->name)
+			continue;
+		name.name = files->name;
+		name.len = strlen(name.name);
+		name.hash = full_name_hash(name.name, name.len);
+		dentry = d_alloc(root, &name);
+		if (!dentry)
+			goto out;
+		inode = new_inode(s);
+		if (!inode)
+			goto out;
+		inode->i_mode = S_IFREG | files->mode;
+		inode->i_uid = inode->i_gid = 0;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_fop = files->ops;
+		inode->i_ino = i;
+		d_add(dentry, inode);
+	}
+	s->s_root = root;
+	return 0;
+out:
+	d_genocide(root);
+	dput(root);
+	return -ENOMEM;
+}
+
+static spinlock_t pin_fs_lock = SPIN_LOCK_UNLOCKED;
+
+int simple_pin_fs(char *name, struct vfsmount **mount, int *count)
+{
+	struct vfsmount *mnt = NULL;
+	spin_lock(&pin_fs_lock);
+	if (unlikely(!*mount)) {
+		spin_unlock(&pin_fs_lock);
+		mnt = do_kern_mount(name, 0, name, NULL);
+		if (IS_ERR(mnt))
+			return PTR_ERR(mnt);
+		spin_lock(&pin_fs_lock);
+		if (!*mount)
+			*mount = mnt;
+	}
+	mntget(*mount);
+	++*count;
+	spin_unlock(&pin_fs_lock);
+	mntput(mnt);
+	return 0;
+}
+
+void simple_release_fs(struct vfsmount **mount, int *count)
+{
+	struct vfsmount *mnt;
+	spin_lock(&pin_fs_lock);
+	mnt = *mount;
+	if (!--*count)
+		*mount = NULL;
+	spin_unlock(&pin_fs_lock);
+	mntput(mnt);
+}
diff -urN linux-2.5.68-bk8/fs/nfsd/nfsctl.c linux-2.5.68-bk9/fs/nfsd/nfsctl.c
--- linux-2.5.68-bk8/fs/nfsd/nfsctl.c	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/fs/nfsd/nfsctl.c	2003-04-29 04:37:11.000000000 -0700
@@ -48,7 +48,6 @@
 	NFSD_List,
 	NFSD_Fh,
 	NFSD_Threads,
-	NFSD_END
 };
 
 /*
@@ -204,22 +203,6 @@
 	.release	= exports_release,
 };
 
-/*
- *	Description of fs contents.
- */
-static struct { char *name; struct file_operations *ops; int mode; } files[] = {
-	[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
-	[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
-	[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
-	[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
-	[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
-	[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
-	[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
-	[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
-	[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
-	[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
-};
-
 /*----------------------------------------------------------------------------*/
 /*
  * payload - write methods
@@ -431,64 +414,22 @@
  *	populating the filesystem.
  */
 
-static struct super_operations s_ops = {
-	.statfs		= simple_statfs,
-};
-
 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 {
-	struct inode *inode;
-	struct dentry *root;
-	struct dentry *dentry;
-	int i;
-
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = 0x6e667364;
-	sb->s_op = &s_ops;
-
-	inode = new_inode(sb);
-	if (!inode)
-		return -ENOMEM;
-	inode->i_mode = S_IFDIR | 0755;
-	inode->i_uid = inode->i_gid = 0;
-	inode->i_blksize = PAGE_CACHE_SIZE;
-	inode->i_blocks = 0;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
-	root = d_alloc_root(inode);
-	if (!root) {
-		iput(inode);
-		return -ENOMEM;
-	}
-	for (i = NFSD_Svc; i < NFSD_END; i++) {
-		struct qstr name;
-		name.name = files[i].name;
-		name.len = strlen(name.name);
-		name.hash = full_name_hash(name.name, name.len);
-		dentry = d_alloc(root, &name);
-		if (!dentry)
-			goto out;
-		inode = new_inode(sb);
-		if (!inode)
-			goto out;
-		inode->i_mode = S_IFREG | files[i].mode;
-		inode->i_uid = inode->i_gid = 0;
-		inode->i_blksize = PAGE_CACHE_SIZE;
-		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		inode->i_fop = files[i].ops;
-		inode->i_ino = i;
-		d_add(dentry, inode);
-	}
-	sb->s_root = root;
-	return 0;
-
-out:
-	d_genocide(root);
-	dput(root);
-	return -ENOMEM;
+	static struct tree_descr nfsd_files[] = {
+		[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
+		[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
+		[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
+		[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
+		[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
+		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
+		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
+		[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
+		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+		/* last one */ {""}
+	};
+	return simple_fill_super(sb, 0x6e667364, nfsd_files);
 }
 
 static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
diff -urN linux-2.5.68-bk8/fs/partitions/check.c linux-2.5.68-bk9/fs/partitions/check.c
--- linux-2.5.68-bk8/fs/partitions/check.c	2003-04-29 04:36:53.000000000 -0700
+++ linux-2.5.68-bk9/fs/partitions/check.c	2003-04-29 04:37:11.000000000 -0700
@@ -311,7 +311,7 @@
 	if (!get_capacity(disk))
 		return;
 
-	bdev = bdget(MKDEV(disk->major, disk->first_minor));
+	bdev = bdget_disk(disk, 0);
 	if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
 		return;
 	state = check_partition(disk, bdev);
@@ -336,13 +336,12 @@
 
 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 {
-	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	struct parsed_partitions *state;
 	int p, res;
 
 	if (bdev->bd_part_count)
 		return -EBUSY;
-	res = invalidate_device(dev, 1);
+	res = invalidate_partition(disk, 0);
 	if (res)
 		return res;
 	bdev->bd_invalidated = 0;
@@ -391,18 +390,14 @@
 
 void del_gendisk(struct gendisk *disk)
 {
-	int max_p = disk->minors;
-	kdev_t devp;
 	int p;
 
 	/* invalidate stuff */
-	for (p = max_p - 1; p > 0; p--) {
-		devp = mk_kdev(disk->major,disk->first_minor + p);
-		invalidate_device(devp, 1);
+	for (p = disk->minors - 1; p > 0; p--) {
+		invalidate_partition(disk, p);
 		delete_partition(disk, p);
 	}
-	devp = mk_kdev(disk->major,disk->first_minor);
-	invalidate_device(devp, 1);
+	invalidate_partition(disk, 0);
 	disk->capacity = 0;
 	disk->flags &= ~GENHD_FL_UP;
 	unlink_gendisk(disk);
diff -urN linux-2.5.68-bk8/fs/reiserfs/journal.c linux-2.5.68-bk9/fs/reiserfs/journal.c
--- linux-2.5.68-bk8/fs/reiserfs/journal.c	2003-04-19 19:50:01.000000000 -0700
+++ linux-2.5.68-bk9/fs/reiserfs/journal.c	2003-04-29 04:37:11.000000000 -0700
@@ -1911,21 +1911,16 @@
 
 	/* there is no "jdev" option and journal is on separate device */
 	if( ( !jdev_name || !jdev_name[ 0 ] ) ) {
-		journal -> j_dev_bd = bdget(jdev);
-		if( journal -> j_dev_bd )
-			result = blkdev_get( journal -> j_dev_bd, 
-					     blkdev_mode, 0, 
-					     BDEV_FS );
-		else
-			result = -ENOMEM;
-		if( result != 0 )
+		journal->j_dev_bd = open_by_devnum(jdev, blkdev_mode, BDEV_FS);
+		if (IS_ERR(journal->j_dev_bd)) {
+			result = PTR_ERR(journal->j_dev_bd);
+			journal->j_dev_bd = NULL;
 			printk( "sh-458: journal_init_dev: cannot init journal device\n '%s': %i", 
-				bdevname(journal->j_dev_bd, b), result );
-
-		else if (jdev != super->s_dev) {
+				__bdevname(jdev, b), result );
+			return result;
+		} else if (jdev != super->s_dev)
 			set_blocksize(journal->j_dev_bd, super->s_blocksize);
-		}
-		return result;
+		return 0;
 	}
 
 	journal -> j_dev_file = filp_open( jdev_name, 0, 0 );
diff -urN linux-2.5.68-bk8/include/asm-arm/arch-iop3xx/iop310-irqs.h linux-2.5.68-bk9/include/asm-arm/arch-iop3xx/iop310-irqs.h
--- linux-2.5.68-bk8/include/asm-arm/arch-iop3xx/iop310-irqs.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.68-bk9/include/asm-arm/arch-iop3xx/iop310-irqs.h	2003-04-29 04:37:11.000000000 -0700
@@ -0,0 +1,80 @@
+/*
+ * linux/include/asm-arm/arch-iop310/irqs.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista 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.
+ *
+ * 06/13/01: Added 80310 on-chip interrupt sources <dsaxena@mvista.com>
+ *
+ */
+#include <linux/config.h>
+
+/*
+ * XS80200 specific IRQs
+ */
+#define IRQ_XS80200_BCU		0	/* Bus Control Unit */
+#define IRQ_XS80200_PMU		1	/* Performance Monitoring Unit */
+#define IRQ_XS80200_EXTIRQ	2	/* external IRQ signal */
+#define IRQ_XS80200_EXTFIQ	3	/* external IRQ signal */
+
+#define NR_XS80200_IRQS		4
+
+#define XSCALE_PMU_IRQ		IRQ_XS80200_PMU
+
+/*
+ * IOP80310 chipset interrupts
+ */
+#define IOP310_IRQ_OFS		NR_XS80200_IRQS
+#define IOP310_IRQ(x)		(IOP310_IRQ_OFS + (x))
+
+/*
+ * On FIQ1ISR register
+ */
+#define IRQ_IOP310_DMA0		IOP310_IRQ(0)	/* DMA Channel 0 */
+#define IRQ_IOP310_DMA1		IOP310_IRQ(1)	/* DMA Channel 1 */
+#define IRQ_IOP310_DMA2		IOP310_IRQ(2)	/* DMA Channel 2 */
+#define IRQ_IOP310_PMON		IOP310_IRQ(3)	/* Bus performance Unit */
+#define IRQ_IOP310_AAU		IOP310_IRQ(4)	/* Application Accelator Unit */
+
+/*
+ * On FIQ2ISR register
+ */
+#define IRQ_IOP310_I2C		IOP310_IRQ(5)	/* I2C unit */
+#define IRQ_IOP310_MU		IOP310_IRQ(6)	/* messaging unit */
+
+#define NR_IOP310_IRQS		(IOP310_IRQ(6) + 1)
+
+#define NR_IRQS			NR_IOP310_IRQS
+
+
+/*
+ * Interrupts available on the Cyclone IQ80310 board
+ */
+#ifdef CONFIG_ARCH_IQ80310
+
+#define IQ80310_IRQ_OFS		NR_IOP310_IRQS
+#define IQ80310_IRQ(y)		((IQ80310_IRQ_OFS) + (y))
+
+#define IRQ_IQ80310_TIMER	IQ80310_IRQ(0)	/* Timer Interrupt */
+#define IRQ_IQ80310_I82559	IQ80310_IRQ(1)	/* I82559 Ethernet Interrupt */
+#define IRQ_IQ80310_UART1	IQ80310_IRQ(2)	/* UART1 Interrupt */
+#define IRQ_IQ80310_UART2	IQ80310_IRQ(3)	/* UART2 Interrupt */
+#define IRQ_IQ80310_INTD	IQ80310_IRQ(4)	/* PCI INTD */
+
+
+/*
+ * ONLY AVAILABLE ON REV F OR NEWER BOARDS!
+ */
+#define	IRQ_IQ80310_INTA	IQ80310_IRQ(5)	/* PCI INTA */
+#define	IRQ_IQ80310_INTB	IQ80310_IRQ(6)	/* PCI INTB */
+#define	IRQ_IQ80310_INTC	IQ80310_IRQ(7)	/* PCI INTC */
+
+#undef	NR_IRQS
+#define NR_IRQS			(IQ80310_IRQ(7) + 1)
+
+#endif // CONFIG_ARCH_IQ80310
+
diff -urN linux-2.5.68-bk8/include/asm-arm/bugs.h linux-2.5.68-bk9/include/asm-arm/bugs.h
--- linux-2.5.68-bk8/include/asm-arm/bugs.h	2003-04-19 19:50:33.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/bugs.h	2003-04-29 04:37:11.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  *  linux/include/asm-arm/bugs.h
  *
- *  Copyright (C) 1995  Russell King
+ *  Copyright (C) 1995-2003 Russell King
  *
  * 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
@@ -12,6 +12,6 @@
 
 #include <asm/proc-fns.h>
 
-#define check_bugs() cpu_check_bugs()
+#define check_bugs() do { } while (0)
 
 #endif
diff -urN linux-2.5.68-bk8/include/asm-arm/cpu-multi26.h linux-2.5.68-bk9/include/asm-arm/cpu-multi26.h
--- linux-2.5.68-bk8/include/asm-arm/cpu-multi26.h	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/cpu-multi26.h	2003-04-29 04:37:11.000000000 -0700
@@ -19,14 +19,12 @@
  * relies on it.
  */
 extern struct processor {
-	/* check for any bugs */
-	void (*_check_bugs)(void);
 	/* Set up any processor specifics */
 	void (*_proc_init)(void);
 	/* Disable any processor specifics */
 	void (*_proc_fin)(void);
 	/* set the MEMC hardware mappings */
-	void (*_set_pgd)(pgd_t *pgd);
+	void (*_switch_mm)(pgd_t *pgd);
 	/* XCHG */
 	unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr);
 	unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr);
@@ -36,11 +34,10 @@
 extern const struct processor arm250_processor_functions;
 extern const struct processor arm3_processor_functions;
 
-#define cpu_check_bugs()			processor._check_bugs()
 #define cpu_proc_init()				processor._proc_init()
 #define cpu_proc_fin()				processor._proc_fin()
 #define cpu_do_idle()				do { } while (0)
-#define cpu_switch_mm(pgd,mm)			processor._set_pgd(pgd)
+#define cpu_switch_mm(pgd,mm)			processor._switch_mm(pgd)
 #define cpu_xchg_1(x,ptr)			processor._xchg_1(x,ptr)
 #define cpu_xchg_4(x,ptr)			processor._xchg_4(x,ptr)
 
diff -urN linux-2.5.68-bk8/include/asm-arm/cpu-multi32.h linux-2.5.68-bk9/include/asm-arm/cpu-multi32.h
--- linux-2.5.68-bk8/include/asm-arm/cpu-multi32.h	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/cpu-multi32.h	2003-04-29 04:37:11.000000000 -0700
@@ -24,10 +24,6 @@
 	 */
 	void (*_data_abort)(unsigned long pc);
 	/*
-	 * check for any bugs
-	 */
-	void (*_check_bugs)(void);
-	/*
 	 * Set up any processor specifics
 	 */
 	void (*_proc_init)(void);
@@ -46,96 +42,36 @@
 	/*
 	 * Processor architecture specific
 	 */
-	struct {	/* CACHE */
-		/*
-		 * flush all caches
-		 */
-		void (*clean_invalidate_all)(void);
-		/*
-		 * flush a specific page or pages
-		 */
-		void (*clean_invalidate_range)(unsigned long address, unsigned long end, int flags);
-	} cache;
-
-	struct {	/* D-cache */
-		/*
-		 * invalidate the specified data range
-		 */
-		void (*invalidate_range)(unsigned long start, unsigned long end);
-		/*
-		 * clean specified data range
-		 */
-		void (*clean_range)(unsigned long start, unsigned long end);
-		/*
-		 * obsolete flush cache entry
-		 */
-		void (*clean_page)(void *virt_page);
-		/*
-		 * clean a virtual address range from the
-		 * D-cache without flushing the cache.
-		 */
-		void (*clean_entry)(unsigned long start);
-	} dcache;
-
-	struct {	/* I-cache */
-		/*
-		 * invalidate the I-cache for the specified range
-		 */
-		void (*invalidate_range)(unsigned long start, unsigned long end);
-		/*
-		 * invalidate the I-cache for the specified virtual page
-		 */
-		void (*invalidate_page)(void *virt_page);
-	} icache;
+	/*
+	 * clean a virtual address range from the
+	 * D-cache without flushing the cache.
+	 */
+	void (*dcache_clean_area)(void *addr, int size);
 
-	struct {	/* PageTable */
-		/*
-		 * Set the page table
-		 */
-		void (*set_pgd)(unsigned long pgd_phys, struct mm_struct *mm);
-		/*
-		 * Set a PMD (handling IMP bit 4)
-		 */
-		void (*flush_pmd)(pmd_t *pmdp);
-		/*
-		 * Set a PTE
-		 */
-		void (*set_pte)(pte_t *ptep, pte_t pte);
-	} pgtable;
+	/*
+	 * Set the page table
+	 */
+	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
+	/*
+	 * Set a PTE
+	 */
+	void (*set_pte)(pte_t *ptep, pte_t pte);
 } processor;
 
-extern const struct processor arm6_processor_functions;
-extern const struct processor arm7_processor_functions;
-extern const struct processor sa110_processor_functions;
-
-#define cpu_check_bugs()			processor._check_bugs()
-#define cpu_proc_init()				processor._proc_init()
-#define cpu_proc_fin()				processor._proc_fin()
-#define cpu_reset(addr)				processor.reset(addr)
-#define cpu_do_idle()				processor._do_idle()
-
-#define cpu_cache_clean_invalidate_all()	processor.cache.clean_invalidate_all()
-#define cpu_cache_clean_invalidate_range(s,e,f)	processor.cache.clean_invalidate_range(s,e,f)
-
-#define cpu_dcache_clean_page(vp)		processor.dcache.clean_page(vp)
-#define cpu_dcache_clean_entry(addr)		processor.dcache.clean_entry(addr)
-#define cpu_dcache_clean_range(s,e)		processor.dcache.clean_range(s,e)
-#define cpu_dcache_invalidate_range(s,e)	processor.dcache.invalidate_range(s,e)
-
-#define cpu_icache_invalidate_range(s,e)	processor.icache.invalidate_range(s,e)
-#define cpu_icache_invalidate_page(vp)		processor.icache.invalidate_page(vp)
-
-#define cpu_set_pgd(pgd,mm)			processor.pgtable.set_pgd(pgd,mm)
-#define cpu_flush_pmd(pmdp)			processor.pgtable.flush_pmd(pmdp)
-#define cpu_set_pte(ptep, pte)			processor.pgtable.set_pte(ptep, pte)
+#define cpu_proc_init()			processor._proc_init()
+#define cpu_proc_fin()			processor._proc_fin()
+#define cpu_reset(addr)			processor.reset(addr)
+#define cpu_do_idle()			processor._do_idle()
+#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
+#define cpu_set_pte(ptep, pte)		processor.set_pte(ptep, pte)
 
-#define cpu_switch_mm(pgd,mm)			cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)),mm)
+#define cpu_switch_mm(pgd,mm)	processor.switch_mm(__virt_to_phys((unsigned long)(pgd)),mm)
 
 #define cpu_get_pgd()	\
 	({						\
 		unsigned long pg;			\
-		__asm__("mrc p15, 0, %0, c2, c0, 0"	\
-			 : "=r" (pg));			\
+		__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
+			 : "=r" (pg) : : "cc");		\
 		pg &= ~0x3fff;				\
 		(pgd_t *)phys_to_virt(pg);		\
 	})
diff -urN linux-2.5.68-bk8/include/asm-arm/cpu-single.h linux-2.5.68-bk9/include/asm-arm/cpu-single.h
--- linux-2.5.68-bk8/include/asm-arm/cpu-single.h	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/cpu-single.h	2003-04-29 04:37:11.000000000 -0700
@@ -22,21 +22,12 @@
  * function pointers for this lot.  Otherwise, we can optimise the
  * table away.
  */
-#define cpu_check_bugs			__cpu_fn(CPU_NAME,_check_bugs)
 #define cpu_proc_init			__cpu_fn(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__cpu_fn(CPU_NAME,_proc_fin)
 #define cpu_reset			__cpu_fn(CPU_NAME,_reset)
 #define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
-#define cpu_cache_clean_invalidate_all	__cpu_fn(CPU_NAME,_cache_clean_invalidate_all)
-#define cpu_cache_clean_invalidate_range __cpu_fn(CPU_NAME,_cache_clean_invalidate_range)
-#define cpu_dcache_invalidate_range	__cpu_fn(CPU_NAME,_dcache_invalidate_range)
-#define cpu_dcache_clean_range		__cpu_fn(CPU_NAME,_dcache_clean_range)
-#define cpu_dcache_clean_page		__cpu_fn(CPU_NAME,_dcache_clean_page)
-#define cpu_dcache_clean_entry		__cpu_fn(CPU_NAME,_dcache_clean_entry)
-#define cpu_icache_invalidate_range	__cpu_fn(CPU_NAME,_icache_invalidate_range)
-#define cpu_icache_invalidate_page	__cpu_fn(CPU_NAME,_icache_invalidate_page)
-#define cpu_set_pgd			__cpu_fn(CPU_NAME,_set_pgd)
-#define cpu_flush_pmd			__cpu_fn(CPU_NAME,_flush_pmd)
+#define cpu_dcache_clean_area		__cpu_fn(CPU_NAME,_dcache_clean_area)
+#define cpu__switch_mm			__cpu_fn(CPU_NAME,_switch_mm)
 #define cpu_set_pte			__cpu_fn(CPU_NAME,_set_pte)
 
 #ifndef __ASSEMBLY__
@@ -47,36 +38,22 @@
 struct mm_struct;
 
 /* declare all the functions as extern */
-extern void cpu_data_abort(unsigned long pc);
-extern void cpu_check_bugs(void);
 extern void cpu_proc_init(void);
 extern void cpu_proc_fin(void);
 extern int cpu_do_idle(void);
-
-extern void cpu_cache_clean_invalidate_all(void);
-extern void cpu_cache_clean_invalidate_range(unsigned long address, unsigned long end, int flags);
-
-extern void cpu_dcache_invalidate_range(unsigned long start, unsigned long end);
-extern void cpu_dcache_clean_range(unsigned long start, unsigned long end);
-extern void cpu_dcache_clean_page(void *virt_page);
-extern void cpu_dcache_clean_entry(unsigned long address);
-
-extern void cpu_icache_invalidate_range(unsigned long start, unsigned long end);
-extern void cpu_icache_invalidate_page(void *virt_page);
-
-extern void cpu_set_pgd(unsigned long pgd_phys, struct mm_struct *mm);
-extern void cpu_flush_pmd(pmd_t *pmdp);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu__switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte(pte_t *ptep, pte_t pte);
 
 extern volatile void cpu_reset(unsigned long addr);
 
-#define cpu_switch_mm(pgd,mm) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)),mm)
+#define cpu_switch_mm(pgd,mm) cpu__switch_mm(__virt_to_phys((unsigned long)(pgd)),mm)
 
 #define cpu_get_pgd()	\
 	({						\
 		unsigned long pg;			\
-		__asm__("mrc p15, 0, %0, c2, c0, 0"	\
-			 : "=r" (pg));			\
+		__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
+			 : "=r" (pg) : : "cc");		\
 		pg &= ~0x3fff;				\
 		(pgd_t *)phys_to_virt(pg);		\
 	})
diff -urN linux-2.5.68-bk8/include/asm-arm/elf.h linux-2.5.68-bk9/include/asm-arm/elf.h
--- linux-2.5.68-bk8/include/asm-arm/elf.h	2003-04-19 19:50:48.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/elf.h	2003-04-29 04:37:11.000000000 -0700
@@ -6,6 +6,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <asm/user.h>
 #include <asm/proc/elf.h>
 #include <asm/procinfo.h>
 
@@ -18,7 +19,7 @@
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
-typedef struct { void *null; } elf_fpregset_t;
+typedef struct user_fp elf_fpregset_t;
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
diff -urN linux-2.5.68-bk8/include/asm-arm/hardirq.h linux-2.5.68-bk9/include/asm-arm/hardirq.h
--- linux-2.5.68-bk8/include/asm-arm/hardirq.h	2003-04-19 19:50:01.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/hardirq.h	2003-04-29 04:37:11.000000000 -0700
@@ -77,11 +77,14 @@
 #endif
 
 #ifndef CONFIG_SMP
+/*
+ * Some compilers get the use of "%?" wrong in the asm below.
+ */
 #define irq_exit()							\
 	do {								\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
 		if (!in_interrupt() && softirq_pending(smp_processor_id())) \
-			__asm__("bl%? __do_softirq": : : "lr");/* out of line */\
+			__asm__("bl	__do_softirq": : : "lr", "cc");/* out of line */\
 		preempt_enable_no_resched();				\
 	} while (0)
 
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/cache.h linux-2.5.68-bk9/include/asm-arm/proc-armv/cache.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/cache.h	2003-04-19 19:49:25.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/cache.h	2003-04-29 04:37:11.000000000 -0700
@@ -11,64 +11,236 @@
 #include <asm/glue.h>
 
 /*
+ *	Cache Model
+ *	===========
+ */
+#undef _CACHE
+#undef MULTI_CACHE
+
+#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM720T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+    defined(CONFIG_CPU_ARM1020)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_ARM926T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm926
+# endif
+#endif
+
+#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4wb
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xscale
+# endif
+#endif
+
+#if !defined(_CACHE) && !defined(MULTI_CACHE)
+#error Unknown cache maintainence model
+#endif
+
+/*
  * This flag is used to indicate that the page pointed to by a pte
  * is dirty and requires cleaning before returning it to the user.
  */
 #define PG_dcache_dirty PG_arch_1
 
 /*
- * Cache handling for 32-bit ARM processors.
+ *	MM Cache Management
+ *	===================
+ *
+ *	The arch/arm/mm/cache-*.S and arch/arm/mm/proc-*.S files
+ *	implement these methods.
+ *
+ *	Start addresses are inclusive and end addresses are exclusive;
+ *	start addresses should be rounded down, end addresses up.
+ *
+ *	See linux/Documentation/cachetlb.txt for more information.
+ *	Please note that the implementation of these, and the required
+ *	effects are cache-type (VIVT/VIPT/PIPT) specific.
+ *
+ *	flush_cache_kern_all()
+ *
+ *		Unconditionally clean and invalidate the entire cache.
+ *
+ *	flush_cache_user_mm(mm)
+ *
+ *		Clean and invalidate all user space cache entries
+ *		before a change of page tables.
  *
- * Note that on ARM, we have a more accurate specification than that
- * Linux's "flush".  We therefore do not use "flush" here, but instead
- * use:
+ *	flush_cache_user_range(start, end, flags)
  *
- * clean:      the act of pushing dirty cache entries out to memory.
- * invalidate: the act of discarding data held within the cache,
- *             whether it is dirty or not.
+ *		Clean and invalidate a range of cache entries in the
+ *		specified address space before a change of page tables.
+ *		- start - user start address (inclusive, page aligned)
+ *		- end   - user end address   (exclusive, page aligned)
+ *		- flags - vma->vm_flags field
+ *
+ *	coherent_kern_range(start, end)
+ *
+ *		Ensure coherency between the Icache and the Dcache in the
+ *		region described by start, end.  If you have non-snooping
+ *		Harvard caches, you need to implement this function.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	DMA Cache Coherency
+ *	===================
+ *
+ *	dma_inv_range(start, end)
+ *
+ *		Invalidate (discard) the specified virtual address range.
+ *		May not write back any entries.  If 'start' or 'end'
+ *		are not cache line aligned, those lines must be written
+ *		back.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	dma_clean_range(start, end)
+ *
+ *		Clean (write back) the specified virtual address range.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	dma_flush_range(start, end)
+ *
+ *		Clean and invalidate the specified virtual address range.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
  */
 
+struct cpu_cache_fns {
+	void (*flush_kern_all)(void);
+	void (*flush_user_all)(void);
+	void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
+
+	void (*coherent_kern_range)(unsigned long, unsigned long);
+	void (*flush_kern_dcache_page)(void *);
+
+	void (*dma_inv_range)(unsigned long, unsigned long);
+	void (*dma_clean_range)(unsigned long, unsigned long);
+	void (*dma_flush_range)(unsigned long, unsigned long);
+};
+
 /*
- * Generic I + D cache
+ * Select the calling method
  */
-#define flush_cache_all()						\
-	do {								\
-		cpu_cache_clean_invalidate_all();			\
-	} while (0)
+#ifdef MULTI_CACHE
 
-/* This is always called for current->mm */
-#define flush_cache_mm(_mm)						\
-	do {								\
-		if ((_mm) == current->active_mm)			\
-			cpu_cache_clean_invalidate_all();		\
-	} while (0)
+extern struct cpu_cache_fns cpu_cache;
 
-#define flush_cache_range(_vma,_start,_end)				\
-	do {								\
-		if ((_vma)->vm_mm == current->active_mm)		\
-			cpu_cache_clean_invalidate_range((_start), (_end), 1); \
-	} while (0)
+#define __cpuc_flush_kern_all		cpu_cache.flush_kern_all
+#define __cpuc_flush_user_all		cpu_cache.flush_user_all
+#define __cpuc_flush_user_range		cpu_cache.flush_user_range
+#define __cpuc_coherent_kern_range	cpu_cache.coherent_kern_range
+#define __cpuc_flush_dcache_page	cpu_cache.flush_kern_dcache_page
 
-#define flush_cache_page(_vma,_vmaddr)					\
-	do {								\
-		if ((_vma)->vm_mm == current->active_mm) {		\
-			cpu_cache_clean_invalidate_range((_vmaddr),	\
-				(_vmaddr) + PAGE_SIZE,			\
-				((_vma)->vm_flags & VM_EXEC));		\
-		} \
-	} while (0)
+/*
+ * These are private to the dma-mapping API.  Do not use directly.
+ * Their sole purpose is to ensure that data held in the cache
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
+ */
+#define dmac_inv_range			cpu_cache.dma_inv_range
+#define dmac_clean_range		cpu_cache.dma_clean_range
+#define dmac_flush_range		cpu_cache.dma_flush_range
+
+#else
+
+#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
+#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
+#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_flush_dcache_page	__glue(_CACHE,_flush_kern_dcache_page)
+
+extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_user_all(void);
+extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
+extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
+extern void __cpuc_flush_dcache_page(void *);
 
 /*
- * D cache only
+ * These are private to the dma-mapping API.  Do not use directly.
+ * Their sole purpose is to ensure that data held in the cache
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
  */
+#define dmac_inv_range			__glue(_CACHE,_dma_inv_range)
+#define dmac_clean_range		__glue(_CACHE,_dma_clean_range)
+#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
+
+extern void dmac_inv_range(unsigned long, unsigned long);
+extern void dmac_clean_range(unsigned long, unsigned long);
+extern void dmac_flush_range(unsigned long, unsigned long);
+
+#endif
 
-#define invalidate_dcache_range(_s,_e)	cpu_dcache_invalidate_range((_s),(_e))
-#define clean_dcache_range(_s,_e)	cpu_dcache_clean_range((_s),(_e))
-#define flush_dcache_range(_s,_e)	cpu_cache_clean_invalidate_range((_s),(_e),0)
+/*
+ * Convert calls to our calling convention.
+ */
+#define flush_cache_all()		__cpuc_flush_kern_all()
 
-#define clean_dcache_area(start,size) \
-	cpu_cache_clean_invalidate_range((unsigned long)start, \
-					 ((unsigned long)start) + size, 0);
+static inline void flush_cache_mm(struct mm_struct *mm)
+{
+	if (current->active_mm == mm)
+		__cpuc_flush_user_all();
+}
+
+static inline void
+flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+{
+	if (current->active_mm == vma->vm_mm)
+		__cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end),
+					vma->vm_flags);
+}
+
+static inline void
+flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr)
+{
+	if (current->active_mm == vma->vm_mm) {
+		unsigned long addr = user_addr & PAGE_MASK;
+		__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
+	}
+}
+
+/*
+ * Perform necessary cache operations to ensure that data previously
+ * stored within this range of addresses can be executed by the CPU.
+ */
+#define flush_icache_range(s,e)		__cpuc_coherent_kern_range(s,e)
+
+/*
+ * Perform necessary cache operations to ensure that the TLB will
+ * see data written in the specified area.
+ */
+#define clean_dcache_area(start,size)	cpu_dcache_clean_area(start, size)
 
 /*
  * flush_dcache_page is used when the kernel has written to the page
@@ -104,18 +276,3 @@
  * duplicate cache flushing elsewhere performed by flush_dcache_page().
  */
 #define flush_icache_page(vma,page)	do { } while (0)
-
-/*
- * I cache coherency stuff.
- *
- * This *is not* just icache.  It is to make data written to memory
- * consistent such that instructions fetched from the region are what
- * we expect.
- *
- * This generally means that we have to clean out the Dcache and write
- * buffers, and maybe flush the Icache in the specified range.
- */
-#define flush_icache_range(_s,_e)					\
-	do {								\
-		cpu_icache_invalidate_range((_s), (_e));		\
-	} while (0)
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/locks.h linux-2.5.68-bk9/include/asm-arm/proc-armv/locks.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/locks.h	2003-04-19 19:51:07.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/locks.h	2003-04-29 04:37:11.000000000 -0700
@@ -67,7 +67,7 @@
 "	blle	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc");			\
+	: "ip", "lr", "cc", "memory");		\
 	})
 
 /*
@@ -133,7 +133,7 @@
 "	bleq	" #wake				\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "ip", "lr", "cc");			\
+	: "ip", "lr", "cc", "memory");		\
 	})
 
 #endif
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/pgalloc.h linux-2.5.68-bk9/include/asm-arm/proc-armv/pgalloc.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/pgalloc.h	2003-04-29 04:36:53.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/pgalloc.h	2003-04-29 04:37:11.000000000 -0700
@@ -6,6 +6,7 @@
  * Page table allocation/freeing primitives for 32-bit ARM processors.
  */
 #include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 #include "pgtable.h"
 
 /*
@@ -92,7 +93,7 @@
 	pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
 	pmdp[0] = __pmd(pmdval);
 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
-	cpu_flush_pmd(pmdp);
+	flush_pmd_entry(pmdp);
 }
 
 static inline void
@@ -105,5 +106,5 @@
 	pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
 	pmdp[0] = __pmd(pmdval);
 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
-	cpu_flush_pmd(pmdp);
+	flush_pmd_entry(pmdp);
 }
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/pgtable.h linux-2.5.68-bk9/include/asm-arm/proc-armv/pgtable.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/pgtable.h	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/pgtable.h	2003-04-29 04:37:11.000000000 -0700
@@ -51,6 +51,7 @@
 #define PMD_SECT_TEX(x)		((x) << 12)	/* v5 */
 
 #define PMD_SECT_UNCACHED	(0)
+#define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
 #define PMD_SECT_WT		(PMD_SECT_CACHEABLE)
 #define PMD_SECT_WB		(PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
 #define PMD_SECT_MINICACHE	(PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
@@ -120,14 +121,19 @@
 #define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
 
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-#define set_pmd(pmdp,pmd)	do { *pmdp = pmd; cpu_flush_pmd(pmdp); } while (0)
 
-static inline void pmd_clear(pmd_t *pmdp)
-{
-	pmdp[0] = __pmd(0);
-	pmdp[1] = __pmd(0);
-	cpu_flush_pmd(pmdp);
-}
+#define set_pmd(pmdp,pmd)		\
+	do {				\
+		*pmdp = pmd;		\
+		flush_pmd_entry(pmdp);	\
+	} while (0)
+
+#define pmd_clear(pmdp)			\
+	do {				\
+		pmdp[0] = __pmd(0);	\
+		pmdp[1] = __pmd(0);	\
+		clean_pmd_entry(pmdp);	\
+	} while (0)
 
 static inline pte_t *pmd_page_kernel(pmd_t pmd)
 {
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/system.h linux-2.5.68-bk9/include/asm-arm/proc-armv/system.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/system.h	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/system.h	2003-04-29 04:37:11.000000000 -0700
@@ -15,12 +15,16 @@
 #define set_cr(x)					\
 	__asm__ __volatile__(				\
 	"mcr	p15, 0, %0, c1, c0, 0	@ set CR"	\
-	: : "r" (x))
+	: : "r" (x) : "cc")
 
-#define get_cr(x)					\
+#define get_cr()					\
+	({						\
+	unsigned int __val;				\
 	__asm__ __volatile__(				\
 	"mrc	p15, 0, %0, c1, c0, 0	@ get CR"	\
-	: "=r" (x))
+	: "=r" (__val) : : "cc");			\
+	__val;						\
+	})
 
 #define CR_M	(1 << 0)	/* MMU enable				*/
 #define CR_A	(1 << 1)	/* Alignment abort enable		*/
@@ -48,16 +52,6 @@
 #endif
 
 /*
- * Save the current interrupt enable state.
- */
-#define local_save_flags(x)					\
-	({							\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ local_save_flags"	\
-	: "=r" (x) : : "memory");				\
-	})
-
-/*
  * Save the current interrupt enable state & disable IRQs
  */
 #define local_irq_save(x)					\
@@ -70,7 +64,7 @@
 "	msr	cpsr_c, %1"					\
 	: "=r" (x), "=r" (temp)					\
 	:							\
-	: "memory");						\
+	: "memory", "cc");					\
 	})
 	
 /*
@@ -85,7 +79,7 @@
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
 	:							\
-	: "memory");						\
+	: "memory", "cc");					\
 	})
 
 /*
@@ -100,7 +94,7 @@
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
 	:							\
-	: "memory");						\
+	: "memory", "cc");					\
 	})
 
 /*
@@ -115,7 +109,7 @@
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
 	:							\
-	: "memory");						\
+	: "memory", "cc");					\
 	})
 
 /*
@@ -130,7 +124,17 @@
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
 	:							\
-	: "memory");						\
+	: "memory", "cc");					\
+	})
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define local_save_flags(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_save_flags"	\
+	: "=r" (x) : : "memory", "cc");				\
 	})
 
 /*
@@ -141,7 +145,7 @@
 	"msr	cpsr_c, %0		@ local_irq_restore\n"	\
 	:							\
 	: "r" (x)						\
-	: "memory")
+	: "memory", "cc")
 
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 /*
@@ -186,12 +190,12 @@
 		case 1:	__asm__ __volatile__ ("swpb %0, %1, [%2]"
 					: "=&r" (ret)
 					: "r" (x), "r" (ptr)
-					: "memory");
+					: "memory", "cc");
 			break;
 		case 4:	__asm__ __volatile__ ("swp %0, %1, [%2]"
 					: "=&r" (ret)
 					: "r" (x), "r" (ptr)
-					: "memory");
+					: "memory", "cc");
 			break;
 #endif
 		default: __bad_xchg(ptr, size), ret = 0;
diff -urN linux-2.5.68-bk8/include/asm-arm/proc-armv/tlbflush.h linux-2.5.68-bk9/include/asm-arm/proc-armv/tlbflush.h
--- linux-2.5.68-bk8/include/asm-arm/proc-armv/tlbflush.h	2003-04-19 19:50:34.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/proc-armv/tlbflush.h	2003-04-29 04:37:11.000000000 -0700
@@ -20,6 +20,7 @@
 #define TLB_V4_D_FULL	(1 << 10)
 #define TLB_V4_I_FULL	(1 << 11)
 
+#define TLB_DCLEAN	(1 << 30)
 #define TLB_WB		(1 << 31)
 
 /*
@@ -65,7 +66,7 @@
 # define v4_always_flags	(-1UL)
 #endif
 
-#define v4wbi_tlb_flags	(TLB_WB | \
+#define v4wbi_tlb_flags	(TLB_WB | TLB_DCLEAN | \
 			 TLB_V4_I_FULL | TLB_V4_D_FULL | \
 			 TLB_V4_I_PAGE | TLB_V4_D_PAGE)
 
@@ -84,7 +85,7 @@
 # define v4wbi_always_flags	(-1UL)
 #endif
 
-#define v4wb_tlb_flags	(TLB_WB | \
+#define v4wb_tlb_flags	(TLB_WB | TLB_DCLEAN | \
 			 TLB_V4_I_FULL | TLB_V4_D_FULL | \
 			 TLB_V4_D_PAGE)
 
@@ -287,6 +288,41 @@
 		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
 }
 
+/*
+ *	flush_pmd_entry
+ *
+ *	Flush a PMD entry (word aligned, or double-word aligned) to
+ *	RAM if the TLB for the CPU we are running on requires this.
+ *	This is typically used when we are creating PMD entries.
+ *
+ *	clean_pmd_entry
+ *
+ *	Clean (but don't drain the write buffer) if the CPU requires
+ *	these operations.  This is typically used when we are removing
+ *	PMD entries.
+ */
+static inline void flush_pmd_entry(pmd_t *pmd)
+{
+	const unsigned int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
+
+	if (tlb_flag(TLB_DCLEAN))
+		asm("mcr%?	p15, 0, %0, c7, c10, 1	@ flush_pmd"
+			: : "r" (pmd));
+	if (tlb_flag(TLB_WB))
+		asm("mcr%?	p15, 0, %0, c7, c10, 4	@ flush_pmd"
+			: : "r" (zero));
+}
+
+static inline void clean_pmd_entry(pmd_t *pmd)
+{
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
+
+	if (tlb_flag(TLB_DCLEAN))
+		asm("mcr%?	p15, 0, %0, c7, c10, 1	@ flush_pmd"
+			: : "r" (pmd));
+}
+
 #undef tlb_flag
 #undef always_tlb_flags
 #undef possible_tlb_flags
diff -urN linux-2.5.68-bk8/include/asm-arm/procinfo.h linux-2.5.68-bk9/include/asm-arm/procinfo.h
--- linux-2.5.68-bk8/include/asm-arm/procinfo.h	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/procinfo.h	2003-04-29 04:37:11.000000000 -0700
@@ -14,6 +14,7 @@
 
 struct cpu_tlb_fns;
 struct cpu_user_fns;
+struct cpu_cache_fns;
 struct processor;
 
 /*
@@ -37,13 +38,14 @@
 	struct processor	*proc;
 	struct cpu_tlb_fns	*tlb;
 	struct cpu_user_fns	*user;
+	struct cpu_cache_fns	*cache;
 };
 
 extern unsigned int elf_hwcap;
 
 #endif	/* __ASSEMBLY__ */
 
-#define PROC_INFO_SZ	44
+#define PROC_INFO_SZ	48
 
 #define HWCAP_SWP	1
 #define HWCAP_HALF	2
diff -urN linux-2.5.68-bk8/include/asm-arm/setup.h linux-2.5.68-bk9/include/asm-arm/setup.h
--- linux-2.5.68-bk8/include/asm-arm/setup.h	2003-04-19 19:49:31.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/setup.h	2003-04-29 04:37:11.000000000 -0700
@@ -202,4 +202,17 @@
 
 extern struct meminfo meminfo;
 
+/*
+ * Early command line parameters.
+ */
+struct early_params {
+	const char *arg;
+	void (*fn)(char **p);
+};
+
+#define __early_param(name,fn)				\
+static struct early_params __early_##fn			\
+__attribute__((section("__early_param"), unused)) =	\
+	{ name, fn }
+
 #endif
diff -urN linux-2.5.68-bk8/include/asm-arm/tlb.h linux-2.5.68-bk9/include/asm-arm/tlb.h
--- linux-2.5.68-bk8/include/asm-arm/tlb.h	2003-04-19 19:48:49.000000000 -0700
+++ linux-2.5.68-bk9/include/asm-arm/tlb.h	2003-04-29 04:37:11.000000000 -0700
@@ -18,6 +18,7 @@
 #define __ASMARM_TLB_H
 
 #include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 
 /*
  * TLB handling.  This allows us to remove pages from the page
@@ -26,6 +27,7 @@
 struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		freed;
+	unsigned int		fullmm;
 
 	unsigned int		flushes;
 	unsigned int		avoided_flushes;
@@ -41,6 +43,7 @@
 
 	tlb->mm = mm;
 	tlb->freed = 0;
+	tlb->fullmm = full_mm_flush;
 
 	return tlb;
 }
@@ -68,7 +71,13 @@
 }
 
 #define tlb_remove_tlb_entry(tlb,ptep,address)	do { } while (0)
-#define tlb_start_vma(tlb,vma)			do { } while (0)
+
+#define tlb_start_vma(tlb,vma)						\
+	do {								\
+		if (!tlb->fullmm)					\
+			flush_cache_range(vma, vma->vm_start, vma->vm_end); \
+	} while (0)
+
 #define tlb_end_vma(tlb,vma)			do { } while (0)
 
 #define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
diff -urN linux-2.5.68-bk8/include/linux/eisa.h linux-2.5.68-bk9/include/linux/eisa.h
--- linux-2.5.68-bk8/include/linux/eisa.h	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/eisa.h	2003-04-29 04:37:11.000000000 -0700
@@ -25,13 +25,15 @@
 };
 
 /* There is not much we can say about an EISA device, apart from
- * signature, slot number, and base address. */
+ * signature, slot number, and base address. dma_mask is set by
+ * default to 32 bits.*/
 
 struct eisa_device {
 	struct eisa_device_id id;
 	int                   slot;
 	unsigned long         base_addr;
 	struct resource       res;
+	u64                   dma_mask;
 	struct device         dev; /* generic device */
 };
 
@@ -63,12 +65,12 @@
  * busses (PA-RISC ?), so we try to handle that. */
 
 struct eisa_root_device {
-	struct list_head node;
 	struct device   *dev;	 /* Pointer to bridge device */
 	struct resource *res;
 	unsigned long    bus_base_addr;
 	int		 slots;  /* Max slot number */
 	int              bus_nr; /* Set by eisa_root_register */
+	struct resource  eisa_root_res;	/* ditto */
 };
 
 int eisa_root_register (struct eisa_root_device *root);
diff -urN linux-2.5.68-bk8/include/linux/fs.h linux-2.5.68-bk9/include/linux/fs.h
--- linux-2.5.68-bk8/include/linux/fs.h	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/fs.h	2003-04-29 04:37:11.000000000 -0700
@@ -1041,6 +1041,7 @@
 extern void bdput(struct block_device *);
 extern int blkdev_open(struct inode *, struct file *);
 extern int blkdev_close(struct inode *, struct file *);
+extern struct block_device *open_by_devnum(dev_t, unsigned, int);
 extern struct file_operations def_blk_fops;
 extern struct address_space_operations def_blk_aops;
 extern struct file_operations def_chr_fops;
@@ -1104,7 +1105,7 @@
 extern int check_disk_change(struct block_device *);
 extern int invalidate_inodes(struct super_block *);
 extern int __invalidate_device(struct block_device *, int);
-extern int invalidate_device(kdev_t, int);
+extern int invalidate_partition(struct gendisk *, int);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
 unsigned long invalidate_inode_pages(struct address_space *mapping);
@@ -1292,6 +1293,10 @@
 extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
 extern struct file_operations simple_dir_operations;
 extern struct inode_operations simple_dir_inode_operations;
+struct tree_descr { char *name; struct file_operations *ops; int mode; };
+extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
+extern void simple_release_fs(struct vfsmount **mount, int *count);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 extern unsigned int real_root_dev;
diff -urN linux-2.5.68-bk8/include/linux/genhd.h linux-2.5.68-bk9/include/linux/genhd.h
--- linux-2.5.68-bk8/include/linux/genhd.h	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/genhd.h	2003-04-29 04:37:11.000000000 -0700
@@ -367,6 +367,11 @@
 			void *data);
 extern void blk_unregister_region(dev_t dev, unsigned long range);
 
+static inline struct block_device *bdget_disk(struct gendisk *disk, int index)
+{
+	return bdget(MKDEV(disk->major, disk->first_minor) + index);
+}
+
 #endif
 
 #endif
diff -urN linux-2.5.68-bk8/include/linux/ide.h linux-2.5.68-bk9/include/linux/ide.h
--- linux-2.5.68-bk8/include/linux/ide.h	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/ide.h	2003-04-29 04:37:11.000000000 -0700
@@ -228,25 +228,6 @@
 #define PRD_ENTRIES     (PAGE_SIZE / (2 * PRD_BYTES))
 
 /*
- * Our Physical Region Descriptor (PRD) table should be large enough
- * to handle the biggest I/O request we are likely to see.  Since requests
- * can have no more than 256 sectors, and since the typical blocksize is
- * two or more sectors, we could get by with a limit of 128 entries here for
- * the usual worst case.  Most requests seem to include some contiguous blocks,
- * further reducing the number of table entries required.
- *
- * The driver reverts to PIO mode for individual requests that exceed
- * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
- * 100% of all crazy scenarios here is not necessary.
- *
- * As it turns out though, we must allocate a full 4KB page for this,
- * so the two PRD tables (ide0 & ide1) will each get half of that,
- * allowing each to have about 256 entries (8 bytes each) from this.
- */
-#define PRD_BYTES	8
-#define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
-
-/*
  * Some more useful definitions
  */
 #define IDE_MAJOR_NAME	"hd"	/* the same for all i/f; see also genhd.c */
diff -urN linux-2.5.68-bk8/include/linux/netfilter.h linux-2.5.68-bk9/include/linux/netfilter.h
--- linux-2.5.68-bk8/include/linux/netfilter.h	2003-04-19 19:49:31.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/netfilter.h	2003-04-29 04:37:11.000000000 -0700
@@ -47,6 +47,7 @@
 
 	/* User fills in from here down. */
 	nf_hookfn *hook;
+	struct module *owner;
 	int pf;
 	int hooknum;
 	/* Hooks are ordered in ascending priority. */
diff -urN linux-2.5.68-bk8/include/linux/netfilter_bridge.h linux-2.5.68-bk9/include/linux/netfilter_bridge.h
--- linux-2.5.68-bk8/include/linux/netfilter_bridge.h	2003-04-19 19:49:57.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/netfilter_bridge.h	2003-04-29 04:37:11.000000000 -0700
@@ -30,6 +30,7 @@
 #define BRNF_PKT_TYPE			0x01
 #define BRNF_BRIDGED_DNAT		0x02
 #define BRNF_DONT_TAKE_PARENT		0x04
+#define BRNF_BRIDGED			0x08
 
 enum nf_br_hook_priorities {
 	NF_BR_PRI_FIRST = INT_MIN,
diff -urN linux-2.5.68-bk8/include/linux/netfilter_ipv4/ipt_physdev.h linux-2.5.68-bk9/include/linux/netfilter_ipv4/ipt_physdev.h
--- linux-2.5.68-bk8/include/linux/netfilter_ipv4/ipt_physdev.h	2003-04-19 19:50:30.000000000 -0700
+++ linux-2.5.68-bk9/include/linux/netfilter_ipv4/ipt_physdev.h	2003-04-29 04:37:11.000000000 -0700
@@ -5,11 +5,16 @@
 #include <linux/if.h>
 #endif
 
-#define IPT_PHYSDEV_OP_MATCH_IN 0x01
-#define IPT_PHYSDEV_OP_MATCH_OUT 0x02
+#define IPT_PHYSDEV_OP_IN		0x01
+#define IPT_PHYSDEV_OP_OUT		0x02
+#define IPT_PHYSDEV_OP_BRIDGED		0x04
+#define IPT_PHYSDEV_OP_ISIN		0x08
+#define IPT_PHYSDEV_OP_ISOUT		0x10
+#define IPT_PHYSDEV_OP_MASK		(0x20 - 1)
 
 struct ipt_physdev_info {
 	u_int8_t invert;
+	u_int8_t bitmask;
 	char physindev[IFNAMSIZ];
 	char in_mask[IFNAMSIZ];
 	char physoutdev[IFNAMSIZ];
diff -urN linux-2.5.68-bk8/include/net/bluetooth/hci_core.h linux-2.5.68-bk9/include/net/bluetooth/hci_core.h
--- linux-2.5.68-bk8/include/net/bluetooth/hci_core.h	2003-04-19 19:49:52.000000000 -0700
+++ linux-2.5.68-bk9/include/net/bluetooth/hci_core.h	2003-04-29 04:37:11.000000000 -0700
@@ -262,7 +262,7 @@
 int hci_conn_auth(struct hci_conn *conn);
 int hci_conn_encrypt(struct hci_conn *conn);
 
-static inline void hci_conn_set_timer(struct hci_conn *conn, long timeout)
+static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout)
 {
 	mod_timer(&conn->timer, jiffies + timeout);
 }
@@ -280,8 +280,12 @@
 
 static inline void hci_conn_put(struct hci_conn *conn)
 {
-	if (atomic_dec_and_test(&conn->refcnt) && conn->out)
-		hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
+	if (atomic_dec_and_test(&conn->refcnt)) {
+		if (conn->type == SCO_LINK)
+			hci_conn_set_timer(conn, HZ / 100);
+		else if (conn->out)
+			hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
+	}
 }
 
 /* ----- HCI tasks ----- */
diff -urN linux-2.5.68-bk8/include/net/bluetooth/rfcomm.h linux-2.5.68-bk9/include/net/bluetooth/rfcomm.h
--- linux-2.5.68-bk8/include/net/bluetooth/rfcomm.h	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/include/net/bluetooth/rfcomm.h	2003-04-29 04:37:11.000000000 -0700
@@ -146,6 +146,11 @@
 	u16 param_mask;
 } __attribute__ ((packed));
 
+struct rfcomm_rls {
+	u8  dlci;
+	u8  status;
+} __attribute__ ((packed));
+
 struct rfcomm_msc {
 	u8  dlci;
 	u8  v24_sig;
@@ -215,10 +220,9 @@
 {
 	if (!rfcomm_thread)
 		return;
-
 	//set_bit(event, &rfcomm_event);
-	if (!test_and_set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event))
-		wake_up_process(rfcomm_thread);
+	set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
+	wake_up_process(rfcomm_thread);
 }
 
 extern struct semaphore rfcomm_sem;
diff -urN linux-2.5.68-bk8/kernel/ksyms.c linux-2.5.68-bk9/kernel/ksyms.c
--- linux-2.5.68-bk8/kernel/ksyms.c	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/kernel/ksyms.c	2003-04-29 04:37:11.000000000 -0700
@@ -188,7 +188,6 @@
 EXPORT_SYMBOL(check_disk_change);
 EXPORT_SYMBOL(invalidate_bdev);
 EXPORT_SYMBOL(invalidate_inodes);
-EXPORT_SYMBOL(invalidate_device);
 EXPORT_SYMBOL(__invalidate_device);
 EXPORT_SYMBOL(invalidate_inode_pages);
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
@@ -209,6 +208,7 @@
 EXPORT_SYMBOL(bd_release);
 EXPORT_SYMBOL(open_bdev_excl);
 EXPORT_SYMBOL(close_bdev_excl);
+EXPORT_SYMBOL(open_by_devnum);
 EXPORT_SYMBOL(__brelse);
 EXPORT_SYMBOL(__bforget);
 EXPORT_SYMBOL(ll_rw_block);
@@ -313,6 +313,9 @@
 EXPORT_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_commit_write);
 EXPORT_SYMBOL(simple_empty);
+EXPORT_SYMBOL(simple_fill_super);
+EXPORT_SYMBOL(simple_pin_fs);
+EXPORT_SYMBOL(simple_release_fs);
 EXPORT_SYMBOL(fd_install);
 EXPORT_SYMBOL(put_unused_fd);
 EXPORT_SYMBOL(get_sb_bdev);
diff -urN linux-2.5.68-bk8/kernel/suspend.c linux-2.5.68-bk9/kernel/suspend.c
--- linux-2.5.68-bk8/kernel/suspend.c	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/kernel/suspend.c	2003-04-29 04:37:11.000000000 -0700
@@ -1161,15 +1161,14 @@
 		struct block_device *bdev;
 		printk("Resuming from device %s\n",
 				__bdevname(resume_device, b));
-		bdev = bdget(resume_device);
-		if (!bdev) {
-			printk("No such block device ?!\n");
-			BUG();
+		bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW);
+		if (IS_ERR(bdev)) {
+			error = PTR_ERR(bdev);
+		} else {
+			set_blocksize(bdev, PAGE_SIZE);
+			error = __read_suspend_image(bdev, cur, noresume);
+			blkdev_put(bdev, BDEV_RAW);
 		}
-		blkdev_get(bdev, FMODE_READ, O_RDONLY, BDEV_RAW);
-		set_blocksize(bdev, PAGE_SIZE);
-		error = __read_suspend_image(bdev, cur, noresume);
-		blkdev_put(bdev, BDEV_RAW);
 	} else error = -ENOMEM;
 
 	if (scratch_page)
diff -urN linux-2.5.68-bk8/net/appletalk/ddp.c linux-2.5.68-bk9/net/appletalk/ddp.c
--- linux-2.5.68-bk8/net/appletalk/ddp.c	2003-04-19 19:51:17.000000000 -0700
+++ linux-2.5.68-bk9/net/appletalk/ddp.c	2003-04-29 04:37:11.000000000 -0700
@@ -190,10 +190,9 @@
 	struct sock *sk = (struct sock *)data;
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags))
 		sock_put(sk);
-		MOD_DEC_USE_COUNT;
-	} else {
+	else {
 		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
 		add_timer(&sk->timer);
 	}
@@ -205,10 +204,9 @@
 	skb_queue_purge(&sk->receive_queue);
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags))
 		sock_put(sk);
-		MOD_DEC_USE_COUNT;
-	} else {
+	else {
 		init_timer(&sk->timer);
 		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
 		sk->timer.function = atalk_destroy_timer;
@@ -249,7 +247,6 @@
 			*iface = tmp->next;
 			kfree(tmp);
 			dev->atalk_ptr = NULL;
-			MOD_DEC_USE_COUNT;
 		} else
 			iface = &tmp->next;
 	}
@@ -259,13 +256,10 @@
 static struct atalk_iface *atif_add_device(struct net_device *dev,
 					   struct atalk_addr *sa)
 {
-	struct atalk_iface *iface;
-
-	MOD_INC_USE_COUNT;
+	struct atalk_iface *iface = kmalloc(sizeof(*iface), GFP_KERNEL);
 
-	iface = kmalloc(sizeof(*iface), GFP_KERNEL);
 	if (!iface)
-		goto out_mem;
+		goto out;
 
 	iface->dev = dev;
 	dev->atalk_ptr = iface;
@@ -278,9 +272,6 @@
 	write_unlock_bh(&atalk_interfaces_lock);
 out:
 	return iface;
-out_mem:
-	MOD_DEC_USE_COUNT;
-	goto out;
 }
 
 /* Perform phase 2 AARP probing on our tentative address */
@@ -982,17 +973,16 @@
 	struct atalk_sock *at;
 	int rc = -ESOCKTNOSUPPORT;
 
-	MOD_INC_USE_COUNT;
 	/*
 	 * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
 	 * and gives you the full ELAP frame. Should be handy for CAP 8) 
 	 */
 	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
-		goto decmod;
+		goto out;
 	rc = -ENOMEM;
 	sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1, NULL);
 	if (!sk)
-		goto decmod;
+		goto out;
 	at = at_sk(sk) = kmalloc(sizeof(*at), GFP_KERNEL);
 	if (!at)
 		goto outsk;
@@ -1005,8 +995,6 @@
 	return rc;
 outsk:
 	sk_free(sk);
-decmod:
-	MOD_DEC_USE_COUNT;
 	goto out;
 }
 
@@ -1785,6 +1773,7 @@
 static struct net_proto_family atalk_family_ops = {
 	.family		= PF_APPLETALK,
 	.create		= atalk_create,
+	.owner		= THIS_MODULE,
 };
 
 static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
diff -urN linux-2.5.68-bk8/net/bluetooth/af_bluetooth.c linux-2.5.68-bk9/net/bluetooth/af_bluetooth.c
--- linux-2.5.68-bk8/net/bluetooth/af_bluetooth.c	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/af_bluetooth.c	2003-04-29 04:37:11.000000000 -0700
@@ -321,6 +321,7 @@
 }
 
 struct net_proto_family bt_sock_family_ops = {
+	.owner  = THIS_MODULE,
 	.family	= PF_BLUETOOTH,
 	.create	= bt_sock_create,
 };
diff -urN linux-2.5.68-bk8/net/bluetooth/hci_conn.c linux-2.5.68-bk9/net/bluetooth/hci_conn.c
--- linux-2.5.68-bk8/net/bluetooth/hci_conn.c	2003-04-19 19:51:14.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/hci_conn.c	2003-04-29 04:37:11.000000000 -0700
@@ -71,6 +71,7 @@
 
 	memset(&cp, 0, sizeof(cp));
 	bacpy(&cp.bdaddr, &conn->dst);
+	cp.pscan_rep_mode = 0x01;
 
 	if ((ie = inquiry_cache_lookup(hdev, &conn->dst)) &&
 			inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
diff -urN linux-2.5.68-bk8/net/bluetooth/hci_sock.c linux-2.5.68-bk9/net/bluetooth/hci_sock.c
--- linux-2.5.68-bk8/net/bluetooth/hci_sock.c	2003-04-19 19:49:56.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/hci_sock.c	2003-04-29 04:37:11.000000000 -0700
@@ -161,8 +161,6 @@
 	skb_queue_purge(&sk->write_queue);
 
 	sock_put(sk);
-
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -591,8 +589,6 @@
 	sk->state   = BT_OPEN;
 
 	bt_sock_link(&hci_sk_list, sk);
-
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
diff -urN linux-2.5.68-bk8/net/bluetooth/l2cap.c linux-2.5.68-bk9/net/bluetooth/l2cap.c
--- linux-2.5.68-bk8/net/bluetooth/l2cap.c	2003-04-19 19:50:09.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/l2cap.c	2003-04-29 04:37:11.000000000 -0700
@@ -1788,7 +1788,7 @@
 		if (sk->state != BT_LISTEN)
 			continue;
 
-		if (!bacmp(&bt_sk(sk)->src, bdaddr)) {
+		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
 			lm1 |= (HCI_LM_ACCEPT | l2cap_pi(sk)->link_mode);
 			exact++;
 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
diff -urN linux-2.5.68-bk8/net/bluetooth/rfcomm/core.c linux-2.5.68-bk9/net/bluetooth/rfcomm/core.c
--- linux-2.5.68-bk8/net/bluetooth/rfcomm/core.c	2003-04-19 19:48:48.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/rfcomm/core.c	2003-04-29 04:37:11.000000000 -0700
@@ -798,6 +798,33 @@
 	return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
+static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
+{
+	struct rfcomm_hdr *hdr;
+	struct rfcomm_mcc *mcc;
+	struct rfcomm_rls *rls;
+	u8 buf[16], *ptr = buf;
+
+	BT_DBG("%p cr %d status 0x%x", s, cr, status);
+
+	hdr = (void *) ptr; ptr += sizeof(*hdr);
+	hdr->addr = __addr(s->initiator, 0);
+	hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
+	hdr->len  = __len8(sizeof(*mcc) + sizeof(*rls));
+
+	mcc = (void *) ptr; ptr += sizeof(*mcc);
+	mcc->type = __mcc_type(cr, RFCOMM_RLS);
+	mcc->len  = __len8(sizeof(*rls));
+
+	rls = (void *) ptr; ptr += sizeof(*rls);
+	rls->dlci   = __addr(1, dlci);
+	rls->status = status;
+
+	*ptr = __fcs(buf); ptr++;
+
+	return rfcomm_send_frame(s, buf, ptr - buf);
+}
+
 static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig)
 {
 	struct rfcomm_hdr *hdr;
@@ -1229,6 +1256,26 @@
 	return 0;
 }
 
+static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
+{
+	struct rfcomm_rls *rls = (void *) skb->data;
+	u8 dlci = __get_dlci(rls->dlci);
+
+	BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
+	
+	if (!cr)
+		return 0;
+
+	/* FIXME: We should probably do something with this
+	   information here. But for now it's sufficient just
+	   to reply -- Bluetooth 1.1 says it's mandatory to 
+	   recognise and respond to RLS */
+
+	rfcomm_send_rls(s, 0, dlci, rls->status);
+
+	return 0;
+}
+
 static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
 {
 	struct rfcomm_msc *msc = (void *) skb->data;
@@ -1279,6 +1326,10 @@
 		rfcomm_recv_rpn(s, cr, len, skb);
 		break;
 
+	case RFCOMM_RLS:
+		rfcomm_recv_rls(s, cr, skb);
+		break;
+
 	case RFCOMM_MSC:
 		rfcomm_recv_msc(s, cr, skb);
 		break;
@@ -1432,9 +1483,9 @@
 			d->rx_credits = d->credits;
 		}
 	} else {
-		/* CFC disabled. 
+		/* CFC disabled.
 		 * Give ourselves some credits */
-		d->tx_credits = RFCOMM_MAX_CREDITS;
+		d->tx_credits = 5;
 	}
 
 	if (test_bit(RFCOMM_TX_THROTTLED, &d->flags))
@@ -1600,7 +1651,7 @@
 	BT_DBG("");
 
 	while (!atomic_read(&terminate)) {
-		if (!test_and_clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
+		if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
 			/* No pending events. Let's sleep.
 			 * Incomming connections and data will wake us up. */
 			set_current_state(TASK_INTERRUPTIBLE);
@@ -1608,6 +1659,7 @@
 		}
 
 		/* Process stuff */
+		clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
 		rfcomm_process_sessions();
 	}
 	set_current_state(TASK_RUNNING);
diff -urN linux-2.5.68-bk8/net/bluetooth/rfcomm/tty.c linux-2.5.68-bk9/net/bluetooth/rfcomm/tty.c
--- linux-2.5.68-bk8/net/bluetooth/rfcomm/tty.c	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/net/bluetooth/rfcomm/tty.c	2003-04-29 04:37:11.000000000 -0700
@@ -72,7 +72,6 @@
 	struct tasklet_struct   wakeup_task;
 
 	atomic_t 		wmem_alloc;
-	unsigned int 		sndbuf;
 };
 
 static LIST_HEAD(rfcomm_dev_list);
@@ -200,8 +199,6 @@
 	dev->flags = req->flags & 
 		((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
 
-	dev->sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
-
 	init_waitqueue_head(&dev->wait);
 	tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
 
@@ -238,6 +235,13 @@
 }
 
 /* ---- Send buffer ---- */
+static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
+{
+	/* We can't let it be zero, because we don't get a callback
+	   when tx_credits becomes nonzero, hence we'd never wake up */
+	return dlc->mtu * (dlc->tx_credits?:1);
+}
+
 static void rfcomm_wfree(struct sk_buff *skb)
 {
 	struct rfcomm_dev *dev = (void *) skb->sk;
@@ -257,7 +261,7 @@
 
 static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, int priority)
 {
-	if (atomic_read(&dev->wmem_alloc) < dev->sndbuf) {
+	if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
 		struct sk_buff *skb = alloc_skb(size, priority);
 		if (skb) {
 			rfcomm_set_owner_w(skb, dev);
@@ -651,11 +655,14 @@
 static int rfcomm_tty_write_room(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-	struct rfcomm_dlc *dlc = dev->dlc;
+	int room;
 
 	BT_DBG("tty %p", tty);
 
-	return dlc->mtu * (dlc->tx_credits ? : 10);
+	room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
+	if (room < 0)
+		room = 0;
+	return room;
 }
 
 static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint status)
@@ -849,6 +856,8 @@
 static struct termios *rfcomm_tty_termios_locked[RFCOMM_TTY_PORTS];
 
 static struct tty_driver rfcomm_tty_driver = {
+	.owner			= THIS_MODULE,
+
 	.magic			= TTY_DRIVER_MAGIC,
 	.driver_name		= "rfcomm",
 #ifdef CONFIG_DEVFS_FS
diff -urN linux-2.5.68-bk8/net/bridge/br_netfilter.c linux-2.5.68-bk9/net/bridge/br_netfilter.c
--- linux-2.5.68-bk8/net/bridge/br_netfilter.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/net/bridge/br_netfilter.c	2003-04-29 04:37:11.000000000 -0700
@@ -348,6 +348,8 @@
 	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;
@@ -572,15 +574,15 @@
  * ip_refrag() can return NF_STOLEN.
  */
 static struct nf_hook_ops br_nf_ops[] = {
-	{ { NULL, NULL }, br_nf_pre_routing, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF },
-	{ { NULL, NULL }, br_nf_local_in, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF },
-	{ { NULL, NULL }, br_nf_forward, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF },
-	{ { NULL, NULL }, br_nf_local_out, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST },
-	{ { NULL, NULL }, br_nf_post_routing, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST },
-	{ { NULL, NULL }, ipv4_sabotage_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST },
-	{ { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD },
-	{ { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT },
-	{ { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST }
+	{ { NULL, NULL }, br_nf_pre_routing, THIS_MODULE, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF },
+	{ { NULL, NULL }, br_nf_local_in, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF },
+	{ { NULL, NULL }, br_nf_forward, THIS_MODULE, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF },
+	{ { NULL, NULL }, br_nf_local_out, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST },
+	{ { NULL, NULL }, br_nf_post_routing, THIS_MODULE, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST },
+	{ { NULL, NULL }, ipv4_sabotage_in, THIS_MODULE, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST },
+	{ { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD },
+	{ { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT },
+	{ { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST }
 };
 
 #define NUMHOOKS (sizeof(br_nf_ops)/sizeof(br_nf_ops[0]))
diff -urN linux-2.5.68-bk8/net/bridge/netfilter/ebt_vlan.c linux-2.5.68-bk9/net/bridge/netfilter/ebt_vlan.c
--- linux-2.5.68-bk8/net/bridge/netfilter/ebt_vlan.c	2003-04-19 19:49:51.000000000 -0700
+++ linux-2.5.68-bk9/net/bridge/netfilter/ebt_vlan.c	2003-04-29 04:37:11.000000000 -0700
@@ -137,7 +137,7 @@
 	 */
 	if (datalen != sizeof(struct ebt_vlan_info)) {
 		DEBUG_MSG
-		    ("passed size %d is not eq to ebt_vlan_info (%d)\n",
+		    ("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
 		     datalen, sizeof(struct ebt_vlan_info));
 		return -EINVAL;
 	}
diff -urN linux-2.5.68-bk8/net/bridge/netfilter/ebtable_filter.c linux-2.5.68-bk9/net/bridge/netfilter/ebtable_filter.c
--- linux-2.5.68-bk8/net/bridge/netfilter/ebtable_filter.c	2003-04-19 19:50:46.000000000 -0700
+++ linux-2.5.68-bk9/net/bridge/netfilter/ebtable_filter.c	2003-04-29 04:37:11.000000000 -0700
@@ -70,18 +70,21 @@
 static struct nf_hook_ops ebt_ops_filter[] = {
 	{
 		.hook		= ebt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_IN,
 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
 	},
 	{
 		.hook		= ebt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_FORWARD,
 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
 	},
 	{
 		.hook		= ebt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
 		.priority	= NF_BR_PRI_FILTER_OTHER,
diff -urN linux-2.5.68-bk8/net/bridge/netfilter/ebtable_nat.c linux-2.5.68-bk9/net/bridge/netfilter/ebtable_nat.c
--- linux-2.5.68-bk8/net/bridge/netfilter/ebtable_nat.c	2003-04-19 19:51:13.000000000 -0700
+++ linux-2.5.68-bk9/net/bridge/netfilter/ebtable_nat.c	2003-04-29 04:37:11.000000000 -0700
@@ -76,18 +76,21 @@
 static struct nf_hook_ops ebt_ops_nat[] = {
 	{
 		.hook		= ebt_nat_dst,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
 		.priority	= NF_BR_PRI_NAT_DST_OTHER,
 	},
 	{
 		.hook		= ebt_nat_src,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_POST_ROUTING,
 		.priority	= NF_BR_PRI_NAT_SRC,
 	},
 	{
 		.hook		= ebt_nat_dst,
+		.owner		= THIS_MODULE,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_PRE_ROUTING,
 		.priority	= NF_BR_PRI_NAT_DST_BRIDGED,
diff -urN linux-2.5.68-bk8/net/core/netfilter.c linux-2.5.68-bk9/net/core/netfilter.c
--- linux-2.5.68-bk8/net/core/netfilter.c	2003-04-19 19:49:26.000000000 -0700
+++ linux-2.5.68-bk9/net/core/netfilter.c	2003-04-29 04:37:11.000000000 -0700
@@ -350,6 +350,8 @@
 		if (hook_thresh > elem->priority)
 			continue;
 
+		/* Optimization: we don't need to hold module
+                   reference here, since function can't sleep. --RR */
 		switch (elem->hook(hook, skb, indev, outdev, okfn)) {
 		case NF_QUEUE:
 			return NF_QUEUE;
@@ -408,12 +410,12 @@
  * Any packet that leaves via this function must come back 
  * through nf_reinject().
  */
-static void nf_queue(struct sk_buff *skb, 
-		     struct list_head *elem, 
-		     int pf, unsigned int hook,
-		     struct net_device *indev,
-		     struct net_device *outdev,
-		     int (*okfn)(struct sk_buff *))
+static int nf_queue(struct sk_buff *skb, 
+		    struct list_head *elem, 
+		    int pf, unsigned int hook,
+		    struct net_device *indev,
+		    struct net_device *outdev,
+		    int (*okfn)(struct sk_buff *))
 {
 	int status;
 	struct nf_info *info;
@@ -422,9 +424,10 @@
 	struct net_device *physoutdev = NULL;
 #endif
 
+	/* QUEUE == DROP if noone is waiting, to be safe. */
 	if (!queue_handler[pf].outfn) {
 		kfree_skb(skb);
-		return;
+		return 1;
 	}
 
 	info = kmalloc(sizeof(*info), GFP_ATOMIC);
@@ -433,12 +436,16 @@
 			printk(KERN_ERR "OOM queueing packet %p\n",
 			       skb);
 		kfree_skb(skb);
-		return;
+		return 1;
 	}
 
 	*info = (struct nf_info) { 
 		(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
 
+	/* If it's going away, ignore hook. */
+	if (!try_module_get(info->elem->owner))
+		return 0;
+
 	/* Bump dev refs so they don't vanish while packet is out */
 	if (indev) dev_hold(indev);
 	if (outdev) dev_hold(outdev);
@@ -461,10 +468,12 @@
 		if (physindev) dev_put(physindev);
 		if (physoutdev) dev_put(physoutdev);
 #endif
+		module_put(info->elem->owner);
 		kfree(info);
 		kfree_skb(skb);
-		return;
+		return 1;
 	}
+	return 1;
 }
 
 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
@@ -497,11 +506,13 @@
 #endif
 
 	elem = &nf_hooks[pf][hook];
+ next_hook:
 	verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
 			     outdev, &elem, okfn, hook_thresh);
 	if (verdict == NF_QUEUE) {
 		NFDEBUG("nf_hook: Verdict = QUEUE.\n");
-		nf_queue(skb, elem, pf, hook, indev, outdev, okfn);
+		if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))
+			goto next_hook;
 	}
 
 	switch (verdict) {
@@ -523,19 +534,12 @@
 		 unsigned int verdict)
 {
 	struct list_head *elem = &info->elem->list;
-	struct list_head *i;
 
 	/* We don't have BR_NETPROTO_LOCK here */
 	br_read_lock_bh(BR_NETPROTO_LOCK);
-	for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) {
-		if (i == &nf_hooks[info->pf][info->hook]) {
-			/* The module which sent it to userspace is gone. */
-			NFDEBUG("%s: module disappeared, dropping packet.\n",
-			         __FUNCTION__);
-			verdict = NF_DROP;
-			break;
-		}
-	}
+
+	/* Drop reference to owner of hook which queued us. */
+	module_put(info->elem->owner);
 
 	/* Continue traversal iff userspace said ok... */
 	if (verdict == NF_REPEAT) {
@@ -544,6 +548,7 @@
 	}
 
 	if (verdict == NF_ACCEPT) {
+	next_hook:
 		verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
 				     &skb, info->hook, 
 				     info->indev, info->outdev, &elem,
@@ -556,8 +561,9 @@
 		break;
 
 	case NF_QUEUE:
-		nf_queue(skb, elem, info->pf, info->hook, 
-			 info->indev, info->outdev, info->okfn);
+		if (!nf_queue(skb, elem, info->pf, info->hook, 
+			      info->indev, info->outdev, info->okfn))
+			goto next_hook;
 		break;
 
 	case NF_DROP:
diff -urN linux-2.5.68-bk8/net/core/wireless.c linux-2.5.68-bk9/net/core/wireless.c
--- linux-2.5.68-bk8/net/core/wireless.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/net/core/wireless.c	2003-04-29 04:37:11.000000000 -0700
@@ -83,99 +83,168 @@
  * Meta-data about all the standard Wireless Extension request we
  * know about.
  */
-static const struct iw_ioctl_description	standard_ioctl[] = {
-	/* SIOCSIWCOMMIT */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCGIWNAME */
-	{ IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWNWID */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-	/* SIOCGIWNWID */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWFREQ */
-	{ IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-	/* SIOCGIWFREQ */
-	{ IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWMODE */
-	{ IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-	/* SIOCGIWMODE */
-	{ IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWSENS */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWSENS */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWRANGE */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCGIWRANGE */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWPRIV */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCGIWPRIV (handled directly by us) */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCSIWSTATS */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCGIWSTATS (handled directly by us) */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWSPY */
-	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
-	/* SIOCGIWSPY */
-	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCSIWAP */
-	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
-	/* SIOCGIWAP */
-	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCGIWAPLIST */
-	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
-	/* SIOCSIWSCAN */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWSCAN */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
-	/* SIOCSIWESSID */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
-	/* SIOCGIWESSID */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_DUMP},
-	/* SIOCSIWNICKN */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
-	/* SIOCGIWNICKN */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* SIOCSIWRATE */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWRATE */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWRTS */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWRTS */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWFRAG */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWFRAG */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWTXPOW */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWTXPOW */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWRETRY */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWRETRY */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCSIWENCODE */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
-	/* SIOCGIWENCODE */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
-	/* SIOCSIWPOWER */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-	/* SIOCGIWPOWER */
-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
+static const struct iw_ioctl_description standard_ioctl[] = {
+	[SIOCSIWCOMMIT	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_NULL,
+	},
+	[SIOCGIWNAME	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_CHAR,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWNWID	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+		.flags		= IW_DESCR_FLAG_EVENT,
+	},
+	[SIOCGIWNWID	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWFREQ	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_FREQ,
+		.flags		= IW_DESCR_FLAG_EVENT,
+	},
+	[SIOCGIWFREQ	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_FREQ,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWMODE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_UINT,
+		.flags		= IW_DESCR_FLAG_EVENT,
+	},
+	[SIOCGIWMODE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_UINT,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWSENS	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWSENS	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWRANGE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_NULL,
+	},
+	[SIOCGIWRANGE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= sizeof(struct iw_range),
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWPRIV	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_NULL,
+	},
+	[SIOCGIWPRIV	- SIOCIWFIRST] = { /* (handled directly by us) */
+		.header_type	= IW_HEADER_TYPE_NULL,
+	},
+	[SIOCSIWSTATS	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_NULL,
+	},
+	[SIOCGIWSTATS	- SIOCIWFIRST] = { /* (handled directly by us) */
+		.header_type	= IW_HEADER_TYPE_NULL,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWSPY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= sizeof(struct sockaddr),
+		.max_tokens	= IW_MAX_SPY,
+	},
+	[SIOCGIWSPY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= sizeof(struct sockaddr) +
+				  sizeof(struct iw_quality),
+		.max_tokens	= IW_MAX_GET_SPY,
+	},
+	[SIOCSIWAP	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_ADDR,
+	},
+	[SIOCGIWAP	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_ADDR,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCGIWAPLIST	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= sizeof(struct sockaddr) +
+				  sizeof(struct iw_quality),
+		.max_tokens	= IW_MAX_AP,
+	},
+	[SIOCSIWSCAN	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWSCAN	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_SCAN_MAX_DATA,
+	},
+	[SIOCSIWESSID	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.flags		= IW_DESCR_FLAG_EVENT,
+	},
+	[SIOCGIWESSID	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+		.flags		= IW_DESCR_FLAG_DUMP,
+	},
+	[SIOCSIWNICKN	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+	},
+	[SIOCGIWNICKN	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ESSID_MAX_SIZE + 1,
+	},
+	[SIOCSIWRATE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWRATE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWRTS	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWRTS	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWFRAG	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWFRAG	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWTXPOW	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWTXPOW	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWRETRY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWRETRY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWENCODE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ENCODING_TOKEN_MAX,
+		.flags		= IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
+	},
+	[SIOCGIWENCODE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_ENCODING_TOKEN_MAX,
+		.flags		= IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
+	},
+	[SIOCSIWPOWER	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWPOWER	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
 };
 static const int standard_ioctl_num = (sizeof(standard_ioctl) /
 				       sizeof(struct iw_ioctl_description));
@@ -184,17 +253,24 @@
  * Meta-data about all the additional standard Wireless Extension events
  * we know about.
  */
-static const struct iw_ioctl_description	standard_event[] = {
-	/* IWEVTXDROP */
-	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
-	/* IWEVQUAL */
-	{ IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0},
-	/* IWEVCUSTOM */
-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_CUSTOM_MAX, 0},
-	/* IWEVREGISTERED */
-	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
-	/* IWEVEXPIRED */
-	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+static const struct iw_ioctl_description standard_event[] = {
+	[IWEVTXDROP	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_ADDR,
+	},
+	[IWEVQUAL	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_QUAL,
+	},
+	[IWEVCUSTOM	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_CUSTOM_MAX,
+	},
+	[IWEVREGISTERED	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_ADDR,
+	},
+	[IWEVEXPIRED	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_ADDR, 
+	},
 };
 static const int standard_event_num = (sizeof(standard_event) /
 				       sizeof(struct iw_ioctl_description));
diff -urN linux-2.5.68-bk8/net/decnet/dn_route.c linux-2.5.68-bk9/net/decnet/dn_route.c
--- linux-2.5.68-bk8/net/decnet/dn_route.c	2003-04-19 19:51:12.000000000 -0700
+++ linux-2.5.68-bk9/net/decnet/dn_route.c	2003-04-29 04:37:11.000000000 -0700
@@ -893,6 +893,7 @@
 			goto out;
 		dev_hold(dev_out);
 source_ok:
+		;
 	}
 
 	/* No destination? Assume its local */
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/arptable_filter.c linux-2.5.68-bk9/net/ipv4/netfilter/arptable_filter.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/arptable_filter.c	2003-04-19 19:48:46.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/arptable_filter.c	2003-04-29 04:37:11.000000000 -0700
@@ -133,11 +133,13 @@
 static struct nf_hook_ops arpt_ops[] = {
 	{
 		.hook		= arpt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= NF_ARP,
 		.hooknum	= NF_ARP_IN,
 	},
 	{
 		.hook		= arpt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= NF_ARP,
 		.hooknum	= NF_ARP_OUT,
 	}
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_amanda.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-04-19 19:50:07.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-04-29 04:37:11.000000000 -0700
@@ -207,5 +207,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(ip_amanda_lock);
+
 module_init(init);
 module_exit(fini);
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_core.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_core.c	2003-04-19 19:48:46.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_core.c	2003-04-29 04:37:11.000000000 -0700
@@ -1421,7 +1421,7 @@
 	ip_conntrack_max = 8 * ip_conntrack_htable_size;
 
 	printk("ip_conntrack version %s (%u buckets, %d max)"
-	       " - %d bytes per conntrack\n", IP_CONNTRACK_VERSION,
+	       " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
 	       ip_conntrack_htable_size, ip_conntrack_max,
 	       sizeof(struct ip_conntrack));
 
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-04-29 04:37:11.000000000 -0700
@@ -437,9 +437,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IP_NF_NAT_NEEDED
 EXPORT_SYMBOL(ip_ftp_lock);
-#endif
 
 MODULE_LICENSE("GPL");
 module_init(init);
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_irc.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_irc.c	2003-04-29 04:37:11.000000000 -0700
@@ -289,9 +289,7 @@
 	}
 }
 
-#ifdef CONFIG_IP_NF_NAT_NEEDED
 EXPORT_SYMBOL(ip_irc_lock);
-#endif
 
 module_init(init);
 module_exit(fini);
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-04-19 19:49:22.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-04-29 04:37:11.000000000 -0700
@@ -227,6 +227,7 @@
    make it the first hook. */
 static struct nf_hook_ops ip_conntrack_in_ops = {
 	.hook		= ip_conntrack_in,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_PRE_ROUTING,
 	.priority	= NF_IP_PRI_CONNTRACK,
@@ -234,6 +235,7 @@
 
 static struct nf_hook_ops ip_conntrack_local_out_ops = {
 	.hook		= ip_conntrack_local,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_OUT,
 	.priority	= NF_IP_PRI_CONNTRACK,
@@ -242,6 +244,7 @@
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops = {
 	.hook		= ip_refrag,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
 	.priority	= NF_IP_PRI_LAST,
@@ -249,6 +252,7 @@
 
 static struct nf_hook_ops ip_conntrack_local_in_ops = {
 	.hook		= ip_confirm,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_IN,
 	.priority	= NF_IP_PRI_LAST-1,
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_fw_compat.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_fw_compat.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_fw_compat.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_fw_compat.c	2003-04-29 04:37:11.000000000 -0700
@@ -226,6 +226,7 @@
 
 static struct nf_hook_ops preroute_ops = {
 	.hook		= fw_in,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_PRE_ROUTING,
 	.priority	= NF_IP_PRI_FILTER,
@@ -233,6 +234,7 @@
 
 static struct nf_hook_ops postroute_ops = {
 	.hook		= fw_in,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
 	.priority	= NF_IP_PRI_FILTER,
@@ -240,6 +242,7 @@
 
 static struct nf_hook_ops forward_ops = {
 	.hook		= fw_in,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_FORWARD,
 	.priority	= NF_IP_PRI_FILTER,
@@ -247,6 +250,7 @@
 
 static struct nf_hook_ops local_in_ops = {
 	.hook		= fw_confirm,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_IN,
 	.priority	= NF_IP_PRI_LAST - 1,
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_nat_standalone.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_nat_standalone.c	2003-04-19 19:50:35.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_nat_standalone.c	2003-04-29 04:37:11.000000000 -0700
@@ -238,6 +238,7 @@
 /* Before packet filtering, change destination */
 static struct nf_hook_ops ip_nat_in_ops = {
 	.hook		= ip_nat_fn,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_PRE_ROUTING,
 	.priority	= NF_IP_PRI_NAT_DST,
@@ -246,6 +247,7 @@
 /* After packet filtering, change source */
 static struct nf_hook_ops ip_nat_out_ops = {
 	.hook		= ip_nat_out,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
 	.priority	= NF_IP_PRI_NAT_SRC,
@@ -254,6 +256,7 @@
 /* Before packet filtering, change destination */
 static struct nf_hook_ops ip_nat_local_out_ops = {
 	.hook		= ip_nat_local_fn,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_OUT,
 	.priority	= NF_IP_PRI_NAT_DST,
@@ -262,6 +265,7 @@
 #ifdef CONFIG_IP_NF_NAT_LOCAL
 static struct nf_hook_ops ip_nat_local_in_ops = {
 	.hook		= ip_nat_fn,
+	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_IN,
 	.priority	= NF_IP_PRI_NAT_SRC,
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ip_queue.c linux-2.5.68-bk9/net/ipv4/netfilter/ip_queue.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ip_queue.c	2003-04-19 19:51:22.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ip_queue.c	2003-04-29 04:37:11.000000000 -0700
@@ -300,8 +300,9 @@
 	write_lock_bh(&queue_lock);
 	
 	if (!peer_pid)
-		goto err_out_unlock;
+		goto err_out_free_nskb; 
 
+ 	/* netlink_unicast will either free the nskb or attach it to a socket */ 
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
 	if (status < 0)
 		goto err_out_unlock;
@@ -312,6 +313,9 @@
 
 	write_unlock_bh(&queue_lock);
 	return status;
+
+err_out_free_nskb:
+	kfree_skb(nskb); 
 	
 err_out_unlock:
 	write_unlock_bh(&queue_lock);
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ipt_REJECT.c linux-2.5.68-bk9/net/ipv4/netfilter/ipt_REJECT.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ipt_REJECT.c	2003-04-19 19:50:41.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ipt_REJECT.c	2003-04-29 04:37:11.000000000 -0700
@@ -11,7 +11,6 @@
 #include <net/icmp.h>
 #include <net/ip.h>
 #include <net/tcp.h>
-struct in_device;
 #include <net/route.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_REJECT.h>
@@ -71,8 +70,7 @@
 						.saddr = (local ?
 							  oldskb->nh.iph->daddr :
 							  0),
-						.tos = (RT_TOS(oldskb->nh.iph->tos) |
-							RTO_CONN) } } };
+						.tos = RT_TOS(oldskb->nh.iph->tos) } } };
 
 		/* Routing: if not headed for us, route won't like source */
 		if (ip_route_output_key(&rt, &fl))
@@ -88,8 +86,10 @@
 	   hh_len of incoming interface < hh_len of outgoing interface */
 	nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb),
 			       GFP_ATOMIC);
-	if (!nskb)
+	if (!nskb) {
+		dst_release(&rt->u.dst);
 		return;
+	}
 
 	dst_release(nskb->dst);
 	nskb->dst = &rt->u.dst;
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/ipt_physdev.c linux-2.5.68-bk9/net/ipv4/netfilter/ipt_physdev.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/ipt_physdev.c	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/ipt_physdev.c	2003-04-29 04:37:11.000000000 -0700
@@ -4,6 +4,9 @@
 #include <linux/skbuff.h>
 #include <linux/netfilter_ipv4/ipt_physdev.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_bridge.h>
+#define MATCH   1
+#define NOMATCH 0
 
 static int
 match(const struct sk_buff *skb,
@@ -25,29 +28,62 @@
 	/* Not a bridged IP packet or no info available yet:
 	 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
 	 * the destination device will be a bridge. */
-	if (!(nf_bridge = skb->nf_bridge))
-		return 1;
+	if (!(nf_bridge = skb->nf_bridge)) {
+		/* Return MATCH if the invert flags of the used options are on */
+		if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
+		    !(info->invert & IPT_PHYSDEV_OP_BRIDGED))
+			return NOMATCH;
+		if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) &&
+		    !(info->invert & IPT_PHYSDEV_OP_ISIN))
+			return NOMATCH;
+		if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) &&
+		    !(info->invert & IPT_PHYSDEV_OP_ISOUT))
+			return NOMATCH;
+		if ((info->bitmask & IPT_PHYSDEV_OP_IN) &&
+		    !(info->invert & IPT_PHYSDEV_OP_IN))
+			return NOMATCH;
+		if ((info->bitmask & IPT_PHYSDEV_OP_OUT) &&
+		    !(info->invert & IPT_PHYSDEV_OP_OUT))
+			return NOMATCH;
+		return MATCH;
+	}
 
-	indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
-	outdev = nf_bridge->physoutdev ?
-		 nf_bridge->physoutdev->name : nulldevname;
+	/* This only makes sense in the FORWARD and POSTROUTING chains */
+	if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
+	    (!!(nf_bridge->mask & BRNF_BRIDGED) ^
+	    !(info->invert & IPT_PHYSDEV_OP_BRIDGED)))
+		return NOMATCH;
+
+	if ((info->bitmask & IPT_PHYSDEV_OP_ISIN &&
+	    (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) ||
+	    (info->bitmask & IPT_PHYSDEV_OP_ISOUT &&
+	    (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT))))
+		return NOMATCH;
 
+	if (!(info->bitmask & IPT_PHYSDEV_OP_IN))
+		goto match_outdev;
+	indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
 		ret |= (((const unsigned long *)indev)[i]
 			^ ((const unsigned long *)info->physindev)[i])
 			& ((const unsigned long *)info->in_mask)[i];
 	}
 
-	if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_MATCH_IN))
-		return 0;
+	if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN))
+		return NOMATCH;
 
+match_outdev:
+	if (!(info->bitmask & IPT_PHYSDEV_OP_OUT))
+		return MATCH;
+	outdev = nf_bridge->physoutdev ?
+		 nf_bridge->physoutdev->name : nulldevname;
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
 		ret |= (((const unsigned long *)outdev)[i]
 			^ ((const unsigned long *)info->physoutdev)[i])
 			& ((const unsigned long *)info->out_mask)[i];
 	}
 
-	return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_MATCH_OUT);
+	return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT);
 }
 
 static int
@@ -57,9 +93,13 @@
 		       unsigned int matchsize,
 		       unsigned int hook_mask)
 {
+	const struct ipt_physdev_info *info = matchinfo;
+
 	if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info)))
 		return 0;
-
+	if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) ||
+	    info->bitmask & ~IPT_PHYSDEV_OP_MASK)
+		return 0;
 	return 1;
 }
 
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/iptable_filter.c linux-2.5.68-bk9/net/ipv4/netfilter/iptable_filter.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/iptable_filter.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/iptable_filter.c	2003-04-29 04:37:11.000000000 -0700
@@ -125,18 +125,21 @@
 static struct nf_hook_ops ipt_ops[] = {
 	{
 		.hook		= ipt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_LOCAL_IN,
 		.priority	= NF_IP_PRI_FILTER,
 	},
 	{
 		.hook		= ipt_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_FORWARD,
 		.priority	= NF_IP_PRI_FILTER,
 	},
 	{
 		.hook		= ipt_local_out_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_LOCAL_OUT,
 		.priority	= NF_IP_PRI_FILTER,
diff -urN linux-2.5.68-bk8/net/ipv4/netfilter/iptable_mangle.c linux-2.5.68-bk9/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.5.68-bk8/net/ipv4/netfilter/iptable_mangle.c	2003-04-19 19:50:45.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/netfilter/iptable_mangle.c	2003-04-29 04:37:11.000000000 -0700
@@ -178,30 +178,35 @@
 static struct nf_hook_ops ipt_ops[] = {
 	{
 		.hook		= ipt_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_PRE_ROUTING, 
 		.priority	= NF_IP_PRI_MANGLE,
 	},
 	{
 		.hook		= ipt_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_LOCAL_IN,
 		.priority	= NF_IP_PRI_MANGLE,
 	},
 	{
 		.hook		= ipt_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_FORWARD,
 		.priority	= NF_IP_PRI_MANGLE,
 	},
 	{
 		.hook		= ipt_local_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_LOCAL_OUT,
 		.priority	= NF_IP_PRI_MANGLE,
 	},
 	{
 		.hook		= ipt_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET,
 		.hooknum	= NF_IP_POST_ROUTING,
 		.priority	= NF_IP_PRI_MANGLE,
diff -urN linux-2.5.68-bk8/net/ipv4/xfrm4_tunnel.c linux-2.5.68-bk9/net/ipv4/xfrm4_tunnel.c
--- linux-2.5.68-bk8/net/ipv4/xfrm4_tunnel.c	2003-04-19 19:48:51.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv4/xfrm4_tunnel.c	2003-04-29 04:37:11.000000000 -0700
@@ -174,6 +174,8 @@
 
 static int ipip_init_state(struct xfrm_state *x, void *args)
 {
+	if (!x->props.mode)
+		return -EINVAL;
 	x->props.header_len = sizeof(struct iphdr);
 
 	return 0;
diff -urN linux-2.5.68-bk8/net/ipv6/netfilter/ip6_queue.c linux-2.5.68-bk9/net/ipv6/netfilter/ip6_queue.c
--- linux-2.5.68-bk8/net/ipv6/netfilter/ip6_queue.c	2003-04-19 19:48:56.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv6/netfilter/ip6_queue.c	2003-04-29 04:37:11.000000000 -0700
@@ -304,8 +304,9 @@
 	write_lock_bh(&queue_lock);
 	
 	if (!peer_pid)
-		goto err_out_unlock;
+		goto err_out_free_nskb; 
 
+ 	/* netlink_unicast will either free the nskb or attach it to a socket */ 
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
 	if (status < 0)
 		goto err_out_unlock;
@@ -317,6 +318,9 @@
 	write_unlock_bh(&queue_lock);
 	return status;
 	
+err_out_free_nskb:
+	kfree_skb(nskb); 
+	
 err_out_unlock:
 	write_unlock_bh(&queue_lock);
 
diff -urN linux-2.5.68-bk8/net/ipv6/netfilter/ip6t_LOG.c linux-2.5.68-bk9/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.5.68-bk8/net/ipv6/netfilter/ip6t_LOG.c	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv6/netfilter/ip6t_LOG.c	2003-04-29 04:37:11.000000000 -0700
@@ -89,7 +89,7 @@
 	printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
-	printk("LEN=%u TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
 	       ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
 	       (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
 	       ipv6h->hop_limit,
diff -urN linux-2.5.68-bk8/net/ipv6/netfilter/ip6table_filter.c linux-2.5.68-bk9/net/ipv6/netfilter/ip6table_filter.c
--- linux-2.5.68-bk8/net/ipv6/netfilter/ip6table_filter.c	2003-04-19 19:48:50.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv6/netfilter/ip6table_filter.c	2003-04-29 04:37:11.000000000 -0700
@@ -123,18 +123,21 @@
 static struct nf_hook_ops ip6t_ops[] = {
 	{
 		.hook		= ip6t_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_LOCAL_IN,
 		.priority	= NF_IP6_PRI_FILTER,
 	},
 	{
 		.hook		= ip6t_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_FORWARD,
 		.priority	= NF_IP6_PRI_FILTER,
 	},
 	{
 		.hook		= ip6t_local_out_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_LOCAL_OUT,
 		.priority	= NF_IP6_PRI_FILTER,
diff -urN linux-2.5.68-bk8/net/ipv6/netfilter/ip6table_mangle.c linux-2.5.68-bk9/net/ipv6/netfilter/ip6table_mangle.c
--- linux-2.5.68-bk8/net/ipv6/netfilter/ip6table_mangle.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/net/ipv6/netfilter/ip6table_mangle.c	2003-04-29 04:37:11.000000000 -0700
@@ -186,30 +186,35 @@
 static struct nf_hook_ops ip6t_ops[] = {
 	{
 		.hook		= ip6t_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_PRE_ROUTING,
 		.priority	= NF_IP6_PRI_MANGLE,
 	},
 	{
 		.hook		= ip6t_local_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_LOCAL_IN,
 		.priority	= NF_IP6_PRI_MANGLE,
 	},
 	{
 		.hook		= ip6t_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_FORWARD,
 		.priority	= NF_IP6_PRI_MANGLE,
 	},
 	{
 		.hook		= ip6t_local_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_LOCAL_OUT,
 		.priority	= NF_IP6_PRI_MANGLE,
 	},
 	{
 		.hook		= ip6t_route_hook,
+		.owner		= THIS_MODULE,
 		.pf		= PF_INET6,
 		.hooknum	= NF_IP6_POST_ROUTING,
 		.priority	= NF_IP6_PRI_MANGLE,
diff -urN linux-2.5.68-bk8/net/ipx/af_ipx.c linux-2.5.68-bk9/net/ipx/af_ipx.c
--- linux-2.5.68-bk8/net/ipx/af_ipx.c	2003-04-19 19:48:53.000000000 -0700
+++ linux-2.5.68-bk9/net/ipx/af_ipx.c	2003-04-29 04:37:11.000000000 -0700
@@ -95,18 +95,6 @@
 atomic_t ipx_sock_nr;
 #endif
 
-static void ipxcfg_set_auto_create(char val)
-{
-	if (ipxcfg_auto_create_interfaces != val) {
-		if (val)
-			MOD_INC_USE_COUNT;
-		else
-			MOD_DEC_USE_COUNT;
-
-		ipxcfg_auto_create_interfaces = val;
-	}
-}
-
 static void ipxcfg_set_auto_select(char val)
 {
 	ipxcfg_auto_select_primary = val;
@@ -373,7 +361,6 @@
 	if (intrfc->if_dev)
 		dev_put(intrfc->if_dev);
 	kfree(intrfc);
-	MOD_DEC_USE_COUNT;
 }
 
 static void ipxitf_down(struct ipx_interface *intrfc)
@@ -949,7 +936,6 @@
 		intrfc->if_sklist 	= NULL;
 		atomic_set(&intrfc->refcnt, 1);
 		spin_lock_init(&intrfc->if_sklist_lock);
-		MOD_INC_USE_COUNT;
 	}
 
 	return intrfc;
@@ -1272,7 +1258,7 @@
 		case SIOCAIPXITFCRT: 
 			if (get_user(val, (unsigned char *) arg))
 				return -EFAULT;
-			ipxcfg_set_auto_create(val);
+			ipxcfg_auto_create_interfaces = val;
 			break;
 
 		case SIOCAIPXPRISLT: 
@@ -1690,13 +1676,12 @@
 	struct ipx_opt *ipx = NULL;
 	struct sock *sk;
 
-	MOD_INC_USE_COUNT;
 	switch (sock->type) {
 		case SOCK_DGRAM:
 			sk = sk_alloc(PF_IPX, GFP_KERNEL, 1, NULL);
                 	ret = -ENOMEM;
 			if (!sk)
-				goto decmod;
+				goto out;
 			ipx = ipx_sk(sk) = kmalloc(sizeof(*ipx), GFP_KERNEL);
 			if (!ipx)
 				goto outsk;
@@ -1713,7 +1698,7 @@
 			 */
 		case SOCK_STREAM:       /* Allow higher levels to piggyback */
 		default:
-			goto decmod;
+			goto out;
 	}
 #ifdef IPX_REFCNT_DEBUG
         atomic_inc(&ipx_sock_nr);
@@ -1727,8 +1712,6 @@
 	return ret;
 outsk:
 	sk_free(sk);
-decmod:
-	MOD_DEC_USE_COUNT;
 	goto out;
 }
 
@@ -1745,10 +1728,6 @@
 	__set_bit(SOCK_DEAD, &sk->flags);
 	sock->sk = NULL;
 	ipx_destroy_socket(sk);
-
-	if (sock->type == SOCK_DGRAM)
-		MOD_DEC_USE_COUNT;
-
 out:
 	return 0;
 }
@@ -2252,6 +2231,7 @@
 static struct net_proto_family ipx_family_ops = {
 	.family		= PF_IPX,
 	.create		= ipx_create,
+	.owner		= THIS_MODULE,
 };
 
 static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
diff -urN linux-2.5.68-bk8/net/llc/af_llc.c linux-2.5.68-bk9/net/llc/af_llc.c
--- linux-2.5.68-bk8/net/llc/af_llc.c	2003-04-19 19:48:48.000000000 -0700
+++ linux-2.5.68-bk9/net/llc/af_llc.c	2003-04-29 04:37:11.000000000 -0700
@@ -22,6 +22,7 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/tcp.h>
 #include <net/llc_sap.h>
 #include <net/llc_pdu.h>
@@ -1013,6 +1014,7 @@
 static struct net_proto_family llc_ui_family_ops = {
 	.family = PF_LLC,
 	.create = llc_ui_create,
+	.owner	= THIS_MODULE,
 };
 
 static struct proto_ops llc_ui_ops = {
diff -urN linux-2.5.68-bk8/net/llc/llc_if.c linux-2.5.68-bk9/net/llc/llc_if.c
--- linux-2.5.68-bk8/net/llc/llc_if.c	2003-04-19 19:49:31.000000000 -0700
+++ linux-2.5.68-bk9/net/llc/llc_if.c	2003-04-29 04:37:11.000000000 -0700
@@ -43,16 +43,15 @@
 	/* verify this SAP is not already open; if so, return error */
 	struct llc_sap *sap;
 
-	MOD_INC_USE_COUNT;
 	sap = llc_sap_find(lsap);
 	if (sap) { /* SAP already exists */
 		sap = NULL;
-		goto err;
+		goto out;
 	}
 	/* sap requested does not yet exist */
 	sap = llc_sap_alloc();
 	if (!sap)
-		goto err;
+		goto out;
 	/* allocated a SAP; initialize it and clear out its memory pool */
 	sap->laddr.lsap = lsap;
 	sap->rcv_func	= func;
@@ -61,9 +60,6 @@
 	llc_sap_save(sap);
 out:
 	return sap;
-err:
-	MOD_DEC_USE_COUNT;
-	goto out;
 }
 
 /**
@@ -76,7 +72,6 @@
 void llc_sap_close(struct llc_sap *sap)
 {
 	llc_free_sap(sap);
-	MOD_DEC_USE_COUNT;
 }
 
 /**
diff -urN linux-2.5.68-bk8/net/llc/llc_main.c linux-2.5.68-bk9/net/llc/llc_main.c
--- linux-2.5.68-bk8/net/llc/llc_main.c	2003-04-19 19:49:10.000000000 -0700
+++ linux-2.5.68-bk9/net/llc/llc_main.c	2003-04-29 04:37:11.000000000 -0700
@@ -224,9 +224,8 @@
 {
 	struct sock *sk = sk_alloc(family, priority, 1, NULL);
 
-	MOD_INC_USE_COUNT;
 	if (!sk)
-		goto decmod;
+		goto out;
 	if (llc_sk_init(sk))
 		goto outsk;
 	sock_init_data(NULL, sk);
@@ -240,8 +239,6 @@
 outsk:
 	sk_free(sk);
 	sk = NULL;
-decmod:
-	MOD_DEC_USE_COUNT;
 	goto out;
 }
 
@@ -279,7 +276,6 @@
 	}
 #endif
 	sock_put(sk);
-	MOD_DEC_USE_COUNT;
 }
 
 /**
diff -urN linux-2.5.68-bk8/net/sched/sch_ingress.c linux-2.5.68-bk9/net/sched/sch_ingress.c
--- linux-2.5.68-bk8/net/sched/sch_ingress.c	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/net/sched/sch_ingress.c	2003-04-29 04:37:11.000000000 -0700
@@ -241,6 +241,7 @@
 {
 	{ NULL, NULL},
 	ing_hook,
+	THIS_MODULE,
 	PF_INET,
 	NF_IP_PRE_ROUTING,
 	NF_IP_PRI_FILTER + 1
diff -urN linux-2.5.68-bk8/net/socket.c linux-2.5.68-bk9/net/socket.c
--- linux-2.5.68-bk8/net/socket.c	2003-04-29 04:36:54.000000000 -0700
+++ linux-2.5.68-bk9/net/socket.c	2003-04-29 04:37:11.000000000 -0700
@@ -1288,24 +1288,28 @@
 	if (err)
 		goto out_release;
 
+	err = -EBUSY;
+	if (!net_family_get(sock->ops->family))
+		goto out_release;
+
 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
 	if (err < 0)
-		goto out_release;
+		goto out_family_put;
 
 	if (upeer_sockaddr) {
 		if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
 			err = -ECONNABORTED;
-			goto out_release;
+			goto out_family_put;
 		}
 		err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
 		if (err < 0)
-			goto out_release;
+			goto out_family_put;
 	}
 
 	/* File flags are not inherited via accept() unlike another OSes. */
 
 	if ((err = sock_map_fd(newsock)) < 0)
-		goto out_release;
+		goto out_family_put;
 
 	security_socket_post_accept(sock, newsock);
 
@@ -1313,7 +1317,8 @@
 	sockfd_put(sock);
 out:
 	return err;
-
+out_family_put:
+	net_family_put(sock->ops->family);
 out_release:
 	sock_release(newsock);
 	goto out_put;
diff -urN linux-2.5.68-bk8/net/sunrpc/rpc_pipe.c linux-2.5.68-bk9/net/sunrpc/rpc_pipe.c
--- linux-2.5.68-bk8/net/sunrpc/rpc_pipe.c	2003-04-19 19:48:57.000000000 -0700
+++ linux-2.5.68-bk9/net/sunrpc/rpc_pipe.c	2003-04-29 04:37:11.000000000 -0700
@@ -29,7 +29,6 @@
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
 static struct vfsmount *rpc_mount;
-static spinlock_t rpc_mount_lock = SPIN_LOCK_UNLOCKED;
 static int rpc_mount_count;
 
 static struct file_system_type rpc_pipe_fs_type;
@@ -379,46 +378,13 @@
 static int
 rpc_get_mount(void)
 {
-	struct vfsmount * mnt = NULL;
-
-	spin_lock(&rpc_mount_lock);
-	if (rpc_mount)
-		goto out_get;
-	spin_unlock(&rpc_mount_lock);
-	mnt = kern_mount(&rpc_pipe_fs_type);
-	if (IS_ERR(mnt))
-		return -ENODEV;
-	spin_lock(&rpc_mount_lock);
-	if (!rpc_mount) {
-		rpc_mount = mnt;
-		mnt = NULL;
-		goto out_dontget;
-	}
-out_get:
-	mntget(rpc_mount);
-out_dontget:
-	++rpc_mount_count;
-	spin_unlock(&rpc_mount_lock);
-	if (mnt)
-		mntput(mnt);
-	return 0;
+	return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
 }
 
 static void
 rpc_put_mount(void)
 {
-	struct vfsmount *mnt;
-
-	spin_lock(&rpc_mount_lock);
-	mnt = rpc_mount;
-	--rpc_mount_count;
-	if (rpc_mount_count == 0)
-		rpc_mount = NULL;
-	else
-		mnt = NULL;
-	spin_unlock(&rpc_mount_lock);
-	if (mnt)
-		mntput(mnt);
+	simple_release_fs(&rpc_mount, &rpc_mount_count);
 }
 
 static int
diff -urN linux-2.5.68-bk8/net/unix/af_unix.c linux-2.5.68-bk9/net/unix/af_unix.c
--- linux-2.5.68-bk8/net/unix/af_unix.c	2003-04-19 19:50:04.000000000 -0700
+++ linux-2.5.68-bk9/net/unix/af_unix.c	2003-04-29 04:37:11.000000000 -0700
@@ -47,6 +47,9 @@
  *	     Alexey Kuznetsov   :	Full scale SMP. Lot of bugs are introduced 8)
  *	      Malcolm Beattie   :	Set peercred for socketpair
  *	     Michal Ostrowski   :       Module initialization cleanup.
+ *	     Arnaldo C. Melo	:	Remove MOD_{INC,DEC}_USE_COUNT,
+ *	     				the core infrastructure is doing that
+ *	     				for all net proto families now (2.5.69+)
  *
  *
  * Known differences from reference BSD that was tested:
@@ -360,7 +363,6 @@
 #ifdef UNIX_REFCNT_DEBUG
 	printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, atomic_read(&unix_nr_socks));
 #endif
-	MOD_DEC_USE_COUNT;
 }
 
 static int unix_release_sock (unix_socket *sk, int embrion)
@@ -478,19 +480,16 @@
 
 static struct sock * unix_create1(struct socket *sock)
 {
-	struct sock *sk;
+	struct sock *sk = NULL;
 	struct unix_sock *u;
 
 	if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files)
-		return NULL;
+		goto out;
 
-	MOD_INC_USE_COUNT;
 	sk = sk_alloc(PF_UNIX, GFP_KERNEL, sizeof(struct unix_sock),
 		      unix_sk_cachep);
-	if (!sk) {
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
+	if (!sk)
+		goto out;
 
 	atomic_inc(&unix_nr_socks);
 
@@ -509,7 +508,7 @@
 	init_MUTEX(&u->readsem); /* single task reading lock */
 	init_waitqueue_head(&u->peer_wait);
 	unix_insert_socket(&unix_sockets_unbound, sk);
-
+out:
 	return sk;
 }
 
@@ -1928,6 +1927,7 @@
 struct net_proto_family unix_family_ops = {
 	.family = PF_UNIX,
 	.create = unix_create,
+	.owner	= THIS_MODULE,
 };
 
 #ifdef CONFIG_SYSCTL
