diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Tue Feb 26 11:57:57 2002
+++ b/CREDITS	Tue Feb 26 11:57:57 2002
@@ -1219,10 +1219,10 @@
 S: Germany
 
 N: Christoph Hellwig
-E: hch@caldera.de
 E: hch@infradead.org
 D: misc driver & makefile hacking
 D: freevxfs driver
+D: sysvfs maintainer
 S: Triftstraße 26
 S: 38644 Goslar
 S: Germany
@@ -2672,6 +2672,16 @@
 D: Linux-Support, -Mailbox, -Stammtisch
 D: several improvements to system programs
 S: Oldenburg
+S: Germany
+
+N: Robert Schwebel
+E: robert@schwebel.de
+W: http://www.schwebel.de
+D: Embedded hacker and book author,
+D: AMD Elan support for Linux
+S: Pengutronix
+S: Braunschweiger Strasse 79
+S: 31134 Hildesheim
 S: Germany
 
 N: Darren Senn
diff -Nru a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/arm/mem_alignment	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,58 @@
+Too many problems poped up because of unnoticed misaligned memory access in
+kernel code lately.  Therefore the alignment fixup is now unconditionally
+configured in for SA11x0 based targets.  According to Alan Cox, this is a
+bad idea to configure it out, but Russell King has some good reasons for
+doing so on some f***ed up ARM architectures like the EBSA110.  However
+this is not the case on many design I'm aware of, like all SA11x0 based
+ones.
+
+Of course this is a bad idea to rely on the alignment trap to perform
+unaligned memory access in general.  If those access are predictable, you
+are better to use the macros provided by include/asm/unaligned.h.  The
+alignment trap can fixup misaligned access for the exception cases, but at
+a high performance cost.  It better be rare.
+
+Now for user space applications, it is possible to configure the alignment
+trap to SIGBUS any code performing unaligned access (good for debugging bad
+code), or even fixup the access by software like for kernel code.  The later
+mode isn't recommended for performance reasons (just think about the
+floating point emulation that works about the same way).  Fix your code
+instead!
+
+Please note that randomly changing the behaviour without good thought is
+real bad - it changes the behaviour of all unaligned instructions in user
+space, and might cause programs to fail unexpectedly.
+
+To change the alignment trap behavior, simply echo a number into
+/proc/sys/debug/alignment.  The number is made up from various bits:
+
+bit		behavior when set
+---		-----------------
+
+0		A user process performing an unaligned memory access
+		will cause the kernel to print a message indicating
+		process name, pid, pc, instruction, address, and the
+		fault code.
+
+1		The kernel will attempt to fix up the user process
+		performing the unaligned access.  This is of course
+		slow (think about the floating point emulator) and
+		not recommended for production use.
+
+2		The kernel will send a SIGBUS signal to the user process
+		performing the unaligned access.
+
+Note that not all combinations are supported - only values 0 through 5.
+(6 and 7 don't make sense).
+
+For example, the following will turn on the warnings, but without
+fixing up or sending SIGBUS signals:
+
+	echo 1 > /proc/sys/debug/alignment
+
+You can also read the content of the same file to get statistical
+information on unaligned access occurences plus the current mode of
+operation for user space code.
+
+
+Nicolas Pitre, Mar 13, 2001.  Modified Russell King, Nov 30, 2001.
diff -Nru a/Documentation/filesystems/porting b/Documentation/filesystems/porting
--- a/Documentation/filesystems/porting	Tue Feb 26 11:57:58 2002
+++ b/Documentation/filesystems/porting	Tue Feb 26 11:57:58 2002
@@ -81,11 +81,12 @@
 [mandatory]
 
 ->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
-->rmdir(), ->link(), ->symlink() and ->rename() are called without BKL now.
-Grab it on the entry, drop upon return - that will guarantee the same
-locking you used to have.  If your method or its parts do not need BKL -
-better yet, now you can shift lock_kernel() / unlock_kernel() so that
-they would protect exactly what needs to be protected.
+->rmdir(), ->link(), ->lseek(), ->symlink() and ->rename() are called
+without BKL now.  Grab it on the entry, drop upon return - that will
+guarantee the same locking you used to have.  If your method or its
+parts do not need BKL - better yet, now you can shift lock_kernel() and
+unlock_kernel() so that they would protect exactly what needs to be
+protected.
 
 ---
 [informational]
diff -Nru a/Documentation/kbuild/config-language.txt b/Documentation/kbuild/config-language.txt
--- a/Documentation/kbuild/config-language.txt	Tue Feb 26 11:57:59 2002
+++ b/Documentation/kbuild/config-language.txt	Tue Feb 26 11:57:59 2002
@@ -30,7 +30,7 @@
     scripts/Configure   make config, make oldconfig
     scripts/Menuconfig  make menuconfig
     scripts/tkparse     make xconfig
-    mconfig             (in development)
+    mconfig             ftp.kernel.org/pub/linux/kernel/people/hch/mconfig/
 
 'Configure' is a bash script which interprets Config.in files by sourcing
 them.  Some of the Config Language commands are native bash commands;
@@ -52,9 +52,6 @@
 into an internal syntax tree and then hands the syntax tree to one of
 several user-interface front ends.
 
-This document describes the behaviour of all four interpreters, even though
-mconfig has not been released at the time of writing.
-
 
 
 === Statements
@@ -489,7 +486,7 @@
 Configure:  implemented
 Menuconfig: implemented
 XConfig:    implemented
-mconfig:    not implemented
+mconfig:    implemented
 
 Example:
 
diff -Nru a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/networking/3c359.txt	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,58 @@
+
+3COM PCI TOKEN LINK VELOCITY XL TOKEN RING CARDS README
+
+Release 0.9.0 - Release   
+	Jul 17th 2000 Mike Phillips 
+
+	1.2.0 - Final
+	Feb 17th 2002 Mike Phillips 
+	Updated for submission to the 2.4.x kernel.
+
+Thanks:
+	Terry Murphy from 3Com for tech docs and support,
+	Adam D. Ligas for testing the driver.
+ 
+Note:
+	This driver will NOT work with the 3C339 Token Ring cards, you need
+to use the tms380 driver instead.
+
+Options:
+
+The driver accepts three options: ringspeed, pkt_buf_sz and message_level.
+
+These options can be specified differently for each card found. 
+
+ringspeed:  Has one of three settings 0 (default), 4 or 16.  0 will 
+make the card autosense the ringspeed and join at the appropriate speed, 
+this will be the default option for most people.  4 or 16 allow you to 
+explicitly force the card to operate at a certain speed.  The card will fail 
+if you try to insert it at the wrong speed. (Although some hubs will allow 
+this so be *very* careful).  The main purpose for explicitly setting the ring
+speed is for when the card is first on the ring.  In autosense mode, if the card
+cannot detect any active monitors on the ring it will open at the same speed as
+its last opening. This can be hazardous if this speed does not match the speed
+you want the ring to operate at.  
+
+pkt_buf_sz:  This is this initial receive buffer allocation size.  This will
+default to 4096 if no value is entered. You may increase performance of the 
+driver by setting this to a value larger than the network packet size, although
+the driver now re-sizes buffers based on MTU settings as well. 
+
+message_level: Controls level of messages created by the driver. Defaults to 0:
+which only displays start-up and critical messages.  Presently any non-zero 
+value will display all soft messages as well.  NB This does not turn 
+debuging messages on, that must be done by modified the source code.
+
+Variable MTU size:
+
+The driver can handle a MTU size upto either 4500 or 18000 depending upon 
+ring speed.  The driver also changes the size of the receive buffers as part
+of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
+to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring 
+position = 296,000 bytes of memory space, plus of course anything 
+necessary for the tx sk_buff's.  Remember this is per card, so if you are
+building routers, gateway's etc, you could start to use a lot of memory
+real fast.
+
+2/17/02 Mike Phillips
+
diff -Nru a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/networking/e1000.txt	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,245 @@
+Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
+===============================================================
+
+February 5, 2002
+
+
+Contents
+========
+
+- In This Release
+- Supported Adapters
+- Command Line Parameters
+- Speed and Duplex Configuration
+- Known Issues
+- Support
+
+
+In This Release
+===============
+
+This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
+of Adapters, version 4.2.x.
+This driver includes support for Itanium(TM)-based systems.
+
+This release version includes the following:
+
+   - support for the ethtool 1.4 interface. A third-party application can use
+     the ethtool interface to get and set driver parameters.
+
+   - the zero copy feature. Zero copy provides faster information throughput.
+     By default, this feature is enabled if using a kernel that supports it.
+     Zero copy is not supported on the original PWLA8490 (plain) adapter.
+
+
+Supported Adapters
+==================
+
+The following Intel network adapters are compatible with the drivers in this
+release:
+
+   Controller  Adapter Name                     Board IDs
+   ----------  ------------                     ---------
+
+   82542       PRO/1000 Gigabit Server Adapter  700262-xxx, 717037-xxx
+
+   82543       PRO/1000 F Server Adapter        738640-xxx, A38888-xxx,
+                                                A06512-xxx
+
+   82543       PRO/1000 T Server Adapter        A19845-xxx, A33948-xxx
+
+   82544       PRO/1000 XT Server Adapter       A51580-xxx
+
+   82544       PRO/1000 XF Server Adapter       A50484-xxx
+
+   82544       PRO/1000 T Desktop Adapter       A62947-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 of
+123456-001 (six digits hyphen three digits). 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://appsr.intel.com/scripts-df/support_intel.asp
+
+
+Command Line Parameters
+=======================
+
+If the driver is built as a module, the following parameters are used by
+entering them on the command line with the modprobe or insmod command.
+For example, with two PRO/1000 PCI adapters, entering:
+
+    insmod e1000 TxDescriptors=80,128
+
+loads the e1000 driver with 80 TX resources for the first adapter and 128 TX
+resources for the second adapter.
+
+For more information about the AutoNeg, Duplex, and Speed parameters, see the
+"Speed and Duplex Configuration" section in this document.
+
+
+AutoNeg (Intel PRO/1000 T and PRO/1000 XT server adapters only)
+Valid Range: 0-0x0F, 0x20-0x2F
+Default Value: 0x2F
+    This parameter is a bit mask that specifies which speed and duplex
+    settings the board advertises. When this parameter is used, the Speed and
+    Duplex parameters must not be specified.
+
+Duplex (Intel PRO/1000 T and PRO/1000 XT server adapters only)
+Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
+Default Value: 0
+    Defines the direction in which data is allowed to flow. Can by either one
+    or two-directional. If both Duplex and the link partner are set to auto-
+    negotiate, the board auto-detects the correct duplex. If the link partner
+    is forced (either full or half), Duplex defaults to half-duplex.
+
+FlowControl
+Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
+Default: Read flow control settings from the EEPROM
+    This parameter controls the automatic generation(Tx) and response(Rx) to
+    Ethernet PAUSE frames.
+
+RxDescriptors
+Valid Range: 80-256 for 82542 and 82543-based adapters
+             80-4096 for 82544-based adapters
+Default Value: 256
+    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, 4096, 8192, or 16384 bytes, depending
+    on the MTU setting.
+
+RxIntDelay
+Valid Range: 0-65535 (0=off)
+Default Value: 64
+    This value delays the generation of receive interrupts in units of 1.024
+    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.
+
+Speed (Intel PRO/1000 T and PRO/1000 XT server adapters only)
+Valid Settings: 0, 10, 100, 1000
+Default Value: 0 (auto-negotiate at all supported speeds)
+    Speed forces the line speed to the specified value in megabits per second
+    (Mbps). If this parameter is not specified or is set to 0 and the link
+    partner is set to auto-negotiate, the board will auto-detect the correct
+    speed. Duplex must also be set when Speed is set to either 10 or 100.
+
+TxDescriptors
+Valid Range: 80-256 for 82542 and 82543-based adapters
+             80-4096 for 82544-based adapters
+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.
+
+TxIntDelay
+Valid Range: 0-65535 (0=off)
+Default Value: 64
+    This value delays the generation of transmit interrupts in units of 1.024
+    microseconds.  Transmit interrupt reduction can improve CPU efficiency if
+    properly tuned for specific network traffic.  If the system is reporting
+    dropped transmits, this value may be set too high causing the driver to
+    run out of available transmit descriptors.
+
+XsumRX (not available on the PRO/1000 Gigabit Server Adapter)
+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.
+
+
+Speed and Duplex Configuration
+==============================
+
+Three keywords are used to control the speed and duplex configuration of the
+PRO/1000 T and PRO/1000 XT server adapters. These keywords are Speed, Duplex,
+and AutoNeg.
+
+If the board uses a fiber interface, these keywords are ignored, and the
+fiber interface board only links at 1000 Mbps full-duplex.
+
+For copper-based boards, the keywords interact as follows:
+
+  The default operation is auto-negotiate. The board advertises all supported
+  speed and duplex combinations, and it links at the highest common speed and
+  duplex mode IF the link partner is set to auto-negotiate.
+
+  If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps is
+  advertised (The 1000BaseT spec requires auto-negotiation.)
+
+  If Speed = 10 or 100, then both Speed and Duplex must be set. Auto-
+  negotiation is disabled, and the AutoNeg parameter is ignored. Partner MUST
+  also be forced.
+
+The AutoNeg parameter is used when more control is required over the auto-
+negotiation process.  When this parameter is used, Speed and Duplex must not
+be specified.  This parameter is a bitmap that specifies which speed and
+duplex settings are advertised to the link partner.
+
+Bit            7      6      5       4       3      2      1       0
+Speed (Mbps)   N/A    N/A    1000    N/A     100    100    10      10
+Duplex                       Full            Full   Half   Full    Half
+
+Note that setting AutoNeg does not guarantee that the board will link at the
+highest specified speed or duplex mode, but the board will link at the
+highest possible speed/duplex of the link partner IF the link partner is also
+set to auto-negotiate. If the link partner is forced speed/duplex, the
+adapter MUST be forced to the same speed/duplex.
+
+
+Known Issues
+============
+
+  Driver Hangs Under Heavy Traffic Loads
+  --------------------------------------
+
+  Intel is aware that previously released e1000 drivers may hang under very
+  specific types of heavy traffic loads. This version includes a workaround
+  that resets the adapter automatically if a hang condition is detected. This
+  workaround ensures network traffic flow is not affected when a hang occurs.
+
+  Jumbo Frames System Requirement
+  -------------------------------
+
+  Memory allocation failures have been observed on Linux systems with 64 MB
+  of RAM or less that are running Jumbo Frames. If you are using Jumbo
+  Frames, your system may require more than the advertised minimum
+  requirement of 64 MB of system memory.
+
+
+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.
+
+
+License
+=======
+
+This software program is released under the terms of a license agreement
+between you ('Licensee') and Intel. Do not use or load this software or any
+associated materials (collectively, the 'Software') until you have carefully
+read the full terms and conditions of the LICENSE located in this software
+package. By loading or using the Software, you agree to the terms of this
+Agreement. If you do not agree with the terms of this Agreement, do not
+install or use the Software.
+
+* Other names and brands may be claimed as the property of others.
diff -Nru a/Documentation/sound/AD1816 b/Documentation/sound/AD1816
--- a/Documentation/sound/AD1816	Tue Feb 26 11:57:57 2002
+++ b/Documentation/sound/AD1816	Tue Feb 26 11:57:57 2002
@@ -80,5 +80,5 @@
   tek@rbg.informatik.tu-darmstadt.de
 
 Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
-Christoph Hellwig <hch@caldera.de>
+Christoph Hellwig <hch@infradead.org>
 	Last modified: 2000/09/20
diff -Nru a/Documentation/sound/NEWS b/Documentation/sound/NEWS
--- a/Documentation/sound/NEWS	Tue Feb 26 11:58:00 2002
+++ b/Documentation/sound/NEWS	Tue Feb 26 11:58:00 2002
@@ -1,6 +1,6 @@
 Linux 2.4 Sound Changes
 2000-September-25
-Christoph Hellwig, <hch@caldera.de>
+Christoph Hellwig, <hch@infradead.org>
 
 
 
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Tue Feb 26 11:57:56 2002
+++ b/MAINTAINERS	Tue Feb 26 11:57:56 2002
@@ -69,6 +69,14 @@
 			it has been replaced by a better system and you
 			should be using that.
 
+3C359 NETWORK DRIVER
+P:	Mike Phillips
+M:	mikep@linuxtr.net
+L:	linux-net@vger.rutgers.edu
+L:	linux-tr@linuxtr.net
+W:	http://www.linuxtr.net
+S:	Maintained
+
 3C501 NETWORK DRIVER
 P:	Alan Cox
 M:	alan@the.3c501.cabal.tm
@@ -118,11 +126,11 @@
 S:	Maintained
 
 A2232 SERIAL BOARD DRIVER
-P:      Enver Haase
-M:      ehaase@inf.fu-berlin.de
-M:      A2232@gmx.net
-L:      linux-m68k@lists.linux-m68k.org
-S:      Maintained
+P:	Enver Haase
+M:	ehaase@inf.fu-berlin.de
+M:	A2232@gmx.net
+L:	linux-m68k@lists.linux-m68k.org
+S:	Maintained
 
 ACENIC DRIVER
 P:	Jes Sorensen
@@ -145,6 +153,14 @@
 W:	http://www.ibm.com/linux/ltc/
 S:	Supported
 
+AACRAID SCSI RAID DRIVER
+P:	Adaptec OEM Raid Solutions
+M:	linux-aacraid-devel@dell.com
+L:	linux-aacraid-devel@dell.com
+L:	linux-aacraid-announce@dell.com
+W:	http://domsch.com/linux
+S:	Supported
+
 ACPI
 P:	Andy Grover
 M:	andrew.grover@intel.com
@@ -290,11 +306,11 @@
 S:	Maintained
 
 COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
-P:      Amy Vanzant-Hodge 
-M:      Amy Vanzant-Hodge (fibrechannel@compaq.com)
+P:	Amy Vanzant-Hodge 
+M:	Amy Vanzant-Hodge (fibrechannel@compaq.com)
 L:	compaqandlinux@cpqlin.van-dijk.net
 W:	ftp.compaq.com/pub/products/drivers/linux
-S:      Supported
+S:	Supported
 
 COMPAQ SMART2 RAID DRIVER
 P:	Charles White	
@@ -311,12 +327,12 @@
 S:	Supported 
 
 COMPUTONE INTELLIPORT MULTIPORT CARD
-P:     Michael H. Warfield
-M:     Michael H. Warfield <mhw@wittsend.com>
-W:     http://www.computone.com/
-W:     http://www.wittsend.com/computone.html
-L:     linux-computone@lazuli.wittsend.com
-S:     Supported
+P:	Michael H. Warfield
+M:	Michael H. Warfield <mhw@wittsend.com>
+W:	http://www.computone.com/
+W:	http://www.wittsend.com/computone.html
+L:	linux-computone@lazuli.wittsend.com
+S:	Supported
 
 COMX/MULTIGATE SYNC SERIAL DRIVERS
 P:	Gergely Madarasz
@@ -330,15 +346,6 @@
 W:	http://kbuild.sourceforge.net
 S:	Maintained
 
-CONFIGURE.HELP
-P:	Steven P. Cole
-M:	Steven P. Cole <elenstev@mesatop.com>
-P:	Eric S. Raymond
-M:	Eric S. Raymond <esr@thyrsus.com>
-L:	kbuild-devel@lists.sourceforge.net
-W:	http://kbuild.sourceforge.net
-S:	Maintained
-
 COSA/SRP SYNC SERIAL DRIVER
 P:	Jan "Yenya" Kasprzak
 M:	kas@fi.muni.cz
@@ -428,9 +435,9 @@
 
 DIGI INTL. EPCA DRIVER
 P:	Chad Schwartz
-M:      support@dgii.com
-L:      digilnux@dgii.com
-S:      Maintained
+M:	support@dgii.com
+L:	digilnux@dgii.com
+S:	Maintained
 
 DIGI RIGHTSWITCH NETWORK DRIVER
 P:	Rick Richardson
@@ -452,12 +459,12 @@
 S:	Supported
 
 DISK GEOMETRY AND PARTITION HANDLING
-P:     Andries Brouwer
-M:     aeb@cwi.nl
-W:     http://www.win.tue.nl/~aeb/linux/Large-Disk.html
-W:     http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
-W:     http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
-S:     Maintained
+P:	Andries Brouwer
+M:	aeb@cwi.nl
+W:	http://www.win.tue.nl/~aeb/linux/Large-Disk.html
+W:	http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
+W:	http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
+S:	Maintained
 
 DISKQUOTA:
 P:	Marco van Wieringen
@@ -532,9 +539,9 @@
 S:	Maintained
 
 ETHERTEAM 16I DRIVER
-P:      Mika Kuoppala
-M:      miku@iki.fi
-S:      Maintained
+P:	Mika Kuoppala
+M:	miku@iki.fi
+S:	Maintained
 
 EXT2 FILE SYSTEM
 P:	Remy Card
@@ -575,7 +582,7 @@
 
 FREEVXFS FILESYSTEM
 P:	Christoph Hellwig
-M:	hch@caldera.de
+M:	hch@infradead.org
 W:	ftp://ftp.openlinux.org/pub/people/hch/vxfs
 S:	Maintained
 
@@ -613,10 +620,10 @@
 S:	Maintained
 
 HFS FILESYSTEM
-P:      Adrian Sun
-M:      asun@cobaltnet.com
-L:      linux-kernel@vger.kernel.org
-S:      Maintained
+P:	Adrian Sun
+M:	asun@cobaltnet.com
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
 
 HGA FRAMEBUFFER DRIVER
 P:	Ferenc Bakonyi
@@ -649,6 +656,11 @@
 W:	http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:	Maintained
 
+HPUSBSCSI
+P:	Oliver Neukum
+M:	drivers@neukum.org
+S:	Maintained
+
 I2C DRIVERS
 P:	Simon Vogl
 M:	simon@tk.uni-linz.ac.at
@@ -691,10 +703,10 @@
 S:	Maintained
 
 IBM ServeRAID RAID DRIVER
-P:      Keith Mitchell
-M:      ipslinux@us.ibm.com
-W:      http://www.developer.ibm.com/welcome/netfinity/serveraid.html
-S:      Supported 
+P:	Keith Mitchell
+M:	ipslinux@us.ibm.com
+W:	http://www.developer.ibm.com/welcome/netfinity/serveraid.html
+S:	Supported 
 
 IDE DRIVER [GENERAL]
 P:	Andre Hedrick
@@ -777,12 +789,19 @@
 M:	tigran@veritas.com
 S:	Maintained
 
+INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
+P:	Chris Leech
+M:	christopher.leech@intel.com
+P:	Scott Feldman
+M:	scott.feldman@intel.com
+S:	Supported
+
 INTERMEZZO FILE SYSTEM
 P:	Peter J. Braam
-M:      braam@clusterfs.com
-W:      http://www.inter-mezzo.org/
-L:      intermezzo-discuss@lists.sourceforge.net
-S:      Maintained
+M:	braam@clusterfs.com
+W:	http://www.inter-mezzo.org/
+L:	intermezzo-discuss@lists.sourceforge.net
+S:	Maintained
 
 IP MASQUERADING:
 P:	Juanjo Ciarlante
@@ -796,11 +815,11 @@
 S:	Maintained
 
 IRDA SUBSYSTEM
-P:      Dag Brattli
-M:      Dag Brattli <dag@brattli.net>
-L:      linux-irda@pasta.cs.uit.no
-W:      http://irda.sourceforge.net/
-S:      Maintained
+P:	Dag Brattli
+M:	Dag Brattli <dag@brattli.net>
+L:	linux-irda@pasta.cs.uit.no
+W:	http://irda.sourceforge.net/
+S:	Maintained
 
 ISAPNP
 P:	Jaroslav Kysela
@@ -875,10 +894,10 @@
 S:	Maintained
 
 LANMEDIA WAN CARD DRIVER
-P:      Andrew Stanley-Jones
-M:      asj@lanmedia.com
-W:      http://www.lanmedia.com/
-S:      Supported
+P:	Andrew Stanley-Jones
+M:	asj@lanmedia.com
+W:	http://www.lanmedia.com/
+S:	Supported
  
 LAPB module
 P:	Henner Eisen
@@ -919,10 +938,10 @@
 S:	Maintained
 
 LOGICAL VOLUME MANAGER
-P:     Heinz Mauelshagen
-L:     linux-LVM@sistina.com
-W:     http://www.sistina.com/lvm
-S:     Maintained 
+P:	Heinz Mauelshagen
+L:	linux-LVM@sistina.com
+W:	http://www.sistina.com/lvm
+S:	Maintained 
 
 LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
 P:	Gerard Roudier
@@ -969,10 +988,9 @@
 S:	Maintained
 
 MICROTEK X6 SCANNER
-P:      Oliver Neukum
-M:      drivers@neukum.org
-W:      http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html
-S:      Maintained
+P:	Oliver Neukum
+M:	drivers@neukum.org
+S:	Maintained
 
 MIPS
 P:	Ralf Baechle
@@ -1015,9 +1033,9 @@
 S:	Maintained
 
 NATSEMI ETHERNET DRIVER (DP8381x)
-P: Tim Hockin
-M:	thockin@hockin.org
-S:	Maintained
+P: 	Tim Hockin
+M:  thockin@hockin.org
+S:  Maintained
 
 NCP FILESYSTEM
 P:	Petr Vandrovec
@@ -1088,17 +1106,17 @@
 S:	Maintained
 
 NFS CLIENT
-P:      Trond Myklebust
-M:      trond.myklebust@fys.uio.no
-L:      linux-kernel@vger.kernel.org
-S:      Maintained
+P:	Trond Myklebust
+M:	trond.myklebust@fys.uio.no
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
 
 NI5010 NETWORK DRIVER
-P:     Jan-Pascal van Best and Andreas Mohr
-M:     Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
-M:     Andreas Mohr <100.30936@germany.net>
-L:     linux-net@vger.kernel.org
-S:     Maintained
+P:	Jan-Pascal van Best and Andreas Mohr
+M:	Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
+M:	Andreas Mohr <100.30936@germany.net>
+L:	linux-net@vger.kernel.org
+S:	Maintained
 
 NINJA SCSI-3 / NINJA SCSI-32Bi PCMCIA SCSI HOST ADAPTER DRIVER
 P:	YOKOTA Hiroshi
@@ -1127,7 +1145,7 @@
 
 OLYMPIC NETWORK DRIVER
 P:	Peter De Shrijver
-M:	p2@ace.ulyssis.student.ac.be
+M:	p2@ace.ulyssis.student.kuleuven.ac.be
 P:	Mike Phillips
 M:	mikep@linuxtr.net 
 L:	linux-net@vger.kernel.org
@@ -1170,9 +1188,9 @@
 
 PERSONALITY HANDLING
 P:	Christoph Hellwig
-M:	hch@caldera.de
+M:	hch@infradead.org
 L:	linux-abi-devel@lists.sourceforge.net
-S:	Supported
+S:	Maintained
 
 PCI ID DATABASE
 P:	Jens Maurer
@@ -1261,6 +1279,12 @@
 W:	http://www.alarsen.net/linux/qnx4fs/
 S:	Maintained
 
+RADEON FRAMEBUFFER DISPLAY DRIVER
+P:  Ani Joshi
+M:  ajoshi@shell.unixbox.com
+L:  linux-fbdev-devel@lists.sourceforge.net
+S:  Maintained
+
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
 P:	Ani Joshi
 M:	ajoshi@shell.unixbox.com
@@ -1280,11 +1304,11 @@
 S:	Maintained
 
 REISERFS FILE SYSTEM
-P:      Hans Reiser
-M:      reiserfs-dev@namesys.com
-L:      reiserfs-list@namesys.com
-W:      http://www.namesys.com
-S:      Supported
+P:	Hans Reiser
+M:	reiserfs-dev@namesys.com
+L:	reiserfs-list@namesys.com
+W:	http://www.namesys.com
+S:	Supported
 
 ROSE NETWORK LAYER
 P:	Jean-Paul Roubelat
@@ -1470,7 +1494,7 @@
 
 SYSV FILESYSTEM
 P:	Christoph Hellwig
-M:	hch@caldera.de
+M:	hch@infradead.org
 S:	Maintained
 
 TLAN NETWORK DRIVER
@@ -1498,10 +1522,10 @@
 S:	Maintained
 
 TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
-P:      Ollie Lho  
-M:      ollie@sis.com.tw
+P:	Ollie Lho  
+M:	ollie@sis.com.tw
 L:	linux-kernel@vger.kernel.org
-S:      Supported
+S:	Supported
 
 TMS380 TOKEN-RING NETWORK DRIVER
 P:	Adam Fritzler
@@ -1613,12 +1637,12 @@
 S:	Maintained
 
 USB OV511 DRIVER
-P:     Mark McClelland
-M:     mmcclell@bigfoot.com
-L:     linux-usb-users@lists.sourceforge.net
-L:     linux-usb-devel@lists.sourceforge.net
-W:     http://alpha.dyndns.org/ov511/
-S:     Maintained
+P:	Mark McClelland
+M:	mmcclell@bigfoot.com
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://alpha.dyndns.org/ov511/
+S:	Maintained
 
 USB PEGASUS DRIVER
 P:	Petko Manolov
@@ -1734,11 +1758,11 @@
 S:	Maintained for 2.2 only
 
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
-P:     Nenad Corbic
-M:     ncorbic@sangoma.com
-M:     dm@sangoma.com
-W:     http://www.sangoma.com
-S:     Supported
+P:	Nenad Corbic
+M:	ncorbic@sangoma.com
+M:	dm@sangoma.com
+W:	http://www.sangoma.com
+S:	Supported
 
 WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
 P:	Jean Tourrilhes
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Tue Feb 26 11:57:57 2002
+++ b/Makefile	Tue Feb 26 11:57:57 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 5
-EXTRAVERSION =
+SUBLEVEL = 6
+EXTRAVERSION =-pre1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Nru a/arch/alpha/Makefile b/arch/alpha/Makefile
--- a/arch/alpha/Makefile	Tue Feb 26 11:57:56 2002
+++ b/arch/alpha/Makefile	Tue Feb 26 11:57:56 2002
@@ -25,6 +25,11 @@
 
 have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
 
+have_msmall_data := $(shell if $(CC) -msmall-data -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+ifeq ($(have_msmall_data),y)
+  CFLAGS := $(CFLAGS) -msmall-data
+endif
+
 # Turn on the proper cpu optimizations.
 ifeq ($(have_mcpu),y)
   # If GENERIC, make sure to turn off any instruction set extensions that
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c	Tue Feb 26 11:57:58 2002
+++ b/arch/alpha/kernel/core_titan.c	Tue Feb 26 11:57:58 2002
@@ -279,7 +279,6 @@
 titan_init_one_pachip_port(titan_pachip_port *port, int index)
 {
 	struct pci_controller *hose;
-	unsigned long sg_size;
 
 	hose = alloc_pci_controller();
 	if (index == 0)
diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
--- a/arch/alpha/kernel/entry.S	Tue Feb 26 11:57:56 2002
+++ b/arch/alpha/kernel/entry.S	Tue Feb 26 11:57:56 2002
@@ -489,22 +489,22 @@
 	.prologue 0
 	bsr	$1,do_switch_stack
 	call_pal PAL_swpctx
-	unop
-	bsr	$1,undo_switch_stack
 	lda	$8,0x3fff
-	mov	$17,$0
+	bsr	$1,undo_switch_stack
 	bic	$30,$8,$8
 	ret	$31,($26),1
 .end alpha_switch_to
 
+#ifdef CONFIG_SMP
 .globl  ret_from_fork
 .align 3
 .ent ret_from_fork
 ret_from_fork:
 	lda	$26,ret_from_sys_call
-	mov	$0,$16
+	mov	$17,$16
 	jmp	$31,schedule_tail
 .end ret_from_fork
+#endif
 
 /*
  * Oh, well.. Disassembling OSF/1 binaries to find out how the
diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
--- a/arch/alpha/kernel/process.c	Tue Feb 26 11:57:58 2002
+++ b/arch/alpha/kernel/process.c	Tue Feb 26 11:57:58 2002
@@ -283,6 +283,7 @@
 	    unsigned long unused,
 	    struct task_struct * p, struct pt_regs * regs)
 {
+	extern void ret_from_sys_call(void);
 	extern void ret_from_fork(void);
 
 	struct thread_info *childti = p->thread_info;
@@ -304,7 +305,11 @@
 	stack = ((struct switch_stack *) regs) - 1;
 	childstack = ((struct switch_stack *) childregs) - 1;
 	*childstack = *stack;
+#ifdef CONFIG_SMP
 	childstack->r26 = (unsigned long) ret_from_fork;
+#else
+	childstack->r26 = (unsigned long) ret_from_sys_call;
+#endif
 	childti->pcb.usp = usp;
 	childti->pcb.ksp = (unsigned long) childstack;
 	childti->pcb.flags = 1;	/* set FEN, clear everything else */
diff -Nru a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
--- a/arch/alpha/kernel/proto.h	Tue Feb 26 11:57:57 2002
+++ b/arch/alpha/kernel/proto.h	Tue Feb 26 11:57:57 2002
@@ -162,9 +162,9 @@
 	unsigned char extra;
 } __mcheck_info;
 
-#define mcheck_expected(cpu)	(__mcheck_info.expected)
-#define mcheck_taken(cpu)	(__mcheck_info.taken)
-#define mcheck_extra(cpu)	(__mcheck_info.extra)
+#define mcheck_expected(cpu)	((void)(cpu), __mcheck_info.expected)
+#define mcheck_taken(cpu)	((void)(cpu), __mcheck_info.taken)
+#define mcheck_extra(cpu)	((void)(cpu), __mcheck_info.extra)
 #endif
 
 #define DEBUG_MCHECK 0          /* 0 = minimal, 1 = debug, 2 = debug+dump.  */
diff -Nru a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
--- a/arch/alpha/kernel/sys_titan.c	Tue Feb 26 11:58:00 2002
+++ b/arch/alpha/kernel/sys_titan.c	Tue Feb 26 11:58:00 2002
@@ -84,8 +84,8 @@
 	*dim3;
 #else
 	volatile unsigned long *dimB;
-	if (bcpu == 0) dimB = &cchip->dim0.csr;
-	else if (bcpu == 1) dimB = &cchip->dim1.csr;
+	dimB = &cchip->dim0.csr;
+	if (bcpu == 1) dimB = &cchip->dim1.csr;
 	else if (bcpu == 2) dimB = &cchip->dim2.csr;
 	else if (bcpu == 3) dimB = &cchip->dim3.csr;
 
@@ -190,9 +190,6 @@
 static void __init
 privateer_init_irq(void)
 {
-	extern asmlinkage void entInt(void);
-	int cpu;
-
 	outb(0, DMA1_RESET_REG);
 	outb(0, DMA2_RESET_REG);
 	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
diff -Nru a/arch/arm/Config.help b/arch/arm/Config.help
--- a/arch/arm/Config.help	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/Config.help	Tue Feb 26 11:57:56 2002
@@ -116,6 +116,16 @@
   information about which PCI hardware does work under Linux and which
   doesn't.
 
+CONFIG_PREEMPT
+  This option reduces the latency of the kernel when reacting to
+  real-time or interactive events by allowing a low priority process to
+  be preempted even if it is in kernel mode executing a system call.
+  This allows applications to run more reliably even when the system is
+  under load.
+
+  Say Y here if you are building a kernel for a desktop, embedded
+  or real-time system.  Say N if you are unsure.
+
 CONFIG_MCA
   MicroChannel Architecture is found in some IBM PS/2 machines and
   laptops.  It is a bus system similar to PCI or ISA. See
@@ -521,6 +531,10 @@
 
   Saying N will reduce the size of the Footbridge kernel.
 
+CONFIG_ARCH_IQ80310
+  Say Y here if you want to run your kernel on the Intel IQ80310
+  evaluation kit for the IOP310 chipset.
+
 CONFIG_ARCH_L7200
   Say Y here if you intend to run this kernel on a LinkUp Systems
   L7200 Software Development Board which uses an ARM720T processor.
@@ -558,6 +572,13 @@
   If you have any questions or comments about the  Compaq Personal
   Server, send e-mail to skiff@crl.dec.com.
 
+CONFIG_PLD_HOTSWAP
+  This enables support for the dynamic loading and configuration of
+  compatible drivers when the contents of the PLD are changed. This
+  is still experimental and requires configuration tools which are
+  not yet generally available. Say N here. You must enable the kernel
+  module loader for this feature to work.
+
 CONFIG_SA1100_ASSABET
   Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
   Microprocessor Development Board (also known as the Assabet).
@@ -567,28 +588,14 @@
   Microprocessor Development Board (Assabet)  with the SA-1111
   Development Board (Nepon).
 
-CONFIG_SA1100_H3600
-  Say Y here if you intend to run this kernel on the Compaq iPAQ
-  H3600 handheld computer.  Information about this machine and the
-  Linux port to this machine can be found at:
-
-  <http://www.handhelds.org/Compaq/index.html#iPAQ_H3600>
-  <http://www.compaq.com/products/handhelds/pocketpc/>
+CONFIG_SA1100_BADGE4
+  Say Y here if you want to build a kernel for the HP Laboratories
+  BadgePAD 4.
 
 CONFIG_SA1100_BRUTUS
   Say Y here if you are using the Intel(R) StrongARM(R) SA-1100
   Microprocessor Development Board (also known as the Brutus).
 
-CONFIG_SA1100_LART
-  Say Y here if you are using the Linux Advanced Radio Terminal
-  (also known as the LART).  See <http://www.lart.tudelft.nl/> for
-  information on the LART.
-
-CONFIG_SA1100_GRAPHICSCLIENT
-  Say Y here if you are using an Applied Data Systems Intel(R)
-  StrongARM(R) SA-1100 based Graphics Client SBC.  See
-  <http://www.flatpanels.com/> for information on this system.
-
 CONFIG_SA1100_CERF
   The Intrinsyc CerfBoard is based on the StrongARM 1110.
   More information is available at:
@@ -602,6 +609,24 @@
   handheld instruments. Information about this machine can be
   found at: <http://www.flexanet.com/>.
 
+CONFIG_SA1100_GRAPHICSCLIENT
+  Say Y here if you are using an Applied Data Systems Intel(R)
+  StrongARM(R) SA-1100 based Graphics Client SBC.  See
+  <http://www.flatpanels.com/> for information on this system.
+
+CONFIG_SA1100_H3600
+  Say Y here if you intend to run this kernel on the Compaq iPAQ
+  H3600 handheld computer.  Information about this machine and the
+  Linux port to this machine can be found at:
+
+  <http://www.handhelds.org/Compaq/index.html#iPAQ_H3600>
+  <http://www.compaq.com/products/handhelds/pocketpc/>
+
+CONFIG_SA1100_LART
+  Say Y here if you are using the Linux Advanced Radio Terminal
+  (also known as the LART).  See <http://www.lart.tudelft.nl/> for
+  information on the LART.
+
 CONFIG_SA1100_NANOENGINE
   The nanoEngine is a StrongARM 1110-based single board computer
   from Bright Star Engineering. More information is available at:
@@ -619,6 +644,19 @@
   Say Y if configuring for a Pangolin.
   Say N otherwise.
 
+CONFIG_SA1100_PFS168
+  The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based
+  computer which includes the SA-1111 Microprocessor Companion Chip and other
+  custom I/O designed to add connectivity and multimedia features for vending
+  and business machine applications. Say Y here if you require support for
+  this target.
+
+CONFIG_SA1100_SHANNON
+  The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
+  limited edition webphone produced by Philips. The Shannon is a SA1100
+  platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
+  and a telco interface.
+
 CONFIG_SA1100_VICTOR
   Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
   SA-1100 based Victor Digital Talking Book Reader.  See
@@ -656,6 +694,31 @@
   Say Y if you want support for the ARM920T processor.
   Otherwise, say N.
 
+CONFIG_CPU_ARM922T
+  The ARM922T is a version of the ARM920T, but with smaller
+  instruction and data caches. It is used in Altera's
+  Excalibur XA device family.
+
+  Say Y if you want support for the ARM922T processor.
+  Otherwise, say N.
+
+CONFIG_CPU_ARM922_CPU_IDLE
+  Saying Y here will allow the processor to enter a low power
+  mode whilst waiting for an interrupt in idle. If you're unsure
+  say Y.
+
+CONFIG_CPU_ARM922_I_CACHE_ON
+  Say Y here to enable the processor instruction cache. Unless
+  you have a reason not to, say Y.
+
+CONFIG_CPU_ARM922_D_CACHE_ON
+  Say Y here to enable the processor data cache. Unless
+  you have a reason not to, say Y.
+
+CONFIG_CPU_ARM922_WRITETHROUGH
+  Say Y here to use the data cache in writethough mode. Unless you
+  specifically require this, say N.
+
 CONFIG_CPU_ARM1020
   The ARM1020 is the cached version of the ARM10 processor,
   with an addition of a floating-point unit.
@@ -688,16 +751,14 @@
 
 CONFIG_FPE_FASTFPE
   Say Y here to include the FAST floating point emulator in the kernel.
-  This is an experimental much faster emulator which has only 32 bit
+  This is an experimental much faster emulator which now also has full
   precision for the mantissa.  It does not support any exceptions.
-  This makes it very simple, it is approximately 4-8 times faster than
-  NWFPE.
+  It is very simple, and approximately 3-6 times faster than NWFPE.
 
-  It should be sufficient for most programs.  It is definitely not
-  suitable if you do scientific calculations that need double
-  precision for iteration formulas that sum up lots of very small
-  numbers.  If you do not feel you need a faster FP emulation you
-  should better choose NWFPE.
+  It should be sufficient for most programs.  It may be not suitable
+  for scientific calculations, but you have to check this for yourself.
+  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.o).  But keep in mind that you should only load the FP
diff -Nru a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c
--- a/arch/arm/boot/compressed/ofw-shark.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/boot/compressed/ofw-shark.c	Tue Feb 26 11:57:59 2002
@@ -19,7 +19,7 @@
 asmlinkage void
 create_params (unsigned long *buffer)
 {
-	/* Is there a better address? Also change in mach-shark/arch.c */
+	/* Is there a better address? Also change in mach-shark/core.c */
 	struct tag *tag = (struct tag *) 0x08003000;
 	int j,i,m,k,nr_banks,size;
 	unsigned char *c;
diff -Nru a/arch/arm/config.in b/arch/arm/config.in
--- a/arch/arm/config.in	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/config.in	Tue Feb 26 11:57:57 2002
@@ -464,6 +464,7 @@
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'Power Management support' CONFIG_PM
+dep_bool 'Preemptible Kernel (experimental)' CONFIG_PREEMPT $CONFIG_CPU_32 $CONFIG_EXPERIMENTAL
 dep_tristate 'Advanced Power Management Emulation' CONFIG_APM $CONFIG_PM
 dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
 
diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
--- a/arch/arm/kernel/armksyms.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/kernel/armksyms.c	Tue Feb 26 11:57:58 2002
@@ -21,6 +21,7 @@
 #include <linux/pm.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
+#include <linux/smp_lock.h>
 
 #include <asm/byteorder.h>
 #include <asm/elf.h>
@@ -273,3 +274,7 @@
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
+
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(kernel_flag);
+#endif
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/kernel/calls.S	Tue Feb 26 11:57:59 2002
@@ -21,13 +21,13 @@
 		.long	SYMBOL_NAME(sys_write)
 /* 5 */		.long	SYMBOL_NAME(sys_open)
 		.long	SYMBOL_NAME(sys_close)
-		.long	SYMBOL_NAME(sys_waitpid)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_waitpid */
 		.long	SYMBOL_NAME(sys_creat)
 		.long	SYMBOL_NAME(sys_link)
 /* 10 */	.long	SYMBOL_NAME(sys_unlink)
 		.long	SYMBOL_NAME(sys_execve_wrapper)
 		.long	SYMBOL_NAME(sys_chdir)
-		.long	SYMBOL_NAME(sys_time)
+		.long	SYMBOL_NAME(sys_time)			/* used by libc4 */
 		.long	SYMBOL_NAME(sys_mknod)
 /* 15 */	.long	SYMBOL_NAME(sys_chmod)
 		.long	SYMBOL_NAME(sys_lchown16)
@@ -36,15 +36,15 @@
 		.long	SYMBOL_NAME(sys_lseek)
 /* 20 */	.long	SYMBOL_NAME(sys_getpid)
 		.long	SYMBOL_NAME(sys_mount)
-		.long	SYMBOL_NAME(sys_oldumount)
+		.long	SYMBOL_NAME(sys_oldumount)		/* used by libc4 */
 		.long	SYMBOL_NAME(sys_setuid16)
 		.long	SYMBOL_NAME(sys_getuid16)
 /* 25 */	.long	SYMBOL_NAME(sys_stime)
 		.long	SYMBOL_NAME(sys_ptrace)
-		.long	SYMBOL_NAME(sys_alarm)
+		.long	SYMBOL_NAME(sys_alarm)			/* used by libc4 */
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_fstat */
 		.long	SYMBOL_NAME(sys_pause)
-/* 30 */	.long	SYMBOL_NAME(sys_utime)
+/* 30 */	.long	SYMBOL_NAME(sys_utime)			/* used by libc4 */
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_stty */
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_getty */
 		.long	SYMBOL_NAME(sys_access)
@@ -62,7 +62,7 @@
 /* 45 */	.long	SYMBOL_NAME(sys_brk)
 		.long	SYMBOL_NAME(sys_setgid16)
 		.long	SYMBOL_NAME(sys_getgid16)
-		.long	SYMBOL_NAME(sys_signal)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_signal */
 		.long	SYMBOL_NAME(sys_geteuid16)
 /* 50 */	.long	SYMBOL_NAME(sys_getegid16)
 		.long	SYMBOL_NAME(sys_acct)
@@ -82,29 +82,29 @@
 /* 65 */	.long	SYMBOL_NAME(sys_getpgrp)
 		.long	SYMBOL_NAME(sys_setsid)
 		.long	SYMBOL_NAME(sys_sigaction)
-		.long	SYMBOL_NAME(sys_sgetmask)
-		.long	SYMBOL_NAME(sys_ssetmask)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_sgetmask */
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_ssetmask */
 /* 70 */	.long	SYMBOL_NAME(sys_setreuid16)
 		.long	SYMBOL_NAME(sys_setregid16)
 		.long	SYMBOL_NAME(sys_sigsuspend_wrapper)
 		.long	SYMBOL_NAME(sys_sigpending)
 		.long	SYMBOL_NAME(sys_sethostname)
 /* 75 */	.long	SYMBOL_NAME(sys_setrlimit)
-		.long	SYMBOL_NAME(sys_old_getrlimit)
+		.long	SYMBOL_NAME(sys_old_getrlimit)		/* used by libc4 */
 		.long	SYMBOL_NAME(sys_getrusage)
 		.long	SYMBOL_NAME(sys_gettimeofday)
 		.long	SYMBOL_NAME(sys_settimeofday)
 /* 80 */	.long	SYMBOL_NAME(sys_getgroups16)
 		.long	SYMBOL_NAME(sys_setgroups16)
-		.long	SYMBOL_NAME(old_select)
+		.long	SYMBOL_NAME(old_select)			/* used by libc4 */
 		.long	SYMBOL_NAME(sys_symlink)
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_lstat */
 /* 85 */	.long	SYMBOL_NAME(sys_readlink)
 		.long	SYMBOL_NAME(sys_uselib)
 		.long	SYMBOL_NAME(sys_swapon)
 		.long	SYMBOL_NAME(sys_reboot)
-		.long	SYMBOL_NAME(old_readdir)
-/* 90 */	.long	SYMBOL_NAME(old_mmap)
+		.long	SYMBOL_NAME(old_readdir)		/* used by libc4 */
+/* 90 */	.long	SYMBOL_NAME(old_mmap)			/* used by libc4 */
 		.long	SYMBOL_NAME(sys_munmap)
 		.long	SYMBOL_NAME(sys_truncate)
 		.long	SYMBOL_NAME(sys_ftruncate)
@@ -236,7 +236,22 @@
 		.long	SYMBOL_NAME(sys_mincore)
 /* 220 */	.long	SYMBOL_NAME(sys_madvise)
 		.long	SYMBOL_NAME(sys_fcntl64)
+		.long	SYMBOL_NAME(sys_ni_syscall) /* TUX */
+		.long	SYMBOL_NAME(sys_ni_syscall) /* Security */
 		.long	SYMBOL_NAME(sys_gettid)
+/* 225 */	.long	SYMBOL_NAME(sys_readahead)
+		.long	SYMBOL_NAME(sys_setxattr)
+		.long	SYMBOL_NAME(sys_lsetxattr)
+		.long	SYMBOL_NAME(sys_fsetxattr)
+		.long	SYMBOL_NAME(sys_getxattr)
+/* 230 */	.long	SYMBOL_NAME(sys_lgetxattr)
+		.long	SYMBOL_NAME(sys_fgetxattr)
+		.long	SYMBOL_NAME(sys_listxattr)
+		.long	SYMBOL_NAME(sys_llistxattr)
+		.long	SYMBOL_NAME(sys_flistxattr)
+/* 235 */	.long	SYMBOL_NAME(sys_removexattr)
+		.long	SYMBOL_NAME(sys_lremovexattr)
+		.long	SYMBOL_NAME(sys_fremovexattr)
 		.long	SYMBOL_NAME(sys_tkill)
 __syscall_end:
 
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/kernel/entry-armv.S	Tue Feb 26 11:57:58 2002
@@ -15,6 +15,7 @@
  */
 #include <linux/config.h>
 #include "entry-header.S"
+#include <asm/thread_info.h>
 
 
 #ifdef IOC_BASE
@@ -690,8 +691,7 @@
 		msr	cpsr_c, r9
 		mov	r2, sp
 		bl	SYMBOL_NAME(do_DataAbort)
-		mov	r0, #PSR_I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -705,17 +705,50 @@
 		add	r4, sp, #S_SP
 		mov	r6, lr
 		stmia	r4, {r5, r6, r7, r8, r9}	@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+#ifdef CONFIG_PREEMPT
+		get_thread_info r8
+		ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
+		add	r7, r9, #1			@ increment it
+		str	r7, [r8, #TI_PREEMPT]
+#endif
 1:		get_irqnr_and_base r0, r6, r5, lr
 		movne	r1, sp
 		@
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
 		adrsvc	ne, lr, 1b
-		bne	do_IRQ
+		bne	asm_do_IRQ
+#ifdef CONFIG_PREEMPT
+		ldr	r0, [r8, #TI_FLAGS]		@ get flags
+		tst	r0, #_TIF_NEED_RESCHED
+		ldrne	r6, .LCirq_stat
+		blne	svc_preempt
+preempt_return:
+		ldr	r0, [r8, #TI_PREEMPT]		@ read preempt value
+		teq	r0, r7
+		strne	r0, [r0, -r0]			@ bug()
+		str	r9, [r8, #TI_PREEMPT]		@ restore preempt count
+#endif
 		ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 
+#ifdef CONFIG_PREEMPT
+svc_preempt:	teq	r9, #0
+		movne	pc, lr
+		ldr	r0, [r6, #4]			@ local_irq_count
+		ldr	r1, [r6, #8]			@ local_b_count
+		adds	r0, r0, r1
+		movne	pc, lr
+1:		set_cpsr_c r0, #MODE_SVC		@ enable IRQs
+		bl	SYMBOL_NAME(preempt_schedule)
+		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC	@ disable IRQs
+		ldr	r0, [r8, #TI_FLAGS]
+		tst	r0, #_TIF_NEED_RESCHED
+		bne	1b
+		b	preempt_return
+#endif
+
 		.align	5
 __und_svc:	sub	sp, sp, #S_FRAME_SIZE
 		stmia	sp, {r0 - r12}			@ save r0 - r12
@@ -733,8 +766,7 @@
 		mov	r1, sp				@ struct pt_regs *regs
 		bl	SYMBOL_NAME(do_undefinstr)
 
-1:		mov	r0, #PSR_I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+1:		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
 		ldr	lr, [sp, #S_PSR]		@ Get SVC cpsr
 		msr	spsr, lr
 		ldmia	sp, {r0 - pc}^			@ Restore SVC registers
@@ -755,8 +787,7 @@
 		mov	r0, r2				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	SYMBOL_NAME(do_PrefetchAbort)	@ call abort handler
-		mov	r0, #PSR_I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -769,6 +800,9 @@
 .LCprocfns:	.word	SYMBOL_NAME(processor)
 #endif
 .LCfp:		.word	SYMBOL_NAME(fp_enter)
+#ifdef CONFIG_PREEMPT
+.LCirq_stat:	.word	SYMBOL_NAME(irq_stat)
+#endif
 
 		irq_prio_table
 
@@ -793,8 +827,7 @@
 #else
 		bl	cpu_data_abort
 #endif
-		mov	r2, #MODE_SVC
-		msr	cpsr_c, r2			@ Enable interrupts
+		set_cpsr_c r2, #MODE_SVC		@ Enable interrupts
 		mov	r2, sp
 		adrsvc	al, lr, ret_from_exception
 		b	SYMBOL_NAME(do_DataAbort)
@@ -809,15 +842,29 @@
 		stmdb	r8, {sp, lr}^
 		alignment_trap r4, r7, __temp_irq
 		zero_fp
+#ifdef CONFIG_PREEMPT
+		get_thread_info r8
+		ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
+		add	r7, r9, #1			@ increment it
+		str	r7, [r8, #TI_PREEMPT]
+#endif
 1:		get_irqnr_and_base r0, r6, r5, lr
 		movne	r1, sp
 		adrsvc	ne, lr, 1b
 		@
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
-		bne	do_IRQ
+		bne	asm_do_IRQ
+#ifdef CONFIG_PREEMPT
+		ldr	r0, [r8, #TI_PREEMPT]
+		teq	r0, r7
+		strne	r0, [r0, -r0]
+		str	r9, [r8, #TI_PREEMPT]
+		mov	tsk, r8
+#else
+		get_thread_info tsk
+#endif
 		mov	why, #0
-		get_current_task tsk
 		b	ret_to_user
 
 		.align	5
@@ -833,15 +880,15 @@
 		adrsvc	al, r9, ret_from_exception	@ r9  = normal FP return
 		adrsvc	al, lr, fpundefinstr		@ lr  = undefined instr return
 
-call_fpe:	get_current_task r10
+call_fpe:	get_thread_info r10			@ get current thread
+		ldr	r4, [r10, #TI_TASK]		@ get current task
 		mov	r8, #1
-		strb	r8, [r10, #TSK_USED_MATH]	@ set current->used_math
+		strb	r8, [r4, #TSK_USED_MATH]	@ set current->used_math
 		ldr	r4, .LCfp
-		add	r10, r10, #TSS_FPESAVE		@ r10 = workspace
+		add	r10, r10, #TI_FPSTATE		@ r10 = workspace
 		ldr	pc, [r4]			@ Call FP module USR entry point
 
-fpundefinstr:	mov	r0, #MODE_SVC
-		msr	cpsr_c, r0			@ Enable interrupts
+fpundefinstr:	set_cpsr_c r0, #MODE_SVC		@ Enable interrupts
 		mov	r0, lr
 		mov	r1, sp
 		adrsvc	al, lr, ret_from_exception
@@ -857,8 +904,7 @@
 		stmdb	r8, {sp, lr}^			@ Save sp_usr lr_usr
 		alignment_trap r4, r7, __temp_abt
 		zero_fp
-		mov	r0, #MODE_SVC
-		msr	cpsr_c, r0			@ Enable interrupts
+		set_cpsr_c r0, #MODE_SVC		@ Enable interrupts
 		mov	r0, r5				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	SYMBOL_NAME(do_PrefetchAbort)	@ call abort handler
@@ -867,7 +913,7 @@
  * This is the return code to user mode for abort handlers
  */
 ENTRY(ret_from_exception)
-		get_current_task tsk
+		get_thread_info tsk
 		mov	why, #0
 		b	ret_to_user
 
@@ -877,16 +923,16 @@
 		.text
 /*
  * Register switch for ARMv3 and ARMv4 processors
- * r0 = previous, r1 = next, return previous.
+ * r0 = previous thread_info, r1 = next thread_info, return previous.
  * previous and next are guaranteed not to be the same.
  */
 ENTRY(__switch_to)
 		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		mrs	ip, cpsr
 		str	ip, [sp, #-4]!			@ Save cpsr_SVC
-		str	sp, [r0, #TSS_SAVE]		@ Save sp_SVC
-		ldr	sp, [r1, #TSS_SAVE]		@ Get saved sp_SVC
-		ldr	r2, [r1, #TSS_DOMAIN]
+		str	sp, [r0, #TI_CPU_SAVE]		@ Save sp_SVC
+		ldr	sp, [r1, #TI_CPU_SAVE]		@ Get saved sp_SVC
+		ldr	r2, [r1, #TI_CPU_DOMAIN]
 		ldr	ip, [sp], #4
 		mcr	p15, 0, r2, c3, c0		@ Set domain register
 		msr	spsr, ip			@ Save tasks CPSR into SPSR for this return
diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
--- a/arch/arm/kernel/entry-common.S	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/kernel/entry-common.S	Tue Feb 26 11:57:56 2002
@@ -9,6 +9,7 @@
  */
 #include <linux/config.h>
 #include "entry-header.S"
+#include <asm/thread_info.h>
 
 /* 
  * We rely on the fact that R0 is at the bottom of the stack (due to
@@ -34,39 +35,42 @@
  * stack.
  */
 ret_fast_syscall:
-#error	ldr	r1, [tsk, #TSK_NEED_RESCHED]
-#error	ldr	r2, [tsk, #TSK_SIGPENDING]
-	teq	r1, #0				@ need_resched || sigpending
-	teqeq	r2, #0
-	bne	slow
+	set_cpsr_c r1, #PSR_I_BIT | MODE_SVC	@ disable interrupts
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	bne	ret_fast_work
 	fast_restore_user_regs
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
  */
-slow:	str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
-	b	1f
+ret_fast_work:
+	str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
+	b	work_pending
 
+work_resched:
+	bl	SYMBOL_NAME(schedule)
 /*
  * "slow" syscall return path.  "why" tells us if this was a real syscall.
  */
-reschedule:
-	bl	SYMBOL_NAME(schedule)
 ENTRY(ret_to_user)
 ret_slow_syscall:
-#error	ldr	r1, [tsk, #TSK_NEED_RESCHED]
-#error	ldr	r2, [tsk, #TSK_SIGPENDING]
-1:	teq	r1, #0				@ need_resched => schedule()
-	bne	reschedule
-	teq	r2, #0				@ sigpending => do_signal()
-	blne	__do_signal
+	set_cpsr_c r1, #PSR_I_BIT | MODE_SVC
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	no_work_pending
+work_pending:
+	tst	r1, #_TIF_NEED_RESCHED
+	bne	work_resched
+	tst	r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING
+	blne	__do_notify_resume
+no_work_pending:
 	restore_user_regs
 
-__do_signal:
-	mov	r0, #0				@ NULL 'oldset'
-	mov	r1, sp				@ 'regs'
+__do_notify_resume:
+	mov	r0, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
-#error	b	SYMBOL_NAME(do_signal)		@ note the bl above sets lr
+	b	SYMBOL_NAME(do_notify_resume)	@ note the bl above sets lr
 
 /*
  * This is how we return from a fork.  __switch_to will be calling us
@@ -75,14 +79,14 @@
  */
 ENTRY(ret_from_fork)
 	bl	SYMBOL_NAME(schedule_tail)
-	get_current_task tsk
-	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
+	get_thread_info tsk
+	ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	mov	why, #1
-	tst	ip, #PT_TRACESYS		@ are we tracing syscalls?
+	tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
 	beq	ret_slow_syscall
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
-#error	bl	SYMBOL_NAME(syscall_trace)
+	bl	SYMBOL_NAME(syscall_trace)
 	b	ret_slow_syscall
 	
 
@@ -134,12 +138,12 @@
 
 	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
-	get_current_task tsk
-	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
+	get_thread_info tsk
+	ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	bic	scno, scno, #0xff000000		@ mask off SWI op-code
 	eor	scno, scno, #OS_NUMBER << 20	@ check OS number
 	adr	tbl, sys_call_table		@ load syscall table pointer
-	tst	ip, #PT_TRACESYS		@ are we tracing syscalls?
+	tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
 	bne	__sys_trace
 
 	adrsvc	al, lr, ret_fast_syscall	@ return address
@@ -160,7 +164,7 @@
 __sys_trace:
 	add	r1, sp, #S_OFF
 	mov	r0, #0				@ trace entry [IP = 0]
-#error	bl	SYMBOL_NAME(syscall_trace)
+	bl	SYMBOL_NAME(syscall_trace)
 
 	adrsvc	al, lr, __sys_trace_return	@ return address
 	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
@@ -173,7 +177,7 @@
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
-#error	bl	SYMBOL_NAME(syscall_trace)
+	bl	SYMBOL_NAME(syscall_trace)
 	b	ret_slow_syscall
 
 	.align	5
diff -Nru a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
--- a/arch/arm/kernel/entry-header.S	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/kernel/entry-header.S	Tue Feb 26 11:57:59 2002
@@ -113,7 +113,7 @@
 		msr	cpsr_c, \temp
 		.endm
 
-		.macro	get_current_task, rd
+		.macro	get_thread_info, rd
 		mov	\rd, sp, lsr #13
 		mov	\rd, \rd, lsl #13
 		.endm
@@ -171,7 +171,7 @@
 		.macro	initialise_traps_extra
 		.endm
 
-		.macro	get_current_task, rd
+		.macro	get_thread_info, rd
 		mov	\rd, sp, lsr #13
 		mov	\rd, \rd, lsl #13
 		.endm
@@ -197,10 +197,10 @@
  *
  * We must set at least "tsk" and "why" when calling ret_with_reschedule.
  */
-scno	.req	r7				@ syscall number
-tbl	.req	r8				@ syscall table pointer
-why	.req	r8				@ Linux syscall (!= 0)
-tsk	.req	r9				@ current task
+scno	.req	r7		@ syscall number
+tbl	.req	r8		@ syscall table pointer
+why	.req	r8		@ Linux syscall (!= 0)
+tsk	.req	r9		@ current thread_info
 
 /*
  * Get the system call number.
@@ -214,6 +214,15 @@
 #else
 	mask_pc	lr, lr
 	ldr	scno, [lr, #-4]		@ get SWI instruction
+#endif
+	.endm
+
+	.macro	set_cpsr_c, reg, mode
+#if 1
+	mov	\reg, \mode
+	msr	cpsr_c, \reg
+#else
+	msr	cpsr_c, \mode
 #endif
 	.endm
 
diff -Nru a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
--- a/arch/arm/kernel/head.S	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/kernel/head.S	Tue Feb 26 11:57:56 2002
@@ -149,7 +149,7 @@
 		.long	SYMBOL_NAME(processor_id)
 		.long	SYMBOL_NAME(__machine_arch_type)
 		.long	SYMBOL_NAME(cr_alignment)
-		.long	SYMBOL_NAME(init_task_union)+8192
+		.long	SYMBOL_NAME(init_thread_union)+8192
 
 		.type	__ret, %function
 __ret:		ldr	lr, __switch_data
diff -Nru a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
--- a/arch/arm/kernel/init_task.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/kernel/init_task.c	Tue Feb 26 11:58:00 2002
@@ -16,7 +16,7 @@
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
- * Initial task structure.
+ * Initial thread structure.
  *
  * We need to make sure that this is 8192-byte aligned due to the
  * way process stacks are handled. This is done by making sure
@@ -25,5 +25,13 @@
  *
  * The things we do for performance..
  */
-union task_union init_task_union __attribute__((__section__(".init.task"))) =
-		{ INIT_TASK(init_task_union.task) };
+union thread_union init_thread_union
+	__attribute__((__section__(".init.task"))) =
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
--- a/arch/arm/kernel/process.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/kernel/process.c	Tue Feb 26 11:57:58 2002
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
+#include <linux/a.out.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
@@ -27,6 +28,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/leds.h>
+#include <asm/processor.h>
 #include <asm/uaccess.h>
 
 /*
@@ -83,9 +85,7 @@
 void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-
+	preempt_disable();
 	while (1) {
 		void (*idle)(void) = pm_idle;
 		if (!idle)
@@ -228,51 +228,61 @@
 /*
  * Task structure and kernel stack allocation.
  */
-static struct task_struct *task_struct_head;
-static unsigned int nr_task_struct;
+static unsigned long *thread_info_head;
+static unsigned int nr_thread_info;
 
 #ifdef CONFIG_CPU_32
 #define EXTRA_TASK_STRUCT	4
+#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 #else
+extern unsigned long get_page_8k(int priority);
+extern void free_page_8k(unsigned long page);
+
 #define EXTRA_TASK_STRUCT	0
+#define ll_alloc_task_struct()	((struct task_struct *)get_page_8k(GFP_KERNEL))
+#define ll_free_task_struct(p)  free_page_8k((unsigned long)(p))
 #endif
 
-struct task_struct *alloc_task_struct(void)
+struct thread_info *alloc_thread_info(void)
 {
-	struct task_struct *tsk;
+	struct thread_info *thread = NULL;
 
-	if (EXTRA_TASK_STRUCT)
-		tsk = task_struct_head;
-	else
-		tsk = NULL;
-
-	if (tsk) {
-		task_struct_head = tsk->next_task;
-		nr_task_struct -= 1;
-	} else
-		tsk = ll_alloc_task_struct();
+	if (EXTRA_TASK_STRUCT) {
+		unsigned long *p = thread_info_head;
+
+		if (p) {
+			thread_info_head = (unsigned long *)p[0];
+			nr_thread_info -= 1;
+		}
+		thread = (struct thread_info *)p;
+	}
+
+	if (!thread)
+		thread = ll_alloc_task_struct();
 
 #ifdef CONFIG_SYSRQ
 	/*
 	 * The stack must be cleared if you want SYSRQ-T to
 	 * give sensible stack usage information
 	 */
-	if (tsk) {
-		char *p = (char *)tsk;
+	if (thread) {
+		char *p = (char *)thread;
 		memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
 	}
 #endif
-	return tsk;
+	return thread;
 }
 
-void __free_task_struct(struct task_struct *p)
+void free_thread_info(struct thread_info *thread)
 {
-	if (EXTRA_TASK_STRUCT && nr_task_struct < EXTRA_TASK_STRUCT) {
-		p->next_task = task_struct_head;
-		task_struct_head = p;
-		nr_task_struct += 1;
+	if (EXTRA_TASK_STRUCT && nr_thread_info < EXTRA_TASK_STRUCT) {
+		unsigned long *p = (unsigned long *)thread;
+		p[0] = (unsigned long)thread_info_head;
+		thread_info_head = p;
+		nr_thread_info += 1;
 	} else
-		ll_free_task_struct(p);
+		ll_free_task_struct(thread);
 }
 
 /*
@@ -284,10 +294,13 @@
 
 void flush_thread(void)
 {
-	memset(&current->thread.debug, 0, sizeof(struct debug_info));
-	memset(&current->thread.fpstate, 0, sizeof(union fp_state));
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+
+	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+	memset(&thread->fpstate, 0, sizeof(union fp_state));
+
 	current->used_math = 0;
-	current->flags &= ~PF_USEDFPU;
 }
 
 void release_thread(struct task_struct *dead_task)
@@ -300,21 +313,19 @@
 	unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
 {
-	struct pt_regs * childregs;
-	struct context_save_struct * save;
-
-	atomic_set(&p->thread.refcount, 1);
+	struct pt_regs *childregs;
+	struct cpu_context_save *save;
 
-	childregs = ((struct pt_regs *)((unsigned long)p + 8192)) - 1;
+	childregs = ((struct pt_regs *)((unsigned long)p->thread_info + THREAD_SIZE)) - 1;
 	*childregs = *regs;
 	childregs->ARM_r0 = 0;
 	childregs->ARM_sp = esp;
 
-	save = ((struct context_save_struct *)(childregs)) - 1;
+	save = ((struct cpu_context_save *)(childregs)) - 1;
 	*save = INIT_CSS;
 	save->pc |= (unsigned long)ret_from_fork;
 
-	p->thread.save = save;
+	p->thread_info->cpu_context = save;
 
 	return 0;
 }
@@ -324,10 +335,13 @@
  */
 int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
 {
-	if (current->used_math)
-		memcpy(fp, &current->thread.fpstate.soft, sizeof (*fp));
+	struct thread_info *thread = current_thread_info();
+	int used_math = current->used_math;
+
+	if (used_math)
+		memcpy(fp, &thread->fpstate.soft, sizeof (*fp));
 
-	return current->used_math;
+	return used_math;
 }
 
 /*
@@ -405,7 +419,7 @@
 		return 0;
 
 	stack_page = 4096 + (unsigned long)p;
-	fp = get_css_fp(&p->thread);
+	fp = thread_saved_fp(p);
 	do {
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/kernel/ptrace.c	Tue Feb 26 11:57:57 2002
@@ -9,6 +9,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -72,7 +73,7 @@
 
 	newregs = *regs;
 	newregs.uregs[offset] = data;
-	
+
 	if (valid_user_regs(&newregs)) {
 		regs->uregs[offset] = data;
 		ret = 0;
@@ -455,9 +456,9 @@
 			if ((unsigned long) data > _NSIG)
 				break;
 			if (request == PTRACE_SYSCALL)
-				child->ptrace |= PT_TRACESYS;
+				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			else
-				child->ptrace &= ~PT_TRACESYS;
+				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			child->exit_code = data;
 			/* make sure single-step breakpoint is gone. */
 			__ptrace_cancel_bpt(child);
@@ -490,7 +491,7 @@
 			if ((unsigned long) data > _NSIG)
 				break;
 			child->thread.debug.nsaved = -1;
-			child->ptrace &= ~PT_TRACESYS;
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			child->exit_code = data;
 			/* give it a chance to run. */
 			wake_up_process(child);
@@ -547,7 +548,7 @@
 				break;
 
 			/* we should check child->used_math here */
-			ret = __copy_to_user((void *)data, &child->thread.fpstate,
+			ret = __copy_to_user((void *)data, &child->thread_info->fpstate,
 					     sizeof(struct user_fp)) ? -EFAULT : 0;
 			break;
 		
@@ -560,7 +561,7 @@
 				break;
 
 			child->used_math = 1;
-			ret = __copy_from_user(&child->thread.fpstate, (void *)data,
+			ret = __copy_from_user(&child->thread_info->fpstate, (void *)data,
 					   sizeof(struct user_fp)) ? -EFAULT : 0;
 			break;
 
@@ -616,7 +617,7 @@
 	ret = do_ptrace(request, child, addr, data);
 
 out_tsk:
-	free_task_struct(child);
+	put_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
@@ -626,8 +627,9 @@
 {
 	unsigned long ip;
 
-	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
-			!= (PT_PTRACED|PT_TRACESYS))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (!(current->ptrace & PT_PTRACED))
 		return;
 
 	/*
diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/kernel/setup.c	Tue Feb 26 11:57:56 2002
@@ -38,6 +38,10 @@
 #define CONFIG_CMDLINE ""
 #endif
 
+#ifdef CONFIG_PREEMPT
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+#endif
+
 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
 char fpe_type[8];
 
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/kernel/signal.c	Tue Feb 26 11:57:56 2002
@@ -480,6 +480,7 @@
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
 	int usig = sig;
 	int ret;
@@ -487,8 +488,8 @@
 	/*
 	 * translate the signal
 	 */
-	if (usig < 32 && tsk->exec_domain && tsk->exec_domain->signal_invmap)
-		usig = tsk->exec_domain->signal_invmap[usig];
+	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
+		usig = thread->exec_domain->signal_invmap[usig];
 
 	/*
 	 * Set up the stack frame
@@ -532,7 +533,7 @@
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
+int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
 	struct k_sigaction *ka;
 	siginfo_t info;
@@ -677,4 +678,11 @@
 	if (single_stepping)
 		ptrace_set_bpt(current);
 	return 0;
+}
+
+asmlinkage void
+do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		do_signal(NULL, regs, syscall);
 }
diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
--- a/arch/arm/kernel/traps.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/kernel/traps.c	Tue Feb 26 11:57:59 2002
@@ -115,7 +115,7 @@
 
 static void dump_stack(struct task_struct *tsk, unsigned long sp)
 {
-	dump_mem("Stack: ", sp - 16, 8192+(unsigned long)tsk);
+	dump_mem("Stack: ", sp - 16, 8192+(unsigned long)tsk->thread_info);
 }
 
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
@@ -146,7 +146,7 @@
 void show_trace_task(struct task_struct *tsk)
 {
 	if (tsk != current) {
-		unsigned int fp = tsk->thread.save->fp;
+		unsigned int fp = thread_saved_fp(tsk);
 		c_backtrace(fp, 0x10);
 	}
 }
@@ -304,16 +304,17 @@
 
 static int bad_syscall(int n, struct pt_regs *regs)
 {
+	struct thread_info *thread = current_thread_info();
 	siginfo_t info;
 
 	/* You might think just testing `handler' would be enough, but PER_LINUX
 	 * points it to no_lcall7 to catch undercover SVr4 binaries.  Gutted.
 	 */
-	if (current->personality != PER_LINUX && current->exec_domain->handler) {
+	if (current->personality != PER_LINUX && thread->exec_domain->handler) {
 		/* Hand it off to iBCS.  The extra parameter and consequent type 
 		 * forcing is necessary because of the weird ARM calling convention.
 		 */
-		current->exec_domain->handler(n, regs);
+		thread->exec_domain->handler(n, regs);
 		return regs->ARM_r0;
 	}
 
diff -Nru a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S
--- a/arch/arm/lib/csumpartial.S	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/lib/csumpartial.S	Tue Feb 26 11:57:59 2002
@@ -41,7 +41,7 @@
 		tst	buf, #1			@ odd address?
 		ldrneb	td0, [buf], #1
 		subne	len, len, #1
-		adcnes	sum, sum, td0, lsl #8
+		adcnes	sum, sum, td0, lsl #byte(1)
 
 .less4:		tst	len, #6
 		beq	.less8_byte
@@ -56,7 +56,11 @@
 		ldrb	td0, [buf], #1
 		ldrb	td3, [buf], #1
 		sub	len, len, #2
+#ifndef __ARMEB__
 		orr	td0, td0, td3, lsl #8
+#else
+		orr	td0, td3, td0, lsl #8
+#endif
 #endif
 		adcs	sum, sum, td0
 		tst	len, #6
@@ -64,7 +68,7 @@
 
 .less8_byte:	tst	len, #1			@ odd number of bytes
 		ldrneb	td0, [buf], #1		@ include last byte
-		adcnes	sum, sum, td0		@ update checksum
+		adcnes	sum, sum, td0, lsl #byte(0)	@ update checksum
 
 .done:		adc	r0, sum, #0		@ collect up the last carry
 		ldr	td0, [sp], #4
@@ -76,7 +80,7 @@
 .not_aligned:	tst	buf, #1			@ odd address
 		ldrneb	td0, [buf], #1		@ make even
 		subne	len, len, #1
-		adcnes	sum, sum, td0, lsl #8	@ update checksum
+		adcnes	sum, sum, td0, lsl #byte(1)	@ update checksum
 
 		tst	buf, #2			@ 32-bit aligned?
 #ifdef __ARM_ARCH_4__
@@ -86,7 +90,11 @@
 		ldrneb	td0, [buf], #1
 		ldrneb	ip, [buf], #1
 		subne	len, len, #2
+#ifndef __ARMEB__
 		orrne	td0, td0, ip, lsl #8
+#else
+		orrne	td0, ip, td0, lsl #8
+#endif
 #endif
 		adcnes	sum, sum, td0		@ update checksum
 		mov	pc, lr
diff -Nru a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
--- a/arch/arm/lib/csumpartialcopygeneric.S	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/lib/csumpartialcopygeneric.S	Tue Feb 26 11:57:57 2002
@@ -36,16 +36,16 @@
 
 		load1b	ip
 		sub	len, len, #1
-		adcs	sum, sum, ip, lsl #8	@ update checksum
+		adcs	sum, sum, ip, lsl #byte(1)	@ update checksum
 		strb	ip, [dst], #1
 		tst	dst, #2
 		moveq	pc, lr			@ dst is now 32bit aligned
 
 .dst_16bit:	load2b	r8, ip
 		sub	len, len, #2
-		adcs	sum, sum, r8
+		adcs	sum, sum, r8, lsl #byte(0)
 		strb	r8, [dst], #1
-		adcs	sum, sum, ip, lsl #8
+		adcs	sum, sum, ip, lsl #byte(1)
 		strb	ip, [dst], #1
 		mov	pc, lr			@ dst is now 32bit aligned
 
@@ -63,16 +63,16 @@
 		/* Align dst */
 		load1b	ip
 		sub	len, len, #1
-		adcs	sum, sum, ip, lsl #8	@ update checksum
+		adcs	sum, sum, ip, lsl #byte(1)	@ update checksum
 		strb	ip, [dst], #1
 		tst	len, #6
 		beq	.less8_byteonly
 
 1:		load2b	r8, ip
 		sub	len, len, #2
-		adcs	sum, sum, r8
+		adcs	sum, sum, r8, lsl #byte(0)
 		strb	r8, [dst], #1
-		adcs	sum, sum, ip, lsl #8
+		adcs	sum, sum, ip, lsl #byte(1)
 		strb	ip, [dst], #1
 .less8_aligned:	tst	len, #6
 		bne	1b
@@ -80,7 +80,7 @@
 		tst	len, #1
 		beq	.done
 		load1b	r8
-		adcs	sum, sum, r8		@ update checksum
+		adcs	sum, sum, r8, lsl #byte(0)	@ update checksum
 		strb	r8, [dst], #1
 		b	.done
 
@@ -137,18 +137,19 @@
 
 4:		ands	len, len, #3
 		beq	.done
-		load1l	r4
+		load1l	r5
 		tst	len, #2
+		mov	r4, r5, lsr #byte(0)
 		beq	.exit
-		adcs	sum, sum, r4, lsl #16
+		adcs	sum, sum, r5, push #16
 		strb	r4, [dst], #1
-		mov	r4, r4, lsr #8
+		mov	r4, r5, lsr #byte(1)
 		strb	r4, [dst], #1
-		mov	r4, r4, lsr #8
+		mov	r4, r5, lsr #byte(2)
 .exit:		tst	len, #1
 		strneb	r4, [dst], #1
 		andne	r4, r4, #255
-		adcnes	sum, sum, r4
+		adcnes	sum, sum, r4, lsl #byte(0)
 
 		/*
 		 * If the dst pointer was not 16-bit aligned, we
@@ -167,27 +168,27 @@
 		adc	sum, sum, #0		@ include C from dst alignment
 		and	ip, src, #3
 		bic	src, src, #3
-		load1l	r4
+		load1l	r5
 		cmp	ip, #2
 		beq	.src2_aligned
 		bhi	.src3_aligned
-		mov	r4, r4, lsr #8		@ C = 0
+		mov	r4, r5, pull #8		@ C = 0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		mov	r7, r7, lsr #8
-		orr	r7, r7, r8, lsl #24
+		orr	r4, r4, r5, push #24
+		mov	r5, r5, pull #8
+		orr	r5, r5, r6, push #24
+		mov	r6, r6, pull #8
+		orr	r6, r6, r7, push #24
+		mov	r7, r7, pull #8
+		orr	r7, r7, r8, push #24
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, lsr #8
+		mov	r4, r8, pull #8
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -196,49 +197,50 @@
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
+		orr	r4, r4, r5, push #24
+		mov	r5, r5, pull #8
+		orr	r5, r5, r6, push #24
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, lsr #8
+		mov	r4, r6, pull #8
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, lsl #24
+		orr	r4, r4, r5, push #24
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, lsr #8
 4:		ands	len, len, #3
 		beq	.done
+		mov	r4, r5, lsr #byte(1)
 		tst	len, #2
 		beq	.exit
-		adcs	sum, sum, r4, lsl #16
+		bic	r5, r5, #0xff << byte(0)
+		adcs	sum, sum, r5, push #8
 		strb	r4, [dst], #1
-		mov	r4, r4, lsr #8
+		mov	r4, r5, lsr #byte(2)
 		strb	r4, [dst], #1
-		mov	r4, r4, lsr #8
+		mov	r4, r5, lsr #byte(3)
 		b	.exit
 
-.src2_aligned:	mov	r4, r4, lsr #16
+.src2_aligned:	mov	r4, r5, pull #16
 		adds	sum, sum, #0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		mov	r7, r7, lsr #16
-		orr	r7, r7, r8, lsl #16
+		orr	r4, r4, r5, push #16
+		mov	r5, r5, pull #16
+		orr	r5, r5, r6, push #16
+		mov	r6, r6, pull #16
+		orr	r6, r6, r7, push #16
+		mov	r7, r7, pull #16
+		orr	r7, r7, r8, push #16
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, lsr #16
+		mov	r4, r8, pull #16
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -247,51 +249,51 @@
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
+		orr	r4, r4, r5, push #16
+		mov	r5, r5, pull #16
+		orr	r5, r5, r6, push #16
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, lsr #16
+		mov	r4, r6, pull #16
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, lsl #16
+		orr	r4, r4, r5, push #16
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, lsr #16
 4:		ands	len, len, #3
 		beq	.done
+		mov	r4, r5, lsr #byte(2)
 		tst	len, #2
 		beq	.exit
-		adcs	sum, sum, r4, lsl #16
+		adcs	sum, sum, r5, pull #16
 		strb	r4, [dst], #1
-		mov	r4, r4, lsr #8
+		mov	r4, r5, lsr #byte(3)
 		strb	r4, [dst], #1
 		tst	len, #1
 		beq	.done
 		load1b	r4
 		b	.exit
 
-.src3_aligned:	mov	r4, r4, lsr #24
+.src3_aligned:	mov	r4, r5, pull #24
 		adds	sum, sum, #0
 		bics	ip, len, #15
 		beq	2f
 1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		mov	r7, r7, lsr #24
-		orr	r7, r7, r8, lsl #8
+		orr	r4, r4, r5, push #8
+		mov	r5, r5, pull #24
+		orr	r5, r5, r6, push #8
+		mov	r6, r6, pull #24
+		orr	r6, r6, r7, push #8
+		mov	r7, r7, pull #24
+		orr	r7, r7, r8, push #8
 		stmia	dst!, {r4, r5, r6, r7}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
 		adcs	sum, sum, r6
 		adcs	sum, sum, r7
-		mov	r4, r8, lsr #24
+		mov	r4, r8, pull #24
 		sub	ip, ip, #16
 		teq	ip, #0
 		bne	1b
@@ -300,28 +302,29 @@
 		tst	ip, #8
 		beq	3f
 		load2l	r5, r6
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
+		orr	r4, r4, r5, push #8
+		mov	r5, r5, pull #24
+		orr	r5, r5, r6, push #8
 		stmia	dst!, {r4, r5}
 		adcs	sum, sum, r4
 		adcs	sum, sum, r5
-		mov	r4, r6, lsr #24
+		mov	r4, r6, pull #24
 		tst	ip, #4
 		beq	4f
 3:		load1l	r5
-		orr	r4, r4, r5, lsl #8
+		orr	r4, r4, r5, push #8
 		str	r4, [dst], #4
 		adcs	sum, sum, r4
-		mov	r4, r5, lsr #24
 4:		ands	len, len, #3
 		beq	.done
+		mov	r4, r5, lsr #byte(3)
 		tst	len, #2
 		beq	.exit
-		adcs	sum, sum, r4, lsl #16
+		adcs	sum, sum, r5, pull #24
 		strb	r4, [dst], #1
-		load1l	r4
+		load1l	r5
+		mov	r4, r5, lsr #byte(0)
 		strb	r4, [dst], #1
-		adcs	sum, sum, r4, lsl #24
-		mov	r4, r4, lsr #8
+		adcs	sum, sum, r4, push #24
+		mov	r4, r5, lsr #byte(1)
 		b	.exit
diff -Nru a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
--- a/arch/arm/lib/getuser.S	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/lib/getuser.S	Tue Feb 26 11:57:59 2002
@@ -27,12 +27,13 @@
  * Note also that it is intended that __get_user_bad is not global.
  */
 #include <asm/constants.h>
+#include <asm/thread_info.h>
 
 	.global	__get_user_1
 __get_user_1:
 	bic	r1, sp, #0x1f00
 	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TSK_ADDR_LIMIT]
+	ldr	r1, [r1, #TI_ADDR_LIMIT]
 	sub	r1, r1, #1
 	cmp	r0, r1
 1:	ldrlsbt	r1, [r0]
@@ -44,7 +45,7 @@
 __get_user_2:
 	bic	r2, sp, #0x1f00
 	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
+	ldr	r2, [r2, #TI_ADDR_LIMIT]
 	sub	r2, r2, #2
 	cmp	r0, r2
 2:	ldrlsbt	r1, [r0], #1
@@ -62,7 +63,7 @@
 __get_user_4:
 	bic	r1, sp, #0x1f00
 	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TSK_ADDR_LIMIT]
+	ldr	r1, [r1, #TI_ADDR_LIMIT]
 	sub	r1, r1, #4
 	cmp	r0, r1
 4:	ldrlst	r1, [r0]
@@ -74,7 +75,7 @@
 __get_user_8:
 	bic	r2, sp, #0x1f00
 	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
+	ldr	r2, [r2, #TI_ADDR_LIMIT]
 	sub	r2, r2, #8
 	cmp	r0, r2
 5:	ldrlst	r1, [r0], #4
diff -Nru a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
--- a/arch/arm/lib/putuser.S	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/lib/putuser.S	Tue Feb 26 11:58:00 2002
@@ -27,12 +27,13 @@
  * Note also that it is intended that __put_user_bad is not global.
  */
 #include <asm/constants.h>
+#include <asm/thread_info.h>
 
 	.global	__put_user_1
 __put_user_1:
 	bic	r2, sp, #0x1f00
 	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
+	ldr	r2, [r2, #TI_ADDR_LIMIT]
 	sub	r2, r2, #1
 	cmp	r0, r2
 1:	strlsbt	r1, [r0]
@@ -44,7 +45,7 @@
 __put_user_2:
 	bic	r2, sp, #0x1f00
 	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
+	ldr	r2, [r2, #TI_ADDR_LIMIT]
 	sub	r2, r2, #2
 	cmp	r0, r2
 	movls	r2, r1, lsr #8
@@ -63,7 +64,7 @@
 __put_user_4:
 	bic	r2, sp, #0x1f00
 	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TSK_ADDR_LIMIT]
+	ldr	r2, [r2, #TI_ADDR_LIMIT]
 	sub	r2, r2, #4
 	cmp	r0, r2
 4:	strlst	r1, [r0]
@@ -75,7 +76,7 @@
 __put_user_8:
 	bic	ip, sp, #0x1f00
 	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TSK_ADDR_LIMIT]
+	ldr	ip, [ip, #TI_ADDR_LIMIT]
 	sub	ip, ip, #8
 	cmp	r0, ip
 5:	strlst	r1, [r0], #4
diff -Nru a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
--- a/arch/arm/lib/strrchr.S	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/lib/strrchr.S	Tue Feb 26 11:57:59 2002
@@ -18,7 +18,7 @@
 		mov	r3, #0
 1:		ldrb	r2, [r0], #1
 		teq	r2, r1
-		moveq	r3, r0
+		subeq	r3, r0, #1
 		teq	r2, #0
 		bne	1b
 		mov	r0, r3
diff -Nru a/arch/arm/mach-adifcc/arch.c b/arch/arm/mach-adifcc/arch.c
--- a/arch/arm/mach-adifcc/arch.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-adifcc/arch.c	Tue Feb 26 11:58:00 2002
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -33,7 +33,7 @@
 
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( 0xc0800000, 3*1024*1024 );
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 #endif
 }
 
diff -Nru a/arch/arm/mach-adifcc/irq.c b/arch/arm/mach-adifcc/irq.c
--- a/arch/arm/mach-adifcc/irq.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-adifcc/irq.c	Tue Feb 26 11:57:59 2002
@@ -12,8 +12,6 @@
  * 80200 on chip interrupts. That'll change once the hardware adds
  * support for PCI though.
  */
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
diff -Nru a/arch/arm/mach-anakin/arch.c b/arch/arm/mach-anakin/arch.c
--- a/arch/arm/mach-anakin/arch.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-anakin/arch.c	Tue Feb 26 11:57:56 2002
@@ -30,7 +30,7 @@
 fixup_anakin(struct machine_desc *desc, struct param_struct *unused,
              char **cmdline, struct meminfo *mi)
 {
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0);
 	setup_ramdisk(1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
 	setup_initrd(0xc0800000, 4 * 1024 * 1024);
 }
diff -Nru a/arch/arm/mach-arc/arch.c b/arch/arm/mach-arc/arch.c
--- a/arch/arm/mach-arc/arch.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-arc/arch.c	Tue Feb 26 11:57:57 2002
@@ -9,6 +9,7 @@
  *
  *  Architecture specific fixups.
  */
+#include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
--- a/arch/arm/mach-clps711x/cdb89712.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-clps711x/cdb89712.c	Tue Feb 26 11:57:56 2002
@@ -17,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/string.h>
diff -Nru a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c
--- a/arch/arm/mach-epxa10db/arch.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-epxa10db/arch.c	Tue Feb 26 11:57:59 2002
@@ -18,7 +18,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -46,7 +45,7 @@
         mi->bank[0].node  = 0;
 
 /*
-        ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+        ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
         setup_ramdisk( 1, 0, 0, 8192 );
         setup_initrd(0xc0200000, 6*1024*1024);
 */
diff -Nru a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c
--- a/arch/arm/mach-ftvpci/core.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/mach-ftvpci/core.c	Tue Feb 26 11:57:58 2002
@@ -8,7 +8,6 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
diff -Nru a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
--- a/arch/arm/mach-integrator/pci_v3.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-integrator/pci_v3.c	Tue Feb 26 11:57:57 2002
@@ -20,6 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff -Nru a/arch/arm/mach-iop310/arch.c b/arch/arm/mach-iop310/arch.c
--- a/arch/arm/mach-iop310/arch.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-iop310/arch.c	Tue Feb 26 11:57:59 2002
@@ -9,7 +9,7 @@
  * published by the Free Software Foundation.
  *
  */
-
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -44,7 +44,7 @@
 #elif defined(CONFIG_BLK_DEV_INITRD)
 	setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE );
 	setup_initrd( 0xc0800000, 4*1024*1024 );
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); /* /dev/ram */
 #endif
 }
 
diff -Nru a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c
--- a/arch/arm/mach-iop310/iop310-irq.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-iop310/iop310-irq.c	Tue Feb 26 11:58:00 2002
@@ -13,8 +13,6 @@
  * Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS
  *
  */
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
diff -Nru a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c
--- a/arch/arm/mach-iop310/iq80310-irq.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-iop310/iq80310-irq.c	Tue Feb 26 11:57:57 2002
@@ -14,8 +14,6 @@
  *     Moved demux from asm to C - DS
  *     Fixes for various revision boards - DS
  */
-
-#include <linux/config.h>
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
diff -Nru a/arch/arm/mach-iop310/mm.c b/arch/arm/mach-iop310/mm.c
--- a/arch/arm/mach-iop310/mm.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-iop310/mm.c	Tue Feb 26 11:57:57 2002
@@ -13,7 +13,7 @@
  * option) any later version.
  *
  */
-
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 
diff -Nru a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c
--- a/arch/arm/mach-iop310/xs80200-irq.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-iop310/xs80200-irq.c	Tue Feb 26 11:57:59 2002
@@ -10,8 +10,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
diff -Nru a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c
--- a/arch/arm/mach-l7200/core.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-l7200/core.c	Tue Feb 26 11:57:57 2002
@@ -5,6 +5,7 @@
  *
  *  Extra MM routines for L7200 architecture
  */
+#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
@@ -90,7 +91,7 @@
         mi->bank[0].size  = (32*1024*1024);
         mi->bank[0].node  = 0;
 
-        ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+        ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
         setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
         setup_initrd( __phys_to_virt(0xf1000000), 0x005dac7b);
 
diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
--- a/arch/arm/mach-sa1100/adsbitsy.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/adsbitsy.c	Tue Feb 26 11:57:56 2002
@@ -26,8 +26,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 
-#include <asm/arch/irq.h>
-
 #include "generic.h"
 #include "sa1111.h"
 
@@ -120,7 +118,7 @@
 	SET_BANK( 0, 0xc0000000, 32*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/brutus.c b/arch/arm/mach-sa1100/brutus.c
--- a/arch/arm/mach-sa1100/brutus.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/mach-sa1100/brutus.c	Tue Feb 26 11:57:58 2002
@@ -32,7 +32,7 @@
 	SET_BANK( 3, 0xd8000000, 4*1024*1024 );
 	mi->nr_banks = 4;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
--- a/arch/arm/mach-sa1100/cerf.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-sa1100/cerf.c	Tue Feb 26 11:57:59 2002
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-sa1100/cerf.c
  */
-
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
@@ -55,7 +55,7 @@
 #error "Undefined memory size for Cerfboard."
 #endif
 
-//	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+//	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 //	setup_ramdisk(1,  0, 0, 8192);
 //	// Save 2Meg for RAMDisk
 //	setup_initrd(0xc0500000, 3*1024*1024);
diff -Nru a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c
--- a/arch/arm/mach-sa1100/empeg.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-sa1100/empeg.c	Tue Feb 26 11:58:00 2002
@@ -24,7 +24,7 @@
 	SET_BANK( 1, 0xc8000000, 4*1024*1024 );
 	mi->nr_banks = 2;
 
-	ROOT_DEV = MKDEV( 3, 1 );  /* /dev/hda1 */
+	ROOT_DEV = mk_kdev( 3, 1 );  /* /dev/hda1 */
 	setup_ramdisk( 1, 0, 0, 4096 );
 	setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) );
 }
diff -Nru a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
--- a/arch/arm/mach-sa1100/flexanet.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-sa1100/flexanet.c	Tue Feb 26 11:57:59 2002
@@ -9,8 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -113,7 +111,6 @@
  *
  * get_mctrl : set state of modem control lines
  * set_mctrl : set the modem control lines
- * enable_ms : enable modem-status interrupts
  * pm        : power-management. Turn device on/off.
  *
  */
@@ -121,7 +118,6 @@
 {
 	set_mctrl : flexanet_set_mctrl,
 	get_mctrl : flexanet_get_mctrl,
-	enable_ms : NULL,
 	pm        : NULL,
 };
 
@@ -168,7 +164,7 @@
 	mi->nr_banks = 1;
 
 	/* setup ramdisk */
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( 0xc0800000, 3*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
--- a/arch/arm/mach-sa1100/freebird.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-sa1100/freebird.c	Tue Feb 26 11:57:57 2002
@@ -58,7 +58,7 @@
 #ifdef CONFIG_SA1100_FREEBIRD_OLD
 	SET_BANK( 0, 0xc0000000, 32*1024*1024 );
 	mi->nr_banks = 1;
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0 ,0 , 8192 );
 	setup_initrd( 0xc0800000, 3*1024*1024 );
 #endif
diff -Nru a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
--- a/arch/arm/mach-sa1100/graphicsclient.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-sa1100/graphicsclient.c	Tue Feb 26 11:58:00 2002
@@ -130,7 +130,7 @@
 	SET_BANK( 1, 0xc8000000, 16*1024*1024 );
 	mi->nr_banks = 2;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
--- a/arch/arm/mach-sa1100/graphicsmaster.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-sa1100/graphicsmaster.c	Tue Feb 26 11:57:59 2002
@@ -193,7 +193,7 @@
 	SET_BANK( 1, 0xc8000000, 16*1024*1024 );
 	mi->nr_banks = 2;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
--- a/arch/arm/mach-sa1100/h3600.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-sa1100/h3600.c	Tue Feb 26 11:57:57 2002
@@ -19,8 +19,6 @@
  *				   and abstracted EGPIO interface.
  *
  */
-
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -Nru a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
--- a/arch/arm/mach-sa1100/huw_webpanel.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-sa1100/huw_webpanel.c	Tue Feb 26 11:57:59 2002
@@ -2,8 +2,6 @@
  * linux/arch/arm/mach-sa1100/huw_webpanel.c
  *
  */
-
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -66,7 +64,7 @@
 	 **/
 	SET_BANK( 0, 0xc0000000, ((32*1024 - (256 + 32)) * 1024));
 	mi->nr_banks = 1;
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 8*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-sa1100/irq.c	Tue Feb 26 11:58:00 2002
@@ -9,8 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/sched.h>
diff -Nru a/arch/arm/mach-sa1100/leds-adsbitsy.c b/arch/arm/mach-sa1100/leds-adsbitsy.c
--- a/arch/arm/mach-sa1100/leds-adsbitsy.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/mach-sa1100/leds-adsbitsy.c	Tue Feb 26 11:57:58 2002
@@ -28,7 +28,7 @@
 {
 	unsigned long flags;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 
 	switch (evt) {
 	case led_start:
@@ -92,5 +92,5 @@
 		GPCR = hw_led_state ^ LED_MASK;
 	}
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
diff -Nru a/arch/arm/mach-sa1100/leds-graphicsclient.c b/arch/arm/mach-sa1100/leds-graphicsclient.c
--- a/arch/arm/mach-sa1100/leds-graphicsclient.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/leds-graphicsclient.c	Tue Feb 26 11:57:56 2002
@@ -30,7 +30,7 @@
 {
 	unsigned long flags;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 
 	switch (evt) {
 	case led_start:
@@ -100,5 +100,5 @@
 		GPCR = hw_led_state ^ LED_MASK;
 	}
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
diff -Nru a/arch/arm/mach-sa1100/leds-graphicsmaster.c b/arch/arm/mach-sa1100/leds-graphicsmaster.c
--- a/arch/arm/mach-sa1100/leds-graphicsmaster.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/leds-graphicsmaster.c	Tue Feb 26 11:57:56 2002
@@ -30,7 +30,7 @@
 {
 	unsigned long flags;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 
 	switch (evt) {
 	case led_start:
@@ -100,5 +100,5 @@
 		GPCR = hw_led_state ^ LED_MASK;
 	}
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
diff -Nru a/arch/arm/mach-sa1100/leds-system3.c b/arch/arm/mach-sa1100/leds-system3.c
--- a/arch/arm/mach-sa1100/leds-system3.c	Tue Feb 26 11:57:59 2002
+++ b/arch/arm/mach-sa1100/leds-system3.c	Tue Feb 26 11:57:59 2002
@@ -26,7 +26,6 @@
  *
  *
  */
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c
--- a/arch/arm/mach-sa1100/leds.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-sa1100/leds.c	Tue Feb 26 11:57:57 2002
@@ -5,7 +5,6 @@
  * 
  * Copyright (C) 2001 Nicolas Pitre
  */
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
diff -Nru a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
--- a/arch/arm/mach-sa1100/nanoengine.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/nanoengine.c	Tue Feb 26 11:57:56 2002
@@ -23,7 +23,7 @@
 	SET_BANK( 0, 0xc0000000, 32*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
 
diff -Nru a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
--- a/arch/arm/mach-sa1100/omnimeter.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/omnimeter.c	Tue Feb 26 11:57:56 2002
@@ -47,7 +47,7 @@
 	SET_BANK( 0, 0xc0000000, 16*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xd0000000), 0x00400000 );
 }
diff -Nru a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c
--- a/arch/arm/mach-sa1100/pangolin.c	Tue Feb 26 11:58:00 2002
+++ b/arch/arm/mach-sa1100/pangolin.c	Tue Feb 26 11:58:00 2002
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-sa1100/pangolin.c
  */
-
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
@@ -23,7 +23,7 @@
 	SET_BANK( 0, 0xc0000000, 128*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 16384 );
 	setup_initrd( 0xc0800000, 3*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
--- a/arch/arm/mach-sa1100/pfs168.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/pfs168.c	Tue Feb 26 11:57:56 2002
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-sa1100/pfs168.c
  */
-
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
@@ -96,7 +96,7 @@
 	SET_BANK( 0, 0xc0000000, 16*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( 0xc0800000, 3*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
--- a/arch/arm/mach-sa1100/pleb.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/mach-sa1100/pleb.c	Tue Feb 26 11:57:58 2002
@@ -28,7 +28,7 @@
 	/* make it 1 if a 16MB memory card is used */
 	mi->nr_banks = 2; /* Default 32MB */
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0);
 	setup_ramdisk(1, 0, 0, 8192);
 	setup_initrd(0xc0400000, 4*1024*1024);
 }
diff -Nru a/arch/arm/mach-sa1100/sa1111-pcibuf.c b/arch/arm/mach-sa1100/sa1111-pcibuf.c
--- a/arch/arm/mach-sa1100/sa1111-pcibuf.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/sa1111-pcibuf.c	Tue Feb 26 11:57:56 2002
@@ -13,7 +13,6 @@
  *
  *  06/13/2001 - created.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff -Nru a/arch/arm/mach-sa1100/sherman.c b/arch/arm/mach-sa1100/sherman.c
--- a/arch/arm/mach-sa1100/sherman.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/sherman.c	Tue Feb 26 11:57:56 2002
@@ -24,7 +24,7 @@
 	SET_BANK( 1, 0xc8000000, 64*1024*1024 );
 	mi->nr_banks = 2;
 
-	ROOT_DEV = MKDEV( 60, 2 );
+	ROOT_DEV = mk_kdev( 60, 2 );
 	setup_ramdisk( 1, 0, 0, 8192 );
 //	setup_initrd( 0xc0400000, 8*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
--- a/arch/arm/mach-sa1100/simpad.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/simpad.c	Tue Feb 26 11:57:56 2002
@@ -50,7 +50,7 @@
 	SET_BANK( 0, 0xc0000000, 32*1024*1024 );
 #endif
 	mi->nr_banks = 1;
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/mach-sa1100/system3.c	Tue Feb 26 11:57:58 2002
@@ -54,8 +54,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/serial_sa1100.h>
 
-#include <asm/arch/irq.h>
-
 #include <linux/serial_core.h>
 
 #include "generic.h"
@@ -227,7 +225,7 @@
 {
 	DPRINTK( "%s\n", "START" );
 
-	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	ROOT_DEV = mk_kdev(RAMDISK_MAJOR,0);
 	setup_ramdisk( 1, 0, 0, 8192 );
 	setup_initrd( 0xc0800000, 8*1024*1024 );
 }
diff -Nru a/arch/arm/mach-sa1100/victor.c b/arch/arm/mach-sa1100/victor.c
--- a/arch/arm/mach-sa1100/victor.c	Tue Feb 26 11:57:56 2002
+++ b/arch/arm/mach-sa1100/victor.c	Tue Feb 26 11:57:56 2002
@@ -48,7 +48,7 @@
 	SET_BANK( 0, 0xc0000000, 4*1024*1024 );
 	mi->nr_banks = 1;
 
-	ROOT_DEV = MKDEV( 60, 2 );
+	ROOT_DEV = mk_kdev( 60, 2 );
 
 	/* Get command line parameters passed from the loader (if any) */
 	if( *((char*)0xc0000000) )
diff -Nru a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
--- a/arch/arm/mach-sa1100/yopy.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mach-sa1100/yopy.c	Tue Feb 26 11:57:57 2002
@@ -1,8 +1,6 @@
 /*
  * linux/arch/arm/mach-sa1100/yopy.c
  */
-
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -Nru a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
--- a/arch/arm/mm/alignment.c	Tue Feb 26 11:57:57 2002
+++ b/arch/arm/mm/alignment.c	Tue Feb 26 11:57:57 2002
@@ -30,6 +30,10 @@
 #include <asm/pgtable.h>
 #include <asm/unaligned.h>
 
+extern void
+do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
+	    int error_code, struct pt_regs *regs);
+
 /*
  * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
  * /proc/sys/debug/alignment, modified and integrated into
@@ -163,9 +167,9 @@
 #define TYPE_LDST	2
 #define TYPE_DONE	3
 
-#define get8_unaligned_check(val,addr,err)		\
+#define __get8_unaligned_check(ins,val,addr,err)	\
 	__asm__(					\
-	"1:	ldrb	%1, [%2], #1\n"			\
+	"1:	"ins"	%1, [%2], #1\n"			\
 	"2:\n"						\
 	"	.section .fixup,\"ax\"\n"		\
 	"	.align	2\n"				\
@@ -179,39 +183,49 @@
 	: "=r" (err), "=&r" (val), "=r" (addr)		\
 	: "0" (err), "2" (addr))
 
-#define get8t_unaligned_check(val,addr,err)		\
-	__asm__(					\
-	"1:	ldrbt	%1, [%2], #1\n"			\
-	"2:\n"						\
-	"	.section .fixup,\"ax\"\n"		\
-	"	.align	2\n"				\
-	"3:	mov	%0, #1\n"			\
-	"	b	2b\n"				\
-	"	.previous\n"				\
-	"	.section __ex_table,\"a\"\n"		\
-	"	.align	3\n"				\
-	"	.long	1b, 3b\n"			\
-	"	.previous\n"				\
-	: "=r" (err), "=&r" (val), "=r" (addr)		\
-	: "0" (err), "2" (addr))
+#define __get16_unaligned_check(ins,val,addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		__get8_unaligned_check(ins,val,a,err);		\
+		__get8_unaligned_check(ins,v,a,err);		\
+		val |= v << 8;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define get16_unaligned_check(val,addr) \
+	__get16_unaligned_check("ldrb",val,addr)
+
+#define get16t_unaligned_check(val,addr) \
+	__get16_unaligned_check("ldrbt",val,addr)
 
-#define get16_unaligned_check(val,addr)				\
+#define __get32_unaligned_check(ins,val,addr)			\
 	do {							\
 		unsigned int err = 0, v, a = addr;		\
-		get8_unaligned_check(val,a,err);		\
-		get8_unaligned_check(v,a,err);			\
+		__get8_unaligned_check(ins,val,a,err);		\
+		__get8_unaligned_check(ins,v,a,err);		\
 		val |= v << 8;					\
+		__get8_unaligned_check(ins,v,a,err);		\
+		val |= v << 16;					\
+		__get8_unaligned_check(ins,v,a,err);		\
+		val |= v << 24;					\
 		if (err)					\
 			goto fault;				\
 	} while (0)
 
-#define put16_unaligned_check(val,addr)				\
+#define get32_unaligned_check(val,addr) \
+	__get32_unaligned_check("ldrb",val,addr)
+
+#define get32t_unaligned_check(val,addr) \
+	__get32_unaligned_check("ldrbt",val,addr)
+
+#define __put16_unaligned_check(ins,val,addr)			\
 	do {							\
 		unsigned int err = 0, v = val, a = addr;	\
 		__asm__(					\
-		"1:	strb	%1, [%2], #1\n"			\
+		"1:	"ins"	%1, [%2], #1\n"			\
 		"	mov	%1, %1, lsr #8\n"		\
-		"2:	strb	%1, [%2]\n"			\
+		"2:	"ins"	%1, [%2]\n"			\
 		"3:\n"						\
 		"	.section .fixup,\"ax\"\n"		\
 		"	.align	2\n"				\
@@ -229,6 +243,12 @@
 			goto fault;				\
 	} while (0)
 
+#define put16_unaligned_check(val,addr)  \
+	__put16_unaligned_check("strb",val,addr)
+
+#define put16t_unaligned_check(val,addr) \
+	__put16_unaligned_check("strbt",val,addr)
+
 #define __put32_unaligned_check(ins,val,addr)			\
 	do {							\
 		unsigned int err = 0, v = val, a = addr;	\
@@ -259,37 +279,9 @@
 			goto fault;				\
 	} while (0)
 
-#define get32_unaligned_check(val,addr)				\
-	do {							\
-		unsigned int err = 0, v, a = addr;		\
-		get8_unaligned_check(val,a,err);		\
-		get8_unaligned_check(v,a,err);			\
-		val |= v << 8;					\
-		get8_unaligned_check(v,a,err);			\
-		val |= v << 16;					\
-		get8_unaligned_check(v,a,err);			\
-		val |= v << 24;					\
-		if (err)					\
-			goto fault;				\
-	} while (0)
-
 #define put32_unaligned_check(val,addr)	 \
 	__put32_unaligned_check("strb", val, addr)
 
-#define get32t_unaligned_check(val,addr)			\
-	do {							\
-		unsigned int err = 0, v, a = addr;		\
-		get8t_unaligned_check(val,a,err);		\
-		get8t_unaligned_check(v,a,err);			\
-		val |= v << 8;					\
-		get8t_unaligned_check(v,a,err);			\
-		val |= v << 16;					\
-		get8t_unaligned_check(v,a,err);			\
-		val |= v << 24;					\
-		if (err)					\
-			goto fault;				\
-	} while (0)
-
 #define put32t_unaligned_check(val,addr) \
 	__put32_unaligned_check("strbt", val, addr)
 
@@ -319,6 +311,9 @@
 
 	ai_half += 1;
 
+	if (user_mode(regs))
+		goto user;
+
 	if (LDST_L_BIT(instr)) {
 		unsigned long val;
 		get16_unaligned_check(val, addr);
@@ -333,12 +328,27 @@
 
 	return TYPE_LDST;
 
-swp:
+ user:
+ 	if (LDST_L_BIT(instr)) {
+ 		unsigned long val;
+ 		get16t_unaligned_check(val, addr);
+
+ 		/* signed half-word? */
+ 		if (instr & 0x40)
+ 			val = (signed long)((signed short) val);
+
+ 		regs->uregs[rd] = val;
+ 	} else
+ 		put16t_unaligned_check(regs->uregs[rd], addr);
+
+ 	return TYPE_LDST;
+
+ swp:
 	printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
-bad:
+ bad:
 	return TYPE_ERROR;
 
-fault:
+ fault:
 	return TYPE_FAULT;
 }
 
@@ -349,23 +359,27 @@
 
 	ai_word += 1;
 
-	if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
+	if ((!LDST_P_BIT(instr) && LDST_W_BIT(instr)) || user_mode(regs))
 		goto trans;
 
-	if (LDST_L_BIT(instr))
-		get32_unaligned_check(regs->uregs[rd], addr);
-	else
+	if (LDST_L_BIT(instr)) {
+		unsigned int val;
+		get32_unaligned_check(val, addr);
+		regs->uregs[rd] = val;
+	} else
 		put32_unaligned_check(regs->uregs[rd], addr);
 	return TYPE_LDST;
 
-trans:
-	if (LDST_L_BIT(instr))
-		get32t_unaligned_check(regs->uregs[rd], addr);
-	else
+ trans:
+	if (LDST_L_BIT(instr)) {
+		unsigned int val;
+		get32t_unaligned_check(val, addr);
+		regs->uregs[rd] = val;
+	} else
 		put32t_unaligned_check(regs->uregs[rd], addr);
 	return TYPE_LDST;
 
-fault:
+ fault:
 	return TYPE_FAULT;
 }
 
@@ -431,14 +445,31 @@
 	}
 #endif
 
-	for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
-		if (regbits & 1) {
-			if (LDST_L_BIT(instr))
-				get32_unaligned_check(regs->uregs[rd], eaddr);
-			else
-				put32_unaligned_check(regs->uregs[rd], eaddr);
-			eaddr += 4;
-		}
+	if (user_mode(regs)) {
+		for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
+		     regbits >>= 1, rd += 1)
+			if (regbits & 1) {
+				if (LDST_L_BIT(instr)) {
+					unsigned int val;
+					get32t_unaligned_check(val, eaddr);
+					regs->uregs[rd] = val;
+				} else
+					put32t_unaligned_check(regs->uregs[rd], eaddr);
+				eaddr += 4;
+			}
+	} else {
+		for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
+		     regbits >>= 1, rd += 1)
+			if (regbits & 1) {
+				if (LDST_L_BIT(instr)) {
+					unsigned int val;
+					get32_unaligned_check(val, eaddr);
+					regs->uregs[rd] = val;
+				} else
+					put32_unaligned_check(regs->uregs[rd], eaddr);
+				eaddr += 4;
+			}
+	}
 
 	if (LDST_W_BIT(instr))
 		regs->uregs[rn] = newaddr;
@@ -539,7 +570,7 @@
 
 	return 0;
 
-bad_or_fault:
+ bad_or_fault:
 	if (type == TYPE_ERROR)
 		goto bad;
 	regs->ARM_pc -= 4;
@@ -549,7 +580,7 @@
 	do_bad_area(current, current->mm, addr, error_code, regs);
 	return 0;
 
-bad:
+ bad:
 	/*
 	 * Oops, we didn't handle the instruction.
 	 */
diff -Nru a/arch/arm/tools/getconstants.c b/arch/arm/tools/getconstants.c
--- a/arch/arm/tools/getconstants.c	Tue Feb 26 11:57:58 2002
+++ b/arch/arm/tools/getconstants.c	Tue Feb 26 11:57:58 2002
@@ -32,23 +32,21 @@
 #endif
 
 #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
+#define OFF_VMA(n) (unsigned long)&(((struct vm_area_struct *)0)->n)
 
 #define DEFN(name,off) asm("\n#define "name" %0" :: "I" (off))
 
 void func(void)
 {
-#error DEFN("TSK_SIGPENDING",		OFF_TSK(sigpending));
-DEFN("TSK_ADDR_LIMIT",		OFF_TSK(addr_limit));
-#error DEFN("TSK_NEED_RESCHED",	OFF_TSK(need_resched));
-#error DEFN("TSK_PTRACE",		OFF_TSK(ptrace));
 DEFN("TSK_USED_MATH",		OFF_TSK(used_math));
+DEFN("TSK_ACTIVE_MM",		OFF_TSK(active_mm));
 
-DEFN("TSS_SAVE",		OFF_TSK(thread.save));
-DEFN("TSS_FPESAVE",		OFF_TSK(thread.fpstate.soft.save));
+DEFN("VMA_VM_MM",		OFF_VMA(vm_mm));
+DEFN("VMA_VM_FLAGS",		OFF_VMA(vm_flags));
 
-#ifdef CONFIG_CPU_32
-DEFN("TSS_DOMAIN",		OFF_TSK(thread.domain));
+DEFN("VM_EXEC",			VM_EXEC);
 
+#ifdef CONFIG_CPU_32
 DEFN("HPTE_TYPE_SMALL",		PTE_TYPE_SMALL);
 DEFN("HPTE_AP_READ",		PTE_AP_READ);
 DEFN("HPTE_AP_WRITE",		PTE_AP_WRITE);
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	Tue Feb 26 11:57:57 2002
+++ b/arch/i386/defconfig	Tue Feb 26 11:57:57 2002
@@ -121,7 +121,18 @@
 #
 # Parallel port support
 #
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_PCMCIA 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=y
 
 #
 # Plug and Play configuration
@@ -333,6 +344,8 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
@@ -454,6 +467,7 @@
 #
 # 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
@@ -550,6 +564,9 @@
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
 
 #
 # I2C support
@@ -718,11 +735,19 @@
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
 # CONFIG_SND_AD1816A is not set
 # CONFIG_SND_AD1848 is not set
 # CONFIG_SND_CS4231 is not set
@@ -749,6 +774,10 @@
 # CONFIG_SND_DT0197H is not set
 # CONFIG_SND_OPL3SA2 is not set
 # CONFIG_SND_SGALAXY is not set
+
+#
+# PCI devices
+#
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_EMU10K1 is not set
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	Tue Feb 26 11:57:59 2002
+++ b/arch/i386/kernel/apic.c	Tue Feb 26 11:57:59 2002
@@ -582,12 +582,17 @@
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
  */
+int dont_enable_local_apic __initdata = 0;
 
 static int __init detect_init_APIC (void)
 {
 	u32 h, l, features;
 	extern void get_cpu_vendor(struct cpuinfo_x86*);
 
+	/* Disabled by DMI scan or kernel option? */
+	if (dont_enable_local_apic)
+		return -1;
+
 	/* Workaround for us being called before identify_cpu(). */
 	get_cpu_vendor(&boot_cpu_data);
 
@@ -903,8 +908,14 @@
 
 static unsigned int calibration_result;
 
+int dont_use_local_apic_timer __initdata = 0;
+
 void __init setup_APIC_clocks (void)
 {
+	/* Disabled by DMI scan or kernel option? */
+	if (dont_use_local_apic_timer)
+		return;
+
 	printk("Using local APIC timer interrupts.\n");
 	using_apic_timer = 1;
 
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Tue Feb 26 11:57:59 2002
+++ b/arch/i386/kernel/dmi_scan.c	Tue Feb 26 11:57:59 2002
@@ -9,6 +9,7 @@
 #include <linux/pm.h>
 #include <asm/keyboard.h>
 #include <asm/system.h>
+#include <linux/bootmem.h>
 
 unsigned long dmi_broken;
 int is_sony_vaio_laptop;
@@ -51,7 +52,7 @@
 	u8 *data;
 	int i=1;
 		
-	buf = ioremap(base, len);
+	buf = bt_ioremap(base, len);
 	if(buf==NULL)
 		return -1;
 
@@ -83,7 +84,7 @@
 		data+=2;
 		i++;
 	}
-	iounmap(buf);
+	bt_iounmap(buf, len);
 	return 0;
 }
 
@@ -155,7 +156,7 @@
 		return;
 	if (dmi_ident[slot])
 		return;
-	dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
+	dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
 	if(dmi_ident[slot])
 		strcpy(dmi_ident[slot], p);
 	else
@@ -416,6 +417,43 @@
 	return 0;
 }
 
+/*
+ * Some machines, usually laptops, can't handle an enabled local APIC.
+ * The symptoms include hangs or reboots when suspending or resuming,
+ * attaching or detaching the power cord, or entering BIOS setup screens
+ * through magic key sequences.
+ */
+static int __init local_apic_kills_bios(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	extern int dont_enable_local_apic;
+	if (!dont_enable_local_apic) {
+		dont_enable_local_apic = 1;
+		printk(KERN_WARNING "%s with broken BIOS detected. "
+		       "Refusing to enable the local APIC.\n",
+		       d->ident);
+	}
+#endif
+	return 0;
+}
+
+/*
+ * The Intel AL440LX mainboard will hang randomly if the local APIC
+ * timer is running and the APM BIOS hasn't been disabled.
+ */
+static int __init apm_kills_local_apic_timer(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	extern int dont_use_local_apic_timer;
+	if (apm_info.bios.version && !dont_use_local_apic_timer) {
+		dont_use_local_apic_timer = 1;
+		printk(KERN_WARNING "%s with broken BIOS detected. "
+		       "The local APIC timer will not be used.\n",
+		       d->ident);
+	}
+#endif
+	return 0;
+}
 
 /*
  *	Simple "print if true" callback
@@ -560,6 +598,25 @@
 			MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
 			} },
 
+	/* Machines which have problems handling enabled local APICs */
+
+	{ local_apic_kills_bios, "Dell Inspiron", {
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+			NO_MATCH, NO_MATCH
+			} },
+
+	{ local_apic_kills_bios, "Dell Latitude", {
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "Latitude"),
+			NO_MATCH, NO_MATCH
+			} },
+
+	{ apm_kills_local_apic_timer, "Intel AL440LX", {
+			MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			MATCH(DMI_BOARD_NAME, "AL440LX"),
+			NO_MATCH, NO_MATCH } },
+
 	/* Problem Intel 440GX bioses */
 
 	{ broken_pirq, "SABR1 Bios", {			/* Bad $PIR */
@@ -588,7 +645,7 @@
 			NO_MATCH, NO_MATCH
 			} },
                         
-	/* Intel in disgiuse - In this case they can't hide and they don't run
+	/* Intel in disguise - In this case they can't hide and they don't run
 	   too well either... */
 	{ broken_pirq, "Dell PowerEdge 8450", {		/* Bad $PIR */
 			MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
@@ -728,12 +785,9 @@
 	}
 }
 
-static int __init dmi_scan_machine(void)
+void __init dmi_scan_machine(void)
 {
 	int err = dmi_iterate(dmi_decode);
 	if(err == 0)
 		dmi_check_blacklist();
-	return err;
 }
-
-module_init(dmi_scan_machine);
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	Tue Feb 26 11:58:00 2002
+++ b/arch/i386/kernel/i8259.c	Tue Feb 26 11:58:00 2002
@@ -79,7 +79,6 @@
  * through the ICC by us (IPIs)
  */
 #ifdef CONFIG_SMP
-BUILD_SMP_INTERRUPT(task_migration_interrupt,TASK_MIGRATION_VECTOR)
 BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
 BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
 BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
@@ -473,9 +472,6 @@
 	 * IPI, driven by wakeup.
 	 */
 	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPI for task migration */
-	set_intr_gate(TASK_MIGRATION_VECTOR, task_migration_interrupt);
 
 	/* IPI for invalidation */
 	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Tue Feb 26 11:57:59 2002
+++ b/arch/i386/kernel/setup.c	Tue Feb 26 11:57:59 2002
@@ -99,8 +99,8 @@
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <asm/processor.h>
 #include <linux/console.h>
+#include <asm/processor.h>
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -113,6 +113,7 @@
 #include <asm/dma.h>
 #include <asm/mpspec.h>
 #include <asm/mmu_context.h>
+
 /*
  * Machine setup..
  */
@@ -158,6 +159,7 @@
 unsigned char aux_device_present;
 
 extern void mcheck_init(struct cpuinfo_x86 *c);
+extern void dmi_scan_machine(void);
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
 extern int blk_nohighio;
@@ -907,7 +909,6 @@
 	 */
 	if (smp_found_config)
 		get_smp_config();
-	init_apic_mappings();
 #endif
 
 
@@ -959,6 +960,7 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
+	dmi_scan_machine();
 }
 
 static int cachesize_override __initdata = -1;
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	Tue Feb 26 11:57:56 2002
+++ b/arch/i386/kernel/smp.c	Tue Feb 26 11:57:56 2002
@@ -485,35 +485,6 @@
 	do_flush_tlb_all_local();
 }
 
-static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
-static task_t *new_task;
-
-/*
- * This function sends a 'task migration' IPI to another CPU.
- * Must be called from syscall contexts, with interrupts *enabled*.
- */
-void smp_migrate_task(int cpu, task_t *p)
-{
-	/*
-	 * The target CPU will unlock the migration spinlock:
-	 */
-	_raw_spin_lock(&migration_lock);
-	new_task = p;
-	send_IPI_mask(1 << cpu, TASK_MIGRATION_VECTOR);
-}
-
-/*
- * Task migration callback.
- */
-asmlinkage void smp_task_migration_interrupt(void)
-{
-	task_t *p;
-
-	ack_APIC_irq();
-	p = new_task;
-	_raw_spin_unlock(&migration_lock);
-	sched_task_migrated(p);
-}
 /*
  * this function sends a 'reschedule' IPI to another CPU.
  * it goes straight through and wastes no time serializing
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Tue Feb 26 11:57:57 2002
+++ b/arch/i386/kernel/traps.c	Tue Feb 26 11:57:57 2002
@@ -974,6 +974,10 @@
 		EISA_bus = 1;
 #endif
 
+#ifdef CONFIG_X86_LOCAL_APIC
+	init_apic_mappings();
+#endif
+
 	set_trap_gate(0,&divide_error);
 	set_trap_gate(1,&debug);
 	set_intr_gate(2,&nmi);
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Tue Feb 26 11:57:58 2002
+++ b/arch/i386/mm/init.c	Tue Feb 26 11:57:58 2002
@@ -105,7 +105,6 @@
 static inline void set_pte_phys (unsigned long vaddr,
 			unsigned long phys, pgprot_t flags)
 {
-	pgprot_t prot;
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
@@ -121,10 +120,8 @@
 		return;
 	}
 	pte = pte_offset_kernel(pmd, vaddr);
-	if (pte_val(*pte))
-		pte_ERROR(*pte);
-	pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
-	set_pte(pte, mk_pte_phys(phys, prot));
+	/* <phys,flags> stored as-is, to permit clearing entries */
+	set_pte(pte, mk_pte_phys(phys, flags));
 
 	/*
 	 * It's enough to flush this one mapping.
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	Tue Feb 26 11:57:58 2002
+++ b/arch/i386/mm/ioremap.c	Tue Feb 26 11:57:58 2002
@@ -161,3 +161,69 @@
 	if (addr > high_memory)
 		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
+
+#include <asm/fixmap.h>
+void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+{
+	unsigned long offset, last_addr;
+	unsigned int nrpages;
+	enum fixed_addresses idx;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Don't remap the low PCI/ISA area, it's always mapped..
+	 */
+	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+		return phys_to_virt(phys_addr);
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr) - phys_addr;
+
+	/*
+	 * Mappings have to fit in the FIX_BTMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > NR_FIX_BTMAPS)
+		return NULL;
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx = FIX_BTMAP_BEGIN;
+	while (nrpages > 0) {
+		set_fixmap(idx, phys_addr);
+		phys_addr += PAGE_SIZE;
+		--idx;
+		--nrpages;
+	}
+	return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
+}
+
+void __init bt_iounmap(void *addr, unsigned long size)
+{
+	unsigned long virt_addr;
+	unsigned long offset;
+	unsigned int nrpages;
+	enum fixed_addresses idx;
+
+	virt_addr = (unsigned long)addr;
+	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
+		return;
+	offset = virt_addr & ~PAGE_MASK;
+	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+
+	idx = FIX_BTMAP_BEGIN;
+	while (nrpages > 0) {
+		__set_fixmap(idx, 0, __pgprot(0));
+		--idx;
+		--nrpages;
+	}
+}
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Tue Feb 26 11:57:59 2002
+++ b/arch/ia64/kernel/perfmon.c	Tue Feb 26 11:57:59 2002
@@ -332,35 +332,8 @@
 	return ia64_get_itc();
 }
 
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long
-uvirt_to_kva(pgd_t *pgd, unsigned long adr)
-{
-	unsigned long ret = 0UL;
-	pmd_t *pmd;
-	pte_t *ptep, pte;
-
-	if (!pgd_none(*pgd)) {
-		pmd = pmd_offset(pgd, adr);
-		if (!pmd_none(*pmd)) {
-			ptep = pte_offset(pmd, adr);
-			pte = *ptep;
-			if (pte_present(pte)) {
-				ret = (unsigned long) page_address(pte_page(pte));
-				ret |= (adr & (PAGE_SIZE - 1));
-			}
-		}
-	}
-	DBprintk(("uv2kva(%lx-->%lx)\n", adr, ret));
-	return ret;
-}
-
-
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long
 kvirt_to_pa(unsigned long adr)
@@ -374,19 +347,15 @@
 rvmalloc(unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
+	unsigned long adr;
 
-	/* XXX: may have to revisit this part because
-	 * vmalloc() does not necessarily return a page-aligned buffer.
-	 * This maybe a security problem when mapped at user level
-	 */
+	size=PAGE_ALIGN(size);
 	mem=vmalloc(size);
 	if (mem) {
 		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 		adr=(unsigned long) mem;
 		while (size > 0) {
-			page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -397,13 +366,12 @@
 static void
 rvfree(void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (mem) {
 		adr=(unsigned long) mem;
-		while (size > 0) {
-			page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+		while ((long) size > 0) {
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -515,7 +483,6 @@
 	vma->vm_file	  = NULL;
 	vma->vm_raend	  = 0;
 
-	/* XXX: see rvmalloc() for page alignment problem */
 	smpl_buf = rvmalloc(size);
 	if (smpl_buf == NULL) goto no_buffer;
 
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Tue Feb 26 11:57:58 2002
+++ b/drivers/Makefile	Tue Feb 26 11:57:58 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the Linux kernel device drivers.
 #
-# 15 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/acorn/block/mfmhd.c	Tue Feb 26 11:57:57 2002
@@ -321,14 +321,14 @@
 	unsigned long flags;
 	va_list ap;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 
 	va_start(ap, fmt);
 	vsprintf(buffer, fmt, ap);
 	console_print(buffer);
 	va_end(fmt);
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 };	/* console_printf */
 
 #define DBG(x...) console_printf(x)
@@ -746,7 +746,7 @@
 			/* Yep - a partial access */
 
 			/* and issue the remainder */
-			issue_request(MINOR(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
+			issue_request(minor(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
 			return;
 		}
 
@@ -929,7 +929,7 @@
 
 		DBG("mfm_request:                 before arg extraction\n");
 
-		dev = MINOR(CURRENT->rq_dev);
+		dev = minor(CURRENT->rq_dev);
 		block = CURRENT->sector;
 		nsect = CURRENT->nr_sectors;
 #ifdef DEBUG
@@ -1187,10 +1187,10 @@
 	if (!inode || !(dev = inode->i_rdev))
 		return -EINVAL;
 
-	major = MAJOR(dev);
-	minor = MINOR(dev);
+	major = major(dev);
+	minor = minor(dev);
 
-	device = DEVICE_NR(MINOR(inode->i_rdev)), err;
+	device = DEVICE_NR(minor(inode->i_rdev)), err;
 	if (device >= mfm_drives)
 		return -EINVAL;
 
@@ -1231,7 +1231,7 @@
 
 static int mfm_open(struct inode *inode, struct file *file)
 {
-	int dev = DEVICE_NR(MINOR(inode->i_rdev));
+	int dev = DEVICE_NR(minor(inode->i_rdev));
 
 	if (dev >= mfm_drives)
 		return -ENODEV;
@@ -1249,7 +1249,7 @@
  */
 static int mfm_release(struct inode *inode, struct file *file)
 {
-	mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--;
+	mfm_info[DEVICE_NR(minor(inode->i_rdev))].access_count--;
 	return 0;
 }
 
@@ -1270,7 +1270,7 @@
 void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
 		     unsigned long discsize, unsigned int secsize)
 {
-	int drive = MINOR(dev) >> 6;
+	int drive = minor(dev) >> 6;
 
 	if (mfm_info[drive].cylinders == 1) {
 		mfm_info[drive].sectors = secsptrack;
@@ -1338,7 +1338,7 @@
 
 	for (i = 0; i < mfm_drives; i++) {
 		mfm_geometry (i);
-		register_disk(&mfm_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6,
+		register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6,
 				&mfm_fops,
 				mfm_info[i].cylinders * mfm_info[i].heads *
 				mfm_info[i].sectors / 2);
@@ -1448,23 +1448,23 @@
  */
 static int mfm_reread_partitions(kdev_t dev)
 {
-	unsigned int start, i, maxp, target = DEVICE_NR(MINOR(dev));
+	unsigned int start, i, maxp, target = DEVICE_NR(minor(dev));
 	unsigned long flags;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 	if (mfm_info[target].busy || mfm_info[target].access_count > 1) {
-		restore_flags (flags);
+		local_irq_restore (flags);
 		return -EBUSY;
 	}
 	mfm_info[target].busy = 1;
-	restore_flags (flags);
+	local_irq_restore (flags);
 
 	maxp = 1 << mfm_gendisk.minor_shift;
 	start = target << mfm_gendisk.minor_shift;
 
 	for (i = maxp - 1; i >= 0; i--) {
 		int minor = start + i;
-		invalidate_device (MKDEV(MAJOR_NR, minor), 1);
+		invalidate_device (mk_kdev(MAJOR_NR, minor), 1);
 		mfm_gendisk.part[minor].start_sect = 0;
 		mfm_gendisk.part[minor].nr_sects = 0;
 	}
diff -Nru a/drivers/acorn/char/mouse_ps2.c b/drivers/acorn/char/mouse_ps2.c
--- a/drivers/acorn/char/mouse_ps2.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/acorn/char/mouse_ps2.c	Tue Feb 26 11:57:58 2002
@@ -1,8 +1,6 @@
 /* 
  * Driver for PS/2 mouse on IOMD interface
  */
-
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
--- a/drivers/acorn/net/ether1.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/acorn/net/ether1.c	Tue Feb 26 11:57:56 2002
@@ -99,13 +99,13 @@
 	unsigned long flags;
 	unsigned short ret;
 
-	if (svflgs) {
-		save_flags_cli (flags);
-	}
+	if (svflgs)
+		local_irq_save (flags);
+
 	outb (addr >> 12, REG_PAGE);
 	ret = inw (ETHER1_RAM + ((addr & 4095) >> 1));
 	if (svflgs)
-		restore_flags (flags);
+		local_irq_restore (flags);
 	return ret;
 }
 
@@ -114,13 +114,13 @@
 {
 	unsigned long flags;
 
-	if (svflgs) {
-		save_flags_cli (flags);
-	}
+	if (svflgs)
+		local_irq_save (flags);
+
 	outb (addr >> 12, REG_PAGE);
 	outw (val, ETHER1_RAM + ((addr & 4095) >> 1));
 	if (svflgs)
-		restore_flags (flags);
+		local_irq_restore (flags);
 }
 
 /*
@@ -722,7 +722,7 @@
 	nop.nop_command = CMD_NOP;
 	nop.nop_link = nopaddr;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 	ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
 	ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
 	ether1_writebuffer (dev, skb->data, dataddr, len);
@@ -733,7 +733,7 @@
 	/* now reset the previous nop pointer */
 	ether1_outw (dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	/* handle transmit */
 	dev->trans_start = jiffies;
diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c
--- a/drivers/acorn/net/ether3.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/acorn/net/ether3.c	Tue Feb 26 11:57:59 2002
@@ -491,7 +491,7 @@
 
 	del_timer(&priv->timer);
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 	printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
 	printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name,
 		ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2));
@@ -501,7 +501,7 @@
 		priv->tx_head, priv->tx_tail);
 	ether3_setbuffer(dev, buffer_read, priv->tx_tail);
 	printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	priv->regs.config2 |= CFG2_CTRLO;
 	priv->stats.tx_errors += 1;
@@ -533,10 +533,10 @@
 
 	next_ptr = (priv->tx_head + 1) & 15;
 
-	save_flags_cli(flags);
+	local_irq_save(flags);
 
 	if (priv->tx_tail == next_ptr) {
-		restore_flags(flags);
+		local_irq_restore(flags);
 		return 1;	/* unable to queue */
 	}
 
@@ -565,7 +565,7 @@
 	}
 
 	next_ptr = (priv->tx_head + 1) & 15;
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 	dev_kfree_skb(skb);
 
diff -Nru a/drivers/atm/eni.c b/drivers/atm/eni.c
--- a/drivers/atm/eni.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/atm/eni.c	Tue Feb 26 11:57:58 2002
@@ -2310,7 +2310,7 @@
 	name:		DEV_LABEL,
 	id_table:	eni_pci_tbl,
 	probe:		eni_init_one,
-	remove:		eni_remove_one,
+	remove:		__devexit_p(eni_remove_one),
 };
 
 
diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/atm/firestream.c	Tue Feb 26 11:57:57 2002
@@ -1530,7 +1530,7 @@
 	fs_dprintk (FS_DEBUG_QUEUE, "Added %d entries. \n", n);
 }
 
-static void __exit free_queue (struct fs_dev *dev, struct queue *txq)
+static void __devexit free_queue (struct fs_dev *dev, struct queue *txq)
 {
 	func_enter ();
 
@@ -1546,7 +1546,7 @@
 	func_exit ();
 }
 
-static void __exit free_freepool (struct fs_dev *dev, struct freepool *fp)
+static void __devexit free_freepool (struct fs_dev *dev, struct freepool *fp)
 {
 	func_enter ();
 
@@ -2088,7 +2088,7 @@
 #endif 
 */
 
-const static struct pci_device_id firestream_pci_tbl[] __devinitdata = {
+static struct pci_device_id firestream_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50, 
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50},
 	{ PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155, 
@@ -2102,7 +2102,7 @@
 	name:           "firestream",
 	id_table:       firestream_pci_tbl,
 	probe:          firestream_init_one,
-	remove:         firestream_remove_one,
+	remove:         __devexit_p(firestream_remove_one),
 };
 
 static int __init firestream_init_module (void)
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Tue Feb 26 11:58:00 2002
+++ b/drivers/block/DAC960.h	Tue Feb 26 11:58:00 2002
@@ -2074,7 +2074,7 @@
 #define DAC960_KernelDevice(ControllerNumber,				       \
 			    LogicalDriveNumber,				       \
 			    PartitionNumber)				       \
-   MKDEV(DAC960_MajorNumber(ControllerNumber),				       \
+   mk_kdev(DAC960_MajorNumber(ControllerNumber),				       \
 	 DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber))
 
 
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	Tue Feb 26 11:58:00 2002
+++ b/drivers/block/Makefile	Tue Feb 26 11:58:00 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the kernel block device drivers.
 #
-# 12 June 2000, Christoph Hellwig <schch@pe.tu-clausthal.de>
+# 12 June 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 # 
 # Note : at this point, these files are compiled on all systems.
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/block/acsi.c	Tue Feb 26 11:57:59 2002
@@ -784,7 +784,7 @@
 	
 	status = acsi_getstatus();
 	if (status != 0) {
-		int dev = DEVICE_NR(MINOR(CURRENT->rq_dev));
+		int dev = DEVICE_NR(minor(CURRENT->rq_dev));
 		printk( KERN_ERR "ad%c: ", dev+'a' );
 		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, 
 					acsi_info[dev].lun))
@@ -815,7 +815,7 @@
 
 	status = acsi_getstatus();
 	if (status != 0) {
-		int	dev = DEVICE_NR(MINOR(CURRENT->rq_dev));
+		int	dev = DEVICE_NR(minor(CURRENT->rq_dev));
 		printk( KERN_ERR "ad%c: ", dev+'a' );
 		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target,
 					acsi_info[dev].lun))
@@ -993,7 +993,7 @@
 			panic(DEVICE_NAME ": block not locked");
 	}
 
-	dev = MINOR(CURRENT->rq_dev);
+	dev = minor(CURRENT->rq_dev);
 	block = CURRENT->sector;
 	if (DEVICE_NR(dev) >= NDevices ||
 		block+CURRENT->nr_sectors >= acsi_part[dev].nr_sects) {
@@ -1111,7 +1111,7 @@
 
 	if (!inode)
 		return -EINVAL;
-	dev = DEVICE_NR(MINOR(inode->i_rdev));
+	dev = DEVICE_NR(minor(inode->i_rdev));
 	if (dev >= NDevices)
 		return -EINVAL;
 	switch (cmd) {
@@ -1174,7 +1174,7 @@
 	int  device;
 	struct acsi_info_struct *aip;
 
-	device = DEVICE_NR(MINOR(inode->i_rdev));
+	device = DEVICE_NR(minor(inode->i_rdev));
 	if (device >= NDevices)
 		return -ENXIO;
 	aip = &acsi_info[device];
@@ -1212,7 +1212,7 @@
 
 static int acsi_release( struct inode * inode, struct file * file )
 {
-	int device = DEVICE_NR(MINOR(inode->i_rdev));
+	int device = DEVICE_NR(minor(inode->i_rdev));
 	if (--access_count[device] == 0 && acsi_info[device].removable)
 		acsi_prevent_removal(device, 0);
 	return( 0 );
@@ -1240,7 +1240,7 @@
 
 static int acsi_media_change (dev_t dev)
 {
-	int device = DEVICE_NR(MINOR(dev));
+	int device = DEVICE_NR(minor(dev));
 	struct acsi_info_struct *aip;
 
 	aip = &acsi_info[device];
@@ -1742,7 +1742,7 @@
 		acsi_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = acsi_blocksizes;
 	for( i = 0; i < NDevices; ++i )
-		register_disk(&acsi_gendisk, MKDEV(MAJOR_NR,i<<4),
+		register_disk(&acsi_gendisk, mk_kdev(MAJOR_NR,i<<4),
 				(acsi_info[i].type==HARDDISK)?1<<4:1,
 				&acsi_fops,
 				acsi_info[i].size);
@@ -1853,7 +1853,7 @@
 	int res;
 	struct acsi_info_struct *aip;
 	
-	device = DEVICE_NR(MINOR(dev));
+	device = DEVICE_NR(minor(dev));
 	aip = &acsi_info[device];
 	gdev = &GENDISK_STRUCT;
 
diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c
--- a/drivers/block/ataflop.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/block/ataflop.c	Tue Feb 26 11:57:57 2002
@@ -659,7 +659,7 @@
 	unsigned char	*p;
 	int sect, nsect;
 	unsigned long	flags;
-	int type, drive = MINOR(device) & 3;
+	int type, drive = minor(device) & 3;
 
 	DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
 		drive, desc->track, desc->head, desc->sect_offset ));
@@ -672,7 +672,7 @@
 	atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
 	restore_flags(flags);
 
-	type = MINOR(device) >> 2;
+	type = minor(device) >> 2;
 	if (type) {
 		if (--type >= NUM_DISK_MINORS ||
 		    minor2disktype[type].drive_types > DriveType) {
@@ -1367,9 +1367,9 @@
 
 static int check_floppy_change (kdev_t dev)
 {
-	unsigned int drive = MINOR(dev) & 0x03;
+	unsigned int drive = minor(dev) & 0x03;
 
-	if (MAJOR(dev) != MAJOR_NR) {
+	if (major(dev) != MAJOR_NR) {
 		printk(KERN_ERR "floppy_changed: not a floppy\n");
 		return 0;
 	}
@@ -1394,7 +1394,7 @@
 
 static int floppy_revalidate (kdev_t dev)
 {
-	int drive = MINOR(dev) & 3;
+	int drive = minor(dev) & 3;
 
 	if (test_bit(drive, &changed_floppies) ||
 	    test_bit(drive, &fake_change) ||
@@ -1466,13 +1466,13 @@
 	if (QUEUE_EMPTY)
 		goto the_end;
 
-	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
+	if (major(CURRENT->rq_dev) != MAJOR_NR)
 		panic(DEVICE_NAME ": request list destroyed");
 
 	if (CURRENT->bh && !buffer_locked(CURRENT->bh))
 		panic(DEVICE_NAME ": block not locked");
 
-	device = MINOR(CURRENT_DEVICE);
+	device = minor(CURRENT_DEVICE);
 	drive = device & 3;
 	type = device >> 2;
 	
@@ -1553,7 +1553,7 @@
 {
 	/* invalidate the buffer track to force a reread */
 	BufferDrive = -1;
-	set_bit(MINOR(rdev) & 3, &fake_change);
+	set_bit(minor(rdev) & 3, &fake_change);
 	check_disk_change(rdev);
 	return 0;
 }
@@ -1576,7 +1576,7 @@
 		case BLKFLSBUF:
 			return blk_ioctl(device, cmd, param);
 	}
-	drive = MINOR (device);
+	drive = minor (device);
 	type  = drive >> 2;
 	drive &= 3;
 	switch (cmd) {
@@ -1896,15 +1896,15 @@
 		return -EIO;
 	}
 
-	drive = MINOR(inode->i_rdev) & 3;
-	type  = MINOR(inode->i_rdev) >> 2;
+	drive = minor(inode->i_rdev) & 3;
+	type  = minor(inode->i_rdev) >> 2;
 	DPRINT(("fd_open: type=%d\n",type));
 	if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
 		return -ENXIO;
 
 	old_dev = fd_device[drive];
 
-	if (fd_ref[drive] && old_dev != MINOR(inode->i_rdev))
+	if (fd_ref[drive] && old_dev != minor(inode->i_rdev))
 		return -EBUSY;
 
 	if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
@@ -1915,10 +1915,10 @@
 	else
 		fd_ref[drive]++;
 
-	fd_device[drive] = MINOR(inode->i_rdev);
+	fd_device[drive] = minor(inode->i_rdev);
 
-	if (old_dev && old_dev != MINOR(inode->i_rdev))
-		invalidate_buffers(MKDEV(FLOPPY_MAJOR, old_dev));
+	if (old_dev && old_dev != minor(inode->i_rdev))
+		invalidate_buffers(mk_kdev(FLOPPY_MAJOR, old_dev));
 
 	if (filp->f_flags & O_NDELAY)
 		return 0;
@@ -1939,7 +1939,7 @@
 
 static int floppy_release( struct inode * inode, struct file * filp )
 {
-	int drive = MINOR(inode->i_rdev) & 3;
+	int drive = minor(inode->i_rdev) & 3;
 
 	if (fd_ref[drive] < 0)
 		fd_ref[drive] = 0;
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/block/cciss.c	Tue Feb 26 11:58:00 2002
@@ -2617,7 +2617,7 @@
 static struct pci_driver cciss_pci_driver = {
 	name:		"cciss",
 	probe:		cciss_init_one,
-	remove:		cciss_remove_one,
+	remove:		__devexit_p(cciss_remove_one),
 	id_table:	cciss_pci_device_id, /* id_table */
 };
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/block/rd.c	Tue Feb 26 11:57:56 2002
@@ -268,7 +268,7 @@
 		goto fail;
 
 	set_bit(BIO_UPTODATE, &sbh->bi_flags);
-	sbh->bi_end_io(sbh, len >> 9);
+	sbh->bi_end_io(sbh);
 	return 0;
  fail:
 	bio_io_error(sbh);
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Tue Feb 26 11:57:59 2002
+++ b/drivers/char/Makefile	Tue Feb 26 11:57:59 2002
@@ -23,7 +23,7 @@
 
 export-objs     :=	busmouse.o console.o keyboard.o sysrq.o \
 			misc.o pty.o random.o selection.o serial.o \
-			sonypi.o tty_io.o tty_ioctl.o generic_serial.o
+			sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o
 
 mod-subdirs	:=	ftape drm pcmcia
 
diff -Nru a/drivers/char/drm/drm_scatter.h b/drivers/char/drm/drm_scatter.h
--- a/drivers/char/drm/drm_scatter.h	Tue Feb 26 11:57:56 2002
+++ b/drivers/char/drm/drm_scatter.h	Tue Feb 26 11:57:56 2002
@@ -66,9 +66,6 @@
 	drm_scatter_gather_t request;
 	drm_sg_mem_t *entry;
 	unsigned long pages, i, j;
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte, pte_entry;
 
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
@@ -135,25 +132,9 @@
 	DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
 
 	for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
-		pgd = pgd_offset_k( i );
-		if ( !pgd_present( *pgd ) )
+		entry->pagelist[j] = vmalloc_to_page((void *)i);
+		if (!entry->pagelist[j])
 			goto failed;
-
-		pmd = pmd_offset( pgd, i );
-		if ( !pmd_present( *pmd ) )
-			goto failed;
-
-		preempt_disable();
-		pte = pte_offset_map(pmd, i);
-		pte_entry = *pte;
-		pte_unmap(pte);
-		preempt_enable();
-
-		if (!pte_present(pte_entry))
-			goto failed;
-
-		entry->pagelist[j] = pte_page(pte_entry);
-
 		SetPageReserved(entry->pagelist[j]);
 	}
 
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h	Tue Feb 26 11:57:59 2002
+++ b/drivers/char/drm/drm_vm.h	Tue Feb 26 11:57:59 2002
@@ -152,9 +152,6 @@
 #endif
 	unsigned long	 offset;
 	unsigned long	 i;
-	pgd_t		 *pgd;
-	pmd_t		 *pmd;
-	pte_t		 *pte, entry;
 	struct page	 *page;
 
 	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
@@ -162,26 +159,9 @@
 
 	offset	 = address - vma->vm_start;
 	i = (unsigned long)map->handle + offset;
-	/* We have to walk page tables here because we need large SAREA's, and
-	 * they need to be virtually contiguous in kernel space.
-	 */
-	pgd = pgd_offset_k( i );
-	if (!pgd_present(*pgd))
-		goto oom;
-	pmd = pmd_offset( pgd, i );
-	if (!pmd_present(*pmd))
-		goto oom;
-
-	preempt_disable();
-	pte = pte_offset_map(pmd, i);
-	entry = *pte;
-	pte_unmap(pte);
-	preempt_enable();
-
-	if (!pte_present(entry))
-		goto oom;
-
-	page = pte_page(entry);
+	page = vmalloc_to_page((void *)i);
+	if (!page)
+		return NOPAGE_OOM;
 	get_page(page);
 
 	DRM_DEBUG("shm_nopage 0x%lx\n", address);
@@ -190,8 +170,6 @@
 #else
 	return page;
 #endif
-oom:
-	return NOPAGE_OOM;
 }
 
 /* Special close routine which deletes map information if we are the last
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/char/mem.c	Tue Feb 26 11:57:59 2002
@@ -273,6 +273,8 @@
  	return virtr + read;
 }
 
+extern long vwrite(char *buf, char *addr, unsigned long count);
+
 /*
  * This function writes to the *virtual* memory as seen by the kernel.
  */
@@ -280,12 +282,46 @@
 			  size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
+	ssize_t wrote = 0;
+	ssize_t virtr = 0;
+	char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+
+	if (p < (unsigned long) high_memory) {
+		wrote = count;
+		if (count > (unsigned long) high_memory - p)
+			wrote = (unsigned long) high_memory - p;
+
+		wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
+
+		p += wrote;
+		buf += wrote;
+		count -= wrote;
+	}
+
+	if (count > 0) {
+		kbuf = (char *)__get_free_page(GFP_KERNEL);
+		if (!kbuf)
+			return -ENOMEM;
+		while (count > 0) {
+			int len = count;
+
+			if (len > PAGE_SIZE)
+				len = PAGE_SIZE;
+			if (len && copy_from_user(kbuf, buf, len)) {
+				free_page((unsigned long)kbuf);
+				return -EFAULT;
+			}
+			len = vwrite(kbuf, (char *)p, len);
+			count -= len;
+			buf += len;
+			virtr += len;
+			p += len;
+		}
+		free_page((unsigned long)kbuf);
+	}
 
-	if (p >= (unsigned long) high_memory)
-		return 0;
-	if (count > (unsigned long) high_memory - p)
-		count = (unsigned long) high_memory - p;
-	return do_write_mem(file, (void*)p, p, buf, count, ppos);
+ 	*ppos = p;
+ 	return virtr + wrote;
 }
 
 #if !defined(__mc68000__)
diff -Nru a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
--- a/drivers/char/mwave/mwavedd.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/char/mwave/mwavedd.c	Tue Feb 26 11:57:58 2002
@@ -461,7 +461,7 @@
 * mwave_exit is called on module unload
 * mwave_exit is also used to clean up after an aborted mwave_init
 */
-static void __exit mwave_exit(void)
+static void mwave_exit(void)
 {
 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
 
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/char/rtc.c	Tue Feb 26 11:57:59 2002
@@ -41,9 +41,11 @@
  *	1.10c	Cesar Barros: SMP locking fixes and cleanup
  *	1.10d	Paul Gortmaker: delete paranoia check in rtc_exit
  *	1.10e	Maciej W. Rozycki: Handle DECstation's year weirdness.
+ *      1.11    Takashi Iwai: Kernel access functions
+ *			      rtc_register/rtc_unregister/rtc_control
  */
 
-#define RTC_VERSION		"1.10e"
+#define RTC_VERSION		"1.11"
 
 #define RTC_IO_EXTENT	0x10	/* Only really two ports, but...	*/
 
@@ -139,6 +141,11 @@
 static unsigned long rtc_freq = 0;	/* Current periodic IRQ rate	*/
 static unsigned long rtc_irq_data = 0;	/* our output to the world	*/
 
+#if RTC_IRQ
+static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
+static rtc_task_t *rtc_callback = NULL;
+#endif
+
 /*
  *	If this driver ever becomes modularised, it will be really nice
  *	to make the epoch retain its value across module reload...
@@ -180,6 +187,10 @@
 	spin_unlock (&rtc_lock);
 
 	/* Now do the rest of the actions */
+	spin_lock(&rtc_task_lock);
+	if (rtc_callback)
+		rtc_callback->func(rtc_callback->private_data);
+	spin_unlock(&rtc_task_lock);
 	wake_up_interruptible(&rtc_wait);	
 
 	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
@@ -244,8 +255,7 @@
 #endif
 }
 
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-		     unsigned long arg)
+static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
 {
 	struct rtc_time wtime; 
 
@@ -295,7 +305,7 @@
 		 * We don't really want Joe User enabling more
 		 * than 64Hz of interrupts on a multi-user machine.
 		 */
-		if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
+		if (!kernel && (rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
 			return -EACCES;
 
 		if (!(rtc_status & RTC_TIMER_ON)) {
@@ -493,7 +503,7 @@
 		 * We don't really want Joe User generating more
 		 * than 64Hz of interrupts on a multi-user machine.
 		 */
-		if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
+		if (!kernel && (arg > 64) && (!capable(CAP_SYS_RESOURCE)))
 			return -EACCES;
 
 		while (arg > (1<<tmp))
@@ -539,6 +549,12 @@
 	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
 }
 
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	return rtc_do_ioctl(cmd, arg, 0);
+}
+
 /*
  *	We enforce only one user at a time here with the open/close.
  *	Also clear the previous interrupt data on an open, and clean
@@ -606,11 +622,8 @@
 
 	spin_lock_irq (&rtc_lock);
 	rtc_irq_data = 0;
-	spin_unlock_irq (&rtc_lock);
-
-	/* No need for locking -- nobody else can do anything until this rmw is
-	 * committed, and no timer is running. */
 	rtc_status &= ~RTC_IS_OPEN;
+	spin_unlock_irq (&rtc_lock);
 	return 0;
 }
 
@@ -636,6 +649,88 @@
 #endif
 
 /*
+ * exported stuffs
+ */
+
+EXPORT_SYMBOL(rtc_register);
+EXPORT_SYMBOL(rtc_unregister);
+EXPORT_SYMBOL(rtc_control);
+
+int rtc_register(rtc_task_t *task)
+{
+#if !RTC_IRQ
+	return -EIO;
+#else
+	if (task == NULL || task->func == NULL)
+		return -EINVAL;
+	spin_lock_irq(&rtc_lock);
+	if (rtc_status & RTC_IS_OPEN) {
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+	spin_lock(&rtc_task_lock);
+	if (rtc_callback) {
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+	rtc_status |= RTC_IS_OPEN;
+	rtc_callback = task;
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
+	return 0;
+#endif
+}
+
+int rtc_unregister(rtc_task_t *task)
+{
+#if !RTC_IRQ
+	return -EIO;
+#else
+	unsigned char tmp;
+
+	spin_lock_irq(&rtc_task_lock);
+	if (rtc_callback != task) {
+		spin_unlock_irq(&rtc_task_lock);
+		return -ENXIO;
+	}
+	rtc_callback = NULL;
+	spin_lock(&rtc_lock);
+	/* disable controls */
+	tmp = CMOS_READ(RTC_CONTROL);
+	tmp &= ~RTC_PIE;
+	tmp &= ~RTC_AIE;
+	tmp &= ~RTC_UIE;
+	CMOS_WRITE(tmp, RTC_CONTROL);
+	CMOS_READ(RTC_INTR_FLAGS);
+	if (rtc_status & RTC_TIMER_ON) {
+		rtc_status &= ~RTC_TIMER_ON;
+		del_timer(&rtc_irq_timer);
+	}
+	rtc_status &= ~RTC_IS_OPEN;
+	spin_unlock(&rtc_lock);
+	spin_unlock_irq(&rtc_task_lock);
+	return 0;
+#endif
+}
+
+int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
+{
+#if !RTC_IRQ
+	return -EIO;
+#else
+	spin_lock_irq(&rtc_task_lock);
+	if (rtc_callback != task) {
+		spin_unlock_irq(&rtc_task_lock);
+		return -ENXIO;
+	}
+	spin_unlock_irq(&rtc_task_lock);
+	return rtc_do_ioctl(cmd, arg, 1);
+#endif
+}
+
+
+/*
  *	The various file operations we support.
  */
 
@@ -822,7 +917,6 @@
 
 module_init(rtc_init);
 module_exit(rtc_exit);
-EXPORT_NO_SYMBOLS;
 
 #if RTC_IRQ
 /*
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/char/synclink.c	Tue Feb 26 11:57:58 2002
@@ -941,7 +941,7 @@
 	name:		"synclink",
 	id_table:	synclink_pci_tbl,
 	probe:		synclink_init_one,
-	remove:		synclink_remove_one,
+	remove:		__devexit_p(synclink_remove_one),
 };
 
 static struct tty_driver serial_driver, callout_driver;
@@ -8220,7 +8220,7 @@
 	return 0;
 }
 
-static void __exit synclink_remove_one (struct pci_dev *dev)
+static void __devexit synclink_remove_one (struct pci_dev *dev)
 {
 }
 
diff -Nru a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
--- a/drivers/char/wdt_pci.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/char/wdt_pci.c	Tue Feb 26 11:57:56 2002
@@ -558,7 +558,7 @@
 }
 
 
-static void __exit wdtpci_remove_one (struct pci_dev *pdev)
+static void __devexit wdtpci_remove_one (struct pci_dev *pdev)
 {
 	/* here we assume only one device will ever have
 	 * been picked up and registered by probe function */
@@ -583,7 +583,7 @@
 	name:		"wdt-pci",
 	id_table:	wdtpci_pci_tbl,
 	probe:		wdtpci_init_one,
-	remove:		wdtpci_remove_one,
+	remove:		__devexit_p(wdtpci_remove_one),
 };
 
 
diff -Nru a/drivers/ide/ataraid.c b/drivers/ide/ataraid.c
--- a/drivers/ide/ataraid.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/ide/ataraid.c	Tue Feb 26 11:57:59 2002
@@ -70,7 +70,7 @@
 static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
 {
 	int minor;
-	minor = MINOR(inode->i_rdev)>>SHIFT;
+	minor = minor(inode->i_rdev)>>SHIFT;
 	
 	if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl))
 		return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg);
@@ -80,7 +80,7 @@
 static int ataraid_open(struct inode * inode, struct file * filp)
 {
 	int minor;
-	minor = MINOR(inode->i_rdev)>>SHIFT;
+	minor = minor(inode->i_rdev)>>SHIFT;
 
 	if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open))
 		return (ataraid_ops[minor]->open)(inode,filp);
@@ -91,7 +91,7 @@
 static int ataraid_release(struct inode * inode, struct file * filp)
 {
 	int minor;
-	minor = MINOR(inode->i_rdev)>>SHIFT;
+	minor = minor(inode->i_rdev)>>SHIFT;
 
 	if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release))
 		return (ataraid_ops[minor]->release)(inode,filp);
@@ -102,7 +102,7 @@
 {
 	int minor;
 	int retval;
-	minor = MINOR(bh->b_rdev)>>SHIFT;
+	minor = minor(bh->b_rdev)>>SHIFT;
 
 	if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) {
 		
@@ -229,7 +229,7 @@
 
 void ataraid_register_disk(int device,long size)
 {
-	register_disk(&ataraid_gendisk, MKDEV(ATAMAJOR,16*device),16,
+	register_disk(&ataraid_gendisk, mk_kdev(ATAMAJOR,16*device),16,
 		&ataraid_fops,size);
 
 }
diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c
--- a/drivers/ide/hd.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/ide/hd.c	Tue Feb 26 11:57:57 2002
@@ -558,7 +558,7 @@
 		reset_hd();
 		return;
 	}
-	dev = MINOR(CURRENT->rq_dev);
+	dev = minor(CURRENT->rq_dev);
 	block = CURRENT->sector;
 	nsect = CURRENT->nr_sectors;
 	if (dev >= (NR_HD<<6) || (dev & 0x3f) ||
@@ -568,7 +568,7 @@
 			       kdevname(CURRENT->rq_dev));
 		else
 			printk("hd%c: bad access: block=%d, count=%d\n",
-				(MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect);
+				(minor(CURRENT->rq_dev)>>6)+'a', block, nsect);
 		end_request(0);
 		goto repeat;
 	}
@@ -626,7 +626,7 @@
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
 	int dev;
 
-	if ((!inode) || !(inode->i_rdev))
+	if ((!inode) || kdev_none(inode->i_rdev))
 		return -EINVAL;
 	dev = DEVICE_NR(inode->i_rdev);
 	if (dev >= NR_HD)
@@ -822,7 +822,7 @@
 	hd_gendisk.nr_real = NR_HD;
 
 	for(drive=0; drive < NR_HD; drive++)
-		register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6,
+		register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6,
 			&hd_fops, hd_info[drive].head * hd_info[drive].sect *
 			hd_info[drive].cyl);
 }
diff -Nru a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c
--- a/drivers/ide/hptraid.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/ide/hptraid.c	Tue Feb 26 11:57:59 2002
@@ -75,16 +75,16 @@
 	unsigned char val;
 	unsigned long sectors;
 	
-	if (!inode || !inode->i_rdev) 	
+	if (!inode || kdev_none(inode->i_rdev))
 		return -EINVAL;
 
-	minor = MINOR(inode->i_rdev)>>SHIFT;
+	minor = minor(inode->i_rdev)>>SHIFT;
 	
 	switch (cmd) {
          	case BLKGETSIZE:   /* Return device size */
 			if (!arg)  return -EINVAL;
-			sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects;
-			if (MINOR(inode->i_rdev)&15)
+			sectors = ataraid_gendisk.part[minor(inode->i_rdev)].nr_sects;
+			if (minor(inode->i_rdev)&15)
 				return put_user(sectors, (unsigned long *) arg);
 			return put_user(raid[minor].sectors , (unsigned long *) arg);
 			break;
@@ -102,7 +102,7 @@
 			if (put_user(val, (byte *) &loc->sectors)) return -EFAULT;
 			bios_cyl = raid[minor].sectors/63/255;
 			if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect,
+			if (put_user((unsigned)ataraid_gendisk.part[minor(inode->i_rdev)].start_sect,
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -118,7 +118,7 @@
 			if (put_user(val, (byte *) &loc->sectors)) return -EFAULT;
 			bios_cyl = raid[minor].sectors/63/255;
 			if (put_user(bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect,
+			if (put_user((unsigned)ataraid_gendisk.part[minor(inode->i_rdev)].start_sect,
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -167,7 +167,7 @@
 
 	/* Partitions need adding of the start sector of the partition to the requested sector */
 	
-	rsect += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect;
+	rsect += ataraid_gendisk.part[minor(bh->b_rdev)].start_sect;
 
 	/* Woops we need to split the request to avoid crossing a stride barrier */
 	if ((rsect/thisraid->stride) != ((rsect+(bh->b_size/512)-1)/thisraid->stride)) {
@@ -248,7 +248,7 @@
 	kdev_t dev;
 	ide_drive_t *ideinfo;
 	
-	dev = MKDEV(major,minor);
+	dev = mk_kdev(major,minor);
 	ideinfo = get_info_ptr (dev);
 	if (ideinfo==NULL)
 		return 0;
@@ -268,7 +268,7 @@
 static void __init probedisk(int major, int minor,int device)
 {
 	int i;
-	struct block_device *bdev = bdget(MKDEV(major,minor));
+	struct block_device *bdev = bdget(mk_kdev(major,minor));
 	struct gendisk *gd;
 
 	if (!bdev)
@@ -301,14 +301,14 @@
 	/* now blank the /proc/partitions table for the wrong partition table,
 	   so that scripts don't accidentally mount it and crash the kernel */
 	 /* XXX: the 0 is an utter hack  --hch */
-	gd=get_gendisk(MKDEV(major, 0));
+	gd=get_gendisk(mk_kdev(major, 0));
 	if (gd!=NULL) {
 		int j;
 		for (j=1+(minor<<gd->minor_shift);j<((minor+1)<<gd->minor_shift);j++) 
 			gd->part[j].nr_sects=0;					
 	}
 
-	raid[device].disk[i].device = MKDEV(major,minor);
+	raid[device].disk[i].device = mk_kdev(major,minor);
 	raid[device].disk[i].sectors = maxsectors(major,minor);
 	raid[device].stride = (1<<prom.raid0_shift);
 	raid[device].disks = prom.raid_disks;
diff -Nru a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c
--- a/drivers/ide/pdcraid.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/ide/pdcraid.c	Tue Feb 26 11:57:59 2002
@@ -102,17 +102,17 @@
 	unsigned int minor;
    	unsigned long sectors;
 
-	if (!inode || !inode->i_rdev) 
+	if (!inode || kdev_none(inode->i_rdev)) 
 		return -EINVAL;
 
-	minor = MINOR(inode->i_rdev)>>SHIFT;
+	minor = minor(inode->i_rdev)>>SHIFT;
 	
 	switch (cmd) {
 
          	case BLKGETSIZE:   /* Return device size */
  			if (!arg)  return -EINVAL;
-			sectors = ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects;
-			if (MINOR(inode->i_rdev)&15)
+			sectors = ataraid_gendisk.part[minor(inode->i_rdev)].nr_sects;
+			if (minor(inode->i_rdev)&15)
 				return put_user(sectors, (unsigned long *) arg);
 			return put_user(raid[minor].sectors , (unsigned long *) arg);
 			break;
@@ -127,7 +127,7 @@
 			if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT;
 			if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT;
 			if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect,
+			if (put_user((unsigned)ataraid_gendisk.part[minor(inode->i_rdev)].start_sect,
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -139,7 +139,7 @@
 			if (put_user(raid[minor].geom.heads, (byte *) &loc->heads)) return -EFAULT;
 			if (put_user(raid[minor].geom.sectors, (byte *) &loc->sectors)) return -EFAULT;
 			if (put_user(raid[minor].geom.cylinders, (unsigned int *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)ataraid_gendisk.part[MINOR(inode->i_rdev)].start_sect,
+			if (put_user((unsigned)ataraid_gendisk.part[minor(inode->i_rdev)].start_sect,
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -463,7 +463,7 @@
 	major = devlist[devindex].major;
 	minor = devlist[devindex].minor; 
 
-	bdev = bdget(MKDEV(major,minor));
+	bdev = bdget(mk_kdev(major,minor));
 	if (!bdev)
 		return;
 
@@ -491,7 +491,7 @@
         	     (prom.raid.disk[i].device == prom.raid.device) ) {
 
 			raid[device].disk[i].bdev = bdev;
-			raid[device].disk[i].device = MKDEV(major,minor);
+			raid[device].disk[i].device = mk_kdev(major,minor);
 			raid[device].disk[i].sectors = prom.raid.disk_secs;
 			raid[device].stride = (1<<prom.raid.raid0_shift);
 			raid[device].disks = prom.raid.total_disks;
@@ -551,7 +551,7 @@
 	for (i=0;i<8;i++) {
 		if (raid[device].disk[i].device!=0) {
 			printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n",
-				i,raid[device].disk[i].sectors/2048,MAJOR(raid[device].disk[i].device),MINOR(raid[device].disk[i].device));
+				i,raid[device].disk[i].sectors/2048,major(raid[device].disk[i].device),minor(raid[device].disk[i].device));
 			count++;
 		}
 	}
diff -Nru a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
--- a/drivers/ide/sl82c105.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/ide/sl82c105.c	Tue Feb 26 11:57:58 2002
@@ -8,8 +8,6 @@
  * Drive tuning added from Rebel.com's kernel sources
  *  -- Russell King (15/11/98) linux@arm.linux.org.uk
  */
-
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/ieee1394/dv1394.c	Tue Feb 26 11:57:57 2002
@@ -185,78 +185,19 @@
 /* Memory management functions */
 /*******************************/
 
-#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
-
-/* [DaveM] I've recoded most of this so that:
- * 1) It's easier to tell what is happening
- * 2) It's more portable, especially for translating things
- *    out of vmalloc mapped areas in the kernel.
- * 3) Less unnecessary translations happen.
- *
- * The code used to assume that the kernel vmalloc mappings
- * existed in the page tables of every process, this is simply
- * not guarenteed.  We now use pgd_offset_k which is the
- * defined way to get at the kernel page tables.
- */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#define page_address(x)	(x)
-#endif
-
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline struct page *uvirt_to_page(pgd_t *pgd, unsigned long adr)
-{
-	pmd_t *pmd;
-	pte_t *ptep, pte;
-	struct page *ret = NULL;
-	
-	if (!pgd_none(*pgd)) {
-                pmd = pmd_offset(pgd, adr);
-                if (!pmd_none(*pmd)) {
-			preempt_disable();
-                        ptep = pte_offset_map(pmd, adr);
-                        pte = *ptep;
-			pte_unmap(pte);
-			preempt_enable();
-                        if(pte_present(pte))
-				ret = pte_page(pte);
-                }
-        }
-	return ret;
-}
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved, and for
- * handling page faults on the rvmalloc()ed buffer
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
-{
-        unsigned long va, kva, ret;
-
-        va = VMALLOC_VMADDR(adr);
-	kva = (unsigned long) page_address(uvirt_to_page(pgd_offset_k(va), va));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
-        return ret;
-}
-
 static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr, page;
-        
+	unsigned long adr;
+
+	size=PAGE_ALIGN(size);
 	mem=vmalloc_32(size);
 	if (mem) {
 		memset(mem, 0, size); /* Clear the ram out, 
 					 no junk to the user */
 	        adr=(unsigned long) mem;
 		while (size > 0) {
-	                page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -266,13 +207,12 @@
 
 static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr, page;
-        
+        unsigned long adr;
+
 	if (mem) {
 	        adr=(unsigned long) mem;
-		while (size > 0) {
-	                page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+		while ((long) size > 0) {
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -1166,9 +1106,9 @@
 		
 		/* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */
 		for(i = 0; i < video->user_dma.n_pages; i++) {
-			unsigned long va = VMALLOC_VMADDR( (unsigned long) video->user_buf + i * PAGE_SIZE );
+			unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE;
 			
-			video->user_dma.sglist[i].page = uvirt_to_page(pgd_offset_k(va), va);
+			video->user_dma.sglist[i].page = vmalloc_to_page((void *)va);
 			video->user_dma.sglist[i].length = PAGE_SIZE;
 		}
 		
@@ -1492,7 +1432,7 @@
 static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access)
 {
 	unsigned long offset;
-	unsigned long page, kernel_virt_addr;
+	unsigned long kernel_virt_addr;
 	struct page *ret = NOPAGE_SIGBUS;
 
 	struct video_card *video = (struct video_card*) area->vm_private_data;
@@ -1510,10 +1450,7 @@
 
 	offset = address - area->vm_start;
 	kernel_virt_addr = (unsigned long) video->user_buf + offset;
-
-	page = kvirt_to_pa(kernel_virt_addr);
-	
-	ret = virt_to_page(__va(page));
+	ret = vmalloc_to_page((void *)kernel_virt_addr);
 	get_page(ret);
 
  out:
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/ieee1394/video1394.c	Tue Feb 26 11:57:57 2002
@@ -159,61 +159,35 @@
 /* Memory management functions */
 /*******************************/
 
-#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
-
-/* [DaveM] I've recoded most of this so that:
- * 1) It's easier to tell what is happening
- * 2) It's more portable, especially for translating things
- *    out of vmalloc mapped areas in the kernel.
- * 3) Less unnecessary translations happen.
- *
- * The code used to assume that the kernel vmalloc mappings
- * existed in the page tables of every process, this is simply
- * not guaranteed.  We now use pgd_offset_k which is the
- * defined way to get at the kernel page tables.
- */
-
-static inline unsigned long uvirt_to_bus(unsigned long adr) 
-{
-        unsigned long kva, ret;
-
-        kva = page_address(vmalloc_to_page(adr));
-	ret = virt_to_bus((void *)kva);
-        MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
-        return ret;
-}
-
 static inline unsigned long kvirt_to_bus(unsigned long adr) 
 {
-        unsigned long va, kva, ret;
+        unsigned long kva, ret;
 
-        va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = virt_to_bus((void *)kva);
-        MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
         return ret;
 }
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr) 
 {
-        unsigned long va, kva, ret;
+        unsigned long kva, ret;
 
-        va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
-        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
         return ret;
 }
 
 static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr, page;
-        
+	unsigned long adr;
+ 
+	size=PAGE_ALIGN(size);
 	mem=vmalloc_32(size);
 	if (mem) 
 	{
@@ -222,8 +196,7 @@
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -233,15 +206,14 @@
 
 static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr, page;
-        
+        unsigned long adr;
+
 	if (mem) 
 	{
 	        adr=(unsigned long) mem;
-		while (size > 0) 
+		while ((long) size > 0) 
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -1381,7 +1353,7 @@
 	if (video->current_ctx == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Current iso context not set");
 	} else
-		res = do_iso_mmap(ohci, video->current_ctx, 
+		res = do_iso_mmap(vma, ohci, video->current_ctx, 
 			   (char *)vma->vm_start, 
 			   (unsigned long)(vma->vm_end-vma->vm_start));
 	unlock_kernel();
diff -Nru a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
--- a/drivers/input/gameport/cs461x.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/input/gameport/cs461x.c	Tue Feb 26 11:57:56 2002
@@ -313,7 +313,7 @@
         name:           "PCI Gameport",
         id_table:       cs461x_pci_tbl,
         probe:          cs461x_pci_probe,
-        remove:         cs461x_pci_remove,
+        remove:         __devexit_p(cs461x_pci_remove),
 };
 
 int __init js_cs461x_init(void)
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- a/drivers/input/gameport/emu10k1-gp.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/input/gameport/emu10k1-gp.c	Tue Feb 26 11:57:59 2002
@@ -108,7 +108,7 @@
         name:           "Emu10k1 Gameport",
         id_table:       emu_tbl,
         probe:          emu_probe,
-        remove:         emu_remove,
+        remove:         __devexit_p(emu_remove),
 };
 
 int __init emu_init(void)
diff -Nru a/drivers/input/gameport/pcigame.c b/drivers/input/gameport/pcigame.c
--- a/drivers/input/gameport/pcigame.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/input/gameport/pcigame.c	Tue Feb 26 11:57:57 2002
@@ -180,7 +180,7 @@
 	name:		"pcigame",
 	id_table:	pcigame_id_table,
 	probe:		pcigame_probe,
-	remove:		pcigame_remove,
+	remove:		__devexit_p(pcigame_remove),
 };
 
 int __init pcigame_init(void)
diff -Nru a/drivers/isdn/Config.help b/drivers/isdn/Config.help
--- a/drivers/isdn/Config.help	Tue Feb 26 11:57:59 2002
+++ b/drivers/isdn/Config.help	Tue Feb 26 11:57:59 2002
@@ -161,6 +161,10 @@
   Enable this if you like to use ISDN in US on a NI1 basic rate
   interface.
 
+CONFIG_HISAX_MAX_CARDS
+  This option allows you to specify the maximum number of cards which
+  the HiSax driver will be able to handle.  
+
 CONFIG_HISAX_16_0
   This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
   and many compatibles.
diff -Nru a/drivers/isdn/Config.in b/drivers/isdn/Config.in
--- a/drivers/isdn/Config.in	Tue Feb 26 11:57:59 2002
+++ b/drivers/isdn/Config.in	Tue Feb 26 11:57:59 2002
@@ -84,6 +84,7 @@
    dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
    dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
    dep_tristate 'AVM Fritz!Card classic support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_CLASSIC $CONFIG_HISAX $CONFIG_EXPERIMENTAL
+   dep_tristate 'HFC PCI support (EXPERIMENTAL)' CONFIG_HISAX_HFCPCI $CONFIG_HISAX $CONFIG_EXPERIMENTAL
 fi
 endmenu
 
diff -Nru a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
--- a/drivers/isdn/avmb1/capi.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/isdn/avmb1/capi.c	Tue Feb 26 11:58:00 2002
@@ -1535,7 +1535,7 @@
 /* -------- init function and module interface ---------------------- */
 
 
-static void __exit alloc_exit(void)
+static void alloc_exit(void)
 {
 	if (capidev_cachep) {
 		(void)kmem_cache_destroy(capidev_cachep);
diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
--- a/drivers/isdn/hisax/Makefile	Tue Feb 26 11:57:59 2002
+++ b/drivers/isdn/hisax/Makefile	Tue Feb 26 11:57:59 2002
@@ -64,6 +64,7 @@
 obj-$(CONFIG_HISAX_ST5481)		+= hisax_st5481.o
 obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_isac.o hisax_fcpcipnp.o
 obj-$(CONFIG_HISAX_FRITZ_CLASSIC)       += hisax_isac.o hisax_hscx.o hisax_fcclassic.o
+obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_hfcpci.o
 
 CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
 CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Tue Feb 26 11:57:57 2002
@@ -945,14 +945,14 @@
 static struct pci_driver fcpci_driver = {
 	name:     "fcpci",
 	probe:    fcpci_probe,
-	remove:   fcpci_remove,
+	remove:   __devexit_p(fcpci_remove),
 	id_table: fcpci_ids,
 };
 
 static struct isapnp_driver fcpnp_driver = {
 	name:     "fcpnp",
 	probe:    fcpnp_probe,
-	remove:   fcpnp_remove,
+	remove:   __devexit_p(fcpnp_remove),
 	id_table: fcpnp_ids,
 };
 
diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/isdn/hisax/hisax_hfcpci.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1646 @@
+/*
+ * Driver for HFC PCI based cards
+ *
+ * Author       Kai Germaschewski
+ * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *              2000 by Karsten Keil       <keil@isdn4linux.de>
+ *              2000 by Werner Cornelius   <werner@isdn4linux.de>
+ * 
+ * based upon Werner Cornelius's original hfc_pci.c driver
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ */
+
+// XXX timer3
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/isapnp.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <asm/delay.h>
+#include "hisax_hfcpci.h"
+
+// debugging cruft
+#define __debug_variable debug
+#include "hisax_debug.h"
+
+#ifdef CONFIG_HISAX_DEBUG
+static int debug = 0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Werner Cornelius <werner@isdn4linux.de>");
+MODULE_DESCRIPTION("HFC PCI ISDN driver");
+
+#define ID(ven, dev, name)                     \
+        { vendor:      PCI_VENDOR_ID_##ven,    \
+	  device:      PCI_DEVICE_ID_##dev,    \
+	  subvendor:   PCI_ANY_ID,             \
+	  subdevice:   PCI_ANY_ID,             \
+	  class:       0,                      \
+          class_mask:  0,                      \
+	  driver_data: (unsigned long) name }
+
+static struct pci_device_id hfcpci_ids[] __devinitdata = {
+	ID(CCD,     CCD_2BD0,         "CCD/Billion/Asuscom 2BD0"),
+	ID(CCD,     CCD_B000,         "Billion B000"),
+	ID(CCD,     CCD_B006,         "Billion B006"),
+	ID(CCD,     CCD_B007,         "Billion B007"),
+	ID(CCD,     CCD_B008,         "Billion B008"),
+	ID(CCD,     CCD_B009,         "Billion B009"),
+	ID(CCD,     CCD_B00A,         "Billion B00A"),
+	ID(CCD,     CCD_B00B,         "Billion B00B"),
+	ID(CCD,     CCD_B00C,         "Billion B00C"),
+	ID(CCD,     CCD_B100,         "Seyeon"),
+	ID(ABOCOM,  ABOCOM_2BD1,      "Abocom/Magitek"),
+	ID(ASUSTEK, ASUSTEK_0675,     "Asuscom/Askey"),
+	ID(BERKOM,  BERKOM_T_CONCEPT, "German Telekom T-Concept"),
+	ID(BERKOM,  BERKOM_A1T,       "German Telekom A1T"),
+	ID(ANIGMA,  ANIGMA_MC145575,  "Motorola MC145575"),
+	ID(ZOLTRIX, ZOLTRIX_2BD0,     "Zoltrix 2BD0"),
+	ID(DIGI,    DIGI_DF_M_IOM2_E, "Digi DataFire Micro V IOM2 (Europe)"),
+	ID(DIGI,    DIGI_DF_M_E,      "Digi DataFire Micro V (Europe)"),
+	ID(DIGI,    DIGI_DF_M_IOM2_A, "Digi DataFire Micro V IOM2 (America)"),
+	ID(DIGI,    DIGI_DF_M_A,      "Digi DataFire Micro V (America)"),
+	{ } 
+};
+MODULE_DEVICE_TABLE(pci, hfcpci_ids);
+
+#undef ID
+
+static int protocol = 2;       /* EURO-ISDN Default */
+MODULE_PARM(protocol, "i");
+
+// ----------------------------------------------------------------------
+//
+
+#define DBG_WARN      0x0001
+#define DBG_INFO      0x0002
+#define DBG_IRQ       0x0010
+#define DBG_L1M       0x0020
+#define DBG_PR        0x0040
+#define DBG_D_XMIT    0x0100
+#define DBG_D_RECV    0x0200
+#define DBG_B_XMIT    0x1000
+#define DBG_B_RECV    0x2000
+
+/* memory window base address offset (in config space) */
+
+#define HFCPCI_MWBA      0x80
+
+/* GCI/IOM bus monitor registers */
+
+#define HCFPCI_C_I       0x08
+#define HFCPCI_TRxR      0x0C
+#define HFCPCI_MON1_D    0x28
+#define HFCPCI_MON2_D    0x2C
+
+
+/* GCI/IOM bus timeslot registers */
+
+#define HFCPCI_B1_SSL    0x80
+#define HFCPCI_B2_SSL    0x84
+#define HFCPCI_AUX1_SSL  0x88
+#define HFCPCI_AUX2_SSL  0x8C
+#define HFCPCI_B1_RSL    0x90
+#define HFCPCI_B2_RSL    0x94
+#define HFCPCI_AUX1_RSL  0x98
+#define HFCPCI_AUX2_RSL  0x9C
+
+/* GCI/IOM bus data registers */
+
+#define HFCPCI_B1_D      0xA0
+#define HFCPCI_B2_D      0xA4
+#define HFCPCI_AUX1_D    0xA8
+#define HFCPCI_AUX2_D    0xAC
+
+/* GCI/IOM bus configuration registers */
+
+#define HFCPCI_MST_EMOD  0xB4
+#define HFCPCI_MST_MODE	 0xB8
+#define HFCPCI_CONNECT 	 0xBC
+
+
+/* Interrupt and status registers */
+
+#define HFCPCI_FIFO_EN   0x44
+#define HFCPCI_TRM       0x48
+#define HFCPCI_B_MODE    0x4C
+#define HFCPCI_CHIP_ID   0x58
+#define HFCPCI_CIRM  	 0x60
+#define HFCPCI_CTMT	 0x64
+#define HFCPCI_INT_M1  	 0x68
+#define HFCPCI_INT_M2  	 0x6C
+#define HFCPCI_INT_S1  	 0x78
+#define HFCPCI_INT_S2  	 0x7C
+#define HFCPCI_STATUS  	 0x70
+
+/* S/T section registers */
+
+#define HFCPCI_STATES  	 0xC0
+#define HFCPCI_SCTRL  	 0xC4
+#define HFCPCI_SCTRL_E   0xC8
+#define HFCPCI_SCTRL_R   0xCC
+#define HFCPCI_SQ  	 0xD0
+#define HFCPCI_CLKDEL  	 0xDC
+#define HFCPCI_B1_REC    0xF0
+#define HFCPCI_B1_SEND   0xF0
+#define HFCPCI_B2_REC    0xF4
+#define HFCPCI_B2_SEND   0xF4
+#define HFCPCI_D_REC     0xF8
+#define HFCPCI_D_SEND    0xF8
+#define HFCPCI_E_REC     0xFC
+
+
+/* bits in status register (READ) */
+#define HFCPCI_PCI_PROC   0x02
+#define HFCPCI_NBUSY	  0x04 
+#define HFCPCI_TIMER_ELAP 0x10
+#define HFCPCI_STATINT	  0x20
+#define HFCPCI_FRAMEINT	  0x40
+#define HFCPCI_ANYINT	  0x80
+
+/* bits in CTMT (Write) */
+#define HFCPCI_CLTIMER    0x80
+#define HFCPCI_TIM3_125   0x04
+#define HFCPCI_TIM25      0x10
+#define HFCPCI_TIM50      0x14
+#define HFCPCI_TIM400     0x18
+#define HFCPCI_TIM800     0x1C
+#define HFCPCI_AUTO_TIMER 0x20
+#define HFCPCI_TRANSB2    0x02
+#define HFCPCI_TRANSB1    0x01
+
+/* bits in CIRM (Write) */
+#define HFCPCI_AUX_MSK    0x07
+#define HFCPCI_RESET  	  0x08
+#define HFCPCI_B1_REV     0x40
+#define HFCPCI_B2_REV     0x80
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCPCI_INTS_B1TRANS  0x01
+#define HFCPCI_INTS_B2TRANS  0x02
+#define HFCPCI_INTS_DTRANS   0x04
+#define HFCPCI_INTS_B1REC    0x08
+#define HFCPCI_INTS_B2REC    0x10
+#define HFCPCI_INTS_DREC     0x20
+#define HFCPCI_INTS_L1STATE  0x40
+#define HFCPCI_INTS_TIMER    0x80
+
+/* bits in INT_M2 */
+#define HFCPCI_PROC_TRANS    0x01
+#define HFCPCI_GCI_I_CHG     0x02
+#define HFCPCI_GCI_MON_REC   0x04
+#define HFCPCI_IRQ_ENABLE    0x08
+#define HFCPCI_PMESEL        0x80
+
+/* bits in STATES */
+#define HFCPCI_STATE_MSK     0x0F
+#define HFCPCI_LOAD_STATE    0x10
+#define HFCPCI_ACTIVATE	     0x20
+#define HFCPCI_DO_ACTION     0x40
+#define HFCPCI_NT_G2_G3      0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCPCI_MASTER	     0x01
+#define HFCPCI_SLAVE         0x00
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA	     0x01
+#define SCTRL_B2_ENA	     0x02
+#define SCTRL_MODE_TE        0x00
+#define SCTRL_MODE_NT        0x04
+#define SCTRL_LOW_PRIO	     0x08
+#define SCTRL_SQ_ENA	     0x10
+#define SCTRL_TEST	     0x20
+#define SCTRL_NONE_CAP	     0x40
+#define SCTRL_PWR_DOWN	     0x80
+
+/* bits in SCTRL_E  */
+#define HFCPCI_AUTO_AWAKE    0x01
+#define HFCPCI_DBIT_1        0x04
+#define HFCPCI_IGNORE_COL    0x08
+#define HFCPCI_CHG_B1_B2     0x80
+
+/* bits in FIFO_EN register */
+#define HFCPCI_FIFOEN_B1     0x03
+#define HFCPCI_FIFOEN_B2     0x0C
+#define HFCPCI_FIFOEN_DTX    0x10
+#define HFCPCI_FIFOEN_DRX    0x20
+#define HFCPCI_FIFOEN_B1TX   0x01
+#define HFCPCI_FIFOEN_B1RX   0x02
+#define HFCPCI_FIFOEN_B2TX   0x04
+#define HFCPCI_FIFOEN_B2RX   0x08
+
+/*
+ * thresholds for transparent B-channel mode
+ * change mask and threshold simultaneously
+ */
+#define HFCPCI_BTRANS_THRESHOLD 128
+#define HFCPCI_BTRANS_THRESMASK 0x00
+
+#define CLKDEL_TE	0x0e	/* CLKDEL in TE mode */
+#define CLKDEL_NT	0x6c	/* CLKDEL in NT mode */
+
+#define MAX_D_FRAMES 0x10
+#define MAX_B_FRAMES 0x20
+#define B_FIFO_START 0x0200
+#define B_FIFO_END   0x2000
+#define B_FIFO_SIZE  (B_FIFO_END - B_FIFO_START)
+#define D_FIFO_START 0x0000
+#define D_FIFO_END   0x0200
+#define D_FIFO_SIZE  (D_FIFO_END - D_FIFO_START)
+
+// ----------------------------------------------------------------------
+// push messages to the upper layers
+
+static inline void D_L1L2(struct hfcpci_adapter *adapter, int pr, void *arg)
+{
+	struct hisax_if *ifc = (struct hisax_if *) &adapter->d_if;
+
+	DBG(DBG_PR, "pr %#x", pr);
+	ifc->l1l2(ifc, pr, arg);
+}
+
+static inline void B_L1L2(struct hfcpci_bcs *bcs, int pr, void *arg)
+{
+	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
+
+	DBG(DBG_PR, "pr %#x", pr);
+	ifc->l1l2(ifc, pr, arg);
+}
+
+// ----------------------------------------------------------------------
+// MMIO
+
+static inline void
+hfcpci_writeb(struct hfcpci_adapter *adapter, u8 b, unsigned char offset)
+{
+	writeb(b, adapter->mmio + offset);
+}
+
+static inline u8
+hfcpci_readb(struct hfcpci_adapter *adapter, unsigned char offset)
+{
+	return readb(adapter->mmio + offset);
+}
+
+// ----------------------------------------------------------------------
+// magic to define the various F/Z counter accesses
+
+#define DECL_B_F(r, f)                                                      \
+static inline u8                                                            \
+get_b_##r##_##f (struct hfcpci_bcs *bcs)                                    \
+{                                                                           \
+	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \
+                                                                            \
+	return *(bcs->adapter->fifo + off);                                 \
+}                                                                           \
+                                                                            \
+static inline void                                                          \
+set_b_##r##_##f (struct hfcpci_bcs *bcs, u8 f)                              \
+{                                                                           \
+	u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f;       \
+                                                                            \
+	*(bcs->adapter->fifo + off) = f;                                    \
+}
+
+#define OFF_B1_rx_f1 0x6080
+#define OFF_B2_rx_f1 0x6180
+#define OFF_B1_rx_f2 0x6081
+#define OFF_B2_rx_f2 0x6181
+
+#define OFF_B1_tx_f1 0x2080
+#define OFF_B2_tx_f1 0x2180
+#define OFF_B1_tx_f2 0x2081
+#define OFF_B2_tx_f2 0x2181
+
+DECL_B_F(rx, f1)
+DECL_B_F(rx, f2)
+DECL_B_F(tx, f1)
+DECL_B_F(tx, f2)
+
+#undef DECL_B_F
+
+#define DECL_B_Z(r, z)                                                      \
+static inline u16                                                           \
+get_b_##r##_##z (struct hfcpci_bcs *bcs, u8 f)                              \
+{                                                                           \
+	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \
+                                                                            \
+	return le16_to_cpu(*((u16 *) (bcs->adapter->fifo + off + f * 4)));  \
+}                                                                           \
+                                                                            \
+static inline void                                                          \
+set_b_##r##_##z(struct hfcpci_bcs *bcs, u8 f, u16 z)                        \
+{                                                                           \
+	u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z;       \
+                                                                            \
+	*((u16 *) (bcs->adapter->fifo + off + f * 4)) = cpu_to_le16(z);     \
+}
+
+#define OFF_B1_rx_z1 0x6000
+#define OFF_B2_rx_z1 0x6100
+#define OFF_B1_rx_z2 0x6002
+#define OFF_B2_rx_z2 0x6102
+
+#define OFF_B1_tx_z1 0x2000
+#define OFF_B2_tx_z1 0x2100
+#define OFF_B1_tx_z2 0x2002
+#define OFF_B2_tx_z2 0x2102
+
+DECL_B_Z(rx, z1)
+DECL_B_Z(rx, z2)
+DECL_B_Z(tx, z1)
+DECL_B_Z(tx, z2)
+
+#undef DECL_B_Z
+
+#define DECL_D_F(r, f)                                                      \
+static inline u8                                                            \
+get_d_##r##_##f (struct hfcpci_adapter *adapter)                            \
+{                                                                           \
+	u16 off = OFF_D_##r##_##f;                                          \
+                                                                            \
+	return *(adapter->fifo + off) & 0xf;                                \
+}                                                                           \
+                                                                            \
+static inline void                                                          \
+set_d_##r##_##f (struct hfcpci_adapter *adapter, u8 f)                      \
+{                                                                           \
+	u16 off = OFF_D_##r##_##f;                                          \
+                                                                            \
+	*(adapter->fifo + off) = f | 0x10;                                  \
+}
+
+#define OFF_D_rx_f1 0x60a0
+#define OFF_D_rx_f2 0x60a1
+
+#define OFF_D_tx_f1 0x20a0
+#define OFF_D_tx_f2 0x20a1
+
+DECL_D_F(rx, f1)
+DECL_D_F(rx, f2)
+DECL_D_F(tx, f1)
+DECL_D_F(tx, f2)
+
+#undef DECL_D_F
+
+#define DECL_D_Z(r, z)                                                      \
+static inline u16                                                           \
+get_d_##r##_##z (struct hfcpci_adapter *adapter, u8 f)                      \
+{                                                                           \
+	u16 off = OFF_D_##r##_##z;                                          \
+                                                                            \
+	return le16_to_cpu(*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)));\
+}                                                                           \
+                                                                            \
+static inline void                                                          \
+set_d_##r##_##z(struct hfcpci_adapter *adapter, u8 f, u16 z)                \
+{                                                                           \
+	u16 off = OFF_D_##r##_##z;                                          \
+                                                                            \
+	*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)) = cpu_to_le16(z); \
+}
+
+#define OFF_D_rx_z1 0x6080
+#define OFF_D_rx_z2 0x6082
+
+#define OFF_D_tx_z1 0x2080
+#define OFF_D_tx_z2 0x2082
+
+DECL_D_Z(rx, z1)
+DECL_D_Z(rx, z2)
+DECL_D_Z(tx, z1)
+DECL_D_Z(tx, z2)
+
+#undef DECL_B_Z
+
+// ----------------------------------------------------------------------
+// fill b / d fifos
+
+static inline void
+hfcpci_fill_d_fifo(struct hfcpci_adapter *adapter)
+{
+	u8 f1, f2;
+	u16 z1, z2;
+	int cnt, fcnt;
+	char *fifo_adr = adapter->fifo;
+	struct sk_buff *tx_skb = adapter->tx_skb;
+	
+	f1 = get_d_tx_f1(adapter);
+	f2 = get_d_tx_f2(adapter);
+	DBG(DBG_D_XMIT, "f1 %#x f2 %#x", f1, f2);
+
+	fcnt = f1 - f2;
+	if (fcnt < 0)
+		fcnt += MAX_D_FRAMES;
+	
+	if (fcnt) {
+		printk("BUG\n");
+		return;
+	}
+
+	z1 = get_d_tx_z1(adapter, f1);
+	z2 = get_d_tx_z2(adapter, f1); //XXX
+	DBG(DBG_D_XMIT, "z1 %#x z2 %#x", z1, z2);
+
+	cnt = z2 - z1;
+	if (cnt <= 0)
+		cnt += D_FIFO_SIZE;
+
+	if (tx_skb->len > cnt) {
+		printk("BUG\n");
+		return;
+	}
+
+	cnt = tx_skb->len;
+	if (z1 + cnt <= D_FIFO_END) {
+		memcpy(fifo_adr + z1, tx_skb->data, cnt);
+	} else {
+		memcpy(fifo_adr + z1, tx_skb->data, D_FIFO_END - z1);
+		memcpy(fifo_adr + D_FIFO_START, 
+		       tx_skb->data + (D_FIFO_END - z1), 
+		       cnt - (D_FIFO_END - z1));
+	}
+	z1 += cnt;
+	if (z1 >= D_FIFO_END)
+		z1 -= D_FIFO_SIZE;
+
+	f1 = (f1 + 1) & (MAX_D_FRAMES - 1);
+	mb();
+	set_d_tx_z1(adapter, f1, z1);
+	mb();
+	set_d_tx_f1(adapter, f1);
+}
+
+static inline void
+hfcpci_fill_b_fifo_hdlc(struct hfcpci_bcs *bcs)
+{
+	u8 f1, f2;
+	u16 z1, z2;
+	int cnt, fcnt;
+	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);
+	struct sk_buff *tx_skb = bcs->tx_skb;
+	
+	f1 = get_b_tx_f1(bcs);
+	f2 = get_b_tx_f2(bcs);
+	DBG(DBG_B_XMIT, "f1 %#x f2 %#x", f1, f2);
+
+	fcnt = f1 - f2;
+	if (fcnt < 0)
+		fcnt += MAX_B_FRAMES;
+	
+	if (fcnt) {
+		printk("BUG\n");
+		return;
+	}
+
+	z1 = get_b_tx_z1(bcs, f1);
+	z2 = get_b_tx_z2(bcs, f1); //XXX
+	DBG(DBG_B_XMIT, "z1 %#x z2 %#x", z1, z2);
+
+	cnt = z2 - z1;
+	if (cnt <= 0)
+		cnt += B_FIFO_SIZE;
+
+	if (tx_skb->len > cnt) {
+		printk("BUG\n");
+		return;
+	}
+
+	cnt = tx_skb->len;
+	if (z1 + cnt <= B_FIFO_END) {
+		memcpy(fifo_adr + z1, tx_skb->data, cnt);
+	} else {
+		memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1);
+		memcpy(fifo_adr + B_FIFO_START,
+		       tx_skb->data + (B_FIFO_END - z1), 
+		       cnt - (B_FIFO_END - z1));
+	}
+	z1 += cnt;
+	if (z1 >= B_FIFO_END)
+		z1 -= B_FIFO_SIZE;
+
+	f1 = (f1 + 1) & (MAX_B_FRAMES - 1);
+	mb();
+	set_b_tx_z1(bcs, f1, z1);
+	mb();
+	set_b_tx_f1(bcs, f1);
+}
+
+static inline void
+hfcpci_fill_b_fifo_trans(struct hfcpci_bcs *bcs)
+{
+	int cnt;
+	char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000);
+	struct sk_buff *tx_skb = bcs->tx_skb;
+	u8 f1, f2;
+	u16 z1, z2;
+
+	f1 = get_b_tx_f1(bcs);
+	f2 = get_b_tx_f2(bcs);
+
+	if (f1 != f2)
+		BUG();
+
+	z1 = get_b_tx_z1(bcs, f1);
+	z2 = get_b_tx_z2(bcs, f1);
+
+	cnt = z2 - z1;
+	if (cnt <= 0)
+		cnt += B_FIFO_SIZE;
+
+	if (tx_skb->len > cnt)
+		BUG();
+
+	if (z1 + cnt <= B_FIFO_END) {
+		memcpy(fifo_adr + z1, tx_skb->data, cnt);
+	} else {
+		memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1);
+		memcpy(fifo_adr + B_FIFO_START,
+		       tx_skb->data + (B_FIFO_END - z1), 
+		       cnt - (B_FIFO_END - z1));
+	}
+	z1 += cnt;
+	if (z1 >= B_FIFO_END)
+		z1 -= B_FIFO_SIZE;
+
+	mb();
+	set_b_tx_z1(bcs, f1, z1);
+}
+
+static inline void
+hfcpci_fill_b_fifo(struct hfcpci_bcs *bcs)
+{
+	if (!bcs->tx_skb) {
+		DBG(DBG_WARN, "?");
+		return;
+	}
+	
+	switch (bcs->mode) {
+	case L1_MODE_TRANS:
+		hfcpci_fill_b_fifo_trans(bcs);
+		break;
+	case L1_MODE_HDLC:
+		hfcpci_fill_b_fifo_hdlc(bcs);
+		break;
+	default:
+		DBG(DBG_WARN, "?");
+	}
+}
+
+static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs);
+static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs);
+
+static void
+hfcpci_b_mode(struct hfcpci_bcs *bcs, int mode)
+{
+	struct hfcpci_adapter *adapter = bcs->adapter;
+	
+	DBG(DBG_B_XMIT, "B%d mode %d --> %d",
+	    bcs->channel + 1, bcs->mode, mode);
+
+	if (bcs->mode == mode)
+		return;
+
+	switch (mode) {
+	case L1_MODE_NULL:
+		if (bcs->channel == 0) {
+			adapter->sctrl &= ~SCTRL_B1_ENA;
+			adapter->sctrl_r &= ~SCTRL_B1_ENA;
+			adapter->fifo_en &= ~HFCPCI_FIFOEN_B1;
+			adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+		} else {
+			adapter->sctrl &= ~SCTRL_B2_ENA;
+			adapter->sctrl_r &= ~SCTRL_B2_ENA;
+			adapter->fifo_en &= ~HFCPCI_FIFOEN_B2;
+			adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+		}
+		break;
+	case L1_MODE_TRANS:
+	case L1_MODE_HDLC:
+		hfcpci_clear_b_rx_fifo(bcs);
+		hfcpci_clear_b_tx_fifo(bcs);
+		if (bcs->channel == 0) {
+			adapter->sctrl |= SCTRL_B1_ENA;
+			adapter->sctrl_r |= SCTRL_B1_ENA;
+			adapter->fifo_en |= HFCPCI_FIFOEN_B1;
+			adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+
+			if (mode == L1_MODE_TRANS)
+				adapter->ctmt |= 1;
+			else
+				adapter->ctmt &= ~1;
+
+		} else {
+			adapter->sctrl |= SCTRL_B2_ENA;
+			adapter->sctrl_r |= SCTRL_B2_ENA;
+			adapter->fifo_en |= HFCPCI_FIFOEN_B2;
+			adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+
+			if (mode == L1_MODE_TRANS)
+				adapter->ctmt |= 2;
+			else
+				adapter->ctmt &= ~2;
+
+		}
+		break;
+	}
+	hfcpci_writeb(adapter, adapter->int_m1,  HFCPCI_INT_M1);
+	hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	hfcpci_writeb(adapter, adapter->sctrl,   HFCPCI_SCTRL);
+	hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R);
+	hfcpci_writeb(adapter, adapter->ctmt,    HFCPCI_CTMT);
+	hfcpci_writeb(adapter, adapter->conn,    HFCPCI_CONNECT);
+
+	bcs->mode = mode;
+}
+
+// ----------------------------------------------------------------------
+// Layer 1 state machine
+
+static struct Fsm l1fsm;
+
+enum {
+	ST_L1_F0,
+	ST_L1_F2,
+	ST_L1_F3,
+	ST_L1_F4,
+	ST_L1_F5,
+	ST_L1_F6,
+	ST_L1_F7,
+	ST_L1_F8,
+};
+
+#define L1_STATE_COUNT (ST_L1_F8+1)
+
+static char *strL1State[] =
+{
+	"ST_L1_F0",
+	"ST_L1_F2",
+	"ST_L1_F3",
+	"ST_L1_F4",
+	"ST_L1_F5",
+	"ST_L1_F6",
+	"ST_L1_F7",
+	"ST_L1_F8",
+};
+
+enum {
+	EV_PH_F0,
+	EV_PH_1,
+	EV_PH_F2,
+	EV_PH_F3,
+	EV_PH_F4,
+	EV_PH_F5,
+	EV_PH_F6,
+	EV_PH_F7,
+	EV_PH_F8,
+	EV_PH_ACTIVATE_REQ,
+	EV_PH_DEACTIVATE_REQ,
+	EV_TIMER3,
+};
+
+#define L1_EVENT_COUNT (EV_TIMER3 + 1)
+
+static char *strL1Event[] =
+{
+	"EV_PH_F0",
+	"EV_PH_1",
+	"EV_PH_F2",
+	"EV_PH_F3",
+	"EV_PH_F4",
+	"EV_PH_F5",
+	"EV_PH_F6",
+	"EV_PH_F7",
+	"EV_PH_F8",
+	"EV_PH_ACTIVATE_REQ",
+	"EV_PH_DEACTIVATE_REQ",
+	"EV_TIMER3",
+};
+
+static void l1_ignore(struct FsmInst *fi, int event, void *arg)
+{
+}
+
+static void l1_go_f3(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F3);
+}
+
+static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct hfcpci_adapter *adapter = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F3);
+	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+static void l1_go_f4(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F3);
+}
+
+static void l1_go_f5(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F3);
+}
+
+static void l1_go_f6(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F6);
+}
+
+static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct hfcpci_adapter *adapter = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F6);
+	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+static void l1_go_f7(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F7);
+}
+
+static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct hfcpci_adapter *adapter = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F7);
+	D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);
+}
+
+static void l1_go_f8(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F8);
+}
+
+static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct hfcpci_adapter *adapter = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F8);
+	D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+static void l1_act_req(struct FsmInst *fi, int event, void *arg)
+{
+	struct hfcpci_adapter *adapter = fi->userdata;
+
+	hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES);
+}
+
+static struct FsmNode L1FnList[] __initdata =
+{
+	{ST_L1_F2,            EV_PH_F3,             l1_go_f3},
+	{ST_L1_F2,            EV_PH_F6,             l1_go_f6},
+	{ST_L1_F2,            EV_PH_F7,             l1_go_f7_act_ind},
+
+	{ST_L1_F3,            EV_PH_F3,             l1_ignore},
+	{ST_L1_F3,            EV_PH_F4,             l1_go_f4},
+	{ST_L1_F3,            EV_PH_F5,             l1_go_f5},
+	{ST_L1_F3,            EV_PH_F6,             l1_go_f6},
+	{ST_L1_F3,            EV_PH_F7,             l1_go_f7_act_ind},
+	{ST_L1_F3,            EV_PH_ACTIVATE_REQ,   l1_act_req},
+
+	{ST_L1_F4,            EV_PH_F7,             l1_ignore},
+	{ST_L1_F4,            EV_PH_F3,             l1_go_f3},
+	{ST_L1_F4,            EV_PH_F5,             l1_go_f5},
+	{ST_L1_F4,            EV_PH_F6,             l1_go_f6},
+	{ST_L1_F4,            EV_PH_F7,             l1_go_f7},
+
+	{ST_L1_F5,            EV_PH_F7,             l1_ignore},
+	{ST_L1_F5,            EV_PH_F3,             l1_go_f3},
+	{ST_L1_F5,            EV_PH_F6,             l1_go_f6},
+	{ST_L1_F5,            EV_PH_F7,             l1_go_f7},
+
+	{ST_L1_F6,            EV_PH_F7,             l1_ignore},
+	{ST_L1_F6,            EV_PH_F3,             l1_go_f3},
+	{ST_L1_F6,            EV_PH_F7,             l1_go_f7_act_ind},
+	{ST_L1_F6,            EV_PH_F8,             l1_go_f8},
+
+	{ST_L1_F7,            EV_PH_F7,             l1_ignore},
+	{ST_L1_F7,            EV_PH_F3,             l1_go_f3_deact_ind},
+	{ST_L1_F7,            EV_PH_F6,             l1_go_f6_deact_ind},
+	{ST_L1_F7,            EV_PH_F8,             l1_go_f8_deact_ind},
+
+	{ST_L1_F8,            EV_PH_F7,             l1_ignore},
+	{ST_L1_F8,            EV_PH_F3,             l1_go_f3},
+	{ST_L1_F8,            EV_PH_F6,             l1_go_f6},
+	{ST_L1_F8,            EV_PH_F7,             l1_go_f7_act_ind},
+
+};
+
+static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+	va_list args;
+	char buf[256];
+	
+	va_start(args, fmt);
+	vsprintf(buf, fmt, args);
+	DBG(DBG_L1M, "%s", buf);
+	va_end(args);
+}
+
+// ----------------------------------------------------------------------
+// clear FIFOs
+
+static void
+hfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter)
+{
+	u8 fifo_state;
+
+	DBG(DBG_D_RECV, "");
+
+	fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX;
+
+	if (fifo_state) { // enabled
+		// XXX locking
+	        adapter->fifo_en &= ~fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+	
+	adapter->last_fcnt = 0;
+
+	set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);
+	set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1);
+	mb();
+	set_d_rx_f1(adapter, MAX_D_FRAMES - 1);
+	set_d_rx_f2(adapter, MAX_D_FRAMES - 1);
+	mb();
+	
+	if (fifo_state) {
+	        adapter->fifo_en |= fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+}   
+
+static void
+hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs)
+{
+	struct hfcpci_adapter *adapter = bcs->adapter;
+	int nr = bcs->channel;
+	u8 fifo_state;
+
+	DBG(DBG_B_RECV, "");
+
+	fifo_state = adapter->fifo_en & 
+		(nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX);
+
+	if (fifo_state) { // enabled
+	        adapter->fifo_en &= ~fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+	
+	bcs->last_fcnt = 0;
+
+	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
+	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
+	mb();
+	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);
+	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);
+	mb();
+	
+	if (fifo_state) {
+	        adapter->fifo_en |= fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+}   
+
+// XXX clear d_tx_fifo?
+
+static void
+hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs)
+{
+	struct hfcpci_adapter *adapter = bcs->adapter;
+	int nr = bcs->channel;
+	u8 fifo_state;
+
+	fifo_state = adapter->fifo_en & 
+		(nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX);
+
+	if (fifo_state) { // enabled
+	        adapter->fifo_en &= ~fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+	
+	bcs->last_fcnt = 0;
+
+	set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
+	set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1);
+	mb();
+	set_b_rx_f1(bcs, MAX_B_FRAMES - 1);
+	set_b_rx_f2(bcs, MAX_B_FRAMES - 1);
+	mb();
+	
+	if (fifo_state) {
+	        adapter->fifo_en |= fifo_state;
+		hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+	}
+}   
+
+// ----------------------------------------------------------------------
+// receive messages from upper layers
+
+static void
+hfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg)
+{
+	struct hfcpci_adapter *adapter = ifc->priv;
+	struct sk_buff *skb = arg;
+
+	DBG(DBG_PR, "pr %#x", pr);
+
+	switch (pr) {
+	case PH_ACTIVATE | REQUEST:
+		FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);
+		break;
+	case PH_DEACTIVATE | REQUEST:
+		FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);
+		break;
+	case PH_DATA | REQUEST:
+		DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);
+		DBG_SKB(DBG_D_XMIT, skb);
+		if (adapter->l1m.state != ST_L1_F7) {
+			DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state);
+			break;
+		}
+		if (adapter->tx_skb)
+			BUG();
+
+		adapter->tx_skb = skb;
+		hfcpci_fill_d_fifo(adapter);
+		break;
+	}
+}
+
+static void
+hfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
+{
+	struct hfcpci_bcs *bcs = ifc->priv;
+	struct sk_buff *skb = arg;
+	int mode;
+
+	DBG(DBG_PR, "pr %#x", pr);
+
+	switch (pr) {
+	case PH_DATA | REQUEST:
+		if (bcs->tx_skb)
+			BUG();
+		
+		bcs->tx_skb = skb;
+		DBG_SKB(DBG_B_XMIT, skb);
+		hfcpci_fill_b_fifo(bcs);
+		break;
+	case PH_ACTIVATE | REQUEST:
+		mode = (int) arg;
+		DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
+		hfcpci_b_mode(bcs, mode);
+		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
+		break;
+	case PH_DEACTIVATE | REQUEST:
+		DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
+		hfcpci_b_mode(bcs, L1_MODE_NULL);
+		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
+		break;
+	}
+}
+
+// ----------------------------------------------------------------------
+// receive IRQ
+
+static inline void
+hfcpci_d_recv_irq(struct hfcpci_adapter *adapter)
+{
+	struct sk_buff *skb;
+	char *fifo_adr = adapter->fifo + 0x4000;
+	char *p;
+	int cnt, fcnt;
+	int loop = 5;
+	u8 f1, f2;
+	u16 z1, z2;
+
+	while (loop-- > 0) {
+		f1 = get_d_rx_f1(adapter);
+		f2 = get_d_rx_f2(adapter);
+		DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2);
+		
+		fcnt = f1 - f2;
+		if (fcnt < 0)
+			fcnt += 16;
+
+		if (!fcnt)
+			return;
+		
+		if (fcnt < adapter->last_fcnt)
+			/* overrun */
+			hfcpci_clear_d_rx_fifo(adapter);
+			// XXX init last_fcnt
+
+		z1 = get_d_rx_z1(adapter, f2);
+		z2 = get_d_rx_z2(adapter, f2);
+		DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2);
+
+		cnt = z1 - z2;
+		if (cnt < 0)
+			cnt += D_FIFO_SIZE;
+		cnt++;
+		
+		if (cnt < 4) {
+			DBG(DBG_WARN, "frame too short");
+			goto next;
+		}
+		if (fifo_adr[z1] != 0) {
+			DBG(DBG_WARN, "CRC error");
+			goto next;
+		}
+		cnt -= 3;
+		skb = dev_alloc_skb(cnt);
+		if (!skb) {
+			DBG(DBG_WARN, "no mem");
+			goto next;
+		}
+		p = skb_put(skb, cnt);
+		if (z2 + cnt <= D_FIFO_END) {
+			memcpy(p, fifo_adr + z2, cnt);
+		} else {
+			memcpy(p, fifo_adr + z2, D_FIFO_END - z2);
+			memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START,
+			       cnt - (D_FIFO_END - z2));
+		}
+
+		DBG_SKB(DBG_D_RECV, skb);
+		D_L1L2(adapter, PH_DATA | INDICATION, skb);
+	
+	next:
+		if (++z1 >= D_FIFO_END)
+			z1 -= D_FIFO_START;
+
+		f2 = (f2 + 1) & (MAX_D_FRAMES - 1);
+		mb();
+		set_d_rx_z2(adapter, f2, z1);
+		mb();
+		set_d_rx_f2(adapter, f2);
+		
+		adapter->last_fcnt = fcnt - 1;
+	}
+}
+
+static inline void
+hfcpci_b_recv_hdlc_irq(struct hfcpci_adapter *adapter, int nr)
+{
+	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
+	struct sk_buff *skb;
+	char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000);
+	char *p;
+	int cnt, fcnt;
+	int loop = 5;
+	u8 f1, f2;
+	u16 z1, z2;
+
+	while (loop-- > 0) {
+		f1 = get_b_rx_f1(bcs);
+		f2 = get_b_rx_f2(bcs);
+		DBG(DBG_B_RECV, "f1 %d f2 %d", f1, f2);
+		
+		fcnt = f1 - f2;
+		if (fcnt < 0)
+			fcnt += 32;
+
+		if (!fcnt)
+			return;
+		
+		if (fcnt < bcs->last_fcnt)
+			/* overrun */
+			hfcpci_clear_b_rx_fifo(bcs);
+			// XXX init last_fcnt
+		
+		z1 = get_b_rx_z1(bcs, f2);
+		z2 = get_b_rx_z2(bcs, f2);
+		DBG(DBG_B_RECV, "z1 %d z2 %d", z1, z2);
+
+		cnt = z1 - z2;
+		if (cnt < 0)
+			cnt += B_FIFO_SIZE;
+		cnt++;
+		
+		if (cnt < 4) {
+			DBG(DBG_WARN, "frame too short");
+			goto next;
+		}
+		if (fifo_adr[z1] != 0) {
+			DBG(DBG_WARN, "CRC error");
+			goto next;
+		}
+		cnt -= 3;
+		skb = dev_alloc_skb(cnt);
+		if (!skb) {
+			DBG(DBG_WARN, "no mem");
+			goto next;
+		}
+		p = skb_put(skb, cnt);
+		if (z2 + cnt <= B_FIFO_END) {
+			memcpy(p, fifo_adr + z2, cnt);
+		} else {
+			memcpy(p, fifo_adr + z2, B_FIFO_END - z2);
+			memcpy(p + (B_FIFO_END - z2), fifo_adr + B_FIFO_START,
+			       cnt - (B_FIFO_END - z2));
+		}
+
+		DBG_SKB(DBG_B_RECV, skb);
+		B_L1L2(bcs, PH_DATA | INDICATION, skb);
+	
+	next:
+		if (++z1 >= B_FIFO_END)
+			z1 -= B_FIFO_SIZE;
+
+		f2 = (f2 + 1) & (MAX_B_FRAMES - 1);
+		mb();
+		set_b_rx_z2(bcs, f2, z1);
+		mb();
+		set_b_rx_f2(bcs, f2);
+		
+		bcs->last_fcnt = fcnt - 1;
+	}
+}
+
+static inline void
+hfcpci_b_recv_trans_irq(struct hfcpci_adapter *adapter, int nr)
+{
+	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
+	struct sk_buff *skb;
+	char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000);
+	char *p;
+	int cnt;
+	int loop = 5;
+	u8 f1, f2;
+	u16 z1, z2;
+
+	f1 = get_b_rx_f1(bcs);
+	f2 = get_b_rx_f2(bcs);
+
+	if (f1 != f2)
+		BUG();
+
+	while (loop-- > 0) {
+		z1 = get_b_rx_z1(bcs, f2);
+		z2 = get_b_rx_z2(bcs, f2);
+		
+		cnt = z1 - z2;
+		if (!cnt)
+			/* no data available */
+			return;
+		
+		if (cnt < 0)
+			cnt += B_FIFO_SIZE;
+		
+		if (cnt > HFCPCI_BTRANS_THRESHOLD)
+			cnt = HFCPCI_BTRANS_THRESHOLD;
+		
+		skb = dev_alloc_skb(cnt);
+		if (!skb) {
+			DBG(DBG_WARN, "no mem");
+			goto next;
+		}
+		
+		p = skb_put(skb, cnt);
+		if (z2 + cnt <= 0x2000) {
+			memcpy(p, fifo_adr + z2, cnt);
+		} else {
+			memcpy(p, fifo_adr + z2, 0x2000 - z2);
+			p += 0x2000 - z2;
+			memcpy(p, fifo_adr + 0x200, cnt - (0x2000 - z2));
+		}
+		
+		DBG_SKB(DBG_B_RECV, skb);
+		B_L1L2(bcs, PH_DATA | INDICATION, skb);
+		
+	next:
+		z2 += cnt;
+		if (z2 >= 0x2000)
+			z2 -= B_FIFO_SIZE;
+		
+		mb();
+		set_b_rx_z2(bcs, f2, z2);
+		// XXX always receive buffers of a given size
+	}
+}
+
+static inline void
+hfcpci_b_recv_irq(struct hfcpci_adapter *adapter, int nr)
+{
+	DBG(DBG_B_RECV, "");
+
+	switch (adapter->bcs[nr].mode) {
+	case L1_MODE_NULL:
+		DBG(DBG_WARN, "?");
+		break;
+		
+	case L1_MODE_HDLC:
+		hfcpci_b_recv_hdlc_irq(adapter, nr);
+		break;
+
+	case L1_MODE_TRANS:
+		hfcpci_b_recv_trans_irq(adapter, nr);
+		break;
+	}
+}
+
+// ----------------------------------------------------------------------
+// transmit IRQ
+
+// XXX make xmit FIFO deeper than 1 
+
+static inline void
+hfcpci_d_xmit_irq(struct hfcpci_adapter *adapter)
+{
+	struct sk_buff *skb;
+
+	DBG(DBG_D_XMIT, "");
+
+	skb = adapter->tx_skb;
+	if (!skb) {
+		DBG(DBG_WARN, "?");
+		return;
+	}
+
+	adapter->tx_skb = NULL;
+	D_L1L2(adapter, PH_DATA | CONFIRM, (void *) skb->truesize);
+	dev_kfree_skb_irq(skb);
+}
+
+static inline void
+hfcpci_b_xmit_irq(struct hfcpci_adapter *adapter, int nr)
+{
+	struct hfcpci_bcs *bcs = &adapter->bcs[nr];
+	struct sk_buff *skb;
+
+	DBG(DBG_B_XMIT, "");
+
+	skb = bcs->tx_skb;
+	if (!skb) {
+		DBG(DBG_WARN, "?");
+		return;
+	}
+
+	bcs->tx_skb = NULL;
+	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+	dev_kfree_skb_irq(skb);
+}
+
+// ----------------------------------------------------------------------
+// Layer 1 state change IRQ
+
+static inline void
+hfcpci_state_irq(struct hfcpci_adapter *adapter)
+{
+	u8 val;
+
+	val = hfcpci_readb(adapter, HFCPCI_STATES);
+	DBG(DBG_L1M, "STATES %#x", val);
+	FsmEvent(&adapter->l1m, val & 0xf, NULL);
+}
+
+// ----------------------------------------------------------------------
+// Timer IRQ
+
+static inline void
+hfcpci_timer_irq(struct hfcpci_adapter *adapter)
+{
+	hfcpci_writeb(adapter, adapter->ctmt | HFCPCI_CLTIMER, HFCPCI_CTMT);
+}
+
+// ----------------------------------------------------------------------
+// IRQ handler
+
+static void
+hfcpci_irq(int intno, void *dev, struct pt_regs *regs)
+{
+	struct hfcpci_adapter *adapter = dev;
+	int loop = 15;
+	u8 val, stat;
+
+	if (!(adapter->int_m2 & 0x08))
+		return;		/* not initialised */ // XX
+
+	stat = hfcpci_readb(adapter, HFCPCI_STATUS);
+	if (!(stat & HFCPCI_ANYINT))
+		return;
+
+	spin_lock(&adapter->hw_lock);
+	while (loop-- > 0) {
+		val = hfcpci_readb(adapter, HFCPCI_INT_S1);
+		DBG(DBG_IRQ, "stat %02x s1 %02x", stat, val);
+		val &= adapter->int_m1;
+
+		if (!val)
+			break;
+
+		if (val & 0x08)
+			hfcpci_b_recv_irq(adapter, 0);
+			
+		if (val & 0x10)
+			hfcpci_b_recv_irq(adapter, 1);
+
+		if (val & 0x01)
+			hfcpci_b_xmit_irq(adapter, 0);
+
+		if (val & 0x02)
+			hfcpci_b_xmit_irq(adapter, 1);
+
+		if (val & 0x20)
+			hfcpci_d_recv_irq(adapter);
+
+		if (val & 0x04)
+			hfcpci_d_xmit_irq(adapter);
+
+		if (val & 0x40)
+			hfcpci_state_irq(adapter);
+
+		if (val & 0x80)
+			hfcpci_timer_irq(adapter);
+	}
+	spin_unlock(&adapter->hw_lock);
+}
+
+// ----------------------------------------------------------------------
+// reset hardware
+
+static void
+hfcpci_reset(struct hfcpci_adapter *adapter)
+{
+	/* disable all interrupts */
+	adapter->int_m1 = 0;
+	adapter->int_m2 = 0;
+	hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1);
+	hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2);
+
+	/* reset */
+	hfcpci_writeb(adapter, HFCPCI_RESET, HFCPCI_CIRM);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((30 * HZ) / 1000);
+	hfcpci_writeb(adapter, 0, HFCPCI_CIRM);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((20 * HZ) / 1000);
+	if (hfcpci_readb(adapter, HFCPCI_STATUS) & 2) // XX
+		printk(KERN_WARNING "HFC-PCI init bit busy\n");
+}
+
+// ----------------------------------------------------------------------
+// init hardware
+
+static void
+hfcpci_hw_init(struct hfcpci_adapter *adapter)
+{
+	adapter->fifo_en = 0x30;	/* only D fifos enabled */ // XX
+	hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN);
+
+	/* no echo connect , threshold */
+	adapter->trm = HFCPCI_BTRANS_THRESMASK;
+	hfcpci_writeb(adapter, adapter->trm, HFCPCI_TRM);
+
+	/* ST-Bit delay for TE-Mode */
+	hfcpci_writeb(adapter, CLKDEL_TE, HFCPCI_CLKDEL);
+
+	/* S/T Auto awake */
+	adapter->sctrl_e = HFCPCI_AUTO_AWAKE;
+	hfcpci_writeb(adapter, adapter->sctrl_e, HFCPCI_SCTRL_E);
+
+	/* no exchange */
+	adapter->bswapped = 0;
+	/* we are in TE mode */
+	adapter->nt_mode = 0;
+
+	adapter->ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
+	hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT);
+
+	adapter->int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
+		HFCPCI_INTS_L1STATE;
+	hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1);
+
+	/* clear already pending ints */
+	hfcpci_readb(adapter, HFCPCI_INT_S1);
+
+	adapter->l1m.state = 2;
+	hfcpci_writeb(adapter, HFCPCI_LOAD_STATE | 2, HFCPCI_STATES);	// XX /* HFC ST 2 */
+	udelay(10);
+	hfcpci_writeb(adapter, 2, HFCPCI_STATES);	/* HFC ST 2 */
+
+	/* HFC Master Mode */
+	adapter->mst_m = HFCPCI_MASTER;
+	hfcpci_writeb(adapter, adapter->mst_m, HFCPCI_MST_MODE);
+
+	/* set tx_lo mode, error in datasheet ! */
+	adapter->sctrl = 0x40;
+	hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL);
+
+	adapter->sctrl_r = 0;
+	hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R);
+
+	// XXX
+	/* Init GCI/IOM2 in master mode */
+	/* Slots 0 and 1 are set for B-chan 1 and 2 */
+	/* D- and monitor/CI channel are not enabled */
+	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
+	/* STIO2 is used as data input, B1+B2 from IOM->ST */
+	/* ST B-channel send disabled -> continous 1s */
+	/* The IOM slots are always enabled */
+	adapter->conn = 0;	/* set data flow directions */
+	hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT);
+	hfcpci_writeb(adapter, 0x80, HFCPCI_B1_SSL);	/* B1-Slot 0 STIO1 out enabled */
+	hfcpci_writeb(adapter, 0x81, HFCPCI_B2_SSL);	/* B2-Slot 1 STIO1 out enabled */
+	hfcpci_writeb(adapter, 0x80, HFCPCI_B1_RSL);	/* B1-Slot 0 STIO2 in enabled */
+	hfcpci_writeb(adapter, 0x81, HFCPCI_B2_RSL);	/* B2-Slot 1 STIO2 in enabled */
+
+	/* Finally enable IRQ output */
+	adapter->int_m2 = HFCPCI_IRQ_ENABLE;
+	hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2);
+
+	hfcpci_readb(adapter, HFCPCI_INT_S2);
+}
+
+// ----------------------------------------------------------------------
+// probe / remove
+
+static struct hfcpci_adapter * __devinit 
+new_adapter(struct pci_dev *pdev)
+{
+	struct hfcpci_adapter *adapter;
+	struct hisax_b_if *b_if[2];
+	int i;
+
+	adapter = kmalloc(sizeof(struct hfcpci_adapter), GFP_KERNEL);
+	if (!adapter)
+		return NULL;
+
+	memset(adapter, 0, sizeof(struct hfcpci_adapter));
+
+	SET_MODULE_OWNER(&adapter->d_if);
+	adapter->d_if.ifc.priv = adapter;
+	adapter->d_if.ifc.l2l1 = hfcpci_d_l2l1;
+	
+	for (i = 0; i < 2; i++) {
+		adapter->bcs[i].adapter = adapter;
+		adapter->bcs[i].channel = i;
+		adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
+		adapter->bcs[i].b_if.ifc.l2l1 = hfcpci_b_l2l1;
+	}
+
+	pci_set_drvdata(pdev, adapter);
+
+	for (i = 0; i < 2; i++)
+		b_if[i] = &adapter->bcs[i].b_if;
+
+	hisax_register(&adapter->d_if, b_if, "hfcpci", protocol);
+
+	return adapter;
+}
+
+static void delete_adapter(struct hfcpci_adapter *adapter)
+{
+	hisax_unregister(&adapter->d_if);
+	kfree(adapter);
+}
+
+static int __devinit hfcpci_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct hfcpci_adapter *adapter;
+	int retval;
+
+	DBG(DBG_INFO, "");
+	retval = -ENOMEM;
+	adapter = new_adapter(pdev);
+	if (!adapter)
+		goto err;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err_free;
+
+	adapter->irq = pdev->irq;
+	retval = request_irq(adapter->irq, hfcpci_irq, SA_SHIRQ, 
+			     "hfcpci", adapter);
+	if (retval)
+		goto err_free;
+
+	retval = -EBUSY;
+	if (!request_mem_region(pci_resource_start(pdev, 1), 256, "hfcpci"))
+		goto err_free_irq;
+
+	adapter->mmio = ioremap(pci_resource_start(pdev, 1), 256); // XX pci_io
+	if (!adapter->mmio)
+		goto err_release_region;
+
+	/* Allocate 32K for FIFOs */
+	if (pci_set_dma_mask(pdev, 0xffffffff))
+		goto err_unmap;
+	
+	adapter->fifo = pci_alloc_consistent(pdev, 32768, &adapter->fifo_dma); 
+	if (!adapter->fifo)
+		goto err_unmap;
+	
+	pci_write_config_dword(pdev, HFCPCI_MWBA, (u32) adapter->fifo_dma);
+	pci_set_master(pdev);
+
+	adapter->l1m.fsm = &l1fsm;
+	adapter->l1m.state = ST_L1_F0;
+#ifdef CONFIG_HISAX_DEBUG
+	adapter->l1m.debug = 1;
+#else
+	adapter->l1m.debug = 0;
+#endif
+	adapter->l1m.userdata = adapter;
+	adapter->l1m.printdebug = l1m_debug;
+	FsmInitTimer(&adapter->l1m, &adapter->timer);
+
+	hfcpci_reset(adapter);
+	hfcpci_hw_init(adapter);
+
+	printk(KERN_INFO "hisax_hfcpci: found adapter %s at %s\n",
+	       (char *) ent->driver_data, pdev->slot_name);
+
+	return 0;
+
+ err_unmap:
+	iounmap(adapter->mmio);
+ err_release_region:
+	release_mem_region(pci_resource_start(pdev, 1), 256);
+ err_free_irq:
+	free_irq(adapter->irq, adapter);
+ err_free:
+	delete_adapter(adapter);
+ err:
+	return retval;
+}
+
+static void __devexit hfcpci_remove(struct pci_dev *pdev)
+{
+	struct hfcpci_adapter *adapter = pci_get_drvdata(pdev);
+
+	hfcpci_reset(adapter);
+
+//	del_timer(&cs->hw.hfcpci.timer); XX
+
+	/* disable DMA */
+	pci_disable_device(pdev);
+	pci_write_config_dword(pdev, HFCPCI_MWBA, 0);
+	pci_free_consistent(pdev, 32768, adapter->fifo, adapter->fifo_dma);
+
+	iounmap(adapter->mmio);
+	release_mem_region(pci_resource_start(pdev, 1), 256);
+	free_irq(adapter->irq, adapter);
+	delete_adapter(adapter);
+}
+
+static struct pci_driver hfcpci_driver = {
+	name:     "hfcpci",
+	probe:    hfcpci_probe,
+	remove:   hfcpci_remove,
+	id_table: hfcpci_ids,
+};
+
+static int __init hisax_hfcpci_init(void)
+{
+	int retval;
+
+	printk(KERN_INFO "hisax_hfcpcipnp: HFC PCI ISDN driver v0.0.1\n");
+
+	l1fsm.state_count = L1_STATE_COUNT;
+	l1fsm.event_count = L1_EVENT_COUNT;
+	l1fsm.strState = strL1State;
+	l1fsm.strEvent = strL1Event;
+	retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
+	if (retval)
+		goto err;
+
+	retval = pci_module_init(&hfcpci_driver);
+	if (retval)
+		goto err_fsm;
+	
+	return 0;
+
+ err_fsm:
+	FsmFree(&l1fsm);
+ err:
+	return retval;
+}
+
+static void __exit hisax_hfcpci_exit(void)
+{
+	FsmFree(&l1fsm);
+	pci_unregister_driver(&hfcpci_driver);
+}
+
+module_init(hisax_hfcpci_init);
+module_exit(hisax_hfcpci_exit);
diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.h b/drivers/isdn/hisax/hisax_hfcpci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/isdn/hisax/hisax_hfcpci.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,40 @@
+#include "hisax_if.h"
+#include "hisax_isac.h"
+#include <linux/pci.h>
+
+struct hfcpci_bcs {
+	struct hisax_b_if b_if;
+	struct hfcpci_adapter *adapter;
+	int mode;
+	int channel;
+	int last_fcnt;
+
+	struct sk_buff *tx_skb;
+};
+
+struct hfcpci_adapter {
+	struct hisax_d_if d_if;
+	spinlock_t hw_lock;
+	unsigned int irq;
+	void *mmio;
+	u8 *fifo;
+	dma_addr_t fifo_dma;
+
+	struct FsmInst l1m;
+	struct FsmTimer timer;
+	struct sk_buff *tx_skb;
+	int last_fcnt;
+
+	u8 int_m1, int_m2;
+	u8 fifo_en;
+	u8 trm;
+	u8 sctrl, sctrl_r, sctrl_e;
+	u8 nt_mode;
+	u8 ctmt;
+	u8 mst_m;
+	u8 conn;
+	u8 bswapped;
+
+	struct hfcpci_bcs bcs[2];
+};
+
diff -Nru a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
--- a/drivers/isdn/hisax/st5481_init.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/isdn/hisax/st5481_init.c	Tue Feb 26 11:58:00 2002
@@ -178,7 +178,7 @@
 static struct usb_driver st5481_usb_driver = {
 	name: "st5481_usb",
 	probe: probe_st5481,
-	disconnect: disconnect_st5481,
+	disconnect: __devexit_p(disconnect_st5481),
 	id_table: st5481_ids,
 };
 
diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
--- a/drivers/isdn/hisax/st5481_usb.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/isdn/hisax/st5481_usb.c	Tue Feb 26 11:57:59 2002
@@ -416,7 +416,7 @@
 
 	for (j = 0; j < 2; j++) {
 		retval = -ENOMEM;
-		urb[j] = usb_alloc_urb(num_packet, GFP_KERNEL);
+		urb[j] = usb_alloc_urb(num_packets, GFP_KERNEL);
 		if (!urb[j])
 			goto err;
 
diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
--- a/drivers/isdn/tpam/tpam_main.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/isdn/tpam/tpam_main.c	Tue Feb 26 11:57:57 2002
@@ -254,7 +254,7 @@
 	name:		"tpam",
 	id_table:	tpam_pci_tbl,
 	probe:		tpam_probe,
-	remove:		tpam_remove,
+	remove:		__devexit_p(tpam_remove),
 };
 
 static int __init tpam_init(void) {
diff -Nru a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
--- a/drivers/media/radio/radio-gemtek-pci.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/media/radio/radio-gemtek-pci.c	Tue Feb 26 11:57:57 2002
@@ -424,7 +424,7 @@
     name:	"gemtek_pci",
 id_table:	gemtek_pci_id,
    probe:	gemtek_pci_probe,
-  remove:	gemtek_pci_remove
+  remove:	__devexit_p(gemtek_pci_remove)
 };
 
 static int __init gemtek_pci_init_module( void )
diff -Nru a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
--- a/drivers/media/radio/radio-maxiradio.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/media/radio/radio-maxiradio.c	Tue Feb 26 11:57:59 2002
@@ -376,7 +376,7 @@
 	name:		"radio-maxiradio",
 	id_table:	maxiradio_pci_tbl,
 	probe:		maxiradio_init_one,
-	remove:		maxiradio_remove_one,
+	remove:		__devexit_p(maxiradio_remove_one),
 };
 
 int __init maxiradio_radio_init(void)
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/media/video/bttv-driver.c	Tue Feb 26 11:57:58 2002
@@ -141,58 +141,63 @@
  * defined way to get at the kernel page tables.
  */
 
-static inline unsigned long uvirt_to_bus(unsigned long adr) 
-{
-        unsigned long kva, ret;
 
-	kva = page_address(vmalloc_to_page(adr));
-	ret = virt_to_bus((void *)kva);
-        MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
-        return ret;
+/*
+ * Take a vmalloc address, and turn it into
+ * the aliased kernel virtual address..
+ *
+ * CAREFUL! Anybody who does this gets to sit
+ * in their own cr*p when it comes to virtual
+ * cache aliases. It's _your_ problem.
+ *
+ * Also, note how it only works within one page.
+ * If you're doing page-crossing stuff, you're on
+ * your own.
+ *
+ * THIS IS BROKEN CODE! You shouldn't do things
+ * like this.
+ */
+static inline void *vmalloc_to_virt(void *addr)
+{
+	struct page *page = vmalloc_to_page(addr);
+	return page_address(page) + (~PAGE_MASK & (unsigned long)addr);
 }
 
-static inline unsigned long kvirt_to_bus(unsigned long adr) 
+static inline unsigned long kvirt_to_bus(unsigned long addr) 
 {
-        unsigned long va, kva, ret;
-
-        va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
-	ret = virt_to_bus((void *)kva);
-        MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
+	unsigned long ret;
+	ret = virt_to_bus(vmalloc_to_virt((void *)addr));
+        MDEBUG(printk("kv2b(%lx-->%lx)", addr, ret));
         return ret;
 }
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
+static inline unsigned long kvirt_to_pa(unsigned long addr) 
 {
-        unsigned long va, kva, ret;
-
-        va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
-	ret = __pa(kva);
-        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+        unsigned long ret;
+	ret = virt_to_phys(vmalloc_to_virt((void *)addr));
+        MDEBUG(printk("kv2pa(%lx-->%lx)", addr, ret));
         return ret;
 }
 
-static void * rvmalloc(signed long size)
+static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr, page;
+	unsigned long adr;
 
+	size=PAGE_ALIGN(size);
 	mem=vmalloc_32(size);
 	if (NULL == mem)
-		printk(KERN_INFO "bttv: vmalloc_32(%ld) failed\n",size);
+		printk(KERN_INFO "bttv: vmalloc_32(%lu) failed\n",size);
 	else {
 		/* Clear the ram out, no junk to the user */
 		memset(mem, 0, size);
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -200,17 +205,16 @@
 	return mem;
 }
 
-static void rvfree(void * mem, signed long size)
+static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr, page;
+        unsigned long adr;
         
 	if (mem) 
 	{
 	        adr=(unsigned long) mem;
-		while (size > 0) 
+		while ((long) size > 0)
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -2794,7 +2798,8 @@
  *	Scan for a Bt848 card, request the irq and map the io memory 
  */
 
-static void __devexit bttv_remove(struct pci_dev *pci_dev)
+/* Can't be marked __devexit with a reference from bttv_probe.  */
+static void bttv_remove(struct pci_dev *pci_dev)
 {
         u8 command;
         int j;
diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
--- a/drivers/media/video/cpia.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/media/video/cpia.c	Tue Feb 26 11:58:00 2002
@@ -181,15 +181,14 @@
  **********************************************************************/
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
 	return ret;
 }
@@ -197,12 +196,9 @@
 static void *rvmalloc(unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
-
-	/* Round it off to PAGE_SIZE */
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32(size);
 	if (!mem)
 		return NULL;
@@ -210,13 +206,9 @@
 	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 	adr = (unsigned long) mem;
 	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_reserve(virt_to_page(__va(page)));
+		mem_map_reserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 
 	return mem;
@@ -224,23 +216,16 @@
 
 static void rvfree(void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (!mem)
 		return;
 
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
-
 	adr = (unsigned long) mem;
-	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_unreserve(virt_to_page(__va(page)));
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	vfree(mem);
 }
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/media/video/meye.c	Tue Feb 26 11:57:56 2002
@@ -115,34 +115,29 @@
 /* Memory allocation routines (stolen from bttv-driver.c)                   */
 /****************************************************************************/
 
-#define MDEBUG(x)	do {} while (0)
-/* #define MDEBUG(x)	x */
-
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr) {
-        unsigned long va, kva, ret;
+        unsigned long kva, ret;
 
-        va = VMALLOC_VMADDR(adr);
-        kva = page_address(vmalloc_to_page(va));
+        kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
-        MDEBUG(printk("kv2pa(%lx-->%lx)\n", adr, ret));
         return ret;
 }
 
-static void *rvmalloc(signed long size) {
+static void *rvmalloc(unsigned long size) {
 	void *mem;
-	unsigned long adr, page;
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32(size);
 	if (mem) {
 		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 	        adr = (unsigned long)mem;
 		while (size > 0) {
-	                page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr += PAGE_SIZE;
 			size -= PAGE_SIZE;
 		}
@@ -150,14 +145,13 @@
 	return mem;
 }
 
-static void rvfree(void * mem, signed long size) {
-        unsigned long adr, page;
-        
+static void rvfree(void * mem, unsigned long size) {
+        unsigned long adr;
+
 	if (mem) {
 	        adr = (unsigned long) mem;
-		while (size > 0) {
-	                page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+		while ((long) size > 0) {
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr += PAGE_SIZE;
 			size -= PAGE_SIZE;
 		}
@@ -1425,7 +1419,7 @@
 	name:		"meye",
 	id_table:	meye_pci_tbl,
 	probe:		meye_probe,
-	remove:		meye_remove,
+	remove:		__devexit_p(meye_remove),
 };
 
 static int __init meye_init_module(void) {
diff -Nru a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
--- a/drivers/media/video/zr36120.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/media/video/zr36120.c	Tue Feb 26 11:57:59 2002
@@ -2024,7 +2024,7 @@
 }
 
 static
-void __exit release_zoran(int max)
+void release_zoran(int max)
 {
 	struct zoran *ztv;
 	int i;
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/message/i2o/i2o_block.c	Tue Feb 26 11:58:00 2002
@@ -116,7 +116,7 @@
 #define I2O_BSA_DSC_VOLUME_CHANGED      0x000D
 #define I2O_BSA_DSC_TIMEOUT             0x000E
 
-#define I2O_UNIT(dev)	(i2ob_dev[MINOR((dev)) & 0xf0])
+#define I2O_UNIT(dev)	(i2ob_dev[minor((dev)) & 0xf0])
 #define I2O_LOCK(unit)	(i2ob_dev[(unit)].req_queue->queue_lock)
 
 /*
@@ -760,7 +760,7 @@
 			{
 				u64 size;
 
-				if(do_i2ob_revalidate(MKDEV(MAJOR_NR, unit),0) != -EBUSY)
+				if(do_i2ob_revalidate(mk_kdev(MAJOR_NR, unit),0) != -EBUSY)
 					continue;
 
 	  			if(i2ob_query_device(&i2ob_dev[unit], 0x0004, 0, &size, 8) !=0 )
@@ -869,7 +869,7 @@
 		if(i2ob_backlog[c->unit] == NULL)
 			i2ob_backlog_tail[c->unit] = NULL;
 			
-		unit = MINOR(ireq->req->rq_dev);
+		unit = minor(ireq->req->rq_dev);
 		i2ob_send(m, dev, ireq, i2ob[unit].start_sect, unit);
 	}
 	if(i2ob_backlog[c->unit])
@@ -905,7 +905,7 @@
 		if(req->rq_status == RQ_INACTIVE)
 			return;
 			
-		unit = MINOR(req->rq_dev);
+		unit = minor(req->rq_dev);
 		dev = &i2ob_dev[(unit&0xF0)];
 
 		/* 
@@ -1038,7 +1038,7 @@
  
 static int do_i2ob_revalidate(kdev_t dev, int maxu)
 {
-	int minor=MINOR(dev);
+	int minor=minor(dev);
 	int i;
 	
 	minor&=0xF0;
@@ -1053,7 +1053,7 @@
 	for( i = 15; i>=0 ; i--)
 	{
 		int m = minor+i;
-		invalidate_device(MKDEV(MAJOR_NR, m), 1);
+		invalidate_device(mk_kdev(MAJOR_NR, m), 1);
 		i2ob_gendisk.part[m].start_sect = 0;
 		i2ob_gendisk.part[m].nr_sects = 0;
 	}
@@ -1079,14 +1079,14 @@
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (!inode || !inode->i_rdev)
+	if (!inode || kdev_none(inode->i_rdev))
 		return -EINVAL;
 
 	switch (cmd) {
 		case HDIO_GETGEO:
 		{
 			struct hd_geometry g;
-			int u = MINOR(inode->i_rdev) & 0xF0;
+			int u = minor(inode->i_rdev) & 0xF0;
 			i2o_block_biosparam(i2ob_sizes[u]<<1, 
 				&g.cylinders, &g.heads, &g.sectors);
 			g.start = get_start_sect(inode->i_rdev);
@@ -1121,7 +1121,7 @@
 	struct i2ob_device *dev;
 	int minor;
 
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 	if (minor >= (MAX_I2OB<<4))
 		return -ENODEV;
 	dev = &i2ob_dev[(minor&0xF0)];
@@ -1193,7 +1193,7 @@
 	
 	if (!inode)
 		return -EINVAL;
-	minor = MINOR(inode->i_rdev);
+	minor = minor(inode->i_rdev);
 	if (minor >= MAX_I2OB<<4)
 		return -ENODEV;
 	dev=&i2ob_dev[(minor&0xF0)];
@@ -1384,7 +1384,7 @@
 	 */
 	dev->req_queue = &i2ob_queues[c->unit]->req_queue;
 
-	grok_partitions(MKDEV(MAJOR_NR, unit), (long)(size>>9));
+	grok_partitions(mk_kdev(MAJOR_NR, unit), (long)(size>>9));
 
 	/*
 	 * Register for the events we're interested in and that the
@@ -1704,7 +1704,7 @@
  */
 static int i2ob_media_change(kdev_t dev)
 {
-	int i=MINOR(dev);
+	int i=minor(dev);
 	i>>=4;
 	if(i2ob_media_change_flag[i])
 	{
@@ -1883,7 +1883,7 @@
 	 *	Finally see what is actually plugged in to our controllers
 	 */
 	for (i = 0; i < MAX_I2OB; i++)
-		register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,
+		register_disk(&i2ob_gendisk, mk_kdev(MAJOR_NR,i<<4), 1<<4,
 			&i2ob_fops, 0);
 	i2ob_probe();
 
diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
--- a/drivers/mtd/devices/blkmtd.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/mtd/devices/blkmtd.c	Tue Feb 26 11:57:56 2002
@@ -989,8 +989,8 @@
   rawdevice->as.nrpages = 0;
   rawdevice->as.a_ops = &blkmtd_aops;
   rawdevice->as.host = inode;
-  rawdevice->as.i_mmap = NULL;
-  rawdevice->as.i_mmap_shared = NULL;
+  INIT_LIST_HEAD(&rawdevice->as.i_mmap);
+  INIT_LIST_HEAD(&rawdevice->as.i_mmap_shared);
   spin_lock_init(&rawdevice->as.i_shared_lock);
   rawdevice->as.gfp_mask = GFP_KERNEL;
   rawdevice->file = file;
diff -Nru a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c
--- a/drivers/mtd/maps/elan-104nc.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/mtd/maps/elan-104nc.c	Tue Feb 26 11:57:59 2002
@@ -213,7 +213,7 @@
 /* MTD device for all of the flash. */
 static struct mtd_info *all_mtd;
 
-static void __exit cleanup_elan_104nc(void)
+static void cleanup_elan_104nc(void)
 {
 	if( all_mtd ) {
 		del_mtd_partitions( all_mtd );
diff -Nru a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c
--- a/drivers/mtd/maps/sbc_gxx.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/mtd/maps/sbc_gxx.c	Tue Feb 26 11:57:59 2002
@@ -221,7 +221,7 @@
 /* MTD device for all of the flash. */
 static struct mtd_info *all_mtd;
 
-static void __exit cleanup_sbc_gxx(void)
+static void cleanup_sbc_gxx(void)
 {
 	if( all_mtd ) {
 		del_mtd_partitions( all_mtd );
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/mtd/nftlcore.c	Tue Feb 26 11:57:56 2002
@@ -156,7 +156,7 @@
 #if LINUX_VERSION_CODE < 0x20328
 	resetup_one_dev(&nftl_gendisk, firstfree);
 #else
-	grok_partitions(MKDEV(MAJOR_NR,firstfree<<NFTL_PARTN_BITS),
+	grok_partitions(mk_kdev(MAJOR_NR,firstfree<<NFTL_PARTN_BITS),
 			nftl->nr_sects);
 #endif
 }
@@ -779,7 +779,7 @@
 	struct NFTLrecord *nftl;
 	int res;
 
-	nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS];
+	nftl = NFTLs[minor(inode->i_rdev) >> NFTL_PARTN_BITS];
 
 	if (!nftl) return -EINVAL;
 
@@ -853,7 +853,7 @@
 		      (req->cmd == READ) ? "Read " : "Write",
 		      req->sector, req->current_nr_sectors);
 
-		dev = MINOR(req->rq_dev);
+		dev = minor(req->rq_dev);
 		block = req->sector;
 		nsect = req->current_nr_sectors;
 		buffer = req->buffer;
@@ -875,7 +875,7 @@
 		if (block + nsect > part_table[dev].nr_sects) {
 			/* access past the end of device */
 			printk("nftl%c%d: bad access: block = %d, count = %d\n",
-			       (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
+			       (minor(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
 			up(&nftl->mutex);
 			res = 0; /* fail */
 			goto repeat;
@@ -933,7 +933,7 @@
 
 static int nftl_open(struct inode *ip, struct file *fp)
 {
-	int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS;
+	int nftlnum = minor(ip->i_rdev) >> NFTL_PARTN_BITS;
 	struct NFTLrecord *thisNFTL;
 	thisNFTL = NFTLs[nftlnum];
 
@@ -947,7 +947,7 @@
 #endif
 	if (!thisNFTL) {
 		DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", 
-		      nftlnum, ip->i_rdev, ip, fp);
+		      nftlnum, minor(ip->i_rdev), ip, fp);
 		return -ENODEV;
 	}
 
@@ -967,7 +967,7 @@
 {
 	struct NFTLrecord *thisNFTL;
 
-	thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
+	thisNFTL = NFTLs[minor(inode->i_rdev) / 16];
 
 	DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");
 
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/3c59x.c	Tue Feb 26 11:57:56 2002
@@ -2916,7 +2916,7 @@
 static struct pci_driver vortex_driver = {
 	name:		"3c59x",
 	probe:		vortex_init_one,
-	remove:		vortex_remove_one,
+	remove:		__devexit_p(vortex_remove_one),
 	id_table:	vortex_pci_tbl,
 #ifdef CONFIG_PM
 	suspend:	vortex_suspend,
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/8139cp.c	Tue Feb 26 11:57:59 2002
@@ -1371,7 +1371,7 @@
 	name:		DRV_NAME,
 	id_table:	cp_pci_tbl,
 	probe:		cp_init_one,
-	remove:		cp_remove_one,
+	remove:		__devexit_p(cp_remove_one),
 };
 
 static int __init cp_init (void)
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/8139too.c	Tue Feb 26 11:57:56 2002
@@ -2499,7 +2499,7 @@
 	name:		DRV_NAME,
 	id_table:	rtl8139_pci_tbl,
 	probe:		rtl8139_init_one,
-	remove:		rtl8139_remove_one,
+	remove:		__devexit_p(rtl8139_remove_one),
 #ifdef CONFIG_PM
 	suspend:	rtl8139_suspend,
 	resume:		rtl8139_resume,
diff -Nru a/drivers/net/Config.help b/drivers/net/Config.help
--- a/drivers/net/Config.help	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/Config.help	Tue Feb 26 11:57:56 2002
@@ -3,6 +3,10 @@
   MIPS-32-based Baget embedded system.  This chipset is better known
   via the NE2100 cards.
 
+CONFIG_LASI_82596
+  Say Y here to support the on-board Intel 82596 ethernet controller
+  built into Hewlett-Packard PA-RISC machines.
+
 CONFIG_MIPS_JAZZ_SONIC
   This is the driver for the onboard card of MIPS Magnum 4000,
   Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
@@ -214,6 +218,12 @@
   pppd, along with binaries of a patched pppd package can be found at:
   <http://www.shoshin.uwaterloo.ca/~mostrows/>.
 
+CONFIG_PPPOATM
+  Support PPP (Point to Point Protocol) encapsulated in ATM frames.
+  This implementation does not yet comply with section 8 of RFC2364,
+  which can lead to bad results if the ATM peer loses state and
+  changes its encapsulation unilaterally.
+
 CONFIG_NET_RADIO
   Support for wireless LANs and everything having to do with radio,
   but not with amateur radio or FM broadcasting.
@@ -806,6 +816,42 @@
   say M here and read <file:Documentation/modules.txt>.  This is
   recommended.  The module will be called dl2k.o.
 
+CONFIG_E1000
+  This driver supports Intel(R) PRO/1000 gigabit ethernet family of
+  adapters, which includes:
+
+     Controller  Adapter Name                     Board IDs
+     ----------  ------------                     ---------
+     82542       PRO/1000 Gigabit Server Adapter  700262-xxx,
+                                                  717037-xxx
+     82543       PRO/1000 F Server Adapter        738640-xxx,
+                                                  A38888-xxx,
+                                                  A06512-xxx
+     82543       PRO/1000 T Server Adapter        A19845-xxx,
+                                                  A33948-xxx
+     82544       PRO/1000 XT Server Adapter       A51580-xxx
+     82544       PRO/1000 XF Server Adapter       A50484-xxx
+     82544       PRO/1000 T Desktop Adapter       A62947-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/e1000.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 e1000.o.  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_LANCE
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -817,6 +863,10 @@
   say M here and read <file:Documentation/modules.txt>.  This is
   recommended.  The module will be called lance.o.
 
+CONFIG_MIPS_AU1000_ENET
+  If you have an Alchemy Semi AU1000 ethernet controller
+  on an SGI MIPS system, say Y.  Otherwise, say N.
+
 CONFIG_SGI_IOC3_ETH
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -1290,6 +1340,24 @@
   module, say M here and read <file:Documentation/modules.txt> as well
   as <file:Documentation/networking/net-modules.txt>.
 
+CONFIG_DE2104X
+  This driver is developed for the SMC EtherPower series Ethernet
+  cards and also works with cards based on the DECchip
+  21040 (Tulip series) chips.  Some LinkSys PCI cards are
+  of this type.  (If your card is NOT SMC EtherPower 10/100 PCI
+  (smc9332dst), you can also try the driver for "Generic DECchip"
+  cards, above.  However, most people with a network card of this type
+  will say Y here.) Do read the Ethernet-HOWTO, available from
+  <http://www.linuxdoc.org/docs.html#howto>.  More specific
+  information is contained in
+  <file:Documentation/DocBook/tulip-user.tmpl>.
+
+  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 tulip.o.  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_TULIP
   This driver is developed for the SMC EtherPower series Ethernet
   cards and also works with cards based on the DECchip 
@@ -1308,6 +1376,20 @@
   module, say M here and read <file:Documentation/modules.txt> as well
   as <file:Documentation/networking/net-modules.txt>.
 
+CONFIG_TULIP_MWI
+  This configures your Tulip card specifically for the card and
+  system cache line size type you are using.
+
+  This is experimental code, not yet tested on many boards.
+
+  If unsure, say N.
+
+CONFIG_TULIP_MMIO
+  Use PCI shared memory for the NIC registers, rather than going through
+  the Tulip's PIO (programmed I/O ports).  Faster, but could produce
+  obscure bugs if your mainboard has memory controller timing issues.
+  If in doubt, say N.
+
 CONFIG_DGRS
   This is support for the Digi International RightSwitch series of
   PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6
@@ -1338,6 +1420,11 @@
   cards. Specifications and data at
   <http://www.myson.com.hk/mtd/datasheet/>.
 
+CONFIG_LP486E
+  Say Y here to support the 82596-based on-board Ethernet controller
+  for the Panther motherboard, which is one of the two shipped in the
+  Intel Professional Workstation.
+
 CONFIG_ETH16I
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -1376,6 +1463,16 @@
   The module will be called via-rhine.o.  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_VIA_RHINE_MMIO
+  This instructs the driver to use PCI shared memory (MMIO) instead of
+  programmed I/O ports (PIO). Enabling this gives an improvement in
+  processing time in parts of the driver.
+
+  It is not known if this works reliably on all "rhine" based cards,
+  but it has been tested successfully on some DFE-530TX adapters.
+
+  If unsure, say N.
 
 CONFIG_DM9102
   This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
diff -Nru a/drivers/net/Config.in b/drivers/net/Config.in
--- a/drivers/net/Config.in	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/Config.in	Tue Feb 26 11:57:56 2002
@@ -231,6 +231,7 @@
    bool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I
 fi
 dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI
+dep_tristate 'Intel(R) PRO/1000 Gigabit Ethernet support' CONFIG_E1000 $CONFIG_PCI
 dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS
 dep_tristate 'National Semiconduct DP83820 support' CONFIG_NS83820 $CONFIG_PCI
 dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/Makefile	Tue Feb 26 11:57:58 2002
@@ -25,6 +25,10 @@
   obj-y += tulip/tulip.o
 endif
 
+ifeq ($(CONFIG_E1000),y)
+  obj-y += e1000/e1000.o
+endif
+
 ifeq ($(CONFIG_ISDN_PPP),y)
   obj-$(CONFIG_ISDN) += slhc.o
 endif
@@ -32,6 +36,7 @@
 subdir-$(CONFIG_NET_PCMCIA) += pcmcia
 subdir-$(CONFIG_NET_WIRELESS) += wireless
 subdir-$(CONFIG_TULIP) += tulip
+subdir-$(CONFIG_E1000) += e1000
 subdir-$(CONFIG_IRDA) += irda
 subdir-$(CONFIG_TR) += tokenring
 subdir-$(CONFIG_WAN) += wan
diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
--- a/drivers/net/arcnet/com20020-pci.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/arcnet/com20020-pci.c	Tue Feb 26 11:57:57 2002
@@ -160,7 +160,7 @@
 	name:		"com20020",
 	id_table:	com20020pci_id_table,
 	probe:		com20020pci_probe,
-	remove:		com20020pci_remove
+	remove:		__devexit_p(com20020pci_remove)
 };
 
 static int __init com20020pci_init(void)
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/defxx.c	Tue Feb 26 11:57:56 2002
@@ -3362,7 +3362,7 @@
 static struct pci_driver dfx_driver = {
 	name:		"defxx",
 	probe:		dfx_init_one,
-	remove:		dfx_remove_one,
+	remove:		__devexit_p(dfx_remove_one),
 	id_table:	dfx_pci_tbl,
 };
 
diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c
--- a/drivers/net/dl2k.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/dl2k.c	Tue Feb 26 11:57:59 2002
@@ -1682,7 +1682,7 @@
 	name:"dl2k",
 	id_table:rio_pci_tbl,
 	probe:rio_probe1,
-	remove:rio_remove1,
+	remove: __devexit_p(rio_remove1),
 };
 
 static int __init
diff -Nru a/drivers/net/e1000/LICENSE b/drivers/net/e1000/LICENSE
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/LICENSE	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,69 @@
+This software program is available to you under a choice of one of two
+licenses. You may choose to be licensed under either the GNU General Public
+License (GPL) Version 2, June 1991, available at
+http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the
+Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which
+are necessarily infringed by the use of sale of the Software alone or when
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to
+any operating system available under the GNU Public License version 2.0 or
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or
+without modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code of the Software may retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above
+copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors
+shall be used to endorse or promote products derived from this Software
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell, offer
+to sell, import and otherwise transfer the Software, if any, in source code
+and object code form. This license shall include changes to the Software
+that are error corrections or other minor changes to the Software that do
+not add functionality or features when the Software is incorporated in any
+version of an operating system that has been distributed under the GNU
+General Public License 2.0 or later. This patent license shall apply to the
+combination of the Software and any operating system licensed under the GNU
+Public License version 2.0 or later if, at the time Intel provides the
+Software to Recipient, such addition of the Software to the then publicly
+available versions of such operating systems available under the GNU Public
+License version 2.0 or later (whether in gold, beta or alpha form) causes
+such combination to be covered by the Licensed Patents. The patent license
+shall not apply to any other combinations which include the Software. NO
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -Nru a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/Makefile	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,16 @@
+#
+# Makefile for the Intel(R) PRO/1000 ethernet driver
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := e1000.o
+
+obj-y   := e1000_main.o e1000_mac.o e1000_phy.o \
+           e1000_ethtool.o e1000_param.o e1000_proc.o
+obj-m   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,233 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+/* Linux PRO/1000 Ethernet Driver main header file */
+
+#ifndef _E1000_H_
+#define _E1000_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/mm.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pagemap.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/capability.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 <asm/uaccess.h>
+
+struct e1000_adapter;
+
+#include "e1000_mac.h"
+#include "e1000_phy.h"
+
+#define BAR_0 0
+
+/* Advertise that we can DMA from any address location */
+#define E1000_DMA_MASK (~0x0UL)
+
+#if DBG
+#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
+#else
+#define E1000_DBG(args...)
+#endif
+
+#define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
+
+#ifdef CONFIG_PPC
+#define E1000_MAX_INTR 1
+#else
+#define E1000_MAX_INTR 10
+#endif
+
+/* Supported Rx Buffer Sizes */
+#define E1000_RXBUFFER_2048  2048
+#define E1000_RXBUFFER_4096  4096
+#define E1000_RXBUFFER_8192  8192
+#define E1000_RXBUFFER_16384 16384
+
+/* How many Tx Descriptors do we need to call netif_wake_queue ? */
+#define E1000_TX_QUEUE_WAKE 16
+
+#define E1000_JUMBO_PBA      0x00000028
+#define E1000_DEFAULT_PBA    0x00000030
+
+/* only works for sizes that are powers of 2 */
+#define E1000_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 e1000_buffer {
+	struct sk_buff *skb;
+	uint64_t dma;
+	unsigned long length;
+};
+
+struct e1000_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;
+	/* (atomic) number of desc with no buffer */
+	atomic_t unused;
+	/* number of desc with no buffer */
+	unsigned int unused_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 e1000_buffer *buffer_info;
+};
+
+#define E1000_RX_DESC(ring, i) \
+	(&(((struct e1000_rx_desc *)((ring).desc))[i]))
+
+#define E1000_TX_DESC(ring, i) \
+	(&(((struct e1000_tx_desc *)((ring).desc))[i]))
+
+#define E1000_CONTEXT_DESC(ring, i) \
+	(&(((struct e1000_context_desc *)((ring).desc))[i]))
+
+/* board specific private data structure */
+
+struct e1000_adapter {
+	struct timer_list watchdog_timer;
+	struct timer_list phy_info_timer;
+#ifdef CONFIG_PROC_FS
+	struct list_head proc_list_head;
+#endif
+	char *id_string;
+	uint32_t bd_number;
+	uint32_t rx_buffer_len;
+	uint32_t part_num;
+	uint32_t wol;
+	uint16_t link_speed;
+	uint16_t link_duplex;
+	spinlock_t stats_lock;
+	atomic_t irq_sem;
+	boolean_t rx_csum;
+
+	/* TX */
+	struct e1000_desc_ring tx_ring;
+	unsigned long trans_finish;
+	uint32_t tx_int_delay;
+	uint32_t txd_cmd;
+
+	/* RX */
+	struct e1000_desc_ring rx_ring;
+	uint64_t hw_csum_err;
+	uint64_t hw_csum_good;
+	uint32_t rx_int_delay;
+
+	/* OS defined structs */
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+
+	/* structs defined in e1000_mac.h or e1000_phy.h */
+	struct e1000_shared_adapter shared;
+	struct e1000_shared_stats stats;
+	struct e1000_phy_info phy_info;
+	struct e1000_phy_stats phy_stats;
+};
+
+#endif /* _E1000_H_ */
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_ethtool.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,377 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* ethtool support for e1000 */
+
+#include "e1000.h"
+
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+
+extern char e1000_driver_name[];
+extern char e1000_driver_version[];
+
+extern int e1000_up(struct e1000_adapter *adapter);
+extern void e1000_down(struct e1000_adapter *adapter);
+extern void e1000_enable_WOL(struct e1000_adapter *adapter);
+
+static void
+e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+
+	if(shared->media_type == e1000_media_type_copper) {
+
+		ecmd->supported = (SUPPORTED_10baseT_Half |
+		                   SUPPORTED_10baseT_Full |
+		                   SUPPORTED_100baseT_Half |
+		                   SUPPORTED_100baseT_Full |
+		                   SUPPORTED_1000baseT_Full|
+		                   SUPPORTED_Autoneg |
+		                   SUPPORTED_TP);
+
+		ecmd->advertising = ADVERTISED_TP;
+
+		if(shared->autoneg == 1) {
+			ecmd->advertising |= ADVERTISED_Autoneg;
+
+			/* the e1000 autoneg seems to match ethtool nicely */
+
+			ecmd->advertising |= shared->autoneg_advertised;
+		}
+
+		ecmd->port = PORT_TP;
+		ecmd->phy_address = shared->phy_addr;
+
+		if(shared->mac_type == e1000_82543)
+			ecmd->transceiver = XCVR_EXTERNAL;
+		else
+			ecmd->transceiver = XCVR_INTERNAL;
+
+	} else {
+		ecmd->supported   = (SUPPORTED_1000baseT_Full |
+				     SUPPORTED_FIBRE |
+				     SUPPORTED_Autoneg);
+
+		ecmd->advertising = (SUPPORTED_1000baseT_Full |
+				     SUPPORTED_FIBRE |
+				     SUPPORTED_Autoneg);
+
+		ecmd->port = PORT_FIBRE;
+
+		ecmd->transceiver = XCVR_EXTERNAL;
+	}
+
+	if(netif_carrier_ok(adapter->netdev)) {
+
+		e1000_get_speed_and_duplex(shared, &adapter->link_speed,
+		                                   &adapter->link_duplex);
+		ecmd->speed = adapter->link_speed;
+
+		/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
+		 *          and HALF_DUPLEX != DUPLEX_HALF */
+
+		if(adapter->link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = (shared->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+	return;
+}
+
+static int
+e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+
+	if(ecmd->autoneg == AUTONEG_ENABLE) {
+		shared->autoneg = 1;
+		shared->autoneg_advertised = (ecmd->advertising & 0x002F);
+	} else {
+		shared->autoneg = 0;
+		switch(ecmd->speed + ecmd->duplex) {
+		case SPEED_10 + DUPLEX_HALF:
+			shared->forced_speed_duplex = e1000_10_half;
+			break;
+		case SPEED_10 + DUPLEX_FULL:
+			shared->forced_speed_duplex = e1000_10_full;
+			break;
+		case SPEED_100 + DUPLEX_HALF:
+			shared->forced_speed_duplex = e1000_100_half;
+			break;
+		case SPEED_100 + DUPLEX_FULL:
+			shared->forced_speed_duplex = e1000_100_full;
+			break;
+		case SPEED_1000 + DUPLEX_FULL:
+			shared->autoneg = 1;
+			shared->autoneg_advertised = ADVERTISE_1000_FULL;
+			break;
+		case SPEED_1000 + DUPLEX_HALF: /* not supported */
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/* reset the link */
+
+	e1000_down(adapter);
+	e1000_up(adapter);
+
+	return 0;
+}
+
+static inline int
+e1000_eeprom_size(struct e1000_shared_adapter *shared)
+{
+	return 128;
+}
+
+static void
+e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
+                       struct ethtool_drvinfo *drvinfo)
+{
+	strncpy(drvinfo->driver,  e1000_driver_name, 32);
+	strncpy(drvinfo->version, e1000_driver_version, 32);
+	strncpy(drvinfo->fw_version, "", 32);
+	strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
+	drvinfo->eedump_len  = e1000_eeprom_size(&adapter->shared);
+	return;
+}
+
+static void
+e1000_ethtool_geeprom(struct e1000_adapter *adapter,
+                      struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	int i, max_len;
+
+	eeprom->magic = shared->vendor_id | (shared->device_id << 16);
+
+	max_len = e1000_eeprom_size(shared);
+
+	if ((eeprom->offset + eeprom->len) > max_len)
+		eeprom->len = (max_len - eeprom->offset);
+
+	for(i = 0; i < max_len; i++)
+		eeprom_buff[i] = e1000_read_eeprom(&adapter->shared, i);
+
+	return;
+}
+
+static void
+e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	
+	if(shared->mac_type < e1000_82544) {
+		wol->supported = 0;
+		wol->wolopts   = 0;
+		return;
+	}
+
+	wol->supported = WAKE_PHY | WAKE_UCAST | 
+	                 WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+	
+	wol->wolopts = 0;
+	if(adapter->wol & E1000_WUFC_LNKC)
+		wol->wolopts |= WAKE_PHY;
+	if(adapter->wol & E1000_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if(adapter->wol & E1000_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if(adapter->wol & E1000_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if(adapter->wol & E1000_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+
+	return;
+}
+
+static int
+e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+
+	if(shared->mac_type < e1000_82544)
+		return wol->wolopts == 0 ? 0 : -EOPNOTSUPP;
+
+	adapter->wol = 0;
+
+	if(wol->wolopts & WAKE_PHY)
+		adapter->wol |= E1000_WUFC_LNKC;
+	if(wol->wolopts & WAKE_UCAST)
+		adapter->wol |= E1000_WUFC_EX;
+	if(wol->wolopts & WAKE_MCAST)
+		adapter->wol |= E1000_WUFC_MC;
+	if(wol->wolopts & WAKE_BCAST)
+		adapter->wol |= E1000_WUFC_BC;
+	if(wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= E1000_WUFC_MAG;
+
+	e1000_enable_WOL(adapter);
+	return 0;
+}
+
+int
+e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	void *addr = ifr->ifr_data;
+	uint32_t cmd;
+
+	if(get_user(cmd, (uint32_t *) addr))
+		return -EFAULT;
+
+	switch(cmd) {
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = {ETHTOOL_GSET};
+		e1000_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 e1000_ethtool_sset(adapter, &ecmd);
+	}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO};
+		e1000_ethtool_gdrvinfo(adapter, &drvinfo);
+		if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_NWAY_RST: {
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		e1000_down(adapter);
+		e1000_up(adapter);
+		return 0;
+	}
+	case ETHTOOL_GLINK: {
+		struct ethtool_value link = {ETHTOOL_GLINK};
+		link.data = netif_carrier_ok(netdev);
+		if(copy_to_user(addr, &link, sizeof(link)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GWOL: {
+		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
+		e1000_ethtool_gwol(adapter, &wol);
+		if(copy_to_user(addr, &wol, sizeof(wol)) != 0)
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SWOL: {
+		struct ethtool_wolinfo wol;
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
+			return -EFAULT;
+		return e1000_ethtool_swol(adapter, &wol);
+	}
+	case ETHTOOL_GEEPROM: {
+		struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
+		uint16_t eeprom_buff[256];
+
+		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
+			return -EFAULT;
+
+		e1000_ethtool_geeprom(adapter, &eeprom, eeprom_buff);
+
+		if(copy_to_user(addr, &eeprom, sizeof(eeprom)))
+			return -EFAULT;
+
+		addr += offsetof(struct ethtool_eeprom, data);
+
+		if(copy_to_user(addr, eeprom_buff + eeprom.offset, eeprom.len))
+			return -EFAULT;
+		return 0;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
diff -Nru a/drivers/net/e1000/e1000_mac.c b/drivers/net/e1000/e1000_mac.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_mac.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1821 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_mac.c
+ * Shared functions for accessing and configuring the MAC
+ */
+
+#include "e1000_mac.h"
+#include "e1000_phy.h"
+
+/******************************************************************************
+ * Raises the EEPROM's clock input.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+e1000_raise_clock(struct e1000_shared_adapter *shared,
+                  uint32_t *eecd_reg)
+{
+    /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+     * wait 50 microseconds.
+     */
+    *eecd_reg = *eecd_reg | E1000_EECD_SK;
+    E1000_WRITE_REG(shared, EECD, *eecd_reg);
+    usec_delay(50);
+    return;
+}
+
+/******************************************************************************
+ * Lowers the EEPROM's clock input.
+ *
+ * shared - Struct containing variables accessed by shared code 
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+e1000_lower_clock(struct e1000_shared_adapter *shared,
+                  uint32_t *eecd_reg)
+{
+    /* Lower the clock input to the EEPROM (by clearing the SK bit), and then 
+     * wait 50 microseconds. 
+     */
+    *eecd_reg = *eecd_reg & ~E1000_EECD_SK;
+    E1000_WRITE_REG(shared, EECD, *eecd_reg);
+    usec_delay(50);
+    return;
+}
+
+/******************************************************************************
+ * Shift data bits out to the EEPROM.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * data - data to send to the EEPROM
+ * count - number of bits to shift out
+ *****************************************************************************/
+static void
+e1000_shift_out_bits(struct e1000_shared_adapter *shared,
+                     uint16_t data,
+                     uint16_t count)
+{
+    uint32_t eecd_reg;
+    uint32_t 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 = E1000_READ_REG(shared, EECD);
+    eecd_reg &= ~(E1000_EECD_DO | E1000_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 &= ~E1000_EECD_DI;
+
+        if(data & mask)
+            eecd_reg |= E1000_EECD_DI;
+
+        E1000_WRITE_REG(shared, EECD, eecd_reg);
+
+        usec_delay(50);
+
+        e1000_raise_clock(shared, &eecd_reg);
+        e1000_lower_clock(shared, &eecd_reg);
+
+        mask = mask >> 1;
+
+    } while(mask);
+
+    /* We leave the "DI" bit set to "0" when we leave this routine. */
+    eecd_reg &= ~E1000_EECD_DI;
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    return;
+}
+
+/******************************************************************************
+ * Shift data bits in from the EEPROM
+ *
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static uint16_t
+e1000_shift_in_bits(struct e1000_shared_adapter *shared)
+{
+    uint32_t eecd_reg;
+    uint32_t i;
+    uint16_t 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 = E1000_READ_REG(shared, EECD);
+
+    eecd_reg &= ~(E1000_EECD_DO | E1000_EECD_DI);
+    data = 0;
+
+    for(i = 0; i < 16; i++) {
+        data = data << 1;
+        e1000_raise_clock(shared, &eecd_reg);
+
+        eecd_reg = E1000_READ_REG(shared, EECD);
+
+        eecd_reg &= ~(E1000_EECD_DI);
+        if(eecd_reg & E1000_EECD_DO)
+            data |= 1;
+
+        e1000_lower_clock(shared, &eecd_reg);
+    }
+
+    return data;
+}
+
+/******************************************************************************
+ * Prepares EEPROM for access
+ *
+ * shared - 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
+e1000_setup_eeprom(struct e1000_shared_adapter *shared)
+{
+    uint32_t eecd_reg;
+
+    eecd_reg = E1000_READ_REG(shared, EECD);
+
+    /* Clear SK and DI */
+    eecd_reg &= ~(E1000_EECD_SK | E1000_EECD_DI);
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+
+    /* Set CS */
+    eecd_reg |= E1000_EECD_CS;
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    return;
+}
+
+/******************************************************************************
+ * Returns EEPROM to a "standby" state
+ * 
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+e1000_standby_eeprom(struct e1000_shared_adapter *shared)
+{
+    uint32_t eecd_reg;
+
+    eecd_reg = E1000_READ_REG(shared, EECD);
+
+    /* Deselct EEPROM */
+    eecd_reg &= ~(E1000_EECD_CS | E1000_EECD_SK);
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    usec_delay(50);
+
+    /* Clock high */
+    eecd_reg |= E1000_EECD_SK;
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    usec_delay(50);
+
+    /* Select EEPROM */
+    eecd_reg |= E1000_EECD_CS;
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    usec_delay(50);
+
+    /* Clock low */
+    eecd_reg &= ~E1000_EECD_SK;
+    E1000_WRITE_REG(shared, EECD, eecd_reg);
+    usec_delay(50);
+    return;
+}
+
+
+/******************************************************************************
+ * Forces the MAC's flow control settings.
+ * 
+ * shared - Struct containing variables accessed by shared code
+ *
+ * Sets the TFCE and RFCE bits in the device control register to reflect
+ * the adapter settings. TFCE and RFCE need to be explicitly set by
+ * software when a Copper PHY is used because autonegotiation is managed
+ * by the PHY rather than the MAC. Software must also configure these
+ * bits when link is forced on a fiber connection.
+ *****************************************************************************/
+static void
+e1000_force_mac_fc(struct e1000_shared_adapter *shared)
+{
+    uint32_t ctrl_reg;
+
+    DEBUGFUNC("e1000_force_mac_fc");
+
+    /* Get the current configuration of the Device Control Register */
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    /* Because we didn't get link via the internal auto-negotiation
+     * mechanism (we either forced link or we got link via PHY
+     * auto-neg), we have to manually enable/disable transmit an
+     * receive flow control.
+     *
+     * The "Case" statement below enables/disable flow control
+     * according to the "shared->fc" parameter.
+     *
+     * The possible values of the "fc" 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
+     *          frames but we do not receive pause frames).
+     *      3:  Both Rx and TX flow control (symmetric) is enabled.
+     *  other:  No other values should be possible at this point.
+     */
+
+    switch (shared->fc) {
+    case e1000_fc_none:
+        ctrl_reg &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+        break;
+    case e1000_fc_rx_pause:
+        ctrl_reg &= (~E1000_CTRL_TFCE);
+        ctrl_reg |= E1000_CTRL_RFCE;
+        break;
+    case e1000_fc_tx_pause:
+        ctrl_reg &= (~E1000_CTRL_RFCE);
+        ctrl_reg |= E1000_CTRL_TFCE;
+        break;
+    case e1000_fc_full:
+        ctrl_reg |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
+        break;
+    default:
+        DEBUGOUT("Flow control param set incorrectly\n");
+        ASSERT(0);
+        break;
+    }
+
+    /* Disable TX Flow Control for 82542 (rev 2.0) */
+    if(shared->mac_type == e1000_82542_rev2_0)
+        ctrl_reg &= (~E1000_CTRL_TFCE);
+
+
+    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+    return;
+}
+
+/******************************************************************************
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ *
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_adapter_stop(struct e1000_shared_adapter *shared)
+{
+    uint32_t ctrl_reg;
+    uint32_t ctrl_ext_reg;
+    uint32_t icr_reg;
+    uint16_t pci_cmd_word;
+
+    DEBUGFUNC("e1000_shared_adapter_stop");
+
+    /* If we are stopped or resetting exit gracefully and wait to be
+     * started again before accessing the hardware.
+     */
+    if(shared->adapter_stopped) {
+        DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+        return;
+    }
+
+    /* Set the Adapter Stopped flag so other driver functions stop
+     * touching the Hardware.
+     */
+    shared->adapter_stopped = TRUE;
+
+    /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
+    if(shared->mac_type == e1000_82542_rev2_0) {
+        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+
+            pci_cmd_word = shared->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
+
+            e1000_write_pci_cfg(shared, PCI_COMMAND_REGISTER, &pci_cmd_word);
+        }
+    }
+
+    /* Clear interrupt mask to stop board from generating interrupts */
+    DEBUGOUT("Masking off all interrupts\n");
+    E1000_WRITE_REG(shared, 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.
+     */
+    E1000_WRITE_REG(shared, RCTL, 0);
+    E1000_WRITE_REG(shared, TCTL, E1000_TCTL_PSP);
+
+    /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+    shared->tbi_compatibility_on = FALSE;
+
+    msec_delay(10);
+
+    /* 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 = E1000_READ_REG(shared, CTRL);
+    E1000_WRITE_REG(shared, CTRL, (ctrl_reg | E1000_CTRL_RST));
+
+    /* Delay a few ms just to allow the reset to complete */
+    msec_delay(10);
+
+#if DBG
+    /* Make sure the self-clearing global reset bit did self clear */
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    ASSERT(!(ctrl_reg & E1000_CTRL_RST));
+#endif
+
+    /* Force a reload from the EEPROM */
+    ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
+    ctrl_ext_reg |= E1000_CTRL_EXT_EE_RST;
+    E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
+    msec_delay(2);
+    
+    /* Clear interrupt mask to stop board from generating interrupts */
+    DEBUGOUT("Masking off all interrupts\n");
+    E1000_WRITE_REG(shared, IMC, 0xffffffff);
+
+    /* Clear any pending interrupt events. */
+    icr_reg = E1000_READ_REG(shared, ICR);
+
+    /* If MWI was previously enabled, reenable it. */
+    if(shared->mac_type == e1000_82542_rev2_0) {
+        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            e1000_write_pci_cfg(shared,
+                                PCI_COMMAND_REGISTER, &shared->pci_cmd_word);
+        }
+    }
+    return;
+}
+
+/******************************************************************************
+ * Performs basic configuration of the adapter.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * 
+ * Assumes that the controller has previously been reset and is in a 
+ * post-reset uninitialized state. Initializes the receive address registers,
+ * multicast table, and VLAN filter table. Calls routines to setup link
+ * configuration and flow control settings. Clears all on-chip counters. Leaves
+ * the transmit and receive units disabled and uninitialized.
+ *****************************************************************************/
+boolean_t
+e1000_init_hw(struct e1000_shared_adapter *shared)
+{
+    uint32_t status_reg;
+    uint32_t i;
+    uint16_t pci_cmd_word;
+    boolean_t status;
+
+    DEBUGFUNC("e1000_init_hw");
+
+    /* Set the Media Type and exit with error if it is not valid. */
+    if(shared->mac_type != e1000_82543) {
+        /* tbi_compatibility is only valid on 82543 */
+        shared->tbi_compatibility_en = FALSE;
+    }
+
+    if(shared->mac_type >= e1000_82543) {
+        status_reg = E1000_READ_REG(shared, STATUS);
+        if(status_reg & E1000_STATUS_TBIMODE) {
+            shared->media_type = e1000_media_type_fiber;
+            /* tbi_compatibility not valid on fiber */
+            shared->tbi_compatibility_en = FALSE;
+        } else {
+            shared->media_type = e1000_media_type_copper;
+        }
+    } else {
+        /* This is an 82542 (fiber only) */
+        shared->media_type = e1000_media_type_fiber;
+    }
+
+    /* Disabling VLAN filtering. */
+    DEBUGOUT("Initializing the IEEE VLAN\n");
+    E1000_WRITE_REG(shared, VET, 0);
+
+    e1000_clear_vfta(shared);
+
+    /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
+    if(shared->mac_type == e1000_82542_rev2_0) {
+        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+            pci_cmd_word = shared->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
+            e1000_write_pci_cfg(shared, PCI_COMMAND_REGISTER, &pci_cmd_word);
+        }
+        E1000_WRITE_REG(shared, RCTL, E1000_RCTL_RST);
+
+        msec_delay(5);
+    }
+
+    /* Setup the receive address. This involves initializing all of the Receive
+     * Address Registers (RARs 0 - 15).
+     */
+    e1000_init_rx_addrs(shared);
+
+    /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
+    if(shared->mac_type == e1000_82542_rev2_0) {
+        E1000_WRITE_REG(shared, RCTL, 0);
+
+        msec_delay(1);
+
+        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            e1000_write_pci_cfg(shared,
+                                PCI_COMMAND_REGISTER, &shared->pci_cmd_word);
+        }
+    }
+
+    /* Zero out the Multicast HASH table */
+    DEBUGOUT("Zeroing the MTA\n");
+    for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+        E1000_WRITE_REG_ARRAY(shared, MTA, i, 0);
+
+    /* Call a subroutine to configure the link and setup flow control. */
+    status = e1000_setup_fc_and_link(shared);
+
+    /* Clear all of the statistics registers (clear on read).  It is
+     * important that we do this after we have tried to establish link
+     * because the symbol error count will increment wildly if there
+     * is no link.
+     */
+    e1000_clear_hw_cntrs(shared);
+
+    return (status);
+}
+
+/******************************************************************************
+ * Initializes receive address filters.
+ *
+ * shared - 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
+e1000_init_rx_addrs(struct e1000_shared_adapter *shared)
+{
+    uint32_t i;
+    uint32_t addr_low;
+    uint32_t addr_high;
+
+    DEBUGFUNC("e1000_init_rx_addrs");
+
+    /* Setup the receive address. */
+    DEBUGOUT("Programming MAC Address into RAR[0]\n");
+    addr_low = (shared->mac_addr[0] |
+                (shared->mac_addr[1] << 8) |
+                (shared->mac_addr[2] << 16) | (shared->mac_addr[3] << 24));
+
+    addr_high = (shared->mac_addr[4] |
+                 (shared->mac_addr[5] << 8) | E1000_RAH_AV);
+
+    E1000_WRITE_REG_ARRAY(shared, RA, 0, addr_low);
+    E1000_WRITE_REG_ARRAY(shared, RA, 1, addr_high);
+
+    /* Zero out the other 15 receive addresses. */
+    DEBUGOUT("Clearing RAR[1-15]\n");
+    for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+        E1000_WRITE_REG_ARRAY(shared, RA, (i << 1), 0);
+        E1000_WRITE_REG_ARRAY(shared, RA, ((i << 1) + 1), 0);
+    }
+
+    return;
+}
+
+/******************************************************************************
+ * Updates the MAC's list of multicast addresses.
+ *
+ * shared - 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
+e1000_mc_addr_list_update(struct e1000_shared_adapter *shared,
+                          uint8_t *mc_addr_list,
+                          uint32_t mc_addr_count,
+                          uint32_t pad)
+{
+    uint32_t hash_value;
+    uint32_t i;
+    uint32_t rar_used_count = 1;        /* RAR[0] is used for our MAC address */
+
+    DEBUGFUNC("e1000_mc_addr_list_update");
+
+    /* Set the new number of MC addresses that we are being requested to use. */
+    shared->num_mc_addrs = mc_addr_count;
+
+    /* Clear RAR[1-15] */
+    DEBUGOUT(" Clearing RAR[1-15]\n");
+    for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) {
+        E1000_WRITE_REG_ARRAY(shared, RA, (i << 1), 0);
+        E1000_WRITE_REG_ARRAY(shared, RA, ((i << 1) + 1), 0);
+    }
+
+    /* Clear the MTA */
+    DEBUGOUT(" Clearing MTA\n");
+    for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) {
+        E1000_WRITE_REG_ARRAY(shared, 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 * (ETH_LENGTH_OF_ADDRESS + pad)],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 1],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 2],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 3],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 4],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 5]);
+
+        hash_value = e1000_hash_mc_addr(shared,
+                                        mc_addr_list +
+                                        (i * (ETH_LENGTH_OF_ADDRESS + pad)));
+
+        DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
+
+        /* Place this multicast address in the RAR if there is room, *
+         * else put it in the MTA            
+         */
+        if(rar_used_count < E1000_RAR_ENTRIES) {
+            e1000_rar_set(shared,
+                          mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
+                          rar_used_count);
+            rar_used_count++;
+        } else {
+            e1000_mta_set(shared, hash_value);
+        }
+    }
+
+    DEBUGOUT("MC Update Complete\n");
+    return;
+}
+
+/******************************************************************************
+ * Hashes an address to determine its location in the multicast table
+ *
+ * shared - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash 
+ *****************************************************************************/
+uint32_t
+e1000_hash_mc_addr(struct e1000_shared_adapter *shared,
+                   uint8_t *mc_addr)
+{
+    uint32_t hash_value = 0;
+
+    /* The portion of the address that is used for the hash table is
+     * determined by the mc_filter_type setting.  
+     */
+    switch (shared->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) | (((uint16_t) mc_addr[5]) << 4));
+        break;
+    case 1:                   /* [46:35] i.e. 0xAC6 for above example address */
+        hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
+        break;
+    case 2:                   /* [45:34] i.e. 0x5D8 for above example address */
+        hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+        break;
+    case 3:                   /* [43:32] i.e. 0x634 for above example address */
+        hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
+        break;
+    }
+
+    hash_value &= 0xFFF;
+    return (hash_value);
+}
+
+/******************************************************************************
+ * Sets the bit in the multicast table corresponding to the hash value.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ *****************************************************************************/
+void
+e1000_mta_set(struct e1000_shared_adapter *shared,
+              uint32_t hash_value)
+{
+    uint32_t hash_bit, hash_reg;
+    uint32_t mta_reg;
+    uint32_t temp;
+
+    /* 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 = E1000_READ_REG_ARRAY(shared, MTA, hash_reg);
+
+    mta_reg |= (1 << hash_bit);
+
+    /* If we are on an 82544 and we are trying to write an odd offset
+     * in the MTA, save off the previous entry before writing and
+     * restore the old value after writing.
+     */
+    if((shared->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
+        temp = E1000_READ_REG_ARRAY(shared, MTA, (hash_reg - 1));
+        E1000_WRITE_REG_ARRAY(shared, MTA, hash_reg, mta_reg);
+        E1000_WRITE_REG_ARRAY(shared, MTA, (hash_reg - 1), temp);
+    } else {
+        E1000_WRITE_REG_ARRAY(shared, MTA, hash_reg, mta_reg);
+    }
+    return;
+}
+
+/******************************************************************************
+ * Puts an ethernet address into a receive address register.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * addr - Address to put into receive address register
+ * index - Receive address register to write
+ *****************************************************************************/
+void
+e1000_rar_set(struct e1000_shared_adapter *shared,
+              uint8_t *addr,
+              uint32_t index)
+{
+    uint32_t rar_low, rar_high;
+
+    /* HW expects these in little endian so we reverse the byte order
+     * from network order (big endian) to little endian              
+     */
+    rar_low = ((uint32_t) addr[0] |
+               ((uint32_t) addr[1] << 8) |
+               ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+
+    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV);
+
+    E1000_WRITE_REG_ARRAY(shared, RA, (index << 1), rar_low);
+    E1000_WRITE_REG_ARRAY(shared, RA, ((index << 1) + 1), rar_high);
+    return;
+}
+
+/******************************************************************************
+ * Writes a value to the specified offset in the VLAN filter table.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * offset - Offset in VLAN filer table to write
+ * value - Value to write into VLAN filter table
+ *****************************************************************************/
+void
+e1000_write_vfta(struct e1000_shared_adapter *shared,
+                 uint32_t offset,
+                 uint32_t value)
+{
+    uint32_t temp;
+
+    if((shared->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
+        temp = E1000_READ_REG_ARRAY(shared, VFTA, (offset - 1));
+        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, value);
+        E1000_WRITE_REG_ARRAY(shared, VFTA, (offset - 1), temp);
+    } else {
+        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, value);
+    }
+    return;
+}
+
+/******************************************************************************
+ * Clears the VLAN filer table
+ *
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_clear_vfta(struct e1000_shared_adapter *shared)
+{
+    uint32_t offset;
+
+    for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
+        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, 0);
+    return;
+}
+
+/******************************************************************************
+ * Configures flow control and link settings.
+ * 
+ * shared - Struct containing variables accessed by shared code
+ * 
+ * Determines which flow control settings to use. Calls the apropriate media-
+ * specific link configuration function. Configures the flow control settings.
+ * Assuming the adapter has a valid link partner, a valid link should be
+ * established. Assumes the hardware has previously been reset and the 
+ * transmitter and receiver are not enabled.
+ *****************************************************************************/
+boolean_t
+e1000_setup_fc_and_link(struct e1000_shared_adapter *shared)
+{
+    uint32_t ctrl_reg;
+    uint32_t eecd_reg;
+    uint32_t ctrl_ext_reg;
+    boolean_t status = TRUE;
+
+    DEBUGFUNC("e1000_setup_fc_and_link");
+
+    /* Read the SWDPIO bits and the ILOS bit out of word 0x0A in the
+     * EEPROM.  Store these bits in a variable that we will later write
+     * to the Device Control Register (CTRL).
+     */
+    eecd_reg = e1000_read_eeprom(shared, EEPROM_INIT_CONTROL1_REG);
+
+    ctrl_reg =
+        (((eecd_reg & EEPROM_WORD0A_SWDPIO) << SWDPIO_SHIFT) |
+         ((eecd_reg & EEPROM_WORD0A_ILOS) << ILOS_SHIFT));
+
+    /* Set the PCI priority bit correctly in the CTRL register.  This
+     * determines if the adapter gives priority to receives, or if it
+     * gives equal priority to transmits and receives.
+     */
+    if(shared->dma_fairness)
+        ctrl_reg |= E1000_CTRL_PRIOR;
+
+    /* Read and store word 0x0F of the EEPROM. This word contains bits
+     * that determine the hardware's default PAUSE (flow control) mode,
+     * a bit that determines whether the HW defaults to enabling or
+     * disabling auto-negotiation, and the direction of the
+     * SW defined pins. If there is no SW over-ride of the flow
+     * control setting, then the variable shared->fc will
+     * be initialized based on a value in the EEPROM.
+     */
+    eecd_reg = e1000_read_eeprom(shared, EEPROM_INIT_CONTROL2_REG);
+
+    if(shared->fc > e1000_fc_full) {
+        if((eecd_reg & EEPROM_WORD0F_PAUSE_MASK) == 0)
+            shared->fc = e1000_fc_none;
+        else if((eecd_reg & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR)
+            shared->fc = e1000_fc_tx_pause;
+        else
+            shared->fc = e1000_fc_full;
+    }
+
+    /* We want to save off the original Flow Control configuration just
+     * in case we get disconnected and then reconnected into a different
+     * hub or switch with different Flow Control capabilities.
+     */
+    shared->original_fc = shared->fc;
+
+    if(shared->mac_type == e1000_82542_rev2_0)
+        shared->fc &= (~e1000_fc_tx_pause);
+
+    if((shared->mac_type < e1000_82543) && (shared->report_tx_early == 1))
+        shared->fc &= (~e1000_fc_rx_pause);
+
+    DEBUGOUT1("After fix-ups FlowControl is now = %x\n", shared->fc);
+
+    /* Take the 4 bits from EEPROM word 0x0F that determine the initial
+     * polarity value for the SW controlled pins, and setup the
+     * Extended Device Control reg with that info.
+     * This is needed because one of the SW controlled pins is used for
+     * signal detection.  So this should be done before e1000_setup_pcs_link()
+     * or e1000_phy_setup() is called.
+     */
+    if(shared->mac_type == e1000_82543) {
+        ctrl_ext_reg = ((eecd_reg & EEPROM_WORD0F_SWPDIO_EXT)
+                        << SWDPIO__EXT_SHIFT);
+        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
+    }
+
+    /* Call the necessary subroutine to configure the link. */
+    if(shared->media_type == e1000_media_type_fiber)
+        status = e1000_setup_pcs_link(shared, ctrl_reg);
+    else
+        status = e1000_phy_setup(shared, ctrl_reg);
+
+    /* Initialize the flow control address, type, and PAUSE timer
+     * registers to their default values.  This is done even if flow
+     * control is disabled, because it does not hurt anything to
+     * initialize these registers.
+     */
+    DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
+
+    E1000_WRITE_REG(shared, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+    E1000_WRITE_REG(shared, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+    E1000_WRITE_REG(shared, FCT, FLOW_CONTROL_TYPE);
+    E1000_WRITE_REG(shared, FCTTV, shared->fc_pause_time);
+
+    /* 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(!(shared->fc & e1000_fc_tx_pause)) {
+        E1000_WRITE_REG(shared, FCRTL, 0);
+        E1000_WRITE_REG(shared, 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(shared->fc_send_xon) {
+            E1000_WRITE_REG(shared, FCRTL,
+                            (shared->fc_low_water | E1000_FCRTL_XONE));
+            E1000_WRITE_REG(shared, FCRTH, shared->fc_high_water);
+        } else {
+            E1000_WRITE_REG(shared, FCRTL, shared->fc_low_water);
+            E1000_WRITE_REG(shared, FCRTH, shared->fc_high_water);
+        }
+    }
+    return (status);
+}
+
+/******************************************************************************
+ * Sets up link for a fiber based adapter
+ *
+ * shared - Struct containing variables accessed by shared code
+ * ctrl_reg - Current value of the device control register
+ *
+ * Manipulates Physical Coding Sublayer functions in order to configure
+ * link. Assumes the hardware has been previously reset and the transmitter
+ * and receiver are not enabled.
+ *****************************************************************************/
+boolean_t
+e1000_setup_pcs_link(struct e1000_shared_adapter *shared,
+                     uint32_t ctrl_reg)
+{
+    uint32_t status_reg;
+    uint32_t tctl_reg;
+    uint32_t txcw_reg = 0;
+    uint32_t i;
+
+    DEBUGFUNC("e1000_setup_pcs_link");
+
+    /* Setup the collsion distance.  Since this is configuring the
+     * TBI it is assumed that we are in Full Duplex.
+     */
+    tctl_reg = E1000_READ_REG(shared, TCTL);
+    i = E1000_FDX_COLLISION_DISTANCE;
+    i <<= E1000_COLD_SHIFT;
+    tctl_reg |= i;
+    E1000_WRITE_REG(shared, TCTL, tctl_reg);
+
+    /* Check for a software override of the flow control settings, and
+     * setup the device accordingly.  If auto-negotiation is enabled,
+     * then software will have to set the "PAUSE" bits to the correct
+     * value in the Tranmsit Config Word Register (TXCW) and re-start
+     * auto-negotiation.  However, if auto-negotiation is disabled,
+     * then software will have to manually configure the two flow
+     * control enable bits in the CTRL register.
+     *
+     * The possible values of the "fc" 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:  No software override.  The flow control configuration
+     *          in the EEPROM is used.
+     */
+    switch (shared->fc) {
+    case e1000_fc_none:        /* 0 */
+        /* Flow control (RX & TX) is completely disabled by a
+         * software over-ride.
+         */
+        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD);
+        break;
+    case e1000_fc_rx_pause:    /* 1 */
+        /* RX Flow control is enabled, and TX Flow control is
+         * disabled, by a software over-ride.
+         */
+        /* Since there really isn't a way to advertise that we are
+         * capable of RX Pause ONLY, we will advertise that we
+         * support both symmetric and asymmetric RX PAUSE.  Later
+         * we will disable the adapter's ability to send PAUSE
+         * frames.
+         */
+        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+        break;
+    case e1000_fc_tx_pause:    /* 2 */
+        /* TX Flow control is enabled, and RX Flow control is
+         * disabled, by a software over-ride.
+         */
+        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+        break;
+    case e1000_fc_full:        /* 3 */
+        /* Flow control (both RX and TX) is enabled by a software
+         * over-ride.
+         */
+        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+        break;
+    default:
+        /* We should never get here.  The value should be 0-3. */
+        DEBUGOUT("Flow control param set incorrectly\n");
+        ASSERT(0);
+        break;
+    }
+
+    /* Since auto-negotiation is enabled, take the link out of reset.
+     * (the link will be in reset, because we previously reset the
+     * chip). This will restart auto-negotiation.  If auto-neogtiation
+     * is successful then the link-up status bit will be set and the
+     * flow control enable bits (RFCE and TFCE) will be set according
+     * to their negotiated value.
+     */
+    DEBUGOUT("Auto-negotiation enabled\n");
+
+    E1000_WRITE_REG(shared, TXCW, txcw_reg);
+    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+    shared->txcw_reg = txcw_reg;
+    msec_delay(1);
+
+    /* If we have a signal then poll for a "Link-Up" indication in the
+     * Device Status Register.   Time-out if a link isn't seen in 500
+     * milliseconds seconds (Auto-negotiation should complete in less
+     * than 500 milliseconds even if the other end is doing it in SW).
+     */
+    if(!(E1000_READ_REG(shared, CTRL) & E1000_CTRL_SWDPIN1)) {
+
+        DEBUGOUT("Looking for Link\n");
+        for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
+            msec_delay(10);
+            status_reg = E1000_READ_REG(shared, STATUS);
+            if(status_reg & E1000_STATUS_LU)
+                break;
+        }
+
+        if(i == (LINK_UP_TIMEOUT / 10)) {
+            /* AutoNeg failed to achieve a link, so we'll call the
+             * "CheckForLink" routine.  This routine will force the link
+             * up if we have "signal-detect".  This will allow us to
+             * communicate with non-autonegotiating link partners.
+             */
+            DEBUGOUT("Never got a valid link from auto-neg!!!\n");
+
+            shared->autoneg_failed = 1;
+            e1000_check_for_link(shared);
+            shared->autoneg_failed = 0;
+        } else {
+            shared->autoneg_failed = 0;
+            DEBUGOUT("Valid Link Found\n");
+        }
+    } else {
+        DEBUGOUT("No Signal Detected\n");
+    }
+
+    return (TRUE);
+}
+
+/******************************************************************************
+ * Configures flow control settings after link is established
+ * 
+ * shared - Struct containing variables accessed by shared code
+ *
+ * Should be called immediately after a valid link has been established.
+ * Forces MAC flow control settings if link was forced. When in MII/GMII mode
+ * and autonegotiation is enabled, the MAC flow control settings will be set
+ * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+ * and RFCE bits will be automaticaly set to the negotiated flow control mode.
+ *****************************************************************************/
+void
+e1000_config_fc_after_link_up(struct e1000_shared_adapter *shared)
+{
+    uint16_t mii_status_reg;
+    uint16_t mii_nway_adv_reg;
+    uint16_t mii_nway_lp_ability_reg;
+    uint16_t speed;
+    uint16_t duplex;
+
+    DEBUGFUNC("e1000_config_fc_after_link_up");
+
+    /* Check for the case where we have fiber media and auto-neg failed
+     * so we had to force link.  In this case, we need to force the
+     * configuration of the MAC to match the "fc" parameter.
+     */
+    if(((shared->media_type == e1000_media_type_fiber)
+        && (shared->autoneg_failed))
+       || ((shared->media_type == e1000_media_type_copper)
+           && (!shared->autoneg))) {
+        e1000_force_mac_fc(shared);
+    }
+
+    /* Check for the case where we have copper media and auto-neg is
+     * enabled.  In this case, we need to check and see if Auto-Neg
+     * has completed, and if so, how the PHY and link partner has
+     * flow control configured.
+     */
+    if((shared->media_type == e1000_media_type_copper) && shared->autoneg) {
+        /* Read the MII Status Register and check to see if AutoNeg
+         * has completed.  We read this twice because this reg has
+         * some "sticky" (latched) bits.
+         */
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
+            /* The AutoNeg process has completed, so we now need to
+             * read both the Auto Negotiation Advertisement Register
+             * (Address 4) and the Auto_Negotiation Base Page Ability
+             * Register (Address 5) to determine how flow control was
+             * negotiated.
+             */
+            mii_nway_adv_reg = e1000_read_phy_reg(shared,
+                                                  PHY_AUTONEG_ADV);
+            mii_nway_lp_ability_reg = e1000_read_phy_reg(shared,
+                                                         PHY_LP_ABILITY);
+
+            /* Two bits in the Auto Negotiation Advertisement Register
+             * (Address 4) and two bits in the Auto Negotiation Base
+             * Page Ability Register (Address 5) determine flow control
+             * for both the PHY and the link partner.  The following
+             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+             * 1999, describes these PAUSE resolution bits and how flow
+             * control is determined based upon these settings.
+             * NOTE:  DC = Don't Care
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+             *-------|---------|-------|---------|--------------------
+             *   0   |    0    |  DC   |   DC    | e1000_fc_none
+             *   0   |    1    |   0   |   DC    | e1000_fc_none
+             *   0   |    1    |   1   |    0    | e1000_fc_none
+             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+             *   1   |    0    |   0   |   DC    | e1000_fc_none
+             *   1   |   DC    |   1   |   DC    | e1000_fc_full
+             *   1   |    1    |   0   |    0    | e1000_fc_none
+             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+             *
+             */
+            /* Are both PAUSE bits set to 1?  If so, this implies
+             * Symmetric Flow Control is enabled at both ends.  The
+             * ASM_DIR bits are irrelevant per the spec.
+             *
+             * For Symmetric Flow Control:
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   1   |   DC    |   1   |   DC    | e1000_fc_full
+             *
+             */
+            if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+               (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+                /* Now we need to check if the user selected RX ONLY
+                 * of pause frames.  In this case, we had to advertise
+                 * FULL flow control because we could not advertise RX
+                 * ONLY. Hence, we must now check to see if we need to
+                 * turn OFF  the TRANSMISSION of PAUSE frames.
+                 */
+                if(shared->original_fc == e1000_fc_full) {
+                    shared->fc = e1000_fc_full;
+                    DEBUGOUT("Flow Control = FULL.\r\n");
+                } else {
+                    shared->fc = e1000_fc_rx_pause;
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                }
+            }
+            /* For receiving PAUSE frames ONLY.
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+             *
+             */
+            else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                shared->fc = e1000_fc_tx_pause;
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+            }
+            /* For transmitting PAUSE frames ONLY.
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+             *
+             */
+            else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                    !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                shared->fc = e1000_fc_rx_pause;
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+            }
+            /* Per the IEEE spec, at this point flow control should be
+             * disabled.  However, we want to consider that we could
+             * be connected to a legacy switch that doesn't advertise
+             * desired flow control, but can be forced on the link
+             * partner.  So if we advertised no flow control, that is
+             * what we will resolve to.  If we advertised some kind of
+             * receive capability (Rx Pause Only or Full Flow Control)
+             * and the link partner advertised none, we will configure
+             * ourselves to enable Rx Flow Control only.  We can do
+             * this safely for two reasons:  If the link partner really
+             * didn't want flow control enabled, and we enable Rx, no
+             * harm done since we won't be receiving any PAUSE frames
+             * anyway.  If the intent on the link partner was to have
+             * flow control enabled, then by us enabling RX only, we
+             * can at least receive pause frames and process them.
+             * This is a good idea because in most cases, since we are
+             * predominantly a server NIC, more times than not we will
+             * be asked to delay transmission of packets than asking
+             * our link partner to pause transmission of frames.
+             */
+            else if(shared->original_fc == e1000_fc_none ||
+                    shared->original_fc == e1000_fc_tx_pause) {
+                shared->fc = e1000_fc_none;
+                DEBUGOUT("Flow Control = NONE.\r\n");
+            } else {
+                shared->fc = e1000_fc_rx_pause;
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+            }
+
+            /* Now we need to do one last check...  If we auto-
+             * negotiated to HALF DUPLEX, flow control should not be
+             * enabled per IEEE 802.3 spec.
+             */
+            e1000_get_speed_and_duplex(shared, &speed, &duplex);
+
+            if(duplex == HALF_DUPLEX)
+                shared->fc = e1000_fc_none;
+
+            /* Now we call a subroutine to actually force the MAC
+             * controller to use the correct flow control settings.
+             */
+            e1000_force_mac_fc(shared);
+        } else {
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+        }
+    }
+    return;  
+}
+
+/******************************************************************************
+ * Checks to see if the link status of the hardware has changed.
+ *
+ * shared - Struct containing variables accessed by shared code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+void
+e1000_check_for_link(struct e1000_shared_adapter *shared)
+{
+    uint32_t rxcw_reg;
+    uint32_t ctrl_reg;
+    uint32_t status_reg;
+    uint32_t rctl_reg;
+    uint16_t phy_data;
+    uint16_t lp_capability;
+
+    DEBUGFUNC("e1000_check_for_link");
+
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+    status_reg = E1000_READ_REG(shared, STATUS);
+    rxcw_reg = E1000_READ_REG(shared, RXCW);
+
+    /* If we have a copper PHY then we only want to go out to the PHY
+     * registers to see if Auto-Neg has completed and/or if our link
+     * status has changed.  The get_link_status flag will be set if we
+     * receive a Link Status Change interrupt or we have Rx Sequence
+     * Errors.
+     */
+    if(shared->media_type == e1000_media_type_copper
+       && shared->get_link_status) {
+        /* First we want to see if the MII Status Register reports
+         * link.  If so, then we want to get the current speed/duplex
+         * of the PHY.
+         * Read the register twice since the link bit is sticky.
+         */
+        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
+        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
+
+        if(phy_data & MII_SR_LINK_STATUS) {
+            shared->get_link_status = FALSE;
+        } else {
+            DEBUGOUT("**** CFL - No link detected. ****\r\n");
+            return;
+        }
+
+        /* If we are forcing speed/duplex, then we simply return since
+         * we have already determined whether we have link or not.
+         */
+        if(!shared->autoneg) {
+            return;
+        }
+
+        switch (shared->phy_id) {
+        case M88E1000_12_PHY_ID:
+        case M88E1000_14_PHY_ID:
+        case M88E1000_I_PHY_ID:
+            /* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+             * have Si on board that is 82544 or newer, Auto
+             * Speed Detection takes care of MAC speed/duplex
+             * configuration.  So we only need to configure Collision
+             * Distance in the MAC.  Otherwise, we need to force
+             * speed/duplex on the MAC to the current PHY speed/duplex
+             * settings.
+             */
+            if(shared->mac_type >= e1000_82544) {
+                DEBUGOUT("CFL - Auto-Neg complete.");
+                DEBUGOUT("Configuring Collision Distance.");
+                e1000_config_collision_dist(shared);
+            } else {
+                /* Read the Phy Specific Status register to get the
+                 * resolved speed/duplex settings.  Then call
+                 * e1000_config_mac_to_phy which will retrieve
+                 * PHY register information and configure the MAC to
+                 * equal the negotiated speed/duplex.
+                 */
+                phy_data = e1000_read_phy_reg(shared, 
+                                              M88E1000_PHY_SPEC_STATUS);
+
+                DEBUGOUT1("CFL - Auto-Neg complete.  phy_data = %x\r\n",
+                          phy_data);
+                e1000_config_mac_to_phy(shared, phy_data);
+            }
+
+            /* Configure Flow Control now that Auto-Neg has completed.
+             * We need to first restore the users desired Flow
+             * Control setting since we may have had to re-autoneg
+             * with a different link partner.
+             */
+            e1000_config_fc_after_link_up(shared);
+            break;
+
+        default:
+            DEBUGOUT("CFL - Invalid PHY detected.\r\n");
+
+        } /* end switch statement */
+
+        /* At this point we know that we are on copper, link is up, 
+         * and we are auto-neg'd.  These are pre-conditions for checking
+         * the link parter capabilities register.  We use the link partner
+         * capabilities to determine if TBI Compatibility needs to be turned on
+         * or turned off.  If the link partner advertises any speed in addition
+         * to Gigabit, then we assume that they are GMII-based and TBI 
+         * compatibility is not needed.
+         * If no other speeds are advertised, then we assume the link partner
+         * is TBI-based and we turn on TBI Compatibility.
+         */
+        if(shared->tbi_compatibility_en) {
+            lp_capability = e1000_read_phy_reg(shared, PHY_LP_ABILITY);
+            if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
+                                NWAY_LPAR_10T_FD_CAPS |
+                                NWAY_LPAR_100TX_HD_CAPS |
+                                NWAY_LPAR_100TX_FD_CAPS |
+                                NWAY_LPAR_100T4_CAPS)) {
+                /* If our link partner advertises below Gig, then they do not
+                 * need the special Tbi Compatibility mode. 
+                 */
+                if(shared->tbi_compatibility_on) {
+                    /* If we previously were in the mode, turn it off, now. */
+                    rctl_reg = E1000_READ_REG(shared, RCTL);
+                    rctl_reg &= ~E1000_RCTL_SBP;
+                    E1000_WRITE_REG(shared, RCTL, rctl_reg);
+                    shared->tbi_compatibility_on = FALSE;
+                }
+            } else {
+                /* If the mode is was previously off, turn it on. 
+                 * For compatibility with a suspected Tbi link partners, 
+                 * we will store bad packets.
+                 * (Certain frames have an additional byte on the end and will 
+                 * look like CRC errors to to the hardware).
+                 */
+                if(!shared->tbi_compatibility_on) {
+                    shared->tbi_compatibility_on = TRUE;
+                    rctl_reg = E1000_READ_REG(shared, RCTL);
+                    rctl_reg |= E1000_RCTL_SBP;
+                    E1000_WRITE_REG(shared, RCTL, rctl_reg);
+                }
+            }
+        }
+    } /* end if e1000_media_type_copper statement */
+    /* If we don't have link (auto-negotiation failed or link partner
+     * cannot auto-negotiate) and the cable is plugged in since we don't
+     * have Loss-Of-Signal (we HAVE a signal) and our link partner is
+     * not trying to AutoNeg with us (we are receiving idles/data
+     * then we need to force our link to connect to a non
+     * auto-negotiating link partner.  We also need to give
+     * auto-negotiation time to complete in case the cable was just
+     * plugged in.  The autoneg_failed flag does this.
+     */
+    else if((shared->media_type == e1000_media_type_fiber) &&  /* Fiber PHY */
+            (!(status_reg & E1000_STATUS_LU)) &&        /* no link and    */
+            (!(ctrl_reg & E1000_CTRL_SWDPIN1)) &&       /* we have signal */
+            (!(rxcw_reg & E1000_RXCW_C))) {     /* and rxing idle/data */
+        if(shared->autoneg_failed == 0) {      /* given AutoNeg time */
+            shared->autoneg_failed = 1;
+            return;
+        }
+
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+
+        /* Disable auto-negotiation in the TXCW register */
+        E1000_WRITE_REG(shared, TXCW, (shared->txcw_reg & ~E1000_TXCW_ANE));
+
+        /* Force link-up and also force full-duplex. */
+        ctrl_reg = E1000_READ_REG(shared, CTRL);
+        ctrl_reg |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+        /* Configure Flow Control after forcing link up. */
+        e1000_config_fc_after_link_up(shared);
+
+    } else if((shared->media_type == e1000_media_type_fiber) && /* Fiber */
+              (ctrl_reg & E1000_CTRL_SLU) &&    /* we have forced link */
+              (rxcw_reg & E1000_RXCW_C)) {      /* and Rxing /C/ ordered sets */
+        /* If we are forcing link and we are receiving /C/ ordered sets,
+         * then re-enable auto-negotiation in the RXCW register and
+         * disable forced link in the Device Control register in an attempt
+         * to AutoNeg with our link partner.
+         */
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+
+        /* Enable auto-negotiation in the TXCW register and stop
+         * forcing link.
+         */
+        E1000_WRITE_REG(shared, TXCW, shared->txcw_reg);
+
+        E1000_WRITE_REG(shared, CTRL, (ctrl_reg & ~E1000_CTRL_SLU));
+    }
+
+    return;
+}
+
+/******************************************************************************
+ * Clears all hardware statistics counters. 
+ *
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_clear_hw_cntrs(struct e1000_shared_adapter *shared)
+{
+    volatile uint32_t temp_reg;
+
+    DEBUGFUNC("e1000_clear_hw_cntrs");
+
+    /* if we are stopped or resetting exit gracefully */
+    if(shared->adapter_stopped) {
+        DEBUGOUT("Exiting because the adapter is stopped!!!\n");
+        return;
+    }
+
+    temp_reg = E1000_READ_REG(shared, CRCERRS);
+    temp_reg = E1000_READ_REG(shared, SYMERRS);
+    temp_reg = E1000_READ_REG(shared, MPC);
+    temp_reg = E1000_READ_REG(shared, SCC);
+    temp_reg = E1000_READ_REG(shared, ECOL);
+    temp_reg = E1000_READ_REG(shared, MCC);
+    temp_reg = E1000_READ_REG(shared, LATECOL);
+    temp_reg = E1000_READ_REG(shared, COLC);
+    temp_reg = E1000_READ_REG(shared, DC);
+    temp_reg = E1000_READ_REG(shared, SEC);
+    temp_reg = E1000_READ_REG(shared, RLEC);
+    temp_reg = E1000_READ_REG(shared, XONRXC);
+    temp_reg = E1000_READ_REG(shared, XONTXC);
+    temp_reg = E1000_READ_REG(shared, XOFFRXC);
+    temp_reg = E1000_READ_REG(shared, XOFFTXC);
+    temp_reg = E1000_READ_REG(shared, FCRUC);
+    temp_reg = E1000_READ_REG(shared, PRC64);
+    temp_reg = E1000_READ_REG(shared, PRC127);
+    temp_reg = E1000_READ_REG(shared, PRC255);
+    temp_reg = E1000_READ_REG(shared, PRC511);
+    temp_reg = E1000_READ_REG(shared, PRC1023);
+    temp_reg = E1000_READ_REG(shared, PRC1522);
+    temp_reg = E1000_READ_REG(shared, GPRC);
+    temp_reg = E1000_READ_REG(shared, BPRC);
+    temp_reg = E1000_READ_REG(shared, MPRC);
+    temp_reg = E1000_READ_REG(shared, GPTC);
+    temp_reg = E1000_READ_REG(shared, GORCL);
+    temp_reg = E1000_READ_REG(shared, GORCH);
+    temp_reg = E1000_READ_REG(shared, GOTCL);
+    temp_reg = E1000_READ_REG(shared, GOTCH);
+    temp_reg = E1000_READ_REG(shared, RNBC);
+    temp_reg = E1000_READ_REG(shared, RUC);
+    temp_reg = E1000_READ_REG(shared, RFC);
+    temp_reg = E1000_READ_REG(shared, ROC);
+    temp_reg = E1000_READ_REG(shared, RJC);
+    temp_reg = E1000_READ_REG(shared, TORL);
+    temp_reg = E1000_READ_REG(shared, TORH);
+    temp_reg = E1000_READ_REG(shared, TOTL);
+    temp_reg = E1000_READ_REG(shared, TOTH);
+    temp_reg = E1000_READ_REG(shared, TPR);
+    temp_reg = E1000_READ_REG(shared, TPT);
+    temp_reg = E1000_READ_REG(shared, PTC64);
+    temp_reg = E1000_READ_REG(shared, PTC127);
+    temp_reg = E1000_READ_REG(shared, PTC255);
+    temp_reg = E1000_READ_REG(shared, PTC511);
+    temp_reg = E1000_READ_REG(shared, PTC1023);
+    temp_reg = E1000_READ_REG(shared, PTC1522);
+    temp_reg = E1000_READ_REG(shared, MPTC);
+    temp_reg = E1000_READ_REG(shared, BPTC);
+
+    if(shared->mac_type < e1000_82543)
+        return;
+
+    temp_reg = E1000_READ_REG(shared, ALGNERRC);
+    temp_reg = E1000_READ_REG(shared, RXERRC);
+    temp_reg = E1000_READ_REG(shared, TNCRS);
+    temp_reg = E1000_READ_REG(shared, CEXTERR);
+    temp_reg = E1000_READ_REG(shared, TSCTC);
+    temp_reg = E1000_READ_REG(shared, TSCTFC);
+    return;
+}
+
+/******************************************************************************
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ *****************************************************************************/
+void
+e1000_get_speed_and_duplex(struct e1000_shared_adapter *shared,
+                           uint16_t *speed,
+                           uint16_t *duplex)
+{
+    uint32_t status_reg;
+#if DBG
+    uint16_t phy_data;
+#endif
+
+    DEBUGFUNC("e1000_get_speed_and_duplex");
+
+    /* If the adapter is stopped we don't have a speed or duplex */
+    if(shared->adapter_stopped) {
+        *speed = 0;
+        *duplex = 0;
+        return;
+    }
+
+    if(shared->mac_type >= e1000_82543) {
+        status_reg = E1000_READ_REG(shared, STATUS);
+        if(status_reg & E1000_STATUS_SPEED_1000) {
+            *speed = SPEED_1000;
+            DEBUGOUT("1000 Mbs, ");
+        } else if(status_reg & E1000_STATUS_SPEED_100) {
+            *speed = SPEED_100;
+            DEBUGOUT("100 Mbs, ");
+        } else {
+            *speed = SPEED_10;
+            DEBUGOUT("10 Mbs, ");
+        }
+
+        if(status_reg & E1000_STATUS_FD) {
+            *duplex = FULL_DUPLEX;
+            DEBUGOUT("Full Duplex\r\n");
+        } else {
+            *duplex = HALF_DUPLEX;
+            DEBUGOUT(" Half Duplex\r\n");
+        }
+    } else {
+        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        *speed = SPEED_1000;
+        *duplex = FULL_DUPLEX;
+    }
+
+#if DBG
+    if(shared->phy_id == M88E1000_12_PHY_ID ||
+       shared->phy_id == M88E1000_14_PHY_ID ||
+       shared->phy_id == M88E1000_I_PHY_ID) {
+        /* read the phy specific status register */
+        phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
+        DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", phy_data);
+        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
+        DEBUGOUT1("Phy MII Status Reg contents = %x\n", phy_data);
+        DEBUGOUT1("Device Status Reg contents = %x\n", 
+                  E1000_READ_REG(shared, STATUS));
+    }
+#endif
+    return;
+}
+
+/******************************************************************************
+ * Reads a 16 bit word from the EEPROM.
+ *
+ * shared - Struct containing variables accessed by shared code
+ * offset - offset of 16 bit word in the EEPROM to read
+ *****************************************************************************/
+uint16_t
+e1000_read_eeprom(struct e1000_shared_adapter *shared,
+                  uint16_t offset)
+{
+    uint16_t data;
+
+    /*  Prepare the EEPROM for reading  */
+    e1000_setup_eeprom(shared);
+
+    /*  Send the READ command (opcode + addr)  */
+    e1000_shift_out_bits(shared, EEPROM_READ_OPCODE, 3);
+    e1000_shift_out_bits(shared, offset, 6);
+
+    /* Read the data */
+    data = e1000_shift_in_bits(shared);
+
+    /* End this read operation */
+    e1000_standby_eeprom(shared);
+
+    return (data);
+}
+
+/******************************************************************************
+ * Verifies that the EEPROM has a valid checksum
+ * 
+ * shared - 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.
+ *****************************************************************************/
+boolean_t
+e1000_validate_eeprom_checksum(struct e1000_shared_adapter *shared)
+{
+    uint16_t checksum = 0;
+    uint16_t i;
+
+    for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+        checksum += e1000_read_eeprom(shared, i);
+
+    if(checksum == (uint16_t) EEPROM_SUM)
+        return (TRUE);
+    else
+        return (FALSE);
+}
+/******************************************************************************
+ * Reads the adapter's part number from the EEPROM
+ *
+ * shared - Struct containing variables accessed by shared code
+ * part_num - Adapter's part number
+ *****************************************************************************/
+boolean_t
+e1000_read_part_num(struct e1000_shared_adapter *shared,
+                    uint32_t *part_num)
+{
+    uint16_t eeprom_word;
+
+    DEBUGFUNC("e1000_read_part_num");
+
+    /* Don't read the EEPROM if we are stopped */
+    if(shared->adapter_stopped) {
+        *part_num = 0;
+        return (FALSE);
+    }
+
+    /* Get word 0 from EEPROM */
+    eeprom_word = e1000_read_eeprom(shared, (uint16_t) (EEPROM_PBA_BYTE_1));
+
+    DEBUGOUT("Read first part number word\n");
+
+    /* Save word 0 in upper half is PartNumber */
+    *part_num = (uint32_t) eeprom_word;
+    *part_num = *part_num << 16;
+
+    /* Get word 1 from EEPROM */
+    eeprom_word =
+        e1000_read_eeprom(shared, (uint16_t) (EEPROM_PBA_BYTE_1 + 1));
+
+    DEBUGOUT("Read second part number word\n");
+
+    /* Save word 1 in lower half of PartNumber */
+    *part_num |= eeprom_word;
+
+    /* read a valid part number */
+    return (TRUE);
+}
+
+void
+e1000_read_mac_addr(struct e1000_shared_adapter * shared)
+{
+    uint16_t temp, x;
+
+    for(x = 0; x < NODE_ADDRESS_SIZE; x += 2) {
+        temp = e1000_read_eeprom(shared, (uint16_t) 
+                                         (EEPROM_NODE_ADDRESS_BYTE_0 + (x/2)));
+        shared->perm_mac_addr[x] = (uint8_t) (temp & 0x00FF);
+        shared->perm_mac_addr[x+1] = (uint8_t) (temp >> 8);
+    }
+    
+    for(x = 0; x < NODE_ADDRESS_SIZE; x++)
+        shared->mac_addr[x] = shared->perm_mac_addr[x];
+}
+
+/******************************************************************************
+ * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
+ * 
+ * shared - Struct containing variables accessed by shared code
+ * frame_len - The length of the frame in question
+ * mac_addr - The Ethernet destination address of the frame in question
+ *****************************************************************************/
+uint32_t
+e1000_tbi_adjust_stats(struct e1000_shared_adapter *shared,
+                       struct e1000_shared_stats *stats,
+                       uint32_t frame_len,
+                       uint8_t *mac_addr)
+{
+    uint64_t carry_bit;
+
+    /* First adjust the frame length. */
+    frame_len--;
+    /* We need to adjust the statistics counters, since the hardware
+     * counters overcount this packet as a CRC error and undercount
+     * the packet as a good packet
+     */
+    /* This packet should not be counted as a CRC error.    */
+    stats->crcerrs--;
+    /* This packet does count as a Good Packet Received.    */
+    stats->gprc++;
+
+    /* Adjust the Good Octets received counters             */
+    carry_bit = 0x80000000 & stats->gorcl;
+    stats->gorcl += frame_len;
+    /* If the high bit of Gorcl (the low 32 bits of the Good Octets
+     * Received Count) was one before the addition, 
+     * AND it is zero after, then we lost the carry out, 
+     * need to add one to Gorch (Good Octets Received Count High).
+     * This could be simplified if all environments supported 
+     * 64-bit integers.
+     */
+    if(carry_bit && ((stats->gorcl & 0x80000000) == 0))
+        stats->gorch++;
+    /* Is this a broadcast or multicast?  Check broadcast first,
+     * since the test for a multicast frame will test positive on 
+     * a broadcast frame.
+     */
+    if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
+        /* Broadcast packet */
+        stats->bprc++;
+    else if(*mac_addr & 0x01)
+        /* Multicast packet */
+        stats->mprc++;
+
+    if(frame_len == shared->max_frame_size) {
+        /* In this case, the hardware has overcounted the number of
+         * oversize frames.
+         */
+        if(stats->roc > 0)
+            stats->roc--;
+    }
+
+    /* Adjust the bin counters when the extra byte put the frame in the
+     * wrong bin. Remember that the frame_len was adjusted above.
+     */
+    if(frame_len == 64) {
+        stats->prc64++;
+        stats->prc127--;
+    } else if(frame_len == 127) {
+        stats->prc127++;
+        stats->prc255--;
+    } else if(frame_len == 255) {
+        stats->prc255++;
+        stats->prc511--;
+    } else if(frame_len == 511) {
+        stats->prc511++;
+        stats->prc1023--;
+    } else if(frame_len == 1023) {
+        stats->prc1023++;
+        stats->prc1522--;
+    } else if(frame_len == 1522) {
+        stats->prc1522++;
+    }
+    return frame_len;
+}
+
+/******************************************************************************
+ * Gets the current PCI bus type, speed, and width of the hardware
+ *
+ * shared - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_get_bus_info(struct e1000_shared_adapter *shared)
+{
+    uint32_t status_reg;
+
+    if(shared->mac_type < e1000_82543) {
+        shared->bus_type = e1000_bus_type_unknown;
+        shared->bus_speed = e1000_bus_speed_unknown;
+        shared->bus_width = e1000_bus_width_unknown;
+        return;
+    }
+
+    status_reg = E1000_READ_REG(shared, STATUS);
+
+    shared->bus_type = (status_reg & E1000_STATUS_PCIX_MODE) ?
+        e1000_bus_type_pcix : e1000_bus_type_pci;
+
+    if(shared->bus_type == e1000_bus_type_pci) {
+        shared->bus_speed = (status_reg & E1000_STATUS_PCI66) ?
+            e1000_bus_speed_66 : e1000_bus_speed_33;
+    } else {
+        switch (status_reg & E1000_STATUS_PCIX_SPEED) {
+        case E1000_STATUS_PCIX_SPEED_66:
+            shared->bus_speed = e1000_bus_speed_66;
+            break;
+        case E1000_STATUS_PCIX_SPEED_100:
+            shared->bus_speed = e1000_bus_speed_100;
+            break;
+        case E1000_STATUS_PCIX_SPEED_133:
+            shared->bus_speed = e1000_bus_speed_133;
+            break;
+        default:
+            shared->bus_speed = e1000_bus_speed_reserved;
+            break;
+        }
+    }
+
+    shared->bus_width = (status_reg & E1000_STATUS_BUS64) ?
+        e1000_bus_width_64 : e1000_bus_width_32;
+
+    return;
+}
diff -Nru a/drivers/net/e1000/e1000_mac.h b/drivers/net/e1000/e1000_mac.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_mac.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1383 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_mac.h
+ * Structures, enums, and macros for the MAC
+ */
+
+#ifndef _E1000_MAC_H_
+#define _E1000_MAC_H_
+
+#include "e1000_osdep.h"
+
+/* Forward declarations of structures used by the shared code */
+struct e1000_shared_adapter;
+struct e1000_shared_stats;
+
+/* Enumerated types specific to the e1000 hardware */
+/* Media Access Controlers */
+typedef enum {
+    e1000_82542_rev2_0 = 0,
+    e1000_82542_rev2_1,
+    e1000_82543,
+    e1000_82544,
+    e1000_num_macs
+} e1000_mac_type;
+
+/* Media Types */
+typedef enum {
+    e1000_media_type_copper = 0,
+    e1000_media_type_fiber = 1,
+    e1000_num_media_types
+} e1000_media_type;
+
+typedef enum {
+    e1000_10_half = 0,
+    e1000_10_full = 1,
+    e1000_100_half = 2,
+    e1000_100_full = 3
+} e1000_speed_duplex_type;
+
+/* Flow Control Settings */
+typedef enum {
+    e1000_fc_none = 0,
+    e1000_fc_rx_pause = 1,
+    e1000_fc_tx_pause = 2,
+    e1000_fc_full = 3,
+    e1000_fc_default = 0xFF
+} e1000_fc_type;
+
+/* PCI bus types */
+typedef enum {
+    e1000_bus_type_unknown = 0,
+    e1000_bus_type_pci,
+    e1000_bus_type_pcix
+} e1000_bus_type;
+
+/* PCI bus speeds */
+typedef enum {
+    e1000_bus_speed_unknown = 0,
+    e1000_bus_speed_33,
+    e1000_bus_speed_66,
+    e1000_bus_speed_100,
+    e1000_bus_speed_133,
+    e1000_bus_speed_reserved
+} e1000_bus_speed;
+
+/* PCI bus widths */
+typedef enum {
+    e1000_bus_width_unknown = 0,
+    e1000_bus_width_32,
+    e1000_bus_width_64
+} e1000_bus_width;
+
+
+
+/* Function prototypes */
+/* Setup */
+void e1000_adapter_stop(struct e1000_shared_adapter *shared);
+boolean_t e1000_init_hw(struct e1000_shared_adapter *shared);
+void e1000_init_rx_addrs(struct e1000_shared_adapter *shared);
+
+/* Filters (multicast, vlan, receive) */
+void e1000_mc_addr_list_update(struct e1000_shared_adapter *shared, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad);
+uint32_t e1000_hash_mc_addr(struct e1000_shared_adapter *shared, uint8_t * mc_addr);
+void e1000_mta_set(struct e1000_shared_adapter *shared, uint32_t hash_value);
+void e1000_rar_set(struct e1000_shared_adapter *shared, uint8_t * mc_addr, uint32_t rar_index);
+void e1000_write_vfta(struct e1000_shared_adapter *shared, uint32_t offset, uint32_t value);
+void e1000_clear_vfta(struct e1000_shared_adapter *shared);
+
+/* Link layer setup functions */
+boolean_t e1000_setup_fc_and_link(struct e1000_shared_adapter *shared);
+boolean_t e1000_setup_pcs_link(struct e1000_shared_adapter *shared, uint32_t dev_ctrl_reg);
+void e1000_config_fc_after_link_up(struct e1000_shared_adapter *shared);
+void e1000_check_for_link(struct e1000_shared_adapter *shared);
+void e1000_get_speed_and_duplex(struct e1000_shared_adapter *shared, uint16_t * speed, uint16_t * duplex);
+
+/* EEPROM Functions */
+uint16_t e1000_read_eeprom(struct e1000_shared_adapter *shared, uint16_t reg);
+boolean_t e1000_validate_eeprom_checksum(struct e1000_shared_adapter *shared);
+
+/* Everything else */
+void e1000_clear_hw_cntrs(struct e1000_shared_adapter *shared);
+boolean_t e1000_read_part_num(struct e1000_shared_adapter *shared, uint32_t * part_num);
+void e1000_read_mac_addr(struct e1000_shared_adapter * shared);
+void e1000_get_bus_info(struct e1000_shared_adapter *shared);
+uint32_t e1000_tbi_adjust_stats(struct e1000_shared_adapter *shared, struct e1000_shared_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
+void e1000_write_pci_cfg(struct e1000_shared_adapter *shared, uint32_t reg, uint16_t * value);
+
+/* PCI Device IDs */
+#define E1000_DEV_ID_82542          0x1000
+#define E1000_DEV_ID_82543GC_FIBER  0x1001
+#define E1000_DEV_ID_82543GC_COPPER 0x1004
+#define E1000_DEV_ID_82544EI_COPPER 0x1008
+#define E1000_DEV_ID_82544EI_FIBER  0x1009
+#define E1000_DEV_ID_82544GC_COPPER 0x100C
+#define E1000_DEV_ID_82544GC_LOM    0x100D
+#define NUM_DEV_IDS 7
+
+#define NODE_ADDRESS_SIZE 6
+#define ETH_LENGTH_OF_ADDRESS 6
+
+/* MAC decode size is 128K - This is the size of BAR0 */
+#define MAC_DECODE_SIZE (128 * 1024)
+
+#define E1000_82542_2_0_REV_ID 2
+#define E1000_82542_2_1_REV_ID 3
+
+#define SPEED_10    10
+#define SPEED_100   100
+#define SPEED_1000  1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/* The sizes (in bytes) of a ethernet packet */
+#define ENET_HEADER_SIZE             14
+#define MAXIMUM_ETHERNET_PACKET_SIZE 1514 /* Without FCS */
+#define MINIMUM_ETHERNET_PACKET_SIZE 60   /* Without FCS */
+#define CRC_LENGTH                   4
+#define MAX_JUMBO_FRAME_SIZE         0x3F00
+
+
+/* 802.1q VLAN Packet Sizes */
+#define VLAN_TAG_SIZE                     4     /* 802.3ac tag (not DMAed) */
+
+/* Ethertype field values */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
+#define ETHERNET_IP_TYPE        0x0800  /* IP packets */
+#define ETHERNET_ARP_TYPE       0x0806  /* Address Resolution Protocol (ARP) */
+
+/* Packet Header defines */
+#define IP_PROTOCOL_TCP    6
+#define IP_PROTOCOL_UDP    0x11
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error 
+ */
+#define POLL_IMS_ENABLE_MASK ( \
+    E1000_IMS_RXDMT0 |         \
+    E1000_IMS_RXSEQ)
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXT0   = Receiver Timer Interrupt (ring 0)
+ *   o TXDW   = Transmit Descriptor Written Back
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ *   o LSC    = Link Status Change
+ */
+#define IMS_ENABLE_MASK ( \
+    E1000_IMS_RXT0   |    \
+    E1000_IMS_TXDW   |    \
+    E1000_IMS_RXDMT0 |    \
+    E1000_IMS_RXSEQ  |    \
+    E1000_IMS_LSC)
+
+/* The number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor. We
+ * reserve one of these spots for our directed address, allowing us room for
+ * E1000_RAR_ENTRIES - 1 multicast addresses. 
+ */
+#define E1000_RAR_ENTRIES 16
+
+#define MIN_NUMBER_OF_DESCRIPTORS 8
+#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
+
+/* Receive Descriptor */
+struct e1000_rx_desc {
+    uint64_t buffer_addr; /* Address of the descriptor's data buffer */
+    uint16_t length;     /* Length of data DMAed into data buffer */
+    uint16_t csum;       /* Packet checksum */
+    uint8_t status;      /* Descriptor status */
+    uint8_t errors;      /* Descriptor Errors */
+    uint16_t special;
+};
+
+/* Receive Decriptor bit definitions */
+#define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
+#define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
+#define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
+#define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS     0x40    /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF      0x80    /* passed in-exact filter */
+#define E1000_RXD_ERR_CE        0x01    /* CRC Error */
+#define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
+#define E1000_RXD_ERR_SEQ       0x04    /* Sequence Error */
+#define E1000_RXD_ERR_CXE       0x10    /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE      0x20    /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE       0x40    /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE       0x80    /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
+#define E1000_RXD_SPC_PRI_MASK  0xE000  /* Priority is in upper 3 bits */
+#define E1000_RXD_SPC_PRI_SHIFT 0x000D  /* Priority is in upper 3 of 16 */
+#define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 0x000C  /* CFI is bit 12 */
+
+/* mask to determine if packets should be dropped due to frame errors */
+#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
+    E1000_RXD_ERR_CE  |                \
+    E1000_RXD_ERR_SE  |                \
+    E1000_RXD_ERR_SEQ |                \
+    E1000_RXD_ERR_CXE |                \
+    E1000_RXD_ERR_RXE)
+
+/* Transmit Descriptor */
+struct e1000_tx_desc {
+    uint64_t buffer_addr;       /* Address of the descriptor's data buffer */
+    union {
+        uint32_t data;
+        struct {
+            uint16_t length;    /* Data buffer length */
+            uint8_t cso;        /* Checksum offset */
+            uint8_t cmd;        /* Descriptor control */
+        } flags;
+    } lower;
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t css;        /* Checksum start */
+            uint16_t special;
+        } fields;
+    } upper;
+};
+
+/* Transmit Descriptor bit definitions */
+#define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C     0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
+
+/* Offload Context Descriptor */
+struct e1000_context_desc {
+    union {
+        uint32_t ip_config;
+        struct {
+            uint8_t ipcss;      /* IP checksum start */
+            uint8_t ipcso;      /* IP checksum offset */
+            uint16_t ipcse;     /* IP checksum end */
+        } ip_fields;
+    } lower_setup;
+    union {
+        uint32_t tcp_config;
+        struct {
+            uint8_t tucss;      /* TCP checksum start */
+            uint8_t tucso;      /* TCP checksum offset */
+            uint16_t tucse;     /* TCP checksum end */
+        } tcp_fields;
+    } upper_setup;
+    uint32_t cmd_and_length;    /* */
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t hdr_len;    /* Header length */
+            uint16_t mss;       /* Maximum segment size */
+        } fields;
+    } tcp_seg_setup;
+};
+
+/* Offload data descriptor */
+struct e1000_data_desc {
+    uint64_t buffer_addr;       /* Address of the descriptor's buffer address */
+    union {
+        uint32_t data;
+        struct {
+            uint16_t length;    /* Data buffer length */
+            uint8_t typ_len_ext;        /* */
+            uint8_t cmd;        /* */
+        } flags;
+    } lower;
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t popts;      /* Packet Options */
+            uint16_t special;   /* */
+        } fields;
+    } upper;
+};
+
+/* Filters */
+#define E1000_NUM_UNICAST          16   /* Unicast filter entries */
+#define E1000_MC_TBL_SIZE          128  /* Multicast Filter Table (4096 bits) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
+
+
+/* Receive Address Register */
+struct e1000_rar {
+    volatile uint32_t low;      /* receive address low */
+    volatile uint32_t high;     /* receive address high */
+};
+
+/* The number of entries in the Multicast Table Array (MTA). */
+#define E1000_NUM_MTA_REGISTERS 128
+
+/* IPv4 Address Table Entry */
+struct e1000_ipv4_at_entry {
+    volatile uint32_t ipv4_addr;        /* IP Address (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Four wakeup IP addresses are supported */
+#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
+#define E1000_IP4AT_SIZE                  E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
+#define E1000_IP6AT_SIZE                  1
+
+/* IPv6 Address Table Entry */
+struct e1000_ipv6_at_entry {
+    volatile uint8_t ipv6_addr[16];
+};
+
+/* Flexible Filter Length Table Entry */
+struct e1000_fflt_entry {
+    volatile uint32_t length;   /* Flexible Filter Length (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Flexible Filter Mask Table Entry */
+struct e1000_ffmt_entry {
+    volatile uint32_t mask;     /* Flexible Filter Mask (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Flexible Filter Value Table Entry */
+struct e1000_ffvt_entry {
+    volatile uint32_t value;    /* Flexible Filter Value (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Four Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+
+/* Each Flexible Filter is at most 128 (0x80) bytes in length */
+#define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
+
+#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
+#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+
+/* Register Set. (82543, 82544)
+ *
+ * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
+ * These registers are physically located on the NIC, but are mapped into the 
+ * host memory address space.
+ *
+ * RW - register is both readable and writable
+ * RO - register is read only
+ * WO - register is write only
+ * R/clr - register is read only and is cleared when read
+ * A - register array
+ */
+#define E1000_CTRL     0x00000  /* Device Control - RW */
+#define E1000_STATUS   0x00008  /* Device Status - RO */
+#define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
+#define E1000_EERD     0x00014  /* EEPROM Read - RW */
+#define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
+#define E1000_MDIC     0x00020  /* MDI Control - RW */
+#define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
+#define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
+#define E1000_FCT      0x00030  /* Flow Control Type - RW */
+#define E1000_VET      0x00038  /* VLAN Ether Type - RW */
+#define E1000_ICR      0x000C0  /* Interrupt Cause Read - R/clr */
+#define E1000_ITR      0x000C4  /* Interrupt Throttling Rate - RW */
+#define E1000_ICS      0x000C8  /* Interrupt Cause Set - WO */
+#define E1000_IMS      0x000D0  /* Interrupt Mask Set - RW */
+#define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
+#define E1000_RCTL     0x00100  /* RX Control - RW */
+#define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
+#define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
+#define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
+#define E1000_TCTL     0x00400  /* TX Control - RW */
+#define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
+#define E1000_TBT      0x00448  /* TX Burst Timer - RW */
+#define E1000_LEDCTL   0x00E00  /* LED Control - RW */
+#define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
+#define E1000_FCRTL    0x02160  /* Flow Control Receive Threshold Low - RW */
+#define E1000_FCRTH    0x02168  /* Flow Control Receive Threshold High - RW */
+#define E1000_RDBAL    0x02800  /* RX Descriptor Base Address Low - RW */
+#define E1000_RDBAH    0x02804  /* RX Descriptor Base Address High - RW */
+#define E1000_RDLEN    0x02808  /* RX Descriptor Length - RW */
+#define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
+#define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
+#define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
+#define E1000_RXDCTL   0x02828  /* RX Descriptor Control - RW */
+#define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
+#define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
+#define E1000_TXDMAC   0x03000  /* TX DMA Control - RW */
+#define E1000_TDBAL    0x03800  /* TX Descriptor Base Address Low - RW */
+#define E1000_TDBAH    0x03804  /* TX Descriptor Base Address High - RW */
+#define E1000_TDLEN    0x03808  /* TX Descriptor Length - RW */
+#define E1000_TDH      0x03810  /* TX Descriptor Head - RW */
+#define E1000_TDT      0x03818  /* TX Descripotr Tail - RW */
+#define E1000_TIDV     0x03820  /* TX Interrupt Delay Value - RW */
+#define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
+#define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
+#define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
+#define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
+#define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
+#define E1000_RXERRC   0x0400C  /* Receive Error Count - R/clr */
+#define E1000_MPC      0x04010  /* Missed Packet Count - R/clr */
+#define E1000_SCC      0x04014  /* Single Collision Count - R/clr */
+#define E1000_ECOL     0x04018  /* Excessive Collision Count - R/clr */
+#define E1000_MCC      0x0401C  /* Multiple Collision Count - R/clr */
+#define E1000_LATECOL  0x04020  /* Late Collision Count - R/clr */
+#define E1000_COLC     0x04028  /* Collision Count - R/clr */
+#define E1000_DC       0x04030  /* Defer Count - R/clr */
+#define E1000_TNCRS    0x04034  /* TX-No CRS - R/clr */
+#define E1000_SEC      0x04038  /* Sequence Error Count - R/clr */
+#define E1000_CEXTERR  0x0403C  /* Carrier Extension Error Count - R/clr */
+#define E1000_RLEC     0x04040  /* Receive Length Error Count - R/clr */
+#define E1000_XONRXC   0x04048  /* XON RX Count - R/clr */
+#define E1000_XONTXC   0x0404C  /* XON TX Count - R/clr */
+#define E1000_XOFFRXC  0x04050  /* XOFF RX Count - R/clr */
+#define E1000_XOFFTXC  0x04054  /* XOFF TX Count - R/clr */
+#define E1000_FCRUC    0x04058  /* Flow Control RX Unsupported Count- R/clr */
+#define E1000_PRC64    0x0405C  /* Packets RX (64 bytes) - R/clr */
+#define E1000_PRC127   0x04060  /* Packets RX (65-127 bytes) - R/clr */
+#define E1000_PRC255   0x04064  /* Packets RX (128-255 bytes) - R/clr */
+#define E1000_PRC511   0x04068  /* Packets RX (255-511 bytes) - R/clr */
+#define E1000_PRC1023  0x0406C  /* Packets RX (512-1023 bytes) - R/clr */
+#define E1000_PRC1522  0x04070  /* Packets RX (1024-1522 bytes) - R/clr */
+#define E1000_GPRC     0x04074  /* Good Packets RX Count - R/clr */
+#define E1000_BPRC     0x04078  /* Broadcast Packets RX Count - R/clr */
+#define E1000_MPRC     0x0407C  /* Multicast Packets RX Count - R/clr */
+#define E1000_GPTC     0x04080  /* Good Packets TX Count - R/clr */
+#define E1000_GORCL    0x04088  /* Good Octets RX Count Low - R/clr */
+#define E1000_GORCH    0x0408C  /* Good Octets RX Count High - R/clr */
+#define E1000_GOTCL    0x04090  /* Good Octets TX Count Low - R/clr */
+#define E1000_GOTCH    0x04094  /* Good Octets TX Count High - R/clr */
+#define E1000_RNBC     0x040A0  /* RX No Buffers Count - R/clr */
+#define E1000_RUC      0x040A4  /* RX Undersize Count - R/clr */
+#define E1000_RFC      0x040A8  /* RX Fragment Count - R/clr */
+#define E1000_ROC      0x040AC  /* RX Oversize Count - R/clr */
+#define E1000_RJC      0x040B0  /* RX Jabber Count - R/clr */
+#define E1000_MGTPRC   0x040B4  /* Management Packets RX Count - R/clr */
+#define E1000_MGTPDC   0x040B8  /* Management Packets Dropped Count - R/clr */
+#define E1000_MGTPTC   0x040BC  /* Management Packets TX Count - R/clr */
+#define E1000_TORL     0x040C0  /* Total Octets RX Low - R/clr */
+#define E1000_TORH     0x040C4  /* Total Octets RX High - R/clr */
+#define E1000_TOTL     0x040C8  /* Total Octets TX Low - R/clr */
+#define E1000_TOTH     0x040CC  /* Total Octets TX High - R/clr */
+#define E1000_TPR      0x040D0  /* Total Packets RX - R/clr */
+#define E1000_TPT      0x040D4  /* Total Packets TX - R/clr */
+#define E1000_PTC64    0x040D8  /* Packets TX (64 bytes) - R/clr */
+#define E1000_PTC127   0x040DC  /* Packets TX (65-127 bytes) - R/clr */
+#define E1000_PTC255   0x040E0  /* Packets TX (128-255 bytes) - R/clr */
+#define E1000_PTC511   0x040E4  /* Packets TX (256-511 bytes) - R/clr */
+#define E1000_PTC1023  0x040E8  /* Packets TX (512-1023 bytes) - R/clr */
+#define E1000_PTC1522  0x040EC  /* Packets TX (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC     0x040F0  /* Multicast Packets TX Count - R/clr */
+#define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
+#define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
+#define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
+#define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
+#define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
+#define E1000_RA       0x05400  /* Receive Address - RW Array */
+#define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
+#define E1000_WUC      0x05800  /* Wakeup Control - RW */
+#define E1000_WUFC     0x05808  /* Wakeup Filter Control - RW */
+#define E1000_WUS      0x05810  /* Wakeup Status - RO */
+#define E1000_MANC     0x05820  /* Management Control - RW */
+#define E1000_IPAV     0x05838  /* IP Address Valid - RW */
+#define E1000_IP4AT    0x05840  /* IPv4 Address Table - RW Array */
+#define E1000_IP6AT    0x05880  /* IPv6 Address Table - RW Array */
+#define E1000_WUPL     0x05900  /* Wakeup Packet Length - RW */
+#define E1000_WUPM     0x05A00  /* Wakeup Packet Memory - RO A */
+#define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
+#define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
+#define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
+
+/* Register Set (82542)
+ *
+ * Some of the 82542 registers are located at different offsets than they are
+ * in more current versions of the 8254x. Despite the difference in location,
+ * the registers function in the same manner.
+ */
+#define E1000_82542_CTRL     E1000_CTRL
+#define E1000_82542_STATUS   E1000_STATUS
+#define E1000_82542_EECD     E1000_EECD
+#define E1000_82542_EERD     E1000_EERD
+#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
+#define E1000_82542_MDIC     E1000_MDIC
+#define E1000_82542_FCAL     E1000_FCAL
+#define E1000_82542_FCAH     E1000_FCAH
+#define E1000_82542_FCT      E1000_FCT
+#define E1000_82542_VET      E1000_VET
+#define E1000_82542_RA       0x00040
+#define E1000_82542_ICR      E1000_ICR
+#define E1000_82542_ITR      E1000_ITR
+#define E1000_82542_ICS      E1000_ICS
+#define E1000_82542_IMS      E1000_IMS
+#define E1000_82542_IMC      E1000_IMC
+#define E1000_82542_RCTL     E1000_RCTL
+#define E1000_82542_RDTR     0x00108
+#define E1000_82542_RDBAL    0x00110
+#define E1000_82542_RDBAH    0x00114
+#define E1000_82542_RDLEN    0x00118
+#define E1000_82542_RDH      0x00120
+#define E1000_82542_RDT      0x00128
+#define E1000_82542_FCRTH    0x00160
+#define E1000_82542_FCRTL    0x00168
+#define E1000_82542_FCTTV    E1000_FCTTV
+#define E1000_82542_TXCW     E1000_TXCW
+#define E1000_82542_RXCW     E1000_RXCW
+#define E1000_82542_MTA      0x00200
+#define E1000_82542_TCTL     E1000_TCTL
+#define E1000_82542_TIPG     E1000_TIPG
+#define E1000_82542_TDBAL    0x00420
+#define E1000_82542_TDBAH    0x00424
+#define E1000_82542_TDLEN    0x00428
+#define E1000_82542_TDH      0x00430
+#define E1000_82542_TDT      0x00438
+#define E1000_82542_TIDV     0x00440
+#define E1000_82542_TBT      E1000_TBT
+#define E1000_82542_VFTA     0x00600
+#define E1000_82542_LEDCTL   E1000_LEDCTL
+#define E1000_82542_PBA      E1000_PBA
+#define E1000_82542_RXDCTL   E1000_RXDCTL
+#define E1000_82542_RADV     E1000_RADV
+#define E1000_82542_RSRPD    E1000_RSRPD
+#define E1000_82542_TXDMAC   E1000_TXDMAC
+#define E1000_82542_TXDCTL   E1000_TXDCTL
+#define E1000_82542_TADV     E1000_TADV
+#define E1000_82542_TSPMT    E1000_TSPMT
+#define E1000_82542_CRCERRS  E1000_CRCERRS
+#define E1000_82542_ALGNERRC E1000_ALGNERRC
+#define E1000_82542_SYMERRS  E1000_SYMERRS
+#define E1000_82542_RXERRC   E1000_RXERRC
+#define E1000_82542_MPC      E1000_MPC
+#define E1000_82542_SCC      E1000_SCC
+#define E1000_82542_ECOL     E1000_ECOL
+#define E1000_82542_MCC      E1000_MCC
+#define E1000_82542_LATECOL  E1000_LATECOL
+#define E1000_82542_COLC     E1000_COLC
+#define E1000_82542_DC       E1000_DC
+#define E1000_82542_TNCRS    E1000_TNCRS
+#define E1000_82542_SEC      E1000_SEC
+#define E1000_82542_CEXTERR  E1000_CEXTERR
+#define E1000_82542_RLEC     E1000_RLEC
+#define E1000_82542_XONRXC   E1000_XONRXC
+#define E1000_82542_XONTXC   E1000_XONTXC
+#define E1000_82542_XOFFRXC  E1000_XOFFRXC
+#define E1000_82542_XOFFTXC  E1000_XOFFTXC
+#define E1000_82542_FCRUC    E1000_FCRUC
+#define E1000_82542_PRC64    E1000_PRC64
+#define E1000_82542_PRC127   E1000_PRC127
+#define E1000_82542_PRC255   E1000_PRC255
+#define E1000_82542_PRC511   E1000_PRC511
+#define E1000_82542_PRC1023  E1000_PRC1023
+#define E1000_82542_PRC1522  E1000_PRC1522
+#define E1000_82542_GPRC     E1000_GPRC
+#define E1000_82542_BPRC     E1000_BPRC
+#define E1000_82542_MPRC     E1000_MPRC
+#define E1000_82542_GPTC     E1000_GPTC
+#define E1000_82542_GORCL    E1000_GORCL
+#define E1000_82542_GORCH    E1000_GORCH
+#define E1000_82542_GOTCL    E1000_GOTCL
+#define E1000_82542_GOTCH    E1000_GOTCH
+#define E1000_82542_RNBC     E1000_RNBC
+#define E1000_82542_RUC      E1000_RUC
+#define E1000_82542_RFC      E1000_RFC
+#define E1000_82542_ROC      E1000_ROC
+#define E1000_82542_RJC      E1000_RJC
+#define E1000_82542_MGTPRC   E1000_MGTPRC
+#define E1000_82542_MGTPDC   E1000_MGTPDC
+#define E1000_82542_MGTPTC   E1000_MGTPTC
+#define E1000_82542_TORL     E1000_TORL
+#define E1000_82542_TORH     E1000_TORH
+#define E1000_82542_TOTL     E1000_TOTL
+#define E1000_82542_TOTH     E1000_TOTH
+#define E1000_82542_TPR      E1000_TPR
+#define E1000_82542_TPT      E1000_TPT
+#define E1000_82542_PTC64    E1000_PTC64
+#define E1000_82542_PTC127   E1000_PTC127
+#define E1000_82542_PTC255   E1000_PTC255
+#define E1000_82542_PTC511   E1000_PTC511
+#define E1000_82542_PTC1023  E1000_PTC1023
+#define E1000_82542_PTC1522  E1000_PTC1522
+#define E1000_82542_MPTC     E1000_MPTC
+#define E1000_82542_BPTC     E1000_BPTC
+#define E1000_82542_TSCTC    E1000_TSCTC
+#define E1000_82542_TSCTFC   E1000_TSCTFC
+#define E1000_82542_RXCSUM   E1000_RXCSUM
+#define E1000_82542_WUC      E1000_WUC
+#define E1000_82542_WUFC     E1000_WUFC
+#define E1000_82542_WUS      E1000_WUS
+#define E1000_82542_MANC     E1000_MANC
+#define E1000_82542_IPAV     E1000_IPAV
+#define E1000_82542_IP4AT    E1000_IP4AT
+#define E1000_82542_IP6AT    E1000_IP6AT
+#define E1000_82542_WUPL     E1000_WUPL
+#define E1000_82542_WUPM     E1000_WUPM
+#define E1000_82542_FFLT     E1000_FFLT
+#define E1000_82542_FFMT     E1000_FFMT
+#define E1000_82542_FFVT     E1000_FFVT
+
+/* Statistics counters collected by the MAC */
+struct e1000_shared_stats {
+    uint64_t crcerrs;
+    uint64_t algnerrc;
+    uint64_t symerrs;
+    uint64_t rxerrc;
+    uint64_t mpc;
+    uint64_t scc;
+    uint64_t ecol;
+    uint64_t mcc;
+    uint64_t latecol;
+    uint64_t colc;
+    uint64_t dc;
+    uint64_t tncrs;
+    uint64_t sec;
+    uint64_t cexterr;
+    uint64_t rlec;
+    uint64_t xonrxc;
+    uint64_t xontxc;
+    uint64_t xoffrxc;
+    uint64_t xofftxc;
+    uint64_t fcruc;
+    uint64_t prc64;
+    uint64_t prc127;
+    uint64_t prc255;
+    uint64_t prc511;
+    uint64_t prc1023;
+    uint64_t prc1522;
+    uint64_t gprc;
+    uint64_t bprc;
+    uint64_t mprc;
+    uint64_t gptc;
+    uint64_t gorcl;
+    uint64_t gorch;
+    uint64_t gotcl;
+    uint64_t gotch;
+    uint64_t rnbc;
+    uint64_t ruc;
+    uint64_t rfc;
+    uint64_t roc;
+    uint64_t rjc;
+    uint64_t mgprc;
+    uint64_t mgpdc;
+    uint64_t mgptc;
+    uint64_t torl;
+    uint64_t torh;
+    uint64_t totl;
+    uint64_t toth;
+    uint64_t tpr;
+    uint64_t tpt;
+    uint64_t ptc64;
+    uint64_t ptc127;
+    uint64_t ptc255;
+    uint64_t ptc511;
+    uint64_t ptc1023;
+    uint64_t ptc1522;
+    uint64_t mptc;
+    uint64_t bptc;
+    uint64_t tsctc;
+    uint64_t tsctfc;
+};
+
+/* Structure containing variables used by the shared code (e1000_mac.c and 
+ * e1000_phy.c)
+ */
+struct e1000_shared_adapter {
+    uint8_t *hw_addr;
+    e1000_mac_type mac_type;
+    e1000_media_type media_type;
+    void *back;
+    e1000_fc_type fc;
+    e1000_bus_speed bus_speed;
+    e1000_bus_width bus_width;
+    e1000_bus_type bus_type;
+    uint32_t phy_id;
+    uint32_t phy_addr;
+    uint32_t original_fc;
+    uint32_t txcw_reg;
+    uint32_t autoneg_failed;
+    uint32_t max_frame_size;
+    uint32_t min_frame_size;
+    uint32_t mc_filter_type;
+    uint32_t num_mc_addrs;
+    uint16_t autoneg_advertised;
+    uint16_t pci_cmd_word;
+    uint16_t fc_high_water;
+    uint16_t fc_low_water;
+    uint16_t fc_pause_time;
+    uint16_t device_id;
+    uint16_t vendor_id;
+    uint16_t subsystem_id;
+    uint16_t subsystem_vendor_id;
+    uint8_t revision_id;
+    boolean_t disable_polarity_correction;
+    boolean_t get_link_status;
+    boolean_t tbi_compatibility_en;
+    boolean_t tbi_compatibility_on;
+    boolean_t adapter_stopped;
+    boolean_t fc_send_xon;
+    boolean_t report_tx_early;
+    uint8_t autoneg;
+    uint8_t mdix;
+    uint8_t forced_speed_duplex;
+    uint8_t wait_autoneg_complete;
+    uint8_t dma_fairness;
+    uint8_t mac_addr[NODE_ADDRESS_SIZE];
+    uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
+};
+
+
+#define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
+#define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
+
+/* Register Bit Masks */
+/* Device Control */
+#define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_BEM      0x00000002  /* Endian Mode.0=little,1=big */
+#define E1000_CTRL_PRIOR    0x00000004  /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_TME      0x00000010  /* Test mode. 0=normal,1=test */
+#define E1000_CTRL_SLE      0x00000020  /* Serial Link on 0=dis,1=en */
+#define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
+#define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL  0x00000300  /* Speed Select Mask */
+#define E1000_CTRL_SPD_10   0x00000000  /* Force 10Mb */
+#define E1000_CTRL_SPD_100  0x00000100  /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200  /* Force 1Gb */
+#define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
+#define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
+#define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
+#define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
+#define E1000_CTRL_SWDPIN3  0x00200000  /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO1  0x00800000  /* SWDPIN 1 input or output */
+#define E1000_CTRL_SWDPIO2  0x01000000  /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3  0x02000000  /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST      0x04000000  /* Global reset */
+#define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE     0x10000000  /* Transmit flow control enable */
+#define E1000_CTRL_RTE      0x20000000  /* Routing tag enable */
+#define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
+
+/* Device Status */
+#define E1000_STATUS_FD         0x00000001      /* Full duplex.0=half,1=full */
+#define E1000_STATUS_LU         0x00000002      /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK  0x0000000C      /* PCI Function Mask */
+#define E1000_STATUS_FUNC_0     0x00000000      /* Function 0 */
+#define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
+#define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
+#define E1000_STATUS_TBIMODE    0x00000020      /* TBI mode */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
+#define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
+#define E1000_STATUS_ASDV       0x00000300      /* Auto speed detect value */
+#define E1000_STATUS_MTXCKOK    0x00000400      /* MTX clock running OK */
+#define E1000_STATUS_PCI66      0x00000800      /* In 66Mhz slot */
+#define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
+
+/* Constants used to intrepret the masked PCI-X bus speed. */
+#define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed  66-100 MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */
+
+/* EEPROM/Flash Control */
+#define E1000_EECD_SK        0x00000001 /* EEPROM Clock */
+#define E1000_EECD_CS        0x00000002 /* EEPROM Chip Select */
+#define E1000_EECD_DI        0x00000004 /* EEPROM Data In */
+#define E1000_EECD_DO        0x00000008 /* EEPROM Data Out */
+#define E1000_EECD_FWE_MASK  0x00000030 
+#define E1000_EECD_FWE_DIS   0x00000010 /* Disable FLASH writes */
+#define E1000_EECD_FWE_EN    0x00000020 /* Enable FLASH writes */
+#define E1000_EECD_FWE_SHIFT 4
+#define E1000_EECD_SIZE      0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
+#define E1000_EECD_REQ       0x00000040 /* EEPROM Access Request */
+#define E1000_EECD_GNT       0x00000080 /* EEPROM Access Grant */
+#define E1000_EECD_PRES      0x00000100 /* EEPROM Present */
+
+/* EEPROM Read */
+#define E1000_EERD_START      0x00000001 /* Start Read */
+#define E1000_EERD_DONE       0x00000010 /* Read Done */
+#define E1000_EERD_ADDR_SHIFT 8
+#define E1000_EERD_ADDR_MASK  0x0000FF00 /* Read Address */
+#define E1000_EERD_DATA_SHIFT 16
+#define E1000_EERD_DATA_MASK  0xFFFF0000 /* Read Data */
+
+/* Extended Device Control */
+#define E1000_CTRL_EXT_GPI0_EN   0x00000001 /* Maps SDP4 to GPI0 */ 
+#define E1000_CTRL_EXT_GPI1_EN   0x00000002 /* Maps SDP5 to GPI1 */
+#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
+#define E1000_CTRL_EXT_GPI2_EN   0x00000004 /* Maps SDP6 to GPI2 */
+#define E1000_CTRL_EXT_GPI3_EN   0x00000008 /* Maps SDP7 to GPI3 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
+#define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+#define E1000_CTRL_EXT_SDP4_DIR  0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP5_DIR  0x00000200 /* Direction of SDP5 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR  0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP7_DIR  0x00000800 /* Direction of SDP7 0=in 1=out */
+#define E1000_CTRL_EXT_ASDCHK    0x00001000 /* Initiate an ASD sequence */
+#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
+#define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
+#define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
+#define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
+#define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
+#define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
+
+/* MDI Control */
+#define E1000_MDIC_DATA_MASK 0x0000FFFF
+#define E1000_MDIC_REG_MASK  0x001F0000
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK  0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE  0x04000000
+#define E1000_MDIC_OP_READ   0x08000000
+#define E1000_MDIC_READY     0x10000000
+#define E1000_MDIC_INT_EN    0x20000000
+#define E1000_MDIC_ERROR     0x40000000
+
+/* LED Control */
+#define E1000_LEDCTL_LED0_MODE_MASK  0x0000000F
+#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_IVRT       0x00000040
+#define E1000_LEDCTL_LED0_BLINK      0x00000080
+#define E1000_LEDCTL_LED1_MODE_MASK  0x00000F00
+#define E1000_LEDCTL_LED1_MODE_SHIFT 8
+#define E1000_LEDCTL_LED1_IVRT       0x00004000
+#define E1000_LEDCTL_LED1_BLINK      0x00008000
+#define E1000_LEDCTL_LED2_MODE_MASK  0x000F0000
+#define E1000_LEDCTL_LED2_MODE_SHIFT 16
+#define E1000_LEDCTL_LED2_IVRT       0x00400000
+#define E1000_LEDCTL_LED2_BLINK      0x00800000
+#define E1000_LEDCTL_LED3_MODE_MASK  0x0F000000
+#define E1000_LEDCTL_LED3_MODE_SHIFT 24
+#define E1000_LEDCTL_LED3_IVRT       0x40000000
+#define E1000_LEDCTL_LED3_BLINK      0x80000000
+
+#define E1000_LEDCTL_MODE_LINK_10_1000  0x0
+#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
+#define E1000_LEDCTL_MODE_LINK_UP       0x2
+#define E1000_LEDCTL_MODE_ACTIVITY      0x3
+#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
+#define E1000_LEDCTL_MODE_LINK_10       0x5
+#define E1000_LEDCTL_MODE_LINK_100      0x6
+#define E1000_LEDCTL_MODE_LINK_1000     0x7
+#define E1000_LEDCTL_MODE_PCIX_MODE     0x8
+#define E1000_LEDCTL_MODE_FULL_DUPLEX   0x9
+#define E1000_LEDCTL_MODE_COLLISION     0xA
+#define E1000_LEDCTL_MODE_BUS_SPEED     0xB
+#define E1000_LEDCTL_MODE_BUS_SIZE      0xC
+#define E1000_LEDCTL_MODE_PAUSED        0xD
+#define E1000_LEDCTL_MODE_LED_ON        0xE
+#define E1000_LEDCTL_MODE_LED_OFF       0xF
+
+/* Receive Address */
+#define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
+
+/* Interrupt Cause Read */
+#define E1000_ICR_TXDW    0x00000001    /* Transmit desc written back */
+#define E1000_ICR_TXQE    0x00000002    /* Transmit Queue empty */
+#define E1000_ICR_LSC     0x00000004    /* Link Status Change */
+#define E1000_ICR_RXSEQ   0x00000008    /* rx sequence error */
+#define E1000_ICR_RXDMT0  0x00000010    /* rx desc min. threshold (0) */
+#define E1000_ICR_RXO     0x00000040    /* rx overrun */
+#define E1000_ICR_RXT0    0x00000080    /* rx timer intr (ring 0) */
+#define E1000_ICR_MDAC    0x00000200    /* MDIO access complete */
+#define E1000_ICR_RXCFG   0x00000400    /* RX /c/ ordered set */
+#define E1000_ICR_GPI_EN0 0x00000800    /* GP Int 0 */
+#define E1000_ICR_GPI_EN1 0x00001000    /* GP Int 1 */
+#define E1000_ICR_GPI_EN2 0x00002000    /* GP Int 2 */
+#define E1000_ICR_GPI_EN3 0x00004000    /* GP Int 3 */
+#define E1000_ICR_TXD_LOW 0x00008000
+#define E1000_ICR_SRPD    0x00010000
+
+/* Interrupt Cause Set */
+#define E1000_ICS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_ICS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_ICS_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_ICS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_ICS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_ICS_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_ICS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_ICS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_ICS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_ICS_SRPD    E1000_ICR_SRPD
+
+/* Interrupt Mask Set */
+#define E1000_IMS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_IMS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_IMS_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_IMS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_IMS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_IMS_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_IMS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_IMS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_IMS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMS_SRPD    E1000_ICR_SRPD
+
+/* Interrupt Mask Clear */
+#define E1000_IMC_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_IMC_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_IMC_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_IMC_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_IMC_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_IMC_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_IMC_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_IMC_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_IMC_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMC_SRPD    E1000_ICR_SRPD
+
+/* Receive Control */
+#define E1000_RCTL_RST          0x00000001      /* Software reset */
+#define E1000_RCTL_EN           0x00000002      /* enable */
+#define E1000_RCTL_SBP          0x00000004      /* store bad packet */
+#define E1000_RCTL_UPE          0x00000008      /* unicast promiscuous enable */
+#define E1000_RCTL_MPE          0x00000010      /* multicast promiscuous enab */
+#define E1000_RCTL_LPE          0x00000020      /* long packet enable */
+#define E1000_RCTL_LBM_NO       0x00000000      /* no loopback mode */
+#define E1000_RCTL_LBM_MAC      0x00000040      /* MAC loopback mode */
+#define E1000_RCTL_LBM_SLP      0x00000080      /* serial link loopback mode */
+#define E1000_RCTL_LBM_TCVR     0x000000C0      /* tcvr loopback mode */
+#define E1000_RCTL_RDMTS_HALF   0x00000000      /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_QUAT   0x00000100      /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_EIGTH  0x00000200      /* rx desc min threshold size */
+#define E1000_RCTL_MO_SHIFT     12              /* multicast offset shift */
+#define E1000_RCTL_MO_0         0x00000000      /* multicast offset 11:0 */
+#define E1000_RCTL_MO_1         0x00001000      /* multicast offset 12:1 */
+#define E1000_RCTL_MO_2         0x00002000      /* multicast offset 13:2 */
+#define E1000_RCTL_MO_3         0x00003000      /* multicast offset 15:4 */
+#define E1000_RCTL_MDR          0x00004000      /* multicast desc ring 0 */
+#define E1000_RCTL_BAM          0x00008000      /* broadcast enable */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+#define E1000_RCTL_SZ_2048      0x00000000      /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024      0x00010000      /* rx buffer size 1024 */
+#define E1000_RCTL_SZ_512       0x00020000      /* rx buffer size 512 */
+#define E1000_RCTL_SZ_256       0x00030000      /* rx buffer size 256 */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+#define E1000_RCTL_SZ_16384     0x00010000      /* rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192      0x00020000      /* rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096      0x00030000      /* rx buffer size 4096 */
+#define E1000_RCTL_VFE          0x00040000      /* vlan filter enable */
+#define E1000_RCTL_CFIEN        0x00080000      /* canonical form enable */
+#define E1000_RCTL_CFI          0x00100000      /* canonical form indicator */
+#define E1000_RCTL_DPF          0x00400000      /* discard pause frames */
+#define E1000_RCTL_PMCF         0x00800000      /* pass MAC control frames */
+#define E1000_RCTL_BSEX         0x02000000      /* Buffer size extension */
+
+/* Receive Descriptor */
+#define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
+#define E1000_RDT_FPDB  0x80000000      /* Flush descriptor block */
+#define E1000_RDLEN_LEN 0x0007ff80      /* descriptor length */
+#define E1000_RDH_RDH   0x0000ffff      /* receive descriptor head */
+#define E1000_RDT_RDT   0x0000ffff      /* receive descriptor tail */
+
+/* Flow Control */
+#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTH_XFCE 0x80000000     /* External Flow Control Enable */
+#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
+
+/* Receive Descriptor Control */
+#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
+#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
+#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
+#define E1000_RXDCTL_GRAN    0x01000000 /* RXDCTL Granularity */
+
+/* Transmit Descriptor Control */
+#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+
+/* Transmit Configuration Word */
+#define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
+#define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
+#define E1000_TXCW_PAUSE      0x00000080        /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR    0x00000100        /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180        /* TXCW pause request mask */
+#define E1000_TXCW_RF         0x00003000        /* TXCW remote fault */
+#define E1000_TXCW_NP         0x00008000        /* TXCW next page */
+#define E1000_TXCW_CW         0x0000ffff        /* TxConfigWord mask */
+#define E1000_TXCW_TXC        0x40000000        /* Transmit Config control */
+#define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
+
+/* Receive Configuration Word */
+#define E1000_RXCW_CW    0x0000ffff     /* RxConfigWord mask */
+#define E1000_RXCW_NC    0x04000000     /* Receive config no carrier */
+#define E1000_RXCW_IV    0x08000000     /* Receive config invalid */
+#define E1000_RXCW_CC    0x10000000     /* Receive config change */
+#define E1000_RXCW_C     0x20000000     /* Receive config */
+#define E1000_RXCW_SYNCH 0x40000000     /* Receive config synch */
+#define E1000_RXCW_ANC   0x80000000     /* Auto-neg complete */
+
+/* Transmit Control */
+#define E1000_TCTL_RST    0x00000001    /* software reset */
+#define E1000_TCTL_EN     0x00000002    /* enable tx */
+#define E1000_TCTL_BCE    0x00000004    /* busy check enable */
+#define E1000_TCTL_PSP    0x00000008    /* pad short packets */
+#define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
+#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
+#define E1000_TCTL_SWXOFF 0x00400000    /* SW Xoff transmission */
+#define E1000_TCTL_PBE    0x00800000    /* Packet Burst Enable */
+#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
+#define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
+
+/* Receive Checksum Control */
+#define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
+#define E1000_RXCSUM_IPOFL     0x00000100   /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_IPV6OFL   0x00000400   /* IPv6 checksum offload */
+
+/* Definitions for power management and wakeup registers */
+/* Wake Up Control */
+#define E1000_WUC_APME       0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
+#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
+#define E1000_WUC_APMPME     0x00000008 /* Assert PME on APM Wakeup */
+
+/* Wake Up Filter Control */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET 16       /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+
+/* Wake Up Status */
+#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */
+#define E1000_WUS_MAG  0x00000002 /* Magic Packet Received */
+#define E1000_WUS_EX   0x00000004 /* Directed Exact Received */
+#define E1000_WUS_MC   0x00000008 /* Directed Multicast Received */
+#define E1000_WUS_BC   0x00000010 /* Broadcast Received */
+#define E1000_WUS_ARP  0x00000020 /* ARP Request Packet Received */
+#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */
+#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */
+#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */
+#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */
+#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */
+#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
+#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+
+/* Management Control */
+#define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_R_ON_FORCE    0x00000004 /* Reset on Force TCO - RO */
+#define E1000_MANC_RMCP_EN       0x00000100 /* Enable RCMP 026Fh Filtering */
+#define E1000_MANC_0298_EN       0x00000200 /* Enable RCMP 0298h Filtering */
+#define E1000_MANC_IPV4_EN       0x00000400 /* Enable IPv4 */
+#define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
+#define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
+#define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
+#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery 
+                                             * Filtering */
+#define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
+#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
+#define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
+#define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
+#define E1000_MANC_SMB_DATA_IN   0x08000000 /* SMBus Data In */
+#define E1000_MANC_SMB_DATA_OUT  0x10000000 /* SMBus Data Out */
+#define E1000_MANC_SMB_CLK_OUT   0x20000000 /* SMBus Clock Out */
+
+#define E1000_MANC_SMB_DATA_OUT_SHIFT  28 /* SMBus Data Out Shift */
+#define E1000_MANC_SMB_CLK_OUT_SHIFT   29 /* SMBus Clock Out Shift */
+
+/* Wake Up Packet Length */
+#define E1000_WUPL_LENGTH_MASK 0x0FFF   /* Only the lower 12 bits are valid */
+
+#define E1000_MDALIGN          4096
+
+/* 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 Word Offsets */
+#define EEPROM_INIT_CONTROL1_REG 0x000A
+#define EEPROM_INIT_CONTROL2_REG 0x000F
+#define EEPROM_FLASH_VERSION     0x0032
+#define EEPROM_CHECKSUM_REG      0x003F
+
+/* Mask bits for fields in Word 0x0a of the EEPROM */
+#define EEPROM_WORD0A_ILOS   0x0010
+#define EEPROM_WORD0A_SWDPIO 0x01E0
+#define EEPROM_WORD0A_LRST   0x0200
+#define EEPROM_WORD0A_FD     0x0400
+#define EEPROM_WORD0A_66MHZ  0x0800
+
+/* Mask bits for fields in Word 0x0f of the EEPROM */
+#define EEPROM_WORD0F_PAUSE_MASK 0x3000
+#define EEPROM_WORD0F_PAUSE      0x1000
+#define EEPROM_WORD0F_ASM_DIR    0x2000
+#define EEPROM_WORD0F_ANE        0x0800
+#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
+
+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
+#define EEPROM_SUM 0xBABA
+
+/* EEPROM Map defines (WORD OFFSETS)*/
+#define EEPROM_NODE_ADDRESS_BYTE_0 0
+#define EEPROM_PBA_BYTE_1          8
+
+/* EEPROM Map Sizes (Byte Counts) */
+#define PBA_SIZE 4
+
+/* Collision related configuration parameters */
+#define E1000_COLLISION_THRESHOLD       16
+#define E1000_CT_SHIFT                  4
+#define E1000_FDX_COLLISION_DISTANCE    64
+#define E1000_HDX_COLLISION_DISTANCE    64
+#define E1000_GB_HDX_COLLISION_DISTANCE 512
+#define E1000_COLD_SHIFT                12
+
+/* The number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE  8
+#define REQ_RX_DESCRIPTOR_MULTIPLE  8
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_82542_TIPG_IPGT        10
+#define DEFAULT_82543_TIPG_IPGT_FIBER  9
+#define DEFAULT_82543_TIPG_IPGT_COPPER 8
+
+#define E1000_TIPG_IPGT_MASK  0x000003FF
+#define E1000_TIPG_IPGR1_MASK 0x000FFC00
+#define E1000_TIPG_IPGR2_MASK 0x3FF00000
+
+#define DEFAULT_82542_TIPG_IPGR1 2
+#define DEFAULT_82543_TIPG_IPGR1 8
+#define E1000_TIPG_IPGR1_SHIFT  10
+
+#define DEFAULT_82542_TIPG_IPGR2 10
+#define DEFAULT_82543_TIPG_IPGR2 6
+#define E1000_TIPG_IPGR2_SHIFT  20
+
+#define E1000_TXDMAC_DPP 0x00000001
+
+/* PBA constants */
+#define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
+#define E1000_PBA_24K 0x0018
+#define E1000_PBA_40K 0x0028
+#define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
+
+/* Flow Control Constants */
+#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
+#define FLOW_CONTROL_TYPE         0x8808
+
+/* The historical defaults for the flow control values are given below. */
+#define FC_DEFAULT_HI_THRESH        (0x8000)    /* 32KB */
+#define FC_DEFAULT_LO_THRESH        (0x4000)    /* 16KB */
+#define FC_DEFAULT_TX_TIMER         (0x100)     /* ~130 us */
+
+
+/* The number of bits that we need to shift right to move the "pause"
+ * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field
+ * in the TXCW register 
+ */
+#define PAUSE_SHIFT 5
+
+/* The number of bits that we need to shift left to move the "SWDPIO"
+ * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field
+ * in the CTRL register 
+ */
+#define SWDPIO_SHIFT 17
+
+/* The number of bits that we need to shift left to move the "SWDPIO_EXT"
+ * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The
+ * Extended CTRL register.
+ * in the CTRL register 
+ */
+#define SWDPIO__EXT_SHIFT 4
+
+/* The number of bits that we need to shift left to move the "ILOS"
+ * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field
+ * in the CTRL register 
+ */
+#define ILOS_SHIFT  3
+
+
+#define RECEIVE_BUFFER_ALIGN_SIZE  (256)
+
+/* The number of milliseconds we wait for auto-negotiation to complete */
+#define LINK_UP_TIMEOUT             500
+
+#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
+
+/* The carrier extension symbol, as received by the NIC. */
+#define CARRIER_EXTENSION   0x0F
+
+/* TBI_ACCEPT macro definition:
+ *
+ * If Tbi Compatibility mode is turned-on, then we should accept frames with
+ * receive errors if and only if:
+ *      1) errors is equal to the CRC error bit.
+ *      2) The last byte is a Carrier extension (0x0F).
+ *      3) The frame length (as reported by Hardware) is greater than 64 (60
+ *         if a VLAN tag was stripped from the frame.
+ *      4) "    "     "      "   "       "   "        <= max_frame_size+1.
+ *
+ * This macro requires:
+ *      adapter = a pointer to struct e1000_shared_adapter 
+ *      special = the 16 bit special field of the RX descriptor with EOP set
+ *      error = the 8 bit error field of the RX descriptor with EOP set
+ *      length = the sum of all the length fields of the RX descriptors that
+ *               make up the current frame
+ *      last_byte = the last byte of the frame DMAed by the hardware
+ *      max_frame_length = the maximum frame length we want to accept.
+ *      min_frame_length = the minimum frame length we want to accept.
+ *
+ * This macro is a conditional that should be used in the interrupt 
+ * handler's Rx processing routine when RxErrors have been detected.
+ *
+ * Typical use:
+ *  ...
+ *  if (TBI_ACCEPT) {
+ *      accept_frame = TRUE;
+ *      e1000_tbi_adjust_stats(adapter, MacAddress);
+ *      frame_length--;
+ *  } else {
+ *      accept_frame = FALSE;
+ *  }
+ *  ...
+ */
+
+#define TBI_ACCEPT(adapter, special, errors, length, last_byte) \
+    ((adapter)->tbi_compatibility_on && \
+     (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
+     ((last_byte) == CARRIER_EXTENSION) && \
+     ((length) <= ((adapter)->max_frame_size + 1)) && \
+     ((length) > ((special == 0x0000) ? \
+		  ((adapter)->min_frame_size) : \
+		  ((adapter)->min_frame_size - VLAN_TAG_SIZE))))
+
+
+#endif /* _E1000_MAC_H_ */
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_main.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,2036 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#define __E1000_MAIN__
+#include "e1000.h"
+
+char e1000_driver_name[] = "e1000";
+
+char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
+
+char e1000_driver_version[] = "4.2.4-k1";
+
+char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation.";
+
+/* e1000_pci_tbl - PCI Device ID Table
+ *
+ * Private driver_data field (last one) stores an index into e1000_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 e1000_pci_tbl[] __devinitdata = {
+	/* Intel(R) PRO/1000 Network Connection */
+	{0x8086, 0x1000, 0x8086, 0x1000, 0, 0, 0},
+	{0x8086, 0x1001, 0x8086, 0x1003, 0, 0, 0},
+	{0x8086, 0x1004, 0x8086, 0x1004, 0, 0, 0},
+	{0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0},
+	{0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0},
+	{0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0},
+	/* Compaq Gigabit Ethernet Server Adapter */
+	{0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1},
+	{0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1},
+	{0x8086, 0x1004, 0x0E11, PCI_ANY_ID, 0, 0, 1},
+	/* IBM Mobile, Desktop & Server Adapters */
+	{0x8086, 0x1000, 0x1014, PCI_ANY_ID, 0, 0, 2},
+	{0x8086, 0x1001, 0x1014, PCI_ANY_ID, 0, 0, 2},
+	{0x8086, 0x1004, 0x1014, PCI_ANY_ID, 0, 0, 2},
+	/* Generic */
+	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	/* required last entry */
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
+
+static char *e1000_strings[] = {
+	"Intel(R) PRO/1000 Network Connection",
+	"Compaq Gigabit Ethernet Server Adapter",
+	"IBM Mobile, Desktop & Server Adapters"
+};
+
+/* Local Function Prototypes */
+
+int e1000_up(struct e1000_adapter *adapter);
+void e1000_down(struct e1000_adapter *adapter);
+static int e1000_init_module(void);
+static void e1000_exit_module(void);
+static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void e1000_remove(struct pci_dev *pdev);
+static void e1000_sw_init(struct e1000_adapter *adapter);
+static int e1000_open(struct net_device *netdev);
+static int e1000_close(struct net_device *netdev);
+static int e1000_setup_tx_resources(struct e1000_adapter *adapter);
+static int e1000_setup_rx_resources(struct e1000_adapter *adapter);
+static void e1000_configure_tx(struct e1000_adapter *adapter);
+static void e1000_configure_rx(struct e1000_adapter *adapter);
+static void e1000_setup_rctl(struct e1000_adapter *adapter);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
+static void e1000_free_tx_resources(struct e1000_adapter *adapter);
+static void e1000_free_rx_resources(struct e1000_adapter *adapter);
+static void e1000_set_multi(struct net_device *netdev);
+static void e1000_update_phy_info(unsigned long data);
+static void e1000_watchdog(unsigned long data);
+static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+static void e1000_tx_timeout(struct net_device *dev);
+static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
+static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
+static int e1000_set_mac(struct net_device *netdev, void *p);
+static void e1000_update_stats(struct e1000_adapter *adapter);
+static inline void e1000_irq_disable(struct e1000_adapter *adapter);
+static inline void e1000_irq_enable(struct e1000_adapter *adapter);
+static void e1000_intr(int irq, void *data, struct pt_regs *regs);
+static void e1000_clean_tx_irq(struct e1000_adapter *adapter);
+static void e1000_clean_rx_irq(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
+static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+static void e1000_reset(struct e1000_adapter *adapter);
+static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
+static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
+static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
+                                     struct e1000_rx_desc *rx_desc,
+                                     struct sk_buff *skb);
+void e1000_enable_WOL(struct e1000_adapter *adapter);
+
+/* Exported from other modules */
+
+extern void e1000_check_options(struct e1000_adapter *adapter);
+extern void e1000_proc_dev_setup(struct e1000_adapter *adapter);
+extern void e1000_proc_dev_free(struct e1000_adapter *adapter);
+extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
+
+static struct pci_driver e1000_driver = {
+	name:     e1000_driver_name,
+	id_table: e1000_pci_tbl,
+	probe:    e1000_probe,
+	remove:   e1000_remove,
+	/* Power Managment Hooks */
+	suspend:  NULL,
+	resume:   NULL
+};
+
+MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
+MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#ifdef EXPORT_SYMTAB
+EXPORT_SYMBOL(e1000_init_module);
+EXPORT_SYMBOL(e1000_exit_module);
+EXPORT_SYMBOL(e1000_probe);
+EXPORT_SYMBOL(e1000_remove);
+EXPORT_SYMBOL(e1000_open);
+EXPORT_SYMBOL(e1000_close);
+EXPORT_SYMBOL(e1000_xmit_frame);
+EXPORT_SYMBOL(e1000_intr);
+EXPORT_SYMBOL(e1000_set_multi);
+EXPORT_SYMBOL(e1000_change_mtu);
+EXPORT_SYMBOL(e1000_set_mac);
+EXPORT_SYMBOL(e1000_get_stats);
+EXPORT_SYMBOL(e1000_watchdog);
+EXPORT_SYMBOL(e1000_ioctl);
+#endif
+
+/**
+ * e1000_init_module - Driver Registration Routine
+ *
+ * e1000_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+
+static int __init
+e1000_init_module(void)
+{
+	printk(KERN_INFO "%s - version %s\n",
+	       e1000_driver_string, e1000_driver_version);
+
+	printk(KERN_INFO "%s\n", e1000_copyright);
+
+	return pci_module_init(&e1000_driver);
+}
+
+module_init(e1000_init_module);
+
+/**
+ * e1000_exit_module - Driver Exit Cleanup Routine
+ *
+ * e1000_exit_module is called just before the driver is removed
+ * from memory.
+ **/
+
+static void __exit
+e1000_exit_module(void)
+{
+	pci_unregister_driver(&e1000_driver);
+
+	return;
+}
+
+module_exit(e1000_exit_module);
+
+
+int
+e1000_up(struct e1000_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ,
+	               netdev->name, netdev))
+		return -1;
+
+	/* hardware has been reset, we need to reload some things */
+
+	e1000_set_multi(netdev);
+
+	e1000_configure_tx(adapter);
+	e1000_setup_rctl(adapter);
+	e1000_configure_rx(adapter);
+	e1000_alloc_rx_buffers(adapter);
+
+	e1000_clear_hw_cntrs(&adapter->shared);
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+	e1000_irq_enable(adapter);
+
+	return 0;
+}
+
+void
+e1000_down(struct e1000_adapter *adapter)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct net_device *netdev = adapter->netdev;
+
+	e1000_irq_disable(adapter);
+	free_irq(netdev->irq, netdev);
+	del_timer_sync(&adapter->watchdog_timer);
+	del_timer_sync(&adapter->phy_info_timer);
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	/* disable the transmit and receive units */
+
+	E1000_WRITE_REG(shared, RCTL, 0);
+	E1000_WRITE_REG(shared, TCTL, E1000_TCTL_PSP);
+
+	/* delay to allow PCI transactions to complete */
+
+	msec_delay(10);
+
+	e1000_clean_tx_ring(adapter);
+	e1000_clean_rx_ring(adapter);
+
+	e1000_reset(adapter);
+}
+
+static void
+e1000_reset(struct e1000_adapter *adapter)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	uint32_t ctrl_ext;
+
+	/* Repartition Pba for greater than 9k mtu
+	 * To take effect CTRL.RST is required.
+	 */
+
+	if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
+		E1000_WRITE_REG(shared, PBA, E1000_JUMBO_PBA);
+	else
+		E1000_WRITE_REG(shared, PBA, E1000_DEFAULT_PBA);
+
+	/* 82542 2.0 needs MWI disabled while issuing a reset */
+
+	if(shared->mac_type == e1000_82542_rev2_0)
+		e1000_enter_82542_rst(adapter);
+
+	/* global reset */
+
+	E1000_WRITE_REG(shared, CTRL, E1000_CTRL_RST);
+	msec_delay(10);
+
+	/* EEPROM reload */
+
+	ctrl_ext = E1000_READ_REG(shared, CTRL_EXT);
+	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+	E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext);
+	msec_delay(5);
+
+	if(shared->mac_type == e1000_82542_rev2_0)
+		e1000_leave_82542_rst(adapter);
+
+	shared->tbi_compatibility_on = FALSE;
+	shared->fc = shared->original_fc;
+
+	e1000_init_hw(shared);
+
+	e1000_enable_WOL(adapter);
+
+	return;
+}
+
+/**
+ * e1000_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in e1000_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * e1000_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+
+static int __devinit
+e1000_probe(struct pci_dev *pdev,
+            const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct e1000_adapter *adapter;
+	static int cards_found = 0;
+	unsigned long mmio_start;
+	int mmio_len;
+	int i;
+
+	if((i = pci_enable_device(pdev)))
+		return i;
+
+	if((i = pci_set_dma_mask(pdev, E1000_DMA_MASK)))
+		return i;
+
+	if((i = pci_request_regions(pdev, e1000_driver_name)))
+		return i;
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
+	if(!netdev)
+		goto err_alloc_etherdev;
+
+	SET_MODULE_OWNER(netdev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev->priv;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->shared.back = adapter;
+
+	mmio_start = pci_resource_start(pdev, BAR_0);
+	mmio_len = pci_resource_len(pdev, BAR_0);
+
+	adapter->shared.hw_addr = ioremap(mmio_start, mmio_len);
+	if(!adapter->shared.hw_addr)
+		goto err_ioremap;
+
+	netdev->open = &e1000_open;
+	netdev->stop = &e1000_close;
+	netdev->hard_start_xmit = &e1000_xmit_frame;
+	netdev->get_stats = &e1000_get_stats;
+	netdev->set_multicast_list = &e1000_set_multi;
+	netdev->set_mac_address = &e1000_set_mac;
+	netdev->change_mtu = &e1000_change_mtu;
+	netdev->do_ioctl = &e1000_ioctl;
+	netdev->tx_timeout = &e1000_tx_timeout;
+	netdev->watchdog_timeo = HZ;
+
+	netdev->irq = pdev->irq;
+	netdev->base_addr = mmio_start;
+
+	adapter->bd_number = cards_found;
+	adapter->id_string = e1000_strings[ent->driver_data];
+
+	/* setup the private structure */
+
+	e1000_sw_init(adapter);
+
+	if(adapter->shared.mac_type >= e1000_82543) {
+		netdev->features = NETIF_F_SG |
+		                   NETIF_F_IP_CSUM |
+		                   NETIF_F_HIGHDMA;
+	} else {
+		netdev->features = NETIF_F_SG | NETIF_F_HIGHDMA;
+	}
+
+	/* make sure the EEPROM is good */
+
+	if(!e1000_validate_eeprom_checksum(&adapter->shared))
+		goto err_eeprom;
+
+	/* copy the MAC address out of the EEPROM */
+
+	e1000_read_mac_addr(&adapter->shared);
+	memcpy(netdev->dev_addr, adapter->shared.mac_addr, netdev->addr_len);
+
+	if(!is_valid_ether_addr(netdev->dev_addr))
+		goto err_eeprom;
+
+	e1000_read_part_num(&adapter->shared, &(adapter->part_num));
+	e1000_get_bus_info(&adapter->shared);
+
+	init_timer(&adapter->watchdog_timer);
+	adapter->watchdog_timer.function = &e1000_watchdog;
+	adapter->watchdog_timer.data = (unsigned long) adapter;
+
+	init_timer(&adapter->phy_info_timer);
+	adapter->phy_info_timer.function = &e1000_update_phy_info;
+	adapter->phy_info_timer.data = (unsigned long) adapter;
+
+	register_netdev(netdev);
+
+	/* 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);
+	e1000_check_options(adapter);
+	e1000_proc_dev_setup(adapter);
+
+	/* reset the hardware with the new settings */
+
+	e1000_reset(adapter);
+
+	cards_found++;
+	return 0;
+
+err_eeprom:
+	iounmap(adapter->shared.hw_addr);
+err_ioremap:
+	pci_release_regions(pdev);
+	kfree(netdev);
+err_alloc_etherdev:
+	return -ENOMEM;
+}
+
+/**
+ * e1000_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * e1000_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.
+ *
+ * This routine is also called to clean up from a failure in
+ * e1000_probe.  The Adapter struct and netdev will always exist,
+ * all other pointers must be checked for NULL before freeing.
+ **/
+
+static void __devexit
+e1000_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct e1000_adapter *adapter = netdev->priv;
+
+	unregister_netdev(netdev);
+
+	e1000_phy_hw_reset(&adapter->shared);
+
+	e1000_proc_dev_free(adapter);
+
+	iounmap(adapter->shared.hw_addr);
+	pci_release_regions(pdev);
+
+	kfree(netdev);
+	return;
+}
+
+/**
+ * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * e1000_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
+e1000_sw_init(struct e1000_adapter *adapter)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* PCI config space info */
+
+	uint16_t *vendor = &shared->vendor_id;
+	uint16_t *device = &shared->device_id;
+	uint16_t *subvendor = &shared->subsystem_vendor_id;
+	uint16_t *subsystem = &shared->subsystem_id;
+	uint8_t  *revision  = &shared->revision_id;
+
+	pci_read_config_word(pdev, PCI_VENDOR_ID, vendor);
+	pci_read_config_word(pdev, PCI_DEVICE_ID, device);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, revision);
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, subvendor);
+	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, subsystem);
+
+	pci_read_config_word(pdev, PCI_COMMAND, &shared->pci_cmd_word);
+
+	adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+	shared->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + CRC_LENGTH;
+	shared->min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH;
+
+	/* identify the MAC */
+
+	switch (*device) {
+	case E1000_DEV_ID_82542:
+		switch (*revision) {
+		case E1000_82542_2_0_REV_ID:
+			shared->mac_type = e1000_82542_rev2_0;
+			break;
+		case E1000_82542_2_1_REV_ID:
+			shared->mac_type = e1000_82542_rev2_1;
+			break;
+		default:
+			shared->mac_type = e1000_82542_rev2_0;
+			E1000_ERR("Could not identify 82542 revision\n");
+		}
+		break;
+	case E1000_DEV_ID_82543GC_FIBER:
+	case E1000_DEV_ID_82543GC_COPPER:
+		shared->mac_type = e1000_82543;
+		break;
+	case E1000_DEV_ID_82544EI_COPPER:
+	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82544GC_COPPER:
+	case E1000_DEV_ID_82544GC_LOM:
+		shared->mac_type = e1000_82544;
+		break;
+	default:
+		/* should never have loaded on this device */
+		BUG();
+	}
+
+	/* flow control settings */
+
+	shared->fc_high_water = FC_DEFAULT_HI_THRESH;
+	shared->fc_low_water = FC_DEFAULT_LO_THRESH;
+	shared->fc_pause_time = FC_DEFAULT_TX_TIMER;
+	shared->fc_send_xon = 1;
+
+	/* Media type - copper or fiber */
+
+	if(shared->mac_type >= e1000_82543) {
+		uint32_t status = E1000_READ_REG(shared, STATUS);
+
+		if(status & E1000_STATUS_TBIMODE)
+			shared->media_type = e1000_media_type_fiber;
+		else
+			shared->media_type = e1000_media_type_copper;
+	} else {
+		shared->media_type = e1000_media_type_fiber;
+	}
+
+	if(shared->mac_type < e1000_82543)
+		shared->report_tx_early = 0;
+	else
+		shared->report_tx_early = 1;
+
+	shared->wait_autoneg_complete = FALSE;
+	shared->tbi_compatibility_en = TRUE;
+
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->stats_lock);
+}
+
+/**
+ * e1000_open - Called when a network interface is made active
+ * @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
+e1000_open(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	/* allocate transmit descriptors */
+
+	if(e1000_setup_tx_resources(adapter))
+		goto err_setup_tx;
+
+	/* allocate receive descriptors */
+
+	if(e1000_setup_rx_resources(adapter))
+		goto err_setup_rx;
+
+	if(e1000_up(adapter))
+		goto err_up;
+
+	return 0;
+
+err_up:
+	e1000_free_rx_resources(adapter);
+err_setup_rx:
+	e1000_free_tx_resources(adapter);
+err_setup_tx:
+	e1000_reset(adapter);
+
+	return -EBUSY;
+}
+
+/**
+ * e1000_close - Disables a network interface
+ * @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
+e1000_close(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	e1000_down(adapter);
+
+	e1000_free_tx_resources(adapter);
+	e1000_free_rx_resources(adapter);
+
+	return 0;
+}
+
+/**
+ * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ *
+ * e1000_setup_tx_resources allocates all software transmit resources
+ * and enabled the Tx unit of the MAC.
+ **/
+
+static int
+e1000_setup_tx_resources(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *txdr = &adapter->tx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+
+	size = sizeof(struct e1000_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 e1000_tx_desc);
+	E1000_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);
+
+	atomic_set(&txdr->unused, txdr->count);
+	txdr->next_to_use = 0;
+	txdr->next_to_clean = 0;
+
+	return 0;
+}
+
+/**
+ * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+
+static void
+e1000_configure_tx(struct e1000_adapter *adapter)
+{
+	uint64_t tdba = adapter->tx_ring.dma;
+	uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
+	uint32_t tctl, tipg;
+
+	E1000_WRITE_REG(&adapter->shared, TDBAL, (tdba & 0x00000000FFFFFFFF));
+	E1000_WRITE_REG(&adapter->shared, TDBAH, (tdba >> 32));
+
+	E1000_WRITE_REG(&adapter->shared, TDLEN, tdlen);
+
+	/* Setup the HW Tx Head and Tail descriptor pointers */
+
+	E1000_WRITE_REG(&adapter->shared, TDH, 0);
+	E1000_WRITE_REG(&adapter->shared, TDT, 0);
+
+	/* Set the default values for the Tx Inter Packet Gap timer */
+
+	switch (adapter->shared.mac_type) {
+	case e1000_82542_rev2_0:
+	case e1000_82542_rev2_1:
+		tipg = DEFAULT_82542_TIPG_IPGT;
+		tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
+		tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+		break;
+	default:
+		if(adapter->shared.media_type == e1000_media_type_fiber)
+			tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
+		else
+			tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
+		tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
+		tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+	}
+	E1000_WRITE_REG(&adapter->shared, TIPG, tipg);
+
+	/* Set the Tx Interrupt Delay register */
+
+	E1000_WRITE_REG(&adapter->shared, TIDV, adapter->tx_int_delay);
+
+	/* Program the Transmit Control Register */
+
+	tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
+	       (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+
+	if(adapter->link_duplex == FULL_DUPLEX) {
+		tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+	} else {
+		tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+	}
+
+	E1000_WRITE_REG(&adapter->shared, TCTL, tctl);
+
+#ifdef CONFIG_PPC
+	if(adapter->shared.mac_type >= e1000_82543) {
+		E1000_WRITE_REG(&adapter->shared, TXDCTL, 0x00020000);
+	}
+#endif
+
+	/* Setup Transmit Descriptor Settings for this adapter */
+	adapter->txd_cmd = E1000_TXD_CMD_IFCS;
+
+	if(adapter->tx_int_delay > 0)
+		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
+	if(adapter->shared.report_tx_early == 1)
+		adapter->txd_cmd |= E1000_TXD_CMD_RS;
+	else
+		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
+
+	return;
+}
+
+/**
+ * e1000_setup_rx_resources - allocate Rx resources (Descriptors, receive SKBs)
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * e1000_setup_rx_resources allocates all software receive resources
+ * and network buffers, and enables the Rx unit of the MAC.
+ **/
+
+static int
+e1000_setup_rx_resources(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+
+	size = sizeof(struct e1000_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 e1000_rx_desc);
+	E1000_ROUNDUP(rxdr->size, 4096);
+
+	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+
+	if(!rxdr->desc) {
+		kfree(rxdr->buffer_info);
+		return -ENOMEM;
+	}
+	memset(rxdr->desc, 0, rxdr->size);
+
+	rxdr->next_to_clean = 0;
+	rxdr->unused_count = rxdr->count;
+	rxdr->next_to_use = 0;
+
+	return 0;
+}
+
+/**
+ * e1000_setup_rctl - configure the receive control register
+ * @adapter: Board private structure
+ **/
+
+static void
+e1000_setup_rctl(struct e1000_adapter *adapter)
+{
+	uint32_t rctl;
+
+	/* Setup the Receive Control Register */
+	rctl = E1000_RCTL_EN | E1000_RCTL_BAM |
+	       E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+	       (adapter->shared.mc_filter_type << E1000_RCTL_MO_SHIFT);
+
+	if(adapter->shared.tbi_compatibility_on == 1)
+		rctl |= E1000_RCTL_SBP;
+
+	switch (adapter->rx_buffer_len) {
+	case E1000_RXBUFFER_2048:
+	default:
+		rctl |= E1000_RCTL_SZ_2048;
+		break;
+	case E1000_RXBUFFER_4096:
+		rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		break;
+	case E1000_RXBUFFER_8192:
+		rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		break;
+	case E1000_RXBUFFER_16384:
+		rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		break;
+	}
+
+	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+}
+
+/**
+ * e1000_configure_rx - Configure 8254x Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+
+static void
+e1000_configure_rx(struct e1000_adapter *adapter)
+{
+	uint64_t rdba = adapter->rx_ring.dma;
+	uint32_t rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+	uint32_t rctl;
+	uint32_t rxcsum;
+
+	/* make sure receives are disabled while setting up the descriptors */
+
+	rctl = E1000_READ_REG(&adapter->shared, RCTL);
+	E1000_WRITE_REG(&adapter->shared, RCTL, rctl & ~E1000_RCTL_EN);
+
+	/* set the Receive Delay Timer Register */
+
+	E1000_WRITE_REG(&adapter->shared, RDTR,
+	                adapter->rx_int_delay | E1000_RDT_FPDB);
+
+	/* Setup the Base and Length of the Rx Descriptor Ring */
+
+	E1000_WRITE_REG(&adapter->shared, RDBAL, (rdba & 0x00000000FFFFFFFF));
+	E1000_WRITE_REG(&adapter->shared, RDBAH, (rdba >> 32));
+
+	E1000_WRITE_REG(&adapter->shared, RDLEN, rdlen);
+
+	/* Setup the HW Rx Head and Tail Descriptor Pointers */
+	E1000_WRITE_REG(&adapter->shared, RDH, 0);
+	E1000_WRITE_REG(&adapter->shared, RDT, 0);
+
+	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
+	if((adapter->shared.mac_type >= e1000_82543) &&
+	   (adapter->rx_csum == TRUE)) {
+		rxcsum = E1000_READ_REG(&adapter->shared, RXCSUM);
+		rxcsum |= E1000_RXCSUM_TUOFL;
+		E1000_WRITE_REG(&adapter->shared, RXCSUM, rxcsum);
+	}
+
+#ifdef CONFIG_PPC
+	if(adapter->shared.mac_type >= e1000_82543) {
+		E1000_WRITE_REG(&adapter->shared, RXDCTL, 0x00020000);
+	}
+#endif
+
+	/* Enable Receives */
+
+	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+
+	return;
+}
+
+/**
+ * e1000_free_tx_resources - Free Tx Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+static void
+e1000_free_tx_resources(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	e1000_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;
+
+	return;
+}
+
+/**
+ * e1000_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_tx_ring(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	int i;
+
+	/* 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 e1000_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);
+
+	atomic_set(&adapter->tx_ring.unused, adapter->tx_ring.count);
+	adapter->tx_ring.next_to_use = 0;
+	adapter->tx_ring.next_to_clean = 0;
+
+	E1000_WRITE_REG(&adapter->shared, TDH, 0);
+	E1000_WRITE_REG(&adapter->shared, TDT, 0);
+
+	return;
+}
+
+/**
+ * e1000_free_rx_resources - Free Rx Resources
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+static void
+e1000_free_rx_resources(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	e1000_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;
+
+	return;
+}
+
+/**
+ * e1000_clean_rx_ring - Free Rx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_rx_ring(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	unsigned long size;
+	int i;
+
+	/* 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 e1000_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.unused_count = adapter->rx_ring.count;
+	adapter->rx_ring.next_to_clean = 0;
+	adapter->rx_ring.next_to_use = 0;
+
+	E1000_WRITE_REG(&adapter->shared, RDH, 0);
+	E1000_WRITE_REG(&adapter->shared, RDT, 0);
+
+	return;
+}
+
+/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
+ * and memory write and invalidate disabled for certain operations
+ */
+static void
+e1000_enter_82542_rst(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	uint16_t pci_command_word = adapter->shared.pci_cmd_word;
+	uint32_t rctl;
+
+	if(pci_command_word & PCI_COMMAND_INVALIDATE) {
+		pci_command_word &= ~PCI_COMMAND_INVALIDATE;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command_word);
+	}
+
+	rctl = E1000_READ_REG(&adapter->shared, RCTL);
+	rctl |= E1000_RCTL_RST;
+	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+	msec_delay(5);
+
+	if(netif_running(netdev))
+		e1000_clean_rx_ring(adapter);
+	return;
+}
+
+static void
+e1000_leave_82542_rst(struct e1000_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	uint16_t pci_command_word = adapter->shared.pci_cmd_word;
+	uint32_t rctl;
+
+	rctl = E1000_READ_REG(&adapter->shared, RCTL);
+	rctl &= ~E1000_RCTL_RST;
+	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+	msec_delay(5);
+
+	if(pci_command_word & PCI_COMMAND_INVALIDATE)
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command_word);
+
+	if(netif_running(netdev)) {
+		e1000_configure_rx(adapter);
+		e1000_alloc_rx_buffers(adapter);
+	}
+	return;
+}
+
+/**
+ * e1000_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+e1000_set_mac(struct net_device *netdev, void *p)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	struct sockaddr *addr = p;
+
+	/* 82542 2.0 needs to be in reset to write receive address registers */
+
+	if(adapter->shared.mac_type == e1000_82542_rev2_0)
+		e1000_enter_82542_rst(adapter);
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->shared.mac_addr, addr->sa_data, netdev->addr_len);
+
+	e1000_rar_set(&adapter->shared, adapter->shared.mac_addr, 0);
+
+	if(adapter->shared.mac_type == e1000_82542_rev2_0)
+		e1000_leave_82542_rst(adapter);
+
+	return 0;
+}
+
+/**
+ * e1000_set_multi - Multicast and Promiscuous mode set
+ * @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.
+ **/
+
+static void
+e1000_set_multi(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct dev_mc_list *mc_ptr;
+	uint32_t rctl;
+	uint32_t hash_value;
+	int i;
+
+	/* Check for Promiscuous and All Multicast modes */
+
+	rctl = E1000_READ_REG(shared, RCTL);
+
+	if(netdev->flags & IFF_PROMISC) {
+		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
+	} else if(netdev->flags & IFF_ALLMULTI) {
+		rctl |= E1000_RCTL_MPE;
+		rctl &= ~E1000_RCTL_UPE;
+	} else {
+		rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
+	}
+
+	E1000_WRITE_REG(shared, RCTL, rctl);
+
+	/* 82542 2.0 needs to be in reset to write receive address registers */
+
+	if(shared->mac_type == e1000_82542_rev2_0)
+		e1000_enter_82542_rst(adapter);
+
+	/* load the first 15 multicast address into the exact filters 1-15
+	 * RAR 0 is used for the station MAC adddress
+	 * if there are not 15 addresses, go ahead and clear the filters
+	 */
+	mc_ptr = netdev->mc_list;
+
+	for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+		if(mc_ptr) {
+			e1000_rar_set(shared, mc_ptr->dmi_addr, i);
+			mc_ptr = mc_ptr->next;
+		} else {
+			E1000_WRITE_REG_ARRAY(shared, RA, i << 1, 0);
+			E1000_WRITE_REG_ARRAY(shared, RA, (i << 1) + 1, 0);
+		}
+	}
+
+	/* clear the old settings from the multicast hash table */
+
+	for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+		E1000_WRITE_REG_ARRAY(shared, MTA, i, 0);
+
+	/* load any remaining addresses into the hash table */
+
+	for(; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = e1000_hash_mc_addr(shared, mc_ptr->dmi_addr);
+		e1000_mta_set(shared, hash_value);
+	}
+
+	if(shared->mac_type == e1000_82542_rev2_0)
+		e1000_leave_82542_rst(adapter);
+	return;
+}
+
+
+/* need to wait a few seconds after link up to get diagnostic information from the phy */
+
+static void
+e1000_update_phy_info(unsigned long data)
+{
+	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	e1000_phy_get_info(&adapter->shared, &adapter->phy_info);
+	return;
+}
+
+/**
+ * e1000_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ **/
+
+static void
+e1000_watchdog(unsigned long data)
+{
+	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct net_device *netdev = adapter->netdev;
+
+	e1000_check_for_link(&adapter->shared);
+
+	if(E1000_READ_REG(&adapter->shared, STATUS) & E1000_STATUS_LU) {
+		if(!netif_carrier_ok(netdev)) {
+			e1000_get_speed_and_duplex(&adapter->shared,
+			                           &adapter->link_speed,
+			                           &adapter->link_duplex);
+
+			printk(KERN_INFO
+			       "e1000: %s NIC Link is Up %d Mbps %s\n",
+			       netdev->name, adapter->link_speed,
+			       adapter->link_duplex == FULL_DUPLEX ?
+			       "Full Duplex" : "Half Duplex");
+
+			netif_carrier_on(netdev);
+			adapter->trans_finish = jiffies;
+			netif_wake_queue(netdev);
+			mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
+		}
+	} else {
+		if(netif_carrier_ok(netdev)) {
+			adapter->link_speed = 0;
+			adapter->link_duplex = 0;
+			printk(KERN_INFO
+			       "e1000: %s NIC Link is Down\n",
+			       netdev->name);
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	}
+
+	e1000_update_stats(adapter);
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+
+	return;
+}
+
+/**
+ * e1000_xmit_frame - Transmit entry point
+ * @skb: buffer with frame data to transmit
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, 1 on error
+ *
+ * e1000_xmit_frame is called by the stack to initiate a transmit.
+ * The out of resource condition is checked after each successful Tx
+ * so that the stack can be notified, preventing the driver from
+ * ever needing to drop a frame.  The atomic operations on
+ * tx_ring.unused are used to syncronize with the transmit
+ * interrupt processing code without the need for a spinlock.
+ **/
+
+#define TXD_USE_COUNT(x) (((x) >> 12) + ((x) & 0x0fff ? 1 : 0))
+
+#define SETUP_TXD_PAGE(L, P, O) do { \
+	tx_ring->buffer_info[i].length = (L); \
+	tx_ring->buffer_info[i].dma = \
+		pci_map_page(pdev, (P), (O), (L), PCI_DMA_TODEVICE); \
+	tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); \
+	tx_desc->lower.data = cpu_to_le32(txd_lower | (L)); \
+	tx_desc->upper.data = cpu_to_le32(txd_upper); \
+} while (0)
+
+#define SETUP_TXD_PTR(L, P) \
+	SETUP_TXD_PAGE((L), virt_to_page(P), (unsigned long)(P) & ~PAGE_MASK)
+
+#define QUEUE_TXD() do { i = (i + 1) % tx_ring->count; \
+                         atomic_dec(&tx_ring->unused); } while (0)
+
+
+static int
+e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	struct e1000_tx_desc *tx_desc;
+	int f, len, offset, txd_needed;
+	skb_frag_t *frag;
+
+	int i = tx_ring->next_to_use;
+	uint32_t txd_upper = 0;
+	uint32_t txd_lower = adapter->txd_cmd;
+
+
+	/* If controller appears hung, force transmit timeout */
+
+	if (time_after(netdev->trans_start, adapter->trans_finish + HZ) &&
+	    /* If transmitting XOFFs, we're not really hung */
+	    !(E1000_READ_REG(&adapter->shared, STATUS) & E1000_STATUS_TXOFF)) {
+		adapter->trans_finish = jiffies;
+		netif_stop_queue(netdev);
+		return 1;
+	}
+
+	txd_needed = TXD_USE_COUNT(skb->len - skb->data_len);
+
+	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
+		frag = &skb_shinfo(skb)->frags[f];
+		txd_needed += TXD_USE_COUNT(frag->size);
+	}
+
+	if(skb->ip_summed == CHECKSUM_HW)
+		txd_needed += 1;
+
+	/* make sure there are enough Tx descriptors available in the ring */
+
+	if(atomic_read(&tx_ring->unused) <= (txd_needed + 1)) {
+		adapter->net_stats.tx_dropped++;
+		netif_stop_queue(netdev);
+		return 1;
+	}
+
+	if(skb->ip_summed == CHECKSUM_HW) {
+		struct e1000_context_desc *context_desc;
+		uint8_t css = skb->h.raw - skb->data;
+		uint8_t cso = (skb->h.raw + skb->csum) - skb->data;
+
+		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+
+		context_desc->upper_setup.tcp_fields.tucss = css;
+		context_desc->upper_setup.tcp_fields.tucso = cso;
+		context_desc->upper_setup.tcp_fields.tucse = 0;
+		context_desc->tcp_seg_setup.data = 0;
+		context_desc->cmd_and_length =
+			cpu_to_le32(txd_lower | E1000_TXD_CMD_DEXT);
+
+		QUEUE_TXD();
+
+		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+	}
+
+	tx_desc = E1000_TX_DESC(*tx_ring, i);
+	len = skb->len - skb->data_len;
+	offset = 0;
+
+	while(len > 4096) {
+		SETUP_TXD_PTR(4096, skb->data + offset);
+		QUEUE_TXD();
+
+		tx_desc = E1000_TX_DESC(*tx_ring, i);
+		len -= 4096;
+		offset += 4096;
+	}
+
+	SETUP_TXD_PTR(len, skb->data + offset);
+
+	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
+		frag = &skb_shinfo(skb)->frags[f];
+
+		QUEUE_TXD();
+
+		tx_desc = E1000_TX_DESC(*tx_ring, i);
+		len = frag->size;
+		offset = 0;
+
+		while(len > 4096) {
+			SETUP_TXD_PAGE(4096, frag->page,
+			               frag->page_offset + offset);
+			QUEUE_TXD();
+
+			tx_desc = E1000_TX_DESC(*tx_ring, i);
+			len -= 4096;
+			offset += 4096;
+		}
+		SETUP_TXD_PAGE(len, frag->page, frag->page_offset + offset);
+	}
+
+	/* EOP and SKB pointer go with the last fragment */
+
+	tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
+	tx_ring->buffer_info[i].skb = skb;
+
+	QUEUE_TXD();
+
+	tx_ring->next_to_use = i;
+
+	/* Move the HW Tx Tail Pointer */
+
+	E1000_WRITE_REG(&adapter->shared, TDT, i);
+
+	netdev->trans_start = jiffies;
+
+	return 0;
+}
+
+#undef TXD_USE_COUNT
+#undef SETUP_TXD
+#undef QUEUE_TXD
+
+/**
+ * e1000_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ **/
+
+static void
+e1000_tx_timeout(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	e1000_down(adapter);
+	e1000_up(adapter);
+}
+
+/**
+ * e1000_get_stats - Get System Network Statistics
+ * @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 *
+e1000_get_stats(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	return &adapter->net_stats;
+}
+
+/**
+ * e1000_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+e1000_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	int old_mtu = adapter->rx_buffer_len;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + CRC_LENGTH;
+
+	if((max_frame < MINIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH) ||
+	   (max_frame > MAX_JUMBO_FRAME_SIZE + CRC_LENGTH)) {
+		E1000_ERR("Invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	if(max_frame <= MAXIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH) {
+		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
+	} else if(adapter->shared.mac_type < e1000_82543) {
+		E1000_ERR("Jumbo Frames not supported on 82542\n");
+		return -EINVAL;
+
+	} else if(max_frame <= E1000_RXBUFFER_2048) {
+		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
+	} else if(max_frame <= E1000_RXBUFFER_4096) {
+		adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+
+	} else if(max_frame <= E1000_RXBUFFER_8192) {
+		adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+
+	} else {
+		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+	}
+
+	if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+
+		e1000_down(adapter);
+		e1000_clean_rx_ring(adapter);
+		e1000_clean_tx_ring(adapter);
+		e1000_up(adapter);
+	}
+
+	netdev->mtu = new_mtu;
+	adapter->shared.max_frame_size = max_frame;
+
+	return 0;
+}
+
+/**
+ * e1000_update_stats - Update the board statistics counters
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_update_stats(struct e1000_adapter *adapter)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	unsigned long flags;
+
+#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
+
+	spin_lock_irqsave(&adapter->stats_lock, flags);
+
+	/* these counters are modified from e1000_adjust_tbi_stats,
+	 * called from the interrupt context, so they must only
+	 * be written while holding adapter->stats_lock
+	 */
+
+	adapter->stats.crcerrs += E1000_READ_REG(shared, CRCERRS);
+	adapter->stats.gprc += E1000_READ_REG(shared, GPRC);
+	adapter->stats.gorcl += E1000_READ_REG(shared, GORCL);
+	adapter->stats.gorch += E1000_READ_REG(shared, GORCH);
+	adapter->stats.bprc += E1000_READ_REG(shared, BPRC);
+	adapter->stats.mprc += E1000_READ_REG(shared, MPRC);
+	adapter->stats.roc += E1000_READ_REG(shared, ROC);
+	adapter->stats.prc64 += E1000_READ_REG(shared, PRC64);
+	adapter->stats.prc127 += E1000_READ_REG(shared, PRC127);
+	adapter->stats.prc255 += E1000_READ_REG(shared, PRC255);
+	adapter->stats.prc511 += E1000_READ_REG(shared, PRC511);
+	adapter->stats.prc1023 += E1000_READ_REG(shared, PRC1023);
+	adapter->stats.prc1522 += E1000_READ_REG(shared, PRC1522);
+
+	spin_unlock_irqrestore(&adapter->stats_lock, flags);
+
+	/* the rest of the counters are only modified here */
+
+	adapter->stats.symerrs += E1000_READ_REG(shared, SYMERRS);
+	adapter->stats.mpc += E1000_READ_REG(shared, MPC);
+	adapter->stats.scc += E1000_READ_REG(shared, SCC);
+	adapter->stats.ecol += E1000_READ_REG(shared, ECOL);
+	adapter->stats.mcc += E1000_READ_REG(shared, MCC);
+	adapter->stats.latecol += E1000_READ_REG(shared, LATECOL);
+	adapter->stats.colc += E1000_READ_REG(shared, COLC);
+	adapter->stats.dc += E1000_READ_REG(shared, DC);
+	adapter->stats.sec += E1000_READ_REG(shared, SEC);
+	adapter->stats.rlec += E1000_READ_REG(shared, RLEC);
+	adapter->stats.xonrxc += E1000_READ_REG(shared, XONRXC);
+	adapter->stats.xontxc += E1000_READ_REG(shared, XONTXC);
+	adapter->stats.xoffrxc += E1000_READ_REG(shared, XOFFRXC);
+	adapter->stats.xofftxc += E1000_READ_REG(shared, XOFFTXC);
+	adapter->stats.fcruc += E1000_READ_REG(shared, FCRUC);
+	adapter->stats.gptc += E1000_READ_REG(shared, GPTC);
+	adapter->stats.gotcl += E1000_READ_REG(shared, GOTCL);
+	adapter->stats.gotch += E1000_READ_REG(shared, GOTCH);
+	adapter->stats.rnbc += E1000_READ_REG(shared, RNBC);
+	adapter->stats.ruc += E1000_READ_REG(shared, RUC);
+	adapter->stats.rfc += E1000_READ_REG(shared, RFC);
+	adapter->stats.rjc += E1000_READ_REG(shared, RJC);
+	adapter->stats.torl += E1000_READ_REG(shared, TORL);
+	adapter->stats.torh += E1000_READ_REG(shared, TORH);
+	adapter->stats.totl += E1000_READ_REG(shared, TOTL);
+	adapter->stats.toth += E1000_READ_REG(shared, TOTH);
+	adapter->stats.tpr += E1000_READ_REG(shared, TPR);
+	adapter->stats.tpt += E1000_READ_REG(shared, TPT);
+	adapter->stats.ptc64 += E1000_READ_REG(shared, PTC64);
+	adapter->stats.ptc127 += E1000_READ_REG(shared, PTC127);
+	adapter->stats.ptc255 += E1000_READ_REG(shared, PTC255);
+	adapter->stats.ptc511 += E1000_READ_REG(shared, PTC511);
+	adapter->stats.ptc1023 += E1000_READ_REG(shared, PTC1023);
+	adapter->stats.ptc1522 += E1000_READ_REG(shared, PTC1522);
+	adapter->stats.mptc += E1000_READ_REG(shared, MPTC);
+	adapter->stats.bptc += E1000_READ_REG(shared, BPTC);
+
+	if(adapter->shared.mac_type >= e1000_82543) {
+		adapter->stats.algnerrc += E1000_READ_REG(shared, ALGNERRC);
+		adapter->stats.rxerrc += E1000_READ_REG(shared, RXERRC);
+		adapter->stats.tncrs += E1000_READ_REG(shared, TNCRS);
+		adapter->stats.cexterr += E1000_READ_REG(shared, CEXTERR);
+		adapter->stats.tsctc += E1000_READ_REG(shared, TSCTC);
+		adapter->stats.tsctfc += E1000_READ_REG(shared, TSCTFC);
+	}
+
+	/* Fill out the OS statistics structure */
+
+	adapter->net_stats.rx_packets = adapter->stats.gprc;
+	adapter->net_stats.tx_packets = adapter->stats.gptc;
+	adapter->net_stats.rx_bytes = adapter->stats.gorcl;
+	adapter->net_stats.tx_bytes = adapter->stats.gotcl;
+	adapter->net_stats.multicast = adapter->stats.mprc;
+	adapter->net_stats.collisions = adapter->stats.colc;
+
+	/* Rx Errors */
+
+	adapter->net_stats.rx_errors = adapter->stats.rxerrc +
+		adapter->stats.crcerrs + adapter->stats.algnerrc +
+		adapter->stats.rlec + adapter->stats.rnbc +
+		adapter->stats.mpc + adapter->stats.cexterr;
+	adapter->net_stats.rx_dropped = adapter->stats.rnbc;
+	adapter->net_stats.rx_length_errors = adapter->stats.rlec;
+	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
+	adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
+	adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
+	adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
+
+	/* Tx Errors */
+
+	adapter->net_stats.tx_errors = adapter->stats.ecol +
+	                               adapter->stats.latecol;
+	adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
+	adapter->net_stats.tx_window_errors = adapter->stats.latecol;
+
+	/* Tx Dropped needs to be maintained elsewhere */
+
+	if(adapter->shared.media_type == e1000_media_type_copper) {
+		adapter->phy_stats.idle_errors +=
+			(e1000_read_phy_reg(shared, PHY_1000T_STATUS)
+			 & PHY_IDLE_ERROR_COUNT_MASK);
+		adapter->phy_stats.receive_errors +=
+			e1000_read_phy_reg(shared, M88E1000_RX_ERR_CNTR);
+	}
+	return;
+}
+
+/**
+ * e1000_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_disable(struct e1000_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	E1000_WRITE_REG(&adapter->shared, IMC, ~0);
+	synchronize_irq();
+	return;
+}
+
+/**
+ * e1000_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_enable(struct e1000_adapter *adapter)
+{
+	if(atomic_dec_and_test(&adapter->irq_sem))
+		E1000_WRITE_REG(&adapter->shared, IMS, IMS_ENABLE_MASK);
+	return;
+}
+
+/**
+ * e1000_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ **/
+
+static void
+e1000_intr(int irq, void *data, struct pt_regs *regs)
+{
+	struct net_device *netdev = data;
+	struct e1000_adapter *adapter = netdev->priv;
+	uint32_t icr;
+	int i = E1000_MAX_INTR;
+
+	while(i && (icr = E1000_READ_REG(&adapter->shared, ICR))) {
+
+		if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+			/* run the watchdog ASAP */
+			adapter->shared.get_link_status = 1;
+			mod_timer(&adapter->watchdog_timer, jiffies);
+		}
+
+		e1000_clean_rx_irq(adapter);
+		e1000_clean_tx_irq(adapter);
+		i--;
+	}
+
+	return;
+}
+
+/**
+ * e1000_clean_tx_irq - Reclaim resources after transmit completes
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_tx_irq(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct e1000_tx_desc *tx_desc;
+	int i;
+
+	i = tx_ring->next_to_clean;
+	tx_desc = E1000_TX_DESC(*tx_ring, i);
+
+	while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+
+		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_irq(tx_ring->buffer_info[i].skb);
+
+			tx_ring->buffer_info[i].skb = NULL;
+		}
+
+		memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
+		mb();
+
+		atomic_inc(&tx_ring->unused);
+		i = (i + 1) % tx_ring->count;
+		tx_desc = E1000_TX_DESC(*tx_ring, i);
+
+		adapter->trans_finish = jiffies;
+	}
+
+	tx_ring->next_to_clean = i;
+
+	if(netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+	   (atomic_read(&tx_ring->unused) > E1000_TX_QUEUE_WAKE)) {
+
+		netif_wake_queue(netdev);
+	}
+	return;
+}
+
+/**
+ * e1000_clean_rx_irq - Send received data up the network stack,
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_rx_irq(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct e1000_rx_desc *rx_desc;
+	struct sk_buff *skb;
+	unsigned long flags;
+	uint32_t length;
+	uint8_t last_byte;
+	int i;
+
+	i = rx_ring->next_to_clean;
+	rx_desc = E1000_RX_DESC(*rx_ring, i);
+
+	while(rx_desc->status & E1000_RXD_STAT_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(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
+
+			/* All receives must fit into a single buffer */
+
+			E1000_DBG("Receive packet consumed multiple buffers\n");
+
+			dev_kfree_skb_irq(skb);
+			memset(rx_desc, 0, 16);
+			mb();
+			rx_ring->buffer_info[i].skb = NULL;
+
+			rx_ring->unused_count++;
+
+			i = (i + 1) % rx_ring->count;
+
+			rx_desc = E1000_RX_DESC(*rx_ring, i);
+			continue;
+		}
+
+		if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
+
+			last_byte = *(skb->data + length - 1);
+
+			if(TBI_ACCEPT(&adapter->shared, rx_desc->special,
+			              rx_desc->errors, length, last_byte)) {
+
+				spin_lock_irqsave(&adapter->stats_lock, flags);
+
+				e1000_tbi_adjust_stats(&adapter->shared,
+				                       &adapter->stats,
+				                       length, skb->data);
+
+				spin_unlock_irqrestore(&adapter->stats_lock,
+				                       flags);
+				length--;
+			} else {
+
+				dev_kfree_skb_irq(skb);
+				memset(rx_desc, 0, 16);
+				mb();
+				rx_ring->buffer_info[i].skb = NULL;
+
+				rx_ring->unused_count++;
+				i = (i + 1) % rx_ring->count;
+
+				rx_desc = E1000_RX_DESC(*rx_ring, i);
+				continue;
+			}
+		}
+
+		/* Good Receive */
+		skb_put(skb, length - CRC_LENGTH);
+
+		/* Receive Checksum Offload */
+		e1000_rx_checksum(adapter, rx_desc, skb);
+
+		skb->protocol = eth_type_trans(skb, netdev);
+		netif_rx(skb);
+
+		memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
+		mb();
+		rx_ring->buffer_info[i].skb = NULL;
+
+		rx_ring->unused_count++;
+
+		i = (i + 1) % rx_ring->count;
+
+		rx_desc = E1000_RX_DESC(*rx_ring, i);
+	}
+
+	rx_ring->next_to_clean = i;
+
+	e1000_alloc_rx_buffers(adapter);
+
+	return;
+}
+
+/**
+ * e1000_alloc_rx_buffers - Replace used receive buffers
+ * @data: address of board private structure
+ **/
+
+static void
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct e1000_rx_desc *rx_desc;
+	struct sk_buff *skb;
+	int reserve_len;
+	int i;
+
+	if(!netif_running(netdev))
+		return;
+
+	reserve_len = 2;
+
+	i = rx_ring->next_to_use;
+
+	while(!rx_ring->buffer_info[i].skb) {
+		rx_desc = E1000_RX_DESC(*rx_ring, i);
+
+		skb = alloc_skb(adapter->rx_buffer_len + reserve_len,
+		                GFP_ATOMIC);
+
+		if(!skb) {
+			/* Better luck next round */
+			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->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
+
+		/* move tail */
+		E1000_WRITE_REG(&adapter->shared, RDT, i);
+
+		atomic_dec(&rx_ring->unused);
+
+		i = (i + 1) % rx_ring->count;
+	}
+
+	rx_ring->next_to_use = i;
+	return;
+}
+
+/**
+ * e1000_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ **/
+
+static int
+e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return e1000_ethtool_ioctl(netdev, ifr);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/**
+ * e1000_rx_checksum - Receive Checksum Offload for 82543
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+e1000_rx_checksum(struct e1000_adapter *adapter,
+                  struct e1000_rx_desc *rx_desc,
+                  struct sk_buff *skb)
+{
+	/* 82543 or newer only */
+	if((adapter->shared.mac_type < e1000_82543) ||
+	/* Ignore Checksum bit is set */
+	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
+	/* TCP Checksum has not been calculated */
+	(!(rx_desc->status & E1000_RXD_STAT_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 & E1000_RXD_ERR_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_err++;
+	} else {
+	/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_good++;
+	}
+	return;
+}
+
+
+/**
+ * e1000_enable_WOL - Wake On Lan Support (Magic Pkt)
+ * @adapter: Adapter structure
+ **/
+
+void
+e1000_enable_WOL(struct e1000_adapter *adapter)
+{
+	uint32_t wuc;
+
+	if(adapter->shared.mac_type < e1000_82544)
+		return;
+
+	if(adapter->wol) {
+		wuc = E1000_WUC_APME | E1000_WUC_PME_EN |
+		      E1000_WUC_PME_STATUS | E1000_WUC_APMPME;
+
+		E1000_WRITE_REG(&adapter->shared, WUC, wuc);
+
+		E1000_WRITE_REG(&adapter->shared, WUFC, adapter->wol);
+	}
+
+	return;
+}
+
+void
+e1000_write_pci_cfg(struct e1000_shared_adapter *shared,
+                    uint32_t reg, uint16_t *value)
+{
+	struct e1000_adapter *adapter = shared->back;
+
+	pci_write_config_word(adapter->pdev, reg, *value);
+	return;
+}
+
+/* e1000_main.c */
diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_osdep.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,142 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+
+/* glue for the OS independant part of e1000 
+ * includes register access macros
+ */
+
+#ifndef _E1000_OSDEP_H_
+#define _E1000_OSDEP_H_
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+
+#define usec_delay(x) udelay(x)
+#define msec_delay(x)	do { if(in_interrupt()) { \
+	                	mdelay(x); \
+			} else { \
+				set_current_state(TASK_UNINTERRUPTIBLE); \
+				schedule_timeout((x * HZ)/1000); \
+			} } while(0)
+
+#define PCI_COMMAND_REGISTER   PCI_COMMAND
+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
+
+typedef enum {
+    FALSE = 0,
+    TRUE = 1
+} boolean_t;
+
+#define ASSERT(x)	if(!(x)) BUG()
+#define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
+
+#if DBG
+#define DEBUGOUT(S)		printk(KERN_DEBUG S "\n")
+#define DEBUGOUT1(S, A...)	printk(KERN_DEBUG S "\n", A)
+#else
+#define DEBUGOUT(S)
+#define DEBUGOUT1(S, A...)
+#endif
+
+#define DEBUGFUNC(F) DEBUGOUT(F)
+#define DEBUGOUT2 DEBUGOUT1
+#define DEBUGOUT3 DEBUGOUT2
+#define DEBUGOUT7 DEBUGOUT3
+
+
+#define E1000_WRITE_REG(a, reg, value) ( \
+    ((a)->mac_type >= e1000_82543) ? \
+        (writel((value), ((a)->hw_addr + E1000_##reg))) : \
+        (writel((value), ((a)->hw_addr + E1000_82542_##reg))))
+
+#define E1000_READ_REG(a, reg) ( \
+    ((a)->mac_type >= e1000_82543) ? \
+        readl((a)->hw_addr + E1000_##reg) : \
+        readl((a)->hw_addr + E1000_82542_##reg))
+
+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+    ((a)->mac_type >= e1000_82543) ? \
+        writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2))) : \
+        writel((value), ((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))))
+
+#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
+    ((a)->mac_type >= e1000_82543) ? \
+        readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \
+        readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))
+
+#endif /* _E1000_OSDEP_H_ */
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_param.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,709 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "e1000.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define E1000_MAX_NIC 32
+
+#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 e1000_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 E1000_PARAM_INIT { [0 ... E1000_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 E1000_PARAM(X, S) \
+static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
+MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \
+MODULE_PARM_DESC(X, S);
+
+/* Transmit Descriptor Count
+ *
+ * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
+ * Valid Range: 80-4096 for 82544
+ *
+ * Default Value: 256
+ */
+
+E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+/* Receive Descriptor Count
+ *
+ * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
+ * Valid Range: 80-4096 for 82544
+ *
+ * Default Value: 80
+ */
+
+E1000_PARAM(RxDescriptors, "Number of receive descriptors");
+
+/* User Specified Speed Override
+ *
+ * Valid Range: 0, 10, 100, 1000
+ *  - 0    - auto-negotiate at all supported speeds
+ *  - 10   - only link at 10 Mbps
+ *  - 100  - only link at 100 Mbps
+ *  - 1000 - only link at 1000 Mbps
+ *
+ * Default Value: 0
+ */
+
+E1000_PARAM(Speed, "Speed setting");
+
+/* User Specified Duplex Override
+ *
+ * Valid Range: 0-2
+ *  - 0 - auto-negotiate for duplex
+ *  - 1 - only link at half duplex
+ *  - 2 - only link at full duplex
+ *
+ * Default Value: 0
+ */
+
+E1000_PARAM(Duplex, "Duplex setting");
+
+/* Auto-negotiation Advertisement Override
+ *
+ * Valid Range: 0x00-0x0F, 0x20-0x2F
+ *
+ * The AutoNeg value is a bit mask describing which speed and duplex
+ * combinations should be advertised during auto-negotiation.
+ * The supported speed and duplex modes are listed below
+ *
+ * Bit           7     6     5      4      3     2     1      0
+ * Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
+ * Duplex                    Full          Full  Half  Full   Half
+ *
+ * Default Value: 0x2F
+ */
+
+E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
+
+/* 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
+ */
+
+E1000_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 82543 based NICs
+ *
+ * Default Value: 1
+ */
+
+E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
+
+/* Transmit Interrupt Delay in units of 1.024 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 64
+ */
+
+E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+
+/* Receive Interrupt Delay in units of 1.024 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 64
+ */
+
+E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
+
+/* MDI-X Support Enable/Disable - Applies only to Copper PHY
+ *
+ * Valid Range: 0, 3
+ *  - 0 - Auto in all modes
+ *  - 1 - MDI
+ *  - 2 - MDI-X
+ *  - 3 - Auto in 1000 Base-T mode (MDI in 10 Base-T and 100 Base-T)
+ *
+ * Default Value: 0 (Auto)
+ */
+
+E1000_PARAM(MdiX, "Set MDI/MDI-X Mode");
+
+/* Automatic Correction of Reversed Cable Polarity Enable/Disable
+ * This setting applies only to Copper PHY
+ *
+ * Valid Range: 0, 1
+ *  - 0 - Disabled
+ *  - 1 - Enabled
+ *
+ * Default Value: 1 (Enabled)
+ */
+
+E1000_PARAM(DisablePolarityCorrection,
+	"Disable or enable Automatic Correction for Reversed Cable Polarity");
+
+
+#define AUTONEG_ADV_DEFAULT  0x2F
+#define AUTONEG_ADV_MASK     0x2F
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
+
+#define DEFAULT_TXD                  256
+#define MAX_TXD                      256
+#define MIN_TXD                       80
+#define MAX_82544_TXD               4096
+
+#define DEFAULT_RXD                   80
+#define MAX_RXD                      256
+#define MIN_RXD                       80
+#define MAX_82544_RXD               4096
+
+#define DEFAULT_TIDV                  64
+#define MAX_TIDV                  0xFFFF
+#define MIN_TIDV                       0
+
+#define DEFAULT_RIDV                  64
+#define MAX_RIDV                  0xFFFF
+#define MIN_RIDV                       0
+
+#define DEFAULT_MDIX                   0
+#define MAX_MDIX                       3
+#define MIN_MDIX                       0
+
+
+struct e1000_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int  def;
+	union {
+		struct { /* range_option info */
+			int min;
+			int max;
+		} r;
+		struct { /* list_option info */
+			int nr;
+			struct e1000_opt_list { int i; char *str; } *p;
+		} l;
+	} arg;
+};
+
+
+static int __devinit
+e1000_validate_option(int *value, struct e1000_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 e1000_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\n", 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]))
+
+static void e1000_check_fiber_options(struct e1000_adapter *adapter);
+static void e1000_check_copper_options(struct e1000_adapter *adapter);
+
+/**
+ * e1000_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
+e1000_check_options(struct e1000_adapter *adapter)
+{
+	int bd = adapter->bd_number;
+	if(bd >= E1000_MAX_NIC) {
+		printk(KERN_NOTICE 
+		       "Warning: no configuration for board #%i\n", bd);
+		printk(KERN_NOTICE "Using defaults for all values\n");
+		bd = E1000_MAX_NIC;
+	}
+
+	{ /* Transmit Descriptor Count */
+		struct e1000_option opt = {
+			type: range_option,
+			name: "Transmit Descriptors",
+			err:  "using default of " __MODULE_STRING(DEFAULT_TXD),
+			def:  DEFAULT_TXD,
+			arg: { r: { min: MIN_TXD }}
+		};
+		struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+		e1000_mac_type mac_type = adapter->shared.mac_type;
+		opt.arg.r.max = mac_type < e1000_82544 ? MAX_TXD : MAX_82544_TXD;
+
+		tx_ring->count = TxDescriptors[bd];
+		e1000_validate_option(&tx_ring->count, &opt);
+		E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+	}
+	{ /* Receive Descriptor Count */
+		struct e1000_option opt = {
+			type: range_option,
+			name: "Receive Descriptors",
+			err:  "using default of " __MODULE_STRING(DEFAULT_RXD),
+			def:  DEFAULT_RXD,
+			arg: { r: { min: MIN_RXD }}
+		};
+		struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+		e1000_mac_type mac_type = adapter->shared.mac_type;
+		opt.arg.r.max = mac_type < e1000_82544 ? MAX_RXD : MAX_82544_RXD;
+
+		rx_ring->count = RxDescriptors[bd];
+		e1000_validate_option(&rx_ring->count, &opt);
+		E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+	}
+	{ /* Checksum Offload Enable/Disable */
+		struct e1000_option opt = {
+			type: enable_option,
+			name: "Checksum Offload",
+			err:  "defaulting to Enabled",
+			def:  OPTION_ENABLED
+		};
+		
+		int rx_csum = XsumRX[bd];
+		e1000_validate_option(&rx_csum, &opt);
+		adapter->rx_csum = rx_csum;
+	}
+	{ /* Flow Control */
+		
+		struct e1000_opt_list fc_list[] =
+			{{ e1000_fc_none,    "Flow Control Disabled" },
+			 { e1000_fc_rx_pause,"Flow Control Receive Only" },
+			 { e1000_fc_tx_pause,"Flow Control Transmit Only" },
+			 { e1000_fc_full,    "Flow Control Enabled" },
+			 { e1000_fc_default, "Flow Control Hardware Default" }};
+
+		struct e1000_option opt = {
+			type: list_option,
+			name: "Flow Control",
+			err:  "reading default settings from EEPROM",
+			def:  e1000_fc_default,
+			arg: { l: { nr: LIST_LEN(fc_list), p: fc_list }}
+		};
+
+		int fc = FlowControl[bd];
+		e1000_validate_option(&fc, &opt);
+		adapter->shared.fc = adapter->shared.original_fc = fc;
+	}
+	{ /* Transmit Interrupt Delay */
+		struct e1000_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[bd];
+		e1000_validate_option(&adapter->tx_int_delay, &opt);
+	}
+	{ /* Receive Interrupt Delay */
+		struct e1000_option opt = {
+			type: range_option,
+			name: "Receive Interrupt Delay",
+			err:  "using default of " __MODULE_STRING(DEFAULT_RIDV),
+			def:  DEFAULT_RIDV,
+			arg: { r: { min: MIN_RIDV, max: MAX_RIDV }}
+		};
+
+		adapter->rx_int_delay = RxIntDelay[bd];
+		e1000_validate_option(&adapter->rx_int_delay, &opt);
+	}
+	
+	switch(adapter->shared.media_type) {
+	case e1000_media_type_fiber:
+		e1000_check_fiber_options(adapter);
+		break;
+	case e1000_media_type_copper:
+		e1000_check_copper_options(adapter);
+		break;
+	default:
+		BUG();
+	}
+}
+
+/**
+ * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
+ * @adapter: board private structure
+ *
+ * Handles speed and duplex options on fiber adapters
+ **/
+
+static void __devinit
+e1000_check_fiber_options(struct e1000_adapter *adapter)
+{
+	int bd = adapter->bd_number;
+	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
+
+	if((Speed[bd] != OPTION_UNSET)) {
+		printk(KERN_INFO "Speed not valid for fiber adapters, "
+		       "parameter ignored\n");
+	}
+	if((Duplex[bd] != OPTION_UNSET)) {
+		printk(KERN_INFO "Duplex not valid for fiber adapters, "
+		       "parameter ignored\n");
+	}
+	if((AutoNeg[bd] != OPTION_UNSET)) {
+		printk(KERN_INFO "AutoNeg not valid for fiber adapters, "
+		       "parameter ignored\n");
+	}
+}
+
+/**
+ * e1000_check_copper_options - Range Checking for Link Options, Copper Version
+ * @adapter: board private structure
+ *
+ * Handles speed and duplex options on copper adapters
+ **/
+
+static void __devinit
+e1000_check_copper_options(struct e1000_adapter *adapter)
+{
+	int speed, dplx;
+	int bd = adapter->bd_number;
+	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
+
+	{ /* Speed */
+		struct e1000_opt_list speed_list[] = {{          0, "" },
+		                                      {   SPEED_10, "" },
+		                                      {  SPEED_100, "" },
+		                                      { SPEED_1000, "" }};
+		struct e1000_option opt = {
+			type: list_option,
+			name: "Speed",
+			err:  "parameter ignored",
+			def:  0,
+			arg: { l: { nr: LIST_LEN(speed_list), p: speed_list }}
+		};
+
+		speed = Speed[bd];
+		e1000_validate_option(&speed, &opt);
+	}
+	{ /* Duplex */
+		struct e1000_opt_list dplx_list[] = {{           0, "" },
+		                                     { HALF_DUPLEX, "" },
+		                                     { FULL_DUPLEX, "" }};
+		struct e1000_option opt = {
+			type: list_option,
+			name: "Duplex",
+			err:  "parameter ignored",
+			def:  0,
+			arg: { l: { nr: LIST_LEN(dplx_list), p: dplx_list }}
+		};
+
+		dplx = Duplex[bd];
+		e1000_validate_option(&dplx, &opt);
+	}
+
+	if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
+		printk(KERN_INFO
+		       "AutoNeg specified along with Speed or Duplex, "
+		       "parameter ignored\n");
+		adapter->shared.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+	} else { /* Autoneg */
+		struct e1000_opt_list an_list[] =
+			#define AA "Autoneg advertising "
+			{{ 0x01, AA "10/HD" },
+			 { 0x02, AA "10/FD" },
+			 { 0x03, AA "10/FD, 10/HD" },
+			 { 0x04, AA "100/HD" },
+			 { 0x05, AA "100/HD, 10/HD" },
+			 { 0x06, AA "100/HD, 10/FD" },
+			 { 0x07, AA "100/HD, 10/FD, 10/HD" },
+			 { 0x08, AA "100/FD" },
+			 { 0x09, AA "100/FD, 10/HD" },
+			 { 0x0a, AA "100/FD, 10/FD" },
+			 { 0x0b, AA "100/FD, 10/FD, 10/HD" },
+			 { 0x0c, AA "100/FD, 100/HD" },
+			 { 0x0d, AA "100/FD, 100/HD, 10/HD" },
+			 { 0x0e, AA "100/FD, 100/HD, 10/FD" },
+			 { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
+			 { 0x20, AA "1000/FD" },
+			 { 0x21, AA "1000/FD, 10/HD" },
+			 { 0x22, AA "1000/FD, 10/FD" },
+			 { 0x23, AA "1000/FD, 10/FD, 10/HD" },
+			 { 0x24, AA "1000/FD, 100/HD" },
+			 { 0x25, AA "1000/FD, 100/HD, 10/HD" },
+			 { 0x26, AA "1000/FD, 100/HD, 10/FD" },
+			 { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
+			 { 0x28, AA "1000/FD, 100/FD" },
+			 { 0x29, AA "1000/FD, 100/FD, 10/HD" },
+			 { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
+			 { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
+			 { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
+			 { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
+			 { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
+			 { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
+
+		struct e1000_option opt = {
+			type: list_option,
+			name: "Autoneg",
+			err:  "parameter ignored",
+			def:  AUTONEG_ADV_DEFAULT,
+			arg: { l: { nr: LIST_LEN(an_list), p: an_list }}
+		};
+
+		int an = AutoNeg[bd];
+		e1000_validate_option(&an, &opt);
+		adapter->shared.autoneg_advertised = an;
+	}
+
+	switch (speed + dplx) {
+	case 0:
+		adapter->shared.autoneg = 1;
+		if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
+			printk(KERN_INFO
+			       "Speed and duplex autonegotiation enabled\n");
+		break;
+	case HALF_DUPLEX:
+		printk(KERN_INFO "Half Duplex specified without Speed\n");
+		printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_10_HALF | 
+		                                     ADVERTISE_100_HALF;
+		break;
+	case FULL_DUPLEX:
+		printk(KERN_INFO "Full Duplex specified without Speed\n");
+		printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_10_FULL |
+		                                     ADVERTISE_100_FULL |
+		                                     ADVERTISE_1000_FULL;
+		break;
+	case SPEED_10:
+		printk(KERN_INFO "10 Mbps Speed specified without Duplex\n");
+		printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_10_HALF |
+		                                     ADVERTISE_10_FULL;
+		break;
+	case SPEED_10 + HALF_DUPLEX:
+		printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n");
+		adapter->shared.autoneg = 0;
+		adapter->shared.forced_speed_duplex = e1000_10_half;
+		adapter->shared.autoneg_advertised = 0;
+		break;
+	case SPEED_10 + FULL_DUPLEX:
+		printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n");
+		adapter->shared.autoneg = 0;
+		adapter->shared.forced_speed_duplex = e1000_10_full;
+		adapter->shared.autoneg_advertised = 0;
+		break;
+	case SPEED_100:
+		printk(KERN_INFO "100 Mbps Speed specified without Duplex\n");
+		printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_100_HALF |
+		                                     ADVERTISE_100_FULL;
+		break;
+	case SPEED_100 + HALF_DUPLEX:
+		printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n");
+		adapter->shared.autoneg = 0;
+		adapter->shared.forced_speed_duplex = e1000_100_half;
+		adapter->shared.autoneg_advertised = 0;
+		break;
+	case SPEED_100 + FULL_DUPLEX:
+		printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n");
+		adapter->shared.autoneg = 0;
+		adapter->shared.forced_speed_duplex = e1000_100_full;
+		adapter->shared.autoneg_advertised = 0;
+		break;
+	case SPEED_1000:
+		printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n");
+		printk(KERN_INFO
+		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		break;
+	case SPEED_1000 + HALF_DUPLEX:
+		printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n");
+		printk(KERN_INFO
+		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		break;
+	case SPEED_1000 + FULL_DUPLEX:
+		printk(KERN_INFO
+		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+		adapter->shared.autoneg = 1;
+		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		break;
+	default:
+		BUG();
+	}
+
+	/* a few other copper only options */
+
+	{ /* MDI/MDI-X */
+		struct e1000_option opt = {
+			type: range_option,
+			name: "MDI/MDI-X",
+			err:  "using default of " __MODULE_STRING(DEFAULT_MDIX),
+			def:  DEFAULT_MDIX,
+			arg: { r: { min: MIN_MDIX, max: MAX_MDIX }}
+		};
+
+		int mdix = MdiX[bd];
+		e1000_validate_option(&mdix, &opt);
+		adapter->shared.mdix = mdix;
+	}
+	{ /* Automatic Correction for Reverse Cable Polarity */
+	  /* option is actually to disable polarity correction,
+	   * so setting to OPTION_ENABLED turns the hardware feature off */
+		struct e1000_option opt = {
+			type: enable_option,
+			name: "Disable Polarity Correction",
+			err:  "defaulting to Disabled",
+			def:  OPTION_DISABLED,
+		};
+
+		int dpc = DisablePolarityCorrection[bd];
+		e1000_validate_option(&dpc, &opt);
+		adapter->shared.disable_polarity_correction = dpc;
+	}
+	
+	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
+	if (!e1000_validate_mdi_setting(&(adapter->shared))) {
+		printk(KERN_INFO "Speed, AutoNeg and MDI-X specifications are "
+		       "incompatible. Setting MDI-X to a compatible value.\n");
+	}
+}
+
diff -Nru a/drivers/net/e1000/e1000_phy.c b/drivers/net/e1000/e1000_phy.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_phy.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1485 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_phy.c
+ * Shared functions for accessing and configuring the PHY
+ */
+
+#include "e1000_mac.h"
+#include "e1000_phy.h"
+
+/******************************************************************************
+* Raises the Management Data Clock
+*
+* shared - Struct containing variables accessed by shared code
+* ctrl_reg - Device control register's current value
+******************************************************************************/
+static void
+e1000_raise_mdc(struct e1000_shared_adapter *shared,
+                uint32_t *ctrl_reg)
+{
+    /* Raise the clock input to the Management Data Clock (by setting
+     * the MDC bit), and then delay 2 microseconds.
+     */
+    E1000_WRITE_REG(shared, CTRL, (*ctrl_reg | E1000_CTRL_MDC));
+    usec_delay(2);
+    return;
+}
+
+/******************************************************************************
+* Lowers the Management Data Clock
+*
+* shared - Struct containing variables accessed by shared code
+* ctrl_reg - Device control register's current value
+******************************************************************************/
+static void
+e1000_lower_mdc(struct e1000_shared_adapter *shared,
+                uint32_t *ctrl_reg)
+{
+    /* Lower the clock input to the Management Data Clock (by clearing
+     * the MDC bit), and then delay 2 microseconds.
+     */
+    E1000_WRITE_REG(shared, CTRL, (*ctrl_reg & ~E1000_CTRL_MDC));
+    usec_delay(2);
+    return;
+}
+
+/******************************************************************************
+* Shifts data bits out to the PHY
+*
+* shared - Struct containing variables accessed by shared code
+* data - Data to send out to the PHY
+* count - Number of bits to shift out
+*
+* Bits are shifted out in MSB to LSB order.
+******************************************************************************/
+static void
+e1000_phy_shift_out(struct e1000_shared_adapter *shared,
+                    uint32_t data,
+                    uint16_t count)
+{
+    uint32_t ctrl_reg;
+    uint32_t mask;
+
+    ASSERT(count <= 32);
+
+    /* We need to shift "count" number of bits out to the PHY.  So, the
+     * value in the "Data" parameter will be shifted out to the PHY
+     * one bit at a time.  In order to do this, "Data" must be broken
+     * down into bits, which is what the "while" logic does below.
+     */
+    mask = 0x01;
+    mask <<= (count - 1);
+
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    /* Set MDIO_DIR (SWDPIO1) and MDC_DIR (SWDPIO2) direction bits to
+     * be used as output pins.
+     */
+    ctrl_reg |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
+
+    while(mask) {
+        /* A "1" is shifted out to the PHY by setting the MDIO bit to
+         * "1" and then raising and lowering the Management Data Clock
+         * (MDC).  A "0" is shifted out to the PHY by setting the MDIO
+         * bit to "0" and then raising and lowering the clock.
+         */
+        if(data & mask)
+            ctrl_reg |= E1000_CTRL_MDIO;
+        else
+            ctrl_reg &= ~E1000_CTRL_MDIO;
+
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+        usec_delay(2);
+
+        e1000_raise_mdc(shared, &ctrl_reg);
+        e1000_lower_mdc(shared, &ctrl_reg);
+
+        mask = mask >> 1;
+    }
+
+    /* Clear the data bit just before leaving this routine. */
+    ctrl_reg &= ~E1000_CTRL_MDIO;
+    return;
+}
+
+/******************************************************************************
+* Shifts data bits in from the PHY
+*
+* shared - Struct containing variables accessed by shared code
+*
+* Bits are shifted in in MSB to LSB order. 
+******************************************************************************/
+static uint16_t
+e1000_phy_shift_in(struct e1000_shared_adapter *shared)
+{
+    uint32_t ctrl_reg;
+    uint16_t data = 0;
+    uint8_t i;
+
+    /* In order to read a register from the PHY, we need to shift in a
+     * total of 18 bits from the PHY.  The first two bit (TurnAround)
+     * times are used to avoid contention on the MDIO pin when a read
+     * operation is performed.  These two bits are ignored by us and
+     * thrown away.  Bits are "shifted in" by raising the clock input
+     * to the Management Data Clock (setting the MDC bit), and then
+     * reading the value of the MDIO bit.
+     */ 
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
+     * input.
+     */ 
+    ctrl_reg &= ~E1000_CTRL_MDIO_DIR;
+    ctrl_reg &= ~E1000_CTRL_MDIO;
+
+    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+    /* Raise and Lower the clock before reading in the data.  This
+     * accounts for the TurnAround bits.  The first clock occurred
+     * when we clocked out the last bit of the Register Address.
+     */
+    e1000_raise_mdc(shared, &ctrl_reg);
+    e1000_lower_mdc(shared, &ctrl_reg);
+
+    for(data = 0, i = 0; i < 16; i++) {
+        data = data << 1;
+        e1000_raise_mdc(shared, &ctrl_reg);
+
+        ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+        /* Check to see if we shifted in a "1". */
+        if(ctrl_reg & E1000_CTRL_MDIO)
+            data |= 1;
+
+        e1000_lower_mdc(shared, &ctrl_reg);
+    }
+
+    e1000_raise_mdc(shared, &ctrl_reg);
+    e1000_lower_mdc(shared, &ctrl_reg);
+
+    /* Clear the MDIO bit just before leaving this routine. */
+    ctrl_reg &= ~E1000_CTRL_MDIO;
+
+    return (data);
+}
+
+/******************************************************************************
+* Force PHY speed and duplex settings to shared->forced_speed_duplex
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+static void
+e1000_phy_force_speed_duplex(struct e1000_shared_adapter *shared)
+{
+    uint32_t tctl_reg;
+    uint32_t ctrl_reg;
+    uint32_t shift;
+    uint16_t mii_ctrl_reg;
+    uint16_t mii_status_reg;
+    uint16_t phy_data;
+    uint16_t i;
+
+    DEBUGFUNC("e1000_phy_force_speed_duplex");
+
+    /* Turn off Flow control if we are forcing speed and duplex. */
+    shared->fc = e1000_fc_none;
+
+    DEBUGOUT1("shared->fc = %d\n", shared->fc);
+
+    /* Read the Device Control Register. */
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
+    ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+    ctrl_reg &= ~(DEVICE_SPEED_MASK);
+
+    /* Clear the Auto Speed Detect Enable bit. */
+    ctrl_reg &= ~E1000_CTRL_ASDE;
+
+    /* Read the MII Control Register. */
+    mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
+
+    /* We need to disable autoneg in order to force link and duplex. */
+
+    mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
+
+    /* Are we forcing Full or Half Duplex? */
+    if(shared->forced_speed_duplex == e1000_100_full ||
+       shared->forced_speed_duplex == e1000_10_full) {
+
+        /* We want to force full duplex so we SET the full duplex bits
+         * in the Device and MII Control Registers.
+         */
+        ctrl_reg |= E1000_CTRL_FD;
+        mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
+
+        DEBUGOUT("Full Duplex\n");
+    } else {
+
+        /* We want to force half duplex so we CLEAR the full duplex
+         * bits in the Device and MII Control Registers.
+         */
+        ctrl_reg &= ~E1000_CTRL_FD;
+        mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;    /* Do this implies HALF */
+
+        DEBUGOUT("Half Duplex\n");
+    }
+
+    /* Are we forcing 100Mbps??? */
+    if(shared->forced_speed_duplex == e1000_100_full ||
+       shared->forced_speed_duplex == e1000_100_half) {
+
+        /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
+        ctrl_reg |= E1000_CTRL_SPD_100;
+        mii_ctrl_reg |= MII_CR_SPEED_100;
+        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
+
+        DEBUGOUT("Forcing 100mb ");
+    } else {                    /* Force 10MB Full or Half */
+
+        /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
+        ctrl_reg &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+        mii_ctrl_reg |= MII_CR_SPEED_10;
+        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
+
+        DEBUGOUT("Forcing 10mb ");
+    }
+
+    /* Now we need to configure the Collision Distance.  We need to read
+     * the Transmit Control Register to do this.
+     * Note: This must be done for both Half or Full Duplex.
+     */
+    tctl_reg = E1000_READ_REG(shared, TCTL);
+    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
+
+    if(!(mii_ctrl_reg & MII_CR_FULL_DUPLEX)) {
+
+       /* We are in Half Duplex mode so we need to set up our collision
+        * distance for 10/100.
+        */
+        tctl_reg &= ~E1000_TCTL_COLD;
+        shift = E1000_HDX_COLLISION_DISTANCE;
+        shift <<= E1000_COLD_SHIFT;
+        tctl_reg |= shift;
+    } else {
+        /* We are in Full Duplex mode.  We have the same collision
+         * distance regardless of speed.
+         */
+        tctl_reg &= ~E1000_TCTL_COLD;
+        shift = E1000_FDX_COLLISION_DISTANCE;
+        shift <<= E1000_COLD_SHIFT;
+        tctl_reg |= shift;
+    }
+
+    /* Write the configured values back to the Transmit Control Reg. */
+    E1000_WRITE_REG(shared, TCTL, tctl_reg);
+
+    /* Write the configured values back to the Device Control Reg. */
+    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+    /* Write the MII Control Register with the new PHY configuration. */
+    phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+
+    /* Clear Auto-Crossover to force MDI manually.
+     * M88E1000 requires MDI forced whenever speed/duplex is forced
+     */
+    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_data);
+
+    DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
+
+    /* Need to reset the PHY or these bits will get ignored. */
+    mii_ctrl_reg |= MII_CR_RESET;
+
+    e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
+
+    /* The wait_autoneg_complete flag may be a little misleading here.
+     * Since we are forcing speed and duplex, Auto-Neg is not enabled.
+     * But we do want to delay for a period while forcing only so we
+     * don't generate false No Link messages.  So we will wait here
+     * only if the user has set wait_autoneg_complete to 1, which is
+     * the default.
+     */
+    if(shared->wait_autoneg_complete) {
+        /* We will wait for autoneg to complete. */
+        DEBUGOUT("Waiting for forced speed/duplex link.\n");
+        mii_status_reg = 0;
+
+        /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+        for(i = PHY_FORCE_TIME; i > 0; i--) {
+            /* Read the MII Status Register and wait for Auto-Neg
+             * Complete bit to be set.
+             */
+            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+            if(mii_status_reg & MII_SR_LINK_STATUS)
+                break;
+
+            msec_delay(100);
+        }                       /* end for loop */
+
+        if(i == 0) {            /* We didn't get link   */
+
+            /* Reset the DSP and wait again for link.   */
+            e1000_phy_reset_dsp(shared);
+        }
+
+        /* This loop will early-out if the link condition has been met.  */
+        for(i = PHY_FORCE_TIME; i > 0; i--) {
+            if(mii_status_reg & MII_SR_LINK_STATUS)
+                break;
+
+            msec_delay(100);
+            /* Read the MII Status Register and wait for Auto-Neg
+             * Complete bit to be set.
+             */
+            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+        }                       /* end for loop */
+    }    /* end if wait_autoneg_complete */
+    /*
+     * Because we reset the PHY above, we need to re-force TX_CLK in the
+     * Extended PHY Specific Control Register to 25MHz clock.  This
+     * value defaults back to a 2.5MHz clock when the PHY is reset.
+     */
+    phy_data = e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
+
+    phy_data |= M88E1000_EPSCR_TX_CLK_25;
+
+    e1000_write_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+
+    /* In addition, because of the s/w reset above, we need to enable
+     * CRS on TX.  This must be set for both full and half duplex
+     * operation.
+     */
+    phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+
+    phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_data);
+    DEBUGOUT1("M88E1000 Phy Specific Ctrl Reg = %4x\r\n", phy_data);
+
+    return;
+}
+
+/*****************************************************************************
+* Reads the value from a PHY register
+*
+* shared - Struct containing variables accessed by shared code
+* reg_addr - address of the PHY register to read
+******************************************************************************/
+uint16_t
+e1000_read_phy_reg(struct e1000_shared_adapter *shared,
+                   uint32_t reg_addr)
+{
+    uint32_t i;
+    uint32_t data = 0;
+    uint32_t command = 0;
+
+    ASSERT(reg_addr <= MAX_PHY_REG_ADDRESS);
+
+    if(shared->mac_type > e1000_82543) {
+        /* Set up Op-code, Phy Address, and
+         * register address in the MDI Control register.  The MAC will
+         * take care of interfacing with the PHY to retrieve the
+         * desired data.
+         */
+        command = ((reg_addr << E1000_MDIC_REG_SHIFT) |
+                   (shared->phy_addr << E1000_MDIC_PHY_SHIFT) | 
+                   (E1000_MDIC_OP_READ));
+
+        E1000_WRITE_REG(shared, MDIC, command);
+
+        /* Check every 10 usec to see if the read completed.  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 < 64; i++) {
+            usec_delay(10);
+
+            data = E1000_READ_REG(shared, MDIC);
+
+            if(data & E1000_MDIC_READY)
+                break;
+        }
+    } else {
+        /* We must first send a preamble through the MDIO pin to signal the
+         * beginning of an MII instruction.  This is done by sending 32
+         * consecutive "1" bits.
+         */
+        e1000_phy_shift_out(shared, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+        /* Now combine the next few fields that are required for a read
+         * operation.  We use this method instead of calling the
+         * e1000_phy_shift_out routine five different times.  The format of
+         * a MII read instruction consists of a shift out of 14 bits and is
+         * defined as follows:
+         *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
+         * followed by a shift in of 18 bits.  This first two bits shifted
+         * in are TurnAround bits used to avoid contention on the MDIO pin
+         * when a READ operation is performed.  These two bits are thrown
+         * away followed by a shift in of 16 bits which contains the
+         * desired data.
+         */
+        command = ((reg_addr) |
+                   (shared->phy_addr << 5) |
+                   (PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+        e1000_phy_shift_out(shared, command, 14);
+
+        /* Now that we've shifted out the read command to the MII, we need
+         * to "shift in" the 16-bit value (18 total bits) of the requested
+         * PHY register address.
+         */
+        data = (uint32_t) e1000_phy_shift_in(shared);
+    }
+
+    ASSERT(!(data & E1000_MDIC_ERROR));
+
+    return ((uint16_t) data);
+}
+
+/******************************************************************************
+* Writes a value to a PHY register
+*
+* shared - Struct containing variables accessed by shared code
+* reg_addr - address of the PHY register to write
+* data - data to write to the PHY
+******************************************************************************/
+void
+e1000_write_phy_reg(struct e1000_shared_adapter *shared,
+                    uint32_t reg_addr,
+                    uint16_t data)
+{
+    uint32_t i;
+    uint32_t command = 0;
+    uint32_t mdic_reg;
+
+    ASSERT(reg_addr <= MAX_PHY_REG_ADDRESS);
+
+    if(shared->mac_type > e1000_82543) {
+        /* Set up Op-code, Phy Address, register
+         * address, and data intended for the PHY register in the MDI
+         * Control register.  The MAC will take care of interfacing
+         * with the PHY to send the desired data.
+         */
+        command = (((uint32_t) data) |
+                   (reg_addr << E1000_MDIC_REG_SHIFT) |
+                   (shared->phy_addr << E1000_MDIC_PHY_SHIFT) | 
+                   (E1000_MDIC_OP_WRITE));
+
+        E1000_WRITE_REG(shared, MDIC, command);
+
+        /* Check every 10 usec to see if the read completed.  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++) {
+            usec_delay(10);
+
+            mdic_reg = E1000_READ_REG(shared, MDIC);
+
+            if(mdic_reg & E1000_MDIC_READY)
+                break;
+        }
+    } else {
+        /* We'll need to use the SW defined pins to shift the write command
+         *  out to the PHY. We first send a preamble to the PHY to signal the
+         * beginning of the MII instruction.  This is done by sending 32 
+         * consecutive "1" bits.
+         */
+        e1000_phy_shift_out(shared, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+        /* Now combine the remaining required fields that will indicate
+         * a write operation.  We use this method instead of calling the
+         * e1000_phy_shift_out routine for each field in the command.  The
+         * format of a MII write instruction is as follows:
+         * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+         */
+        command = ((PHY_TURNAROUND) |
+                   (reg_addr << 2) |
+                   (shared->phy_addr << 7) |
+                   (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+        command <<= 16;
+        command |= ((uint32_t) data);
+
+        e1000_phy_shift_out(shared, command, 32);
+    }
+    return;
+}
+
+/******************************************************************************
+* Returns the PHY to the power-on reset state
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+void
+e1000_phy_hw_reset(struct e1000_shared_adapter *shared)
+{
+    uint32_t ctrl_reg;
+    uint32_t ctrl_ext_reg;
+
+    DEBUGFUNC("e1000_phy_hw_reset");
+
+    DEBUGOUT("Resetting Phy...\n");
+
+    if(shared->mac_type > e1000_82543) {
+        /* Read the device control register and assert the
+         * E1000_CTRL_PHY_RST bit.  Hold for 20ms and then take it out
+         * of reset.
+         */
+        ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+        ctrl_reg |= E1000_CTRL_PHY_RST;
+
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+        msec_delay(20);
+
+        ctrl_reg &= ~E1000_CTRL_PHY_RST;
+
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+        msec_delay(20);
+    } else {
+        /* Read the Extended Device Control Register, assert the
+         * PHY_RESET_DIR bit.  Then clock it out to the PHY.
+         */
+        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
+
+        ctrl_ext_reg |= E1000_CTRL_PHY_RESET_DIR4;
+
+        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
+
+        msec_delay(20);
+
+        /* Set the reset bit in the device control register and clock
+         * it out to the PHY.
+         */
+        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
+
+        ctrl_ext_reg &= ~E1000_CTRL_PHY_RESET4;
+
+        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
+
+        msec_delay(20);
+
+        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
+
+        ctrl_ext_reg |= E1000_CTRL_PHY_RESET4;
+
+        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
+
+        msec_delay(20);
+    }
+    return;
+}
+
+/******************************************************************************
+* Resets the PHY
+*
+* shared - Struct containing variables accessed by shared code
+*
+* Sets bit 15 of the MII Control regiser
+******************************************************************************/
+boolean_t
+e1000_phy_reset(struct e1000_shared_adapter *shared)
+{
+    uint16_t reg_data;
+    uint16_t i;
+
+    DEBUGFUNC("e1000_phy_reset");
+
+    /* Read the MII control register, set the reset bit and write the
+     * value back by clocking it out to the PHY.
+     */
+    reg_data = e1000_read_phy_reg(shared, PHY_CTRL);
+
+    reg_data |= MII_CR_RESET;
+
+    e1000_write_phy_reg(shared, PHY_CTRL, reg_data);
+
+    /* Wait for bit 15 of the MII Control Register to be cleared
+     * indicating the PHY has been reset.
+     */
+    i = 0;
+    while((reg_data & MII_CR_RESET) && i++ < 500) {
+        reg_data = e1000_read_phy_reg(shared, PHY_CTRL);
+        usec_delay(1);
+    }
+
+    if(i >= 500) {
+        DEBUGOUT("Timeout waiting for PHY to reset.\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/******************************************************************************
+* Detects which PHY is present and the speed and duplex
+*
+* shared - Struct containing variables accessed by shared code
+* ctrl_reg - current value of the device control register
+******************************************************************************/
+boolean_t
+e1000_phy_setup(struct e1000_shared_adapter *shared,
+                uint32_t ctrl_reg)
+{
+    uint16_t mii_ctrl_reg;
+    uint16_t mii_status_reg;
+    uint16_t phy_specific_ctrl_reg;
+    uint16_t mii_autoneg_adv_reg;
+    uint16_t mii_1000t_ctrl_reg;
+    uint16_t i;
+    uint16_t data;
+    uint16_t autoneg_hw_setting;
+    uint16_t autoneg_fc_setting;
+    boolean_t restart_autoneg = FALSE;
+    boolean_t force_autoneg_restart = FALSE;
+
+    DEBUGFUNC("e1000_phy_setup");
+
+    /* We want to enable the Auto-Speed Detection bit in the Device
+     * Control Register.  When set to 1, the MAC automatically detects
+     * the resolved speed of the link and self-configures appropriately.
+     * The Set Link Up bit must also be set for this behavior work
+     * properly.
+     */
+    /* Nothing but 82543 and newer */
+    ASSERT(shared->mac_type >= e1000_82543);
+
+    /* With 82543, we need to force speed/duplex
+     * on the MAC equal to what the PHY speed/duplex configuration is.
+     * In addition, on 82543, we need to perform a hardware reset
+     * on the PHY to take it out of reset.
+     */
+    if(shared->mac_type >= e1000_82544) {
+        ctrl_reg |= E1000_CTRL_SLU;
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+    } else {
+        ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
+        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+        if(shared->mac_type == e1000_82543)
+            e1000_phy_hw_reset(shared);
+    }
+
+    if(!e1000_detect_gig_phy(shared)) {
+        /* No PHY detected, return FALSE */
+        DEBUGOUT("PhySetup failure, did not detect valid phy.\n");
+        return (FALSE);
+    }
+
+    DEBUGOUT1("Phy ID = %x \n", shared->phy_id);
+
+    /* Read the MII Control Register. */
+    mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
+
+    DEBUGOUT1("MII Ctrl Reg contents = %x\n", mii_ctrl_reg);
+
+    /* Check to see if the Auto Neg Enable bit is set in the MII Control
+     * Register.  If not, we could be in a situation where a driver was
+     * loaded previously and was forcing speed and duplex.  Then the
+     * driver was unloaded but a e1000_phy_hw_reset was not performed, so
+     * link was still being forced and link was still achieved.  Then
+     * the driver was reloaded with the intention to auto-negotiate, but
+     * since link is already established we end up not restarting
+     * auto-neg.  So if the auto-neg bit is not enabled and the driver
+     * is being loaded with the desire to auto-neg, we set this flag to
+     * to ensure the restart of the auto-neg engine later in the logic.
+     */
+    if(!(mii_ctrl_reg & MII_CR_AUTO_NEG_EN))
+        force_autoneg_restart = TRUE;
+
+    /* Clear the isolate bit for normal operation and write it back to
+     * the MII Control Reg.  Although the spec says this doesn't need
+     * to be done when the PHY address is not equal to zero, we do it
+     * anyway just to be safe.
+     */
+    mii_ctrl_reg &= ~(MII_CR_ISOLATE);
+
+    e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
+
+    data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+
+    /* Enable CRS on TX.  This must be set for half-duplex operation. */
+    data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+    DEBUGOUT1("M88E1000 PSCR: %x \n", data);
+
+    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, data);
+
+    data = e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
+
+    /* Force TX_CLK in the Extended PHY Specific Control Register
+     * to 25MHz clock.
+     */
+    data |= M88E1000_EPSCR_TX_CLK_25;
+
+    e1000_write_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL, data);
+
+    /* Certain PHYs will set the default of MII register 4 differently.
+     * We need to check this against our fc value.  If it is
+     * different, we need to setup up register 4 correctly and restart
+     * autonegotiation.
+     */
+    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+    mii_autoneg_adv_reg = e1000_read_phy_reg(shared, PHY_AUTONEG_ADV);
+
+    /* Shift right to put 10T-Half bit in bit 0
+     * Isolate the four bits for 100/10 Full/Half.
+     */ 
+    autoneg_hw_setting = (mii_autoneg_adv_reg >> 5) & 0xF;
+
+    /* Get the 1000T settings. */
+    mii_1000t_ctrl_reg = e1000_read_phy_reg(shared, PHY_1000T_CTRL);
+
+    /* Isolate and OR in the 1000T settings. */
+    autoneg_hw_setting |= ((mii_1000t_ctrl_reg & 0x0300) >> 4);
+
+    /* mask all bits in the MII Auto-Neg Advertisement Register
+     * except for ASM_DIR and PAUSE and shift.  This value
+     * will be used later to see if we need to restart Auto-Negotiation.
+     */
+    autoneg_fc_setting = ((mii_autoneg_adv_reg & 0x0C00) >> 10);
+
+    /* Perform some bounds checking on the shared->autoneg_advertised
+     * parameter.  If this variable is zero, then set it to the default.
+     */
+    shared->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+    /* If autoneg_advertised is zero, we assume it was not defaulted
+     * by the calling code so we set to advertise full capability.
+     */
+    if(shared->autoneg_advertised == 0)
+        shared->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+    /* We could be in the situation where Auto-Neg has already completed
+     * and the user has not indicated any overrides.  In this case we
+     * simply need to call e1000_get_speed_and_duplex to obtain the Auto-
+     * Negotiated speed and duplex, then return.
+     */
+    if(!force_autoneg_restart && shared->autoneg &&
+       (shared->autoneg_advertised == autoneg_hw_setting) &&
+       (shared->fc == autoneg_fc_setting)) {
+
+        DEBUGOUT("No overrides - Reading MII Status Reg..\n");
+
+        /* Read the MII Status Register.  We read this twice because
+         * certain bits are "sticky" and need to be read twice.
+         */
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+        DEBUGOUT1("MII Status Reg contents = %x\n", mii_status_reg);
+
+        /* Do we have link now? (if so, auto-neg has completed) */
+        if(mii_status_reg & MII_SR_LINK_STATUS) {
+            data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
+            DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", data);
+
+            /* We have link, so we need to finish the config process:
+             *   1) Set up the MAC to the current PHY speed/duplex
+             *      if we are on 82543.  If we
+             *      are on newer silicon, we only need to configure
+             *      collision distance in the Transmit Control Register.
+             *   2) Set up flow control on the MAC to that established
+             *      with the link partner.
+             */
+            if(shared->mac_type >= e1000_82544)
+                e1000_config_collision_dist(shared);
+            else
+                e1000_config_mac_to_phy(shared, data);
+
+            e1000_config_fc_after_link_up(shared);
+
+            return (TRUE);
+        }
+    }
+
+    /* Options:
+     *   MDI/MDI-X = 0 (default)
+     *   0 - Auto for all speeds
+     *   1 - MDI mode
+     *   2 - MDI-X mode
+     *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+     */
+    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+
+    phy_specific_ctrl_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+    switch (shared->mdix) {
+    case 1:
+        phy_specific_ctrl_reg |= M88E1000_PSCR_MDI_MANUAL_MODE;
+        break;
+    case 2:
+        phy_specific_ctrl_reg |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+        break;
+    case 3:
+        phy_specific_ctrl_reg |= M88E1000_PSCR_AUTO_X_1000T;
+        break;
+    case 0:
+    default:
+        phy_specific_ctrl_reg |= M88E1000_PSCR_AUTO_X_MODE;
+        break;
+    }
+
+    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_specific_ctrl_reg);
+
+    /* Options:
+     *   disable_polarity_correction = 0 (default)
+     *       Automatic Correction for Reversed Cable Polarity
+     *   0 - Disabled
+     *   1 - Enabled
+     */
+    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+
+    phy_specific_ctrl_reg &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+
+    if(shared->disable_polarity_correction == 1)
+        phy_specific_ctrl_reg |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_specific_ctrl_reg);
+
+    /* Options:
+     *   autoneg = 1 (default)
+     *      PHY will advertise value(s) parsed from
+     *      autoneg_advertised and fc
+     *   autoneg = 0
+     *      PHY will be set to 10H, 10F, 100H, or 100F
+     *      depending on value parsed from forced_speed_duplex.
+     */
+
+    /* Is autoneg enabled?  This is enabled by default or by software override.
+     * If so, call e1000_phy_setup_autoneg routine to parse the
+     * autoneg_advertised and fc options. If autoneg is NOT enabled, then the
+     * user should have provided a speed/duplex override.  If so, then call
+     * e1000_phy_force_speed_duplex to parse and set this up.  Otherwise,
+     * we are in an error situation and need to bail.
+     */
+    if(shared->autoneg) {
+        DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+        restart_autoneg = e1000_phy_setup_autoneg(shared);
+    } else {
+        DEBUGOUT("Forcing speed and duplex\n");
+        e1000_phy_force_speed_duplex(shared);
+    }
+
+    /* Based on information parsed above, check the flag to indicate
+     * whether we need to restart Auto-Neg.
+     */
+    if(restart_autoneg) {
+        DEBUGOUT("Restarting Auto-Neg\n");
+
+        /* Read the MII Control Register. */
+        mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
+
+        /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+         * the Auto Neg Restart bit.
+         */
+        mii_ctrl_reg |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+
+        e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
+
+        /* Does the user want to wait for Auto-Neg to complete here, or
+         * check at a later time (for example, callback routine).
+         */
+        if(shared->wait_autoneg_complete)
+            e1000_wait_autoneg(shared);
+    } /* end if restart_autoneg */
+
+    /* Read the MII Status Register. */
+    mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+    mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+    DEBUGOUT1("Checking for link status - MII Status Reg contents = %x\n",
+              mii_status_reg);
+
+    /* Check link status.  Wait up to 100 microseconds for link to
+     * become valid.
+     */
+    for(i = 0; i < 10; i++) {
+        if(mii_status_reg & MII_SR_LINK_STATUS)
+            break;
+        usec_delay(10);
+        DEBUGOUT(". ");
+
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+    }
+
+    if(mii_status_reg & MII_SR_LINK_STATUS) {
+        /* Yes, so configure MAC to PHY settings as well as flow control
+         * registers.
+         */
+        data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
+
+        DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", data);
+
+        /* We have link, so we need to finish the config process:
+         *   1) Set up the MAC to the current PHY speed/duplex
+         *      if we are on 82543.  If we
+         *      are on newer silicon, we only need to configure
+         *      collision distance in the Transmit Control Register.
+         *   2) Set up flow control on the MAC to that established with
+         *      the link partner.
+         */
+        if(shared->mac_type >= e1000_82544)
+            e1000_config_collision_dist(shared);
+        else
+            e1000_config_mac_to_phy(shared, data);
+
+        e1000_config_fc_after_link_up(shared);
+
+        DEBUGOUT("Valid link established!!!\n");
+    } else {
+        DEBUGOUT("Unable to establish link!!!\n");
+    }
+
+    return (TRUE);
+}
+
+/******************************************************************************
+* Configures PHY autoneg and flow control advertisement settings
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+boolean_t
+e1000_phy_setup_autoneg(struct e1000_shared_adapter *shared)
+{
+    uint16_t mii_autoneg_adv_reg;
+    uint16_t mii_1000t_ctrl_reg;
+
+    DEBUGFUNC("e1000_phy_setup_autoneg");
+
+    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+    mii_autoneg_adv_reg = e1000_read_phy_reg(shared, PHY_AUTONEG_ADV);
+
+    /* Read the MII 1000Base-T Control Register (Address 9). */
+    mii_1000t_ctrl_reg = e1000_read_phy_reg(shared, PHY_1000T_CTRL);
+
+    /* Need to parse both autoneg_advertised and fc and set up
+     * the appropriate PHY registers.  First we will parse for
+     * autoneg_advertised software override.  Since we can advertise
+     * a plethora of combinations, we need to check each bit
+     * individually.
+     */
+
+    /* First we clear all the 10/100 mb speed bits in the Auto-Neg
+     * Advertisement Register (Address 4) and the 1000 mb speed bits in
+     * the  1000Base-T Control Register (Address 9).
+     */
+    mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
+    mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
+
+    DEBUGOUT1("autoneg_advertised %x\n", shared->autoneg_advertised);
+
+    /* Do we want to advertise 10 Mb Half Duplex? */
+    if(shared->autoneg_advertised & ADVERTISE_10_HALF) {
+        DEBUGOUT("Advertise 10mb Half duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
+    }
+
+    /* Do we want to advertise 10 Mb Full Duplex? */
+    if(shared->autoneg_advertised & ADVERTISE_10_FULL) {
+        DEBUGOUT("Advertise 10mb Full duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
+    }
+
+    /* Do we want to advertise 100 Mb Half Duplex? */
+    if(shared->autoneg_advertised & ADVERTISE_100_HALF) {
+        DEBUGOUT("Advertise 100mb Half duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
+    }
+
+    /* Do we want to advertise 100 Mb Full Duplex? */
+    if(shared->autoneg_advertised & ADVERTISE_100_FULL) {
+        DEBUGOUT("Advertise 100mb Full duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
+    }
+
+    /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
+    if(shared->autoneg_advertised & ADVERTISE_1000_HALF) {
+        DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
+    }
+
+    /* Do we want to advertise 1000 Mb Full Duplex? */
+    if(shared->autoneg_advertised & ADVERTISE_1000_FULL) {
+        DEBUGOUT("Advertise 1000mb Full duplex\n");
+        mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+    }
+
+    /* Check for a software override of the flow control settings, and
+     * setup the PHY advertisement registers accordingly.  If
+     * auto-negotiation is enabled, then software will have to set the
+     * "PAUSE" bits to the correct value in the Auto-Negotiation
+     * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
+     *
+     * The possible values of the "fc" 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:  No software override.  The flow control configuration
+     *          in the EEPROM is used.
+     */
+    switch (shared->fc) {
+    case e1000_fc_none:        /* 0 */
+            /* Flow control (RX & TX) is completely disabled by a
+             * software over-ride.
+             */
+        mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        break;
+    case e1000_fc_rx_pause:    /* 1 */
+            /* RX Flow control is enabled, and TX Flow control is
+             * disabled, by a software over-ride.
+             */
+
+            /* Since there really isn't a way to advertise that we are
+             * capable of RX Pause ONLY, we will advertise that we
+             * support both symmetric and asymmetric RX PAUSE.  Later
+             * (in e1000_config_fc_after_link_up) we will disable the
+             *shared's ability to send PAUSE frames.
+             */
+        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        break;
+    case e1000_fc_tx_pause:    /* 2 */
+            /* TX Flow control is enabled, and RX Flow control is
+             * disabled, by a software over-ride.
+             */
+        mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+        mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+        break;
+    case e1000_fc_full:        /* 3 */
+            /* Flow control (both RX and TX) is enabled by a software
+             * over-ride.
+             */
+        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        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 MII Auto-Neg Advertisement Register (Address 4). */
+    e1000_write_phy_reg(shared, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
+
+    DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
+
+    /* Write the MII 1000Base-T Control Register (Address 9). */
+    e1000_write_phy_reg(shared, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+    return (TRUE);
+}
+
+/******************************************************************************
+* Sets MAC speed and duplex settings to reflect the those in the PHY
+*
+* shared - Struct containing variables accessed by shared code
+* mii_reg - data to write to the MII control register
+*
+* The contents of the PHY register containing the needed information need to
+* be passed in.
+******************************************************************************/
+void
+e1000_config_mac_to_phy(struct e1000_shared_adapter *shared,
+                        uint16_t mii_reg)
+{
+    uint32_t ctrl_reg;
+    uint32_t tctl_reg;
+    uint32_t shift;
+
+    DEBUGFUNC("e1000_config_mac_to_phy");
+
+    /* We need to read the Transmit Control register to configure the
+     * collision distance.
+     * Note: This must be done for both Half or Full Duplex.
+     */
+    tctl_reg = E1000_READ_REG(shared, TCTL);
+    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
+
+    /* Read the Device Control Register and set the bits to Force Speed
+     * and Duplex.
+     */
+    ctrl_reg = E1000_READ_REG(shared, CTRL);
+
+    ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+    ctrl_reg &= ~(DEVICE_SPEED_MASK);
+
+    DEBUGOUT1("MII Register Data = %x\r\n", mii_reg);
+
+    /* Clear the ILOS bit. */
+    ctrl_reg &= ~E1000_CTRL_ILOS;
+
+    /* Set up duplex in the Device Control and Transmit Control
+     * registers depending on negotiated values.
+     */
+    if(mii_reg & M88E1000_PSSR_DPLX) {
+        ctrl_reg |= E1000_CTRL_FD;
+
+        /* We are in Full Duplex mode.  We have the same collision
+         * distance regardless of speed.
+         */
+        tctl_reg &= ~E1000_TCTL_COLD;
+        shift = E1000_FDX_COLLISION_DISTANCE;
+        shift <<= E1000_COLD_SHIFT;
+        tctl_reg |= shift;
+    } else {
+        ctrl_reg &= ~E1000_CTRL_FD;
+
+        /* We are in Half Duplex mode.  Our Half Duplex collision
+         * distance is different for Gigabit than for 10/100 so we will
+         * set accordingly.
+         */
+        if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { 
+            /* 1000Mbs HDX */
+            tctl_reg &= ~E1000_TCTL_COLD;
+            shift = E1000_GB_HDX_COLLISION_DISTANCE;
+            shift <<= E1000_COLD_SHIFT;
+            tctl_reg |= shift;
+            tctl_reg |= E1000_TCTL_PBE; /* Enable Packet Bursting */
+        } else {
+            /* 10/100Mbs HDX */
+            tctl_reg &= ~E1000_TCTL_COLD;
+            shift = E1000_HDX_COLLISION_DISTANCE;
+            shift <<= E1000_COLD_SHIFT;
+            tctl_reg |= shift;
+        }
+    }
+
+    /* Set up speed in the Device Control register depending on
+     * negotiated values.
+     */
+    if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+        ctrl_reg |= E1000_CTRL_SPD_1000;
+    else if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+        ctrl_reg |= E1000_CTRL_SPD_100;
+    else
+        ctrl_reg &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+
+    /* Write the configured values back to the Transmit Control Reg. */
+    E1000_WRITE_REG(shared, TCTL, tctl_reg);
+
+    /* Write the configured values back to the Device Control Reg. */
+    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
+
+    return;
+}
+
+/******************************************************************************
+* Sets the collision distance in the Transmit Control register
+*
+* shared - Struct containing variables accessed by shared code
+*
+* Link should have been established previously. Reads the speed and duplex
+* information from the Device Status register.
+******************************************************************************/
+void
+e1000_config_collision_dist(struct e1000_shared_adapter *shared)
+{
+    uint32_t tctl_reg;
+    uint16_t speed;
+    uint16_t duplex;
+    uint32_t shift;
+
+    DEBUGFUNC("e1000_config_collision_dist");
+
+    /* Get our current speed and duplex from the Device Status Register. */
+    e1000_get_speed_and_duplex(shared, &speed, &duplex);
+
+    /* We need to configure the Collision Distance for both Full or
+     * Half Duplex.
+     */
+    tctl_reg = E1000_READ_REG(shared, TCTL);
+    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
+
+    /* mask the Collision Distance bits in the Transmit Control Reg. */
+    tctl_reg &= ~E1000_TCTL_COLD;
+
+    if(duplex == FULL_DUPLEX) {
+        /* We are in Full Duplex mode.  Therefore, the collision distance
+         * is the same regardless of speed.
+         */
+        shift = E1000_FDX_COLLISION_DISTANCE;
+        shift <<= E1000_COLD_SHIFT;
+        tctl_reg |= shift;
+    } else {
+        /* We are in Half Duplex mode.  Half Duplex collision distance is
+         * different for Gigabit vs. 10/100, so we will set accordingly.
+         */
+        if(speed == SPEED_1000) {       /* 1000Mbs HDX */
+            shift = E1000_GB_HDX_COLLISION_DISTANCE;
+            shift <<= E1000_COLD_SHIFT;
+            tctl_reg |= shift;
+            tctl_reg |= E1000_TCTL_PBE; /* Enable Packet Bursting */
+        } else {                /* 10/100Mbs HDX */
+            shift = E1000_HDX_COLLISION_DISTANCE;
+            shift <<= E1000_COLD_SHIFT;
+            tctl_reg |= shift;
+        }
+    }
+
+    /* Write the configured values back to the Transmit Control Reg. */
+    E1000_WRITE_REG(shared, TCTL, tctl_reg);
+
+    return;
+}
+
+/******************************************************************************
+* Probes the expected PHY address for known PHY IDs
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+boolean_t
+e1000_detect_gig_phy(struct e1000_shared_adapter *shared)
+{
+    uint32_t phy_id_high;
+    uint16_t phy_id_low;
+
+    DEBUGFUNC("e1000_detect_gig_phy");
+
+    /* Read the PHY ID Registers to identify which PHY is onboard. */
+    shared->phy_addr = 1;
+
+    phy_id_high = e1000_read_phy_reg(shared, PHY_ID1);
+
+    usec_delay(2);
+
+    phy_id_low = e1000_read_phy_reg(shared, PHY_ID2);
+
+    shared->phy_id = (phy_id_low | (phy_id_high << 16)) & PHY_REVISION_MASK;
+
+    if(shared->phy_id == M88E1000_12_PHY_ID ||
+       shared->phy_id == M88E1000_14_PHY_ID ||
+       shared->phy_id == M88E1000_I_PHY_ID) {
+
+        DEBUGOUT2("phy_id 0x%x detected at address 0x%x\n",
+                  shared->phy_id, shared->phy_addr);
+        return (TRUE);
+    } else {
+        DEBUGOUT("Could not auto-detect Phy!\n");
+        return (FALSE);
+    }
+}
+
+/******************************************************************************
+* Resets the PHY's DSP
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+void
+e1000_phy_reset_dsp(struct e1000_shared_adapter *shared)
+{
+    e1000_write_phy_reg(shared, 29, 0x1d);
+    e1000_write_phy_reg(shared, 30, 0xc1);
+    e1000_write_phy_reg(shared, 30, 0x00);
+    return;
+}
+
+/******************************************************************************
+* Blocks until autoneg completes or times out (~4.5 seconds)
+*
+* shared - Struct containing variables accessed by shared code
+******************************************************************************/
+boolean_t
+e1000_wait_autoneg(struct e1000_shared_adapter *shared)
+{
+    uint16_t i;
+    uint16_t mii_status_reg;
+    boolean_t autoneg_complete = FALSE;
+
+    DEBUGFUNC("e1000_wait_autoneg");
+
+    /* We will wait for autoneg to complete. */
+    DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+    mii_status_reg = 0;
+
+    /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+
+    for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Auto-Neg
+         * Complete bit to be set.
+         */
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+
+        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
+            autoneg_complete = TRUE;
+            break;
+        }
+
+        msec_delay(100);
+    }
+
+    return (autoneg_complete);
+}
+
+/******************************************************************************
+* Get PHY information from various PHY registers
+*
+* shared - Struct containing variables accessed by shared code
+* phy_status_info - PHY information structure
+******************************************************************************/
+boolean_t
+e1000_phy_get_info(struct e1000_shared_adapter *shared,
+                   struct e1000_phy_info *phy_status_info)
+{
+    uint16_t phy_mii_status_reg;
+    uint16_t phy_specific_ctrl_reg;
+    uint16_t phy_specific_status_reg;
+    uint16_t phy_specific_ext_ctrl_reg;
+    uint16_t phy_1000t_stat_reg;
+
+    phy_status_info->cable_length = e1000_cable_length_undefined;
+    phy_status_info->extended_10bt_distance =
+        e1000_10bt_ext_dist_enable_undefined;
+    phy_status_info->cable_polarity = e1000_rev_polarity_undefined;
+    phy_status_info->polarity_correction = e1000_polarity_reversal_undefined;
+    phy_status_info->link_reset = e1000_down_no_idle_undefined;
+    phy_status_info->mdix_mode = e1000_auto_x_mode_undefined;
+    phy_status_info->local_rx = e1000_1000t_rx_status_undefined;
+    phy_status_info->remote_rx = e1000_1000t_rx_status_undefined;
+
+    /* PHY info only valid for copper media. */
+    if(shared == NULL || shared->media_type != e1000_media_type_copper)
+        return FALSE;
+
+    /* PHY info only valid for LINK UP.  Read MII status reg 
+     * back-to-back to get link status.
+     */
+    phy_mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+    phy_mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
+    if((phy_mii_status_reg & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS)
+        return FALSE;
+
+    /* Read various PHY registers to get the PHY info. */
+    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
+    phy_specific_status_reg =
+        e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
+    phy_specific_ext_ctrl_reg =
+        e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
+    phy_1000t_stat_reg = e1000_read_phy_reg(shared, PHY_1000T_STATUS);
+
+    phy_status_info->cable_length =
+        ((phy_specific_status_reg & M88E1000_PSSR_CABLE_LENGTH) >>
+         M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+
+    phy_status_info->extended_10bt_distance =
+        (phy_specific_ctrl_reg & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
+        M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT;
+
+    phy_status_info->cable_polarity =
+        (phy_specific_status_reg & M88E1000_PSSR_REV_POLARITY) >>
+        M88E1000_PSSR_REV_POLARITY_SHIFT;
+
+    phy_status_info->polarity_correction =
+        (phy_specific_ctrl_reg & M88E1000_PSCR_POLARITY_REVERSAL) >>
+        M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
+
+    phy_status_info->link_reset =
+        (phy_specific_ext_ctrl_reg & M88E1000_EPSCR_DOWN_NO_IDLE) >>
+        M88E1000_EPSCR_DOWN_NO_IDLE_SHIFT;
+
+    phy_status_info->mdix_mode =
+        (phy_specific_status_reg & M88E1000_PSSR_MDIX) >>
+        M88E1000_PSSR_MDIX_SHIFT;
+
+    phy_status_info->local_rx =
+        (phy_1000t_stat_reg & SR_1000T_LOCAL_RX_STATUS) >>
+        SR_1000T_LOCAL_RX_STATUS_SHIFT;
+
+    phy_status_info->remote_rx =
+        (phy_1000t_stat_reg & SR_1000T_REMOTE_RX_STATUS) >>
+        SR_1000T_REMOTE_RX_STATUS_SHIFT;
+
+    return TRUE;
+}
+
+boolean_t
+e1000_validate_mdi_setting(struct e1000_shared_adapter *shared)
+{
+    if(!shared->autoneg && (shared->mdix == 0 || shared->mdix == 3)) {
+        shared->mdix = 1;
+        return FALSE;
+    }
+    return TRUE;
+}
diff -Nru a/drivers/net/e1000/e1000_phy.h b/drivers/net/e1000/e1000_phy.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_phy.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,422 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_phy.h
+ * Structures, enums, and macros for the PHY
+ */
+
+#ifndef _E1000_PHY_H_
+#define _E1000_PHY_H_
+
+#include "e1000_osdep.h"
+
+/* PHY status info structure and supporting enums */
+typedef enum {
+    e1000_cable_length_50 = 0,
+    e1000_cable_length_50_80,
+    e1000_cable_length_80_110,
+    e1000_cable_length_110_140,
+    e1000_cable_length_140,
+    e1000_cable_length_undefined = 0xFF
+} e1000_cable_length;
+
+typedef enum {
+    e1000_10bt_ext_dist_enable_normal = 0,
+    e1000_10bt_ext_dist_enable_lower,
+    e1000_10bt_ext_dist_enable_undefined = 0xFF
+} e1000_10bt_ext_dist_enable;
+
+typedef enum {
+    e1000_rev_polarity_normal = 0,
+    e1000_rev_polarity_reversed,
+    e1000_rev_polarity_undefined = 0xFF
+} e1000_rev_polarity;
+
+typedef enum {
+    e1000_polarity_reversal_enabled = 0,
+    e1000_polarity_reversal_disabled,
+    e1000_polarity_reversal_undefined = 0xFF
+} e1000_polarity_reversal;
+
+typedef enum {
+    e1000_down_no_idle_no_detect = 0,
+    e1000_down_no_idle_detect,
+    e1000_down_no_idle_undefined = 0xFF
+} e1000_down_no_idle;
+
+typedef enum {
+    e1000_auto_x_mode_manual_mdi = 0,
+    e1000_auto_x_mode_manual_mdix,
+    e1000_auto_x_mode_auto1,
+    e1000_auto_x_mode_auto2,
+    e1000_auto_x_mode_undefined = 0xFF
+} e1000_auto_x_mode;
+
+typedef enum {
+    e1000_1000t_rx_status_not_ok = 0,
+    e1000_1000t_rx_status_ok,
+    e1000_1000t_rx_status_undefined = 0xFF
+} e1000_1000t_rx_status;
+
+struct e1000_phy_info {
+    e1000_cable_length cable_length;
+    e1000_10bt_ext_dist_enable extended_10bt_distance;
+    e1000_rev_polarity cable_polarity;
+    e1000_polarity_reversal polarity_correction;
+    e1000_down_no_idle link_reset;
+    e1000_auto_x_mode mdix_mode;
+    e1000_1000t_rx_status local_rx;
+    e1000_1000t_rx_status remote_rx;
+};
+
+struct e1000_phy_stats {
+    uint32_t idle_errors;
+    uint32_t receive_errors;
+};
+
+/* Function Prototypes */
+uint16_t e1000_read_phy_reg(struct e1000_shared_adapter *shared, uint32_t reg_addr);
+void e1000_write_phy_reg(struct e1000_shared_adapter *shared, uint32_t reg_addr, uint16_t data);
+void e1000_phy_hw_reset(struct e1000_shared_adapter *shared);
+boolean_t e1000_phy_reset(struct e1000_shared_adapter *shared);
+boolean_t e1000_phy_setup(struct e1000_shared_adapter *shared, uint32_t ctrl_reg);
+boolean_t e1000_phy_setup_autoneg(struct e1000_shared_adapter *shared);
+void e1000_config_mac_to_phy(struct e1000_shared_adapter *shared, uint16_t mii_reg);
+void e1000_config_collision_dist(struct e1000_shared_adapter *shared);
+boolean_t e1000_detect_gig_phy(struct e1000_shared_adapter *shared);
+void e1000_phy_reset_dsp(struct e1000_shared_adapter *shared);
+boolean_t e1000_wait_autoneg(struct e1000_shared_adapter *shared);
+boolean_t e1000_phy_get_info(struct e1000_shared_adapter *shared, struct e1000_phy_info *phy_status_info);
+boolean_t e1000_validate_mdi_setting(struct e1000_shared_adapter *shared);
+
+/* Bit definitions for the Management Data IO (MDIO) and Management Data
+ * Clock (MDC) pins in the Device Control Register.
+ */
+#define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
+#define E1000_CTRL_PHY_RESET      E1000_CTRL_SWDPIN0
+#define E1000_CTRL_MDIO_DIR       E1000_CTRL_SWDPIO2
+#define E1000_CTRL_MDIO           E1000_CTRL_SWDPIN2
+#define E1000_CTRL_MDC_DIR        E1000_CTRL_SWDPIO3
+#define E1000_CTRL_MDC            E1000_CTRL_SWDPIN3
+#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
+#define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CTRL         0x00 /* Control Register */
+#define PHY_STATUS       0x01 /* Status Regiser */
+#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
+
+/* M88E1000 Specific Registers */
+#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
+#define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
+#define M88E1000_INT_ENABLE        0x12  /* Interrupt Enable Register */
+#define M88E1000_INT_STATUS        0x13  /* Interrupt Status Register */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
+#define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
+
+#define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN       0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_SELECTOR_FIELD 0x0001   /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS  0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS  0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS     0x0200   /* 100T4 Capable */
+#define NWAY_AR_PAUSE          0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT   0x2000   /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE      0x8000   /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT  0x0100 /* LP is 100TX Full Duplex Capable */
+
+/* Next Page TX Register */
+#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define NPTX_TOGGLE         0x0800 /* Toggles between exchanges
+                                    * of different NP
+                                    */
+#define NPTX_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
+                                    * 0 = cannot comply with msg
+                                    */
+#define NPTX_MSG_PAGE       0x2000 /* formatted(1)/unformatted(0) pg */
+#define NPTX_NEXT_PAGE      0x8000 /* 1 = addition NP will follow 
+                                    * 0 = sending last NP
+                                    */
+
+/* Link Partner Next Page Register */
+#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define LP_RNPR_TOGGLE         0x0800 /* Toggles between exchanges
+                                       * of different NP
+                                       */
+#define LP_RNPR_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg 
+                                       * 0 = cannot comply with msg
+                                       */
+#define LP_RNPR_MSG_PAGE       0x2000  /* formatted(1)/unformatted(0) pg */
+#define LP_RNPR_ACKNOWLDGE     0x4000  /* 1 = ACK / 0 = NO ACK */
+#define LP_RNPR_NEXT_PAGE      0x8000  /* 1 = addition NP will follow
+                                        * 0 = sending last NP 
+                                        */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
+#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
+                                        /* 0=DTE device */
+#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
+                                        /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
+                                        /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register */
+#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR   0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
+#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define SR_1000T_LOCAL_RX_STATUS_SHIFT  13
+
+/* Extended Status Register */
+#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+#define PHY_TX_POLARITY_MASK   0x0100 /* register 10h bit 8 (polarity bit) */
+#define PHY_TX_NORMAL_POLARITY 0      /* register 10h bit 8 (normal polarity) */
+
+#define AUTO_POLARITY_DISABLE  0x0010 /* register 11h bit 4 */
+                                      /* (0=enable, 1=disable) */
+
+/* M88E1000 PHY Specific Control Register */
+#define M88E1000_PSCR_JABBER_DISABLE    0x0001 /* 1=Jabber Function disabled */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define M88E1000_PSCR_SQE_TEST          0x0004 /* 1=SQE Test enabled */
+#define M88E1000_PSCR_CLK125_DISABLE    0x0010 /* 1=CLK125 low, 
+                                                * 0=CLK125 toggling
+                                                */
+#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 */
+                                               /* Manual MDI configuration */
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
+#define M88E1000_PSCR_AUTO_X_1000T     0x0040  /* 1000BASE-T: Auto crossover,
+                                                *  100BASE-TX/10BASE-T: 
+                                                *  MDI Mode
+                                                */
+#define M88E1000_PSCR_AUTO_X_MODE      0x0060  /* Auto crossover enabled 
+                                                * all speeds. 
+                                                */
+#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 
+                                        /* 1=Enable Extended 10BASE-T distance
+                                         * (Lower 10BASE-T RX Threshold)
+                                         * 0=Normal 10BASE-T RX Threshold */
+#define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
+                                        /* 1=5-Bit interface in 100BASE-TX
+                                         * 0=MII interface in 100BASE-TX */
+#define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200 /* 1=Scrambler disable */
+#define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400 /* 1=Force link good */
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Transmit */
+
+#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT    1
+#define M88E1000_PSCR_AUTO_X_MODE_SHIFT          5
+#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+
+/* M88E1000 PHY Specific Status Register */
+#define M88E1000_PSSR_JABBER             0x0001 /* 1=Jabber */
+#define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
+#define M88E1000_PSSR_CABLE_LENGTH       0x0380 /* 0=<50M;1=50-80M;2=80-110M;
+                                            * 3=110-140M;4=>140M */
+#define M88E1000_PSSR_LINK               0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_PAGE_RCVD          0x1000 /* 1=Page received */
+#define M88E1000_PSSR_DPLX               0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_10MBS              0x0000 /* 00=10Mbs */
+#define M88E1000_PSSR_100MBS             0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
+
+#define M88E1000_PSSR_REV_POLARITY_SHIFT 1
+#define M88E1000_PSSR_MDIX_SHIFT         6
+#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+/* M88E1000 Extended PHY Specific Control Register */
+#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
+#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000 /* 1=Lost lock detect enabled.
+                                              * Will assert lost lock and bring
+                                              * link down if idle not seen
+                                              * within 1ms in 1000BASE-T 
+                                              */
+#define M88E1000_EPSCR_TX_CLK_2_5     0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0       0x0000 /* NO  TX_CLK */
+
+#define M88E1000_EPSCR_DOWN_NO_IDLE_SHIFT 15
+
+/* Bit definitions for valid PHY IDs. */
+#define M88E1000_12_PHY_ID 0x01410C50
+#define M88E1000_14_PHY_ID 0x01410C40
+#define M88E1000_I_PHY_ID  0x01410C30
+
+/* Miscellaneous PHY bit definitions. */
+#define PHY_PREAMBLE        0xFFFFFFFF
+#define PHY_SOF             0x01
+#define PHY_OP_READ         0x02
+#define PHY_OP_WRITE        0x01
+#define PHY_TURNAROUND      0x02
+#define PHY_PREAMBLE_SIZE   32
+#define MII_CR_SPEED_1000   0x0040
+#define MII_CR_SPEED_100    0x2000
+#define MII_CR_SPEED_10     0x0000
+#define E1000_PHY_ADDRESS   0x01
+#define PHY_AUTO_NEG_TIME   45  /* 4.5 Seconds */
+#define PHY_FORCE_TIME      20  /* 2.0 Seconds */
+#define PHY_REVISION_MASK   0xFFFFFFF0
+#define DEVICE_SPEED_MASK   0x00000300  /* Device Ctrl Reg Speed Mask */
+#define REG4_SPEED_MASK     0x01E0
+#define REG9_SPEED_MASK     0x0300
+#define ADVERTISE_10_HALF   0x0001
+#define ADVERTISE_10_FULL   0x0002
+#define ADVERTISE_100_HALF  0x0004
+#define ADVERTISE_100_FULL  0x0008
+#define ADVERTISE_1000_HALF 0x0010
+#define ADVERTISE_1000_FULL 0x0020
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F  /* Everything but 1000-Half */
+
+#endif /* _E1000_PHY_H_ */
diff -Nru a/drivers/net/e1000/e1000_proc.c b/drivers/net/e1000/e1000_proc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_proc.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,760 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License (GPL) Version 2, June 1991, available at
+  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
+  text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU Public License version 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  Public License version 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU Public
+  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/*
+ * Proc fs support.
+ *
+ * Read-only files created by driver (if CONFIG_PROC_FS):
+ *
+ * /proc/net/PRO_LAN_Adapters/<ethx>.info
+ * /proc/net/PRO_LAN_Adapters/<ethx>/<attribute>
+ *
+ * where <ethx>      is the system device name, i.e eth0.
+ *       <attribute> is the driver attribute name.
+ *
+ * There is one file for each driver attribute, where the contents
+ * of the file is the attribute value.  The ethx.info file contains
+ * a list of all driver attributes in one file.
+ *
+ */
+
+#include "e1000.h"
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/proc_fs.h>
+
+#define ADAPTERS_PROC_DIR           "PRO_LAN_Adapters"
+#define TAG_MAX_LENGTH              36
+
+extern char e1000_driver_name[];
+extern char e1000_driver_version[];
+
+/*
+ * The list of driver proc attributes is stored in a proc_list link
+ * list.  The list is build with proc_list_setup and is used to
+ * build the proc fs nodes.  The private data for each node is the
+ * corresponding link in the link list.
+ */
+
+struct proc_list {
+	struct list_head list;                  /* link list */
+	char tag[TAG_MAX_LENGTH];               /* attribute name */
+	void *data;                             /* attribute data */
+	size_t len;				/* sizeof data */
+	char *(*func)(void *, size_t, char *);  /* format data func */
+};
+
+static int
+e1000_proc_read(char *page, char **start, off_t off, int count, int *eof)
+{
+	int len = strlen(page);
+
+	page[len++] = '\n';
+
+	if(len <= off + count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if(len > count)
+		len = count;
+	if(len < 0)
+		len = 0;
+
+	return len;
+}
+
+static int
+e1000_proc_info_read(char *page, char **start, off_t off,
+                     int count, int *eof, void *data)
+{
+	struct list_head *proc_list_head = data, *curr;
+	struct proc_list *elem;
+	char *p = page;
+	char buf[64];
+
+	list_for_each(curr, proc_list_head) {
+		elem = list_entry(curr, struct proc_list, list);
+
+		if(strlen(elem->tag) == 0)
+			p += sprintf(p, "\n");
+		else
+			p += sprintf(p, "%-32s %s\n", elem->tag,
+				elem->func(elem->data, elem->len, buf));
+	}
+
+	*p = '\0';
+
+	return e1000_proc_read(page, start, off, count, eof);
+}
+
+static int
+e1000_proc_single_read(char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+	struct proc_list *elem = data;
+
+	sprintf(page, "%s", elem->func(elem->data, elem->len, page));
+
+	return e1000_proc_read(page, start, off, count, eof);
+}
+
+static void __devexit
+e1000_proc_dirs_free(char *name, struct list_head *proc_list_head)
+{
+	struct proc_dir_entry *intel_proc_dir, *proc_dir;
+	char info_name[strlen(name) + strlen(".info")];
+
+	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
+		intel_proc_dir = intel_proc_dir->next) {
+		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
+			(memcmp(intel_proc_dir->name,
+			ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)) == 0))
+			break;
+	}
+
+	if(!intel_proc_dir)
+		return;
+
+	for(proc_dir = intel_proc_dir->subdir; proc_dir;
+		proc_dir = proc_dir->next) {
+		if ((proc_dir->namelen == strlen(name)) &&
+		    !memcmp(proc_dir->name, name, strlen(name)))
+			break;
+	}
+
+	if(proc_dir) {
+		struct list_head *curr;
+		struct proc_list *elem;
+
+		list_for_each(curr, proc_list_head) {
+			elem = list_entry(curr, struct proc_list, list);
+			remove_proc_entry(elem->tag, proc_dir);
+		}
+
+		strcpy(info_name, name);
+		strcat(info_name, ".info");
+
+		remove_proc_entry(info_name, intel_proc_dir);
+		remove_proc_entry(name, intel_proc_dir);
+	}
+
+	/* If the intel dir is empty, remove it */
+
+	for(proc_dir = intel_proc_dir->subdir; proc_dir;
+		proc_dir = proc_dir->next) {
+
+		/* ignore . and .. */
+
+		if(*(proc_dir->name) == '.')
+			continue;
+		break;
+	}
+
+	if(!proc_dir)
+		remove_proc_entry(ADAPTERS_PROC_DIR, proc_net);
+
+	return;
+}
+
+
+static int __devinit
+e1000_proc_singles_create(struct proc_dir_entry *parent,
+                          struct list_head *proc_list_head)
+{
+	struct list_head *curr;
+	struct proc_list *elem;
+
+	list_for_each(curr, proc_list_head) {
+		struct proc_dir_entry *proc_entry;
+
+		elem = list_entry(curr, struct proc_list, list);
+
+		if(strlen(elem->tag) == 0)
+			continue;
+
+		if(!(proc_entry =
+			create_proc_entry(elem->tag, S_IFREG, parent)))
+			return 0;
+
+		proc_entry->read_proc = e1000_proc_single_read;
+		proc_entry->data = elem;
+		SET_MODULE_OWNER(proc_entry);
+	}
+
+	return 1;
+}
+
+static int __devinit
+e1000_proc_dirs_create(char *name, struct list_head *proc_list_head)
+{
+	struct proc_dir_entry *intel_proc_dir, *proc_dir, *info_entry;
+	char info_name[strlen(name) + strlen(".info")];
+
+	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
+		intel_proc_dir = intel_proc_dir->next) {
+		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
+			(memcmp(intel_proc_dir->name,
+			ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)) == 0))
+			break;
+	}
+
+	if(!intel_proc_dir)
+		if(!(intel_proc_dir =
+			create_proc_entry(ADAPTERS_PROC_DIR,
+				S_IFDIR, proc_net)))
+			return 0;
+
+	if(!(proc_dir =
+		create_proc_entry(name, S_IFDIR, intel_proc_dir)))
+		return 0;
+	SET_MODULE_OWNER(proc_dir);
+
+	if(!e1000_proc_singles_create(proc_dir, proc_list_head))
+		return 0;
+
+	strcpy(info_name, name);
+	strcat(info_name, ".info");
+
+	if(!(info_entry =
+		create_proc_entry(info_name, S_IFREG, intel_proc_dir)))
+		return 0;
+	SET_MODULE_OWNER(info_entry);
+
+	info_entry->read_proc = e1000_proc_info_read;
+	info_entry->data = proc_list_head;
+
+	return 1;
+}
+
+static void __devinit
+e1000_proc_list_add(struct list_head *proc_list_head, char *tag,
+                    void *data, size_t len, 
+		    char *(*func)(void *, size_t, char *))
+{
+	struct proc_list *new = (struct proc_list *)
+		kmalloc(sizeof(struct proc_list), GFP_KERNEL);
+
+	if(!new)
+		return;
+
+	strncpy(new->tag, tag, TAG_MAX_LENGTH);
+	new->data = data;
+	new->len  = len;
+	new->func = func;
+
+	list_add_tail(&new->list, proc_list_head);
+
+	return;
+}
+
+static void __devexit
+e1000_proc_list_free(struct list_head *proc_list_head)
+{
+	struct proc_list *elem;
+
+	while(!list_empty(proc_list_head)) {
+		elem = list_entry(proc_list_head->next, struct proc_list, list);
+		list_del(&elem->list);
+		kfree(elem);
+	}
+
+	return;
+}
+
+/*
+ * General purpose formating functions
+ */
+
+static char *
+e1000_proc_str(void *data, size_t len, char *buf)
+{
+	sprintf(buf, "%s", (char *)data);
+	return buf;
+}
+
+static char *
+e1000_proc_hex(void *data, size_t len, char *buf)
+{
+	switch(len) {
+	case sizeof(uint8_t):
+		sprintf(buf, "0x%02x", *(uint8_t *)data);
+		break;
+	case sizeof(uint16_t):
+		sprintf(buf, "0x%04x", *(uint16_t *)data);
+		break;
+	case sizeof(uint32_t):
+		sprintf(buf, "0x%08x", *(uint32_t *)data);
+		break;
+	case sizeof(uint64_t):
+		sprintf(buf, "0x%08Lx", (unsigned long long)*(uint64_t *)data);
+		break;
+	}
+	return buf;
+}
+
+static char *
+e1000_proc_unsigned(void *data, size_t len, char *buf)
+{
+	switch(len) {
+	case sizeof(uint8_t):
+		sprintf(buf, "%u", *(uint8_t *)data);
+		break;
+	case sizeof(uint16_t):
+		sprintf(buf, "%u", *(uint16_t *)data);
+		break;
+	case sizeof(uint32_t):
+		sprintf(buf, "%u", *(uint32_t *)data);
+		break;
+	case sizeof(uint64_t):
+		sprintf(buf, "%Lu", (unsigned long long)*(uint64_t *)data);
+		break;
+	}
+	return buf;
+}
+
+/*
+ * Specific formating functions
+ */
+
+static char *
+e1000_proc_part_number(void *data, size_t len, char *buf)
+{
+	sprintf(buf, "%06x-%03x", *(uint32_t *)data >> 8,
+	        *(uint32_t *)data & 0x000000FF);
+	return buf;
+}
+
+static char *
+e1000_proc_slot(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	sprintf(buf, "%u", PCI_SLOT(adapter->pdev->devfn));
+	return buf;
+}
+
+static char *
+e1000_proc_bus_type(void *data, size_t len, char *buf)
+{
+	e1000_bus_type bus_type = *(e1000_bus_type *)data;
+	sprintf(buf,
+		bus_type == e1000_bus_type_pci  ? "PCI"   :
+		bus_type == e1000_bus_type_pcix ? "PCI-X" :
+		"UNKNOWN");
+	return buf;
+}
+
+static char *
+e1000_proc_bus_speed(void *data, size_t len, char *buf)
+{
+	e1000_bus_speed bus_speed = *(e1000_bus_speed *)data;
+	sprintf(buf,
+		bus_speed == e1000_bus_speed_33  ? "33MHz"  :
+		bus_speed == e1000_bus_speed_66  ? "66MHz"  :
+		bus_speed == e1000_bus_speed_100 ? "100MHz" :
+		bus_speed == e1000_bus_speed_133 ? "133MHz" :
+		"UNKNOWN");
+	return buf;
+}
+
+static char *
+e1000_proc_bus_width(void *data, size_t len, char *buf)
+{
+	e1000_bus_width bus_width = *(e1000_bus_width *)data;
+	sprintf(buf,
+		bus_width == e1000_bus_width_32 ? "32-bit"   :
+		bus_width == e1000_bus_width_64 ? "64-bit" :
+		"UNKNOWN");
+	return buf;
+}
+
+static char *
+e1000_proc_hwaddr(void *data, size_t len, char *buf)
+{
+	unsigned char *hwaddr = data;
+	sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+		hwaddr[0], hwaddr[1], hwaddr[2],
+		hwaddr[3], hwaddr[4], hwaddr[5]);
+	return buf;
+}
+
+static char *
+e1000_proc_link(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	sprintf(buf, netif_running(adapter->netdev) ?
+		netif_carrier_ok(adapter->netdev) ?
+		"up" : "down" : "N/A");
+	return buf;
+}
+
+static char *
+e1000_proc_link_speed(void *data, size_t len, char *buf)
+{
+	uint16_t link_speed = *(uint16_t *)data;
+	sprintf(buf, link_speed ? "%u" : "N/A", link_speed);
+	return buf;
+}
+
+static char *
+e1000_proc_link_duplex(void *data, size_t len, char *buf)
+{
+	uint16_t link_duplex = *(uint16_t *)data;
+	sprintf(buf,
+		link_duplex == FULL_DUPLEX ? "Full" :
+		link_duplex == HALF_DUPLEX ? "Half" :
+		"N/A");
+	return buf;
+}
+
+static char *
+e1000_proc_state(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	sprintf(buf, adapter->netdev->flags & IFF_UP ? "up" : "down");
+	return buf;
+}
+
+static char *
+e1000_proc_media_type(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	sprintf(buf,
+		adapter->shared.media_type == e1000_media_type_copper ?
+		"Copper" : "Fiber");
+	return buf;
+}
+
+static char *
+e1000_proc_cable_length(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_cable_length cable_length = adapter->phy_info.cable_length;
+	sprintf(buf, "%s%s",
+		cable_length == e1000_cable_length_50      ? "0-50"    :
+		cable_length == e1000_cable_length_50_80   ? "50-80"   :
+		cable_length == e1000_cable_length_80_110  ? "80-110"  :
+		cable_length == e1000_cable_length_110_140 ? "110-140" :
+		cable_length == e1000_cable_length_140     ? "> 140"   :
+		"Unknown",
+		cable_length != e1000_cable_length_undefined ?
+		" Meters (+/- 20 Meters)" : "");
+	return buf;
+}
+
+static char *
+e1000_proc_extended(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_10bt_ext_dist_enable dist_enable =
+		adapter->phy_info.extended_10bt_distance;
+	sprintf(buf,
+		dist_enable == e1000_10bt_ext_dist_enable_normal ? "Disabled" :
+		dist_enable == e1000_10bt_ext_dist_enable_lower  ? "Enabled"  :
+		"Unknown");
+	return buf;
+}
+
+static char *
+e1000_proc_cable_polarity(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_rev_polarity polarity = adapter->phy_info.cable_polarity;
+	sprintf(buf,
+		polarity == e1000_rev_polarity_normal   ? "Normal"   :
+		polarity == e1000_rev_polarity_reversed ? "Reversed" :
+		"Unknown");
+	return buf;
+}
+
+static char *
+e1000_proc_polarity_correction(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_polarity_reversal correction =
+		adapter->phy_info.polarity_correction;
+	sprintf(buf,
+		correction == e1000_polarity_reversal_enabled  ? "Disabled" :
+		correction == e1000_polarity_reversal_disabled ? "Enabled"  :
+		"Undefined");
+	return buf;
+}
+
+static char *
+e1000_proc_link_reset_enabled(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_down_no_idle link_reset = adapter->phy_info.link_reset;
+	sprintf(buf,
+		link_reset == e1000_down_no_idle_no_detect ? "Disabled" :
+		link_reset == e1000_down_no_idle_detect    ? "Enabled"  :
+		"Unknown");
+	return buf;
+}
+
+static char *
+e1000_proc_mdi_x_enabled(void *data, size_t len, char *buf)
+{
+	struct e1000_adapter *adapter = data;
+	e1000_auto_x_mode mdix_mode = adapter->phy_info.mdix_mode;
+	sprintf(buf, mdix_mode == 0 ? "MDI" : "MDI-X");
+	return buf;
+}
+
+static char *
+e1000_proc_rx_status(void *data, size_t len, char *buf)
+{
+	e1000_1000t_rx_status rx_status = *(e1000_1000t_rx_status *)data;
+	sprintf(buf,
+		rx_status == e1000_1000t_rx_status_not_ok ? "NOT_OK" :
+		rx_status == e1000_1000t_rx_status_ok     ? "OK"     :
+		"Unknown");
+	return buf;
+}
+
+/*
+ * e1000_proc_list_setup - build link list of proc praramters
+ * @adapter: board private structure
+ *
+ * Order matters - ethx.info entries are ordered in the order links 
+ * are added to list.
+ */
+
+#define LIST_ADD_F(T,D,F) \
+	e1000_proc_list_add(proc_list_head, (T), (D), sizeof(*(D)), (F))
+#define LIST_ADD_BLANK() LIST_ADD_F("", NULL, NULL)
+#define LIST_ADD_S(T,D) LIST_ADD_F((T), (D), e1000_proc_str)
+#define LIST_ADD_H(T,D) LIST_ADD_F((T), (D), e1000_proc_hex)
+#define LIST_ADD_U(T,D) LIST_ADD_F((T), (D), e1000_proc_unsigned)
+
+static void __devinit
+e1000_proc_list_setup(struct e1000_adapter *adapter)
+{
+	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct list_head *proc_list_head = &adapter->proc_list_head;
+
+	INIT_LIST_HEAD(proc_list_head);
+
+	LIST_ADD_S("Description", adapter->id_string);
+	LIST_ADD_F("Part_Number", &adapter->part_num, e1000_proc_part_number);
+	LIST_ADD_S("Driver_Name", e1000_driver_name);
+	LIST_ADD_S("Driver_Version", e1000_driver_version);
+	LIST_ADD_H("PCI_Vendor", &shared->vendor_id);
+	LIST_ADD_H("PCI_Device_ID", &shared->device_id);
+	LIST_ADD_H("PCI_Subsystem_Vendor", &shared->subsystem_vendor_id);
+	LIST_ADD_H("PCI_Subsystem_ID", &shared->subsystem_id);
+	LIST_ADD_H("PCI_Revision_ID", &shared->revision_id);
+	LIST_ADD_U("PCI_Bus", &adapter->pdev->bus->number);
+	LIST_ADD_F("PCI_Slot", adapter, e1000_proc_slot);
+
+	if(adapter->shared.mac_type >= e1000_82543) {
+		LIST_ADD_F("PCI_Bus_Type",
+		           &shared->bus_type, e1000_proc_bus_type);
+		LIST_ADD_F("PCI_Bus_Speed",
+		           &shared->bus_speed, e1000_proc_bus_speed);
+		LIST_ADD_F("PCI_Bus_Width",
+		           &shared->bus_width, e1000_proc_bus_width);
+	}
+
+	LIST_ADD_U("IRQ", &adapter->pdev->irq);
+	LIST_ADD_S("System_Device_Name", adapter->netdev->name);
+	LIST_ADD_F("Current_HWaddr",
+	            adapter->netdev->dev_addr, e1000_proc_hwaddr);
+	LIST_ADD_F("Permanent_HWaddr",
+	            adapter->shared.perm_mac_addr, e1000_proc_hwaddr);
+
+	LIST_ADD_BLANK();
+
+	LIST_ADD_F("Link", adapter, e1000_proc_link);
+	LIST_ADD_F("Speed", &adapter->link_speed, e1000_proc_link_speed);
+	LIST_ADD_F("Duplex", &adapter->link_duplex, e1000_proc_link_duplex);
+	LIST_ADD_F("State", adapter, e1000_proc_state);
+
+	LIST_ADD_BLANK();
+
+	/* Standard net device stats */
+	LIST_ADD_U("Rx_Packets", &adapter->net_stats.rx_packets);
+	LIST_ADD_U("Tx_Packets", &adapter->net_stats.tx_packets);
+	LIST_ADD_U("Rx_Bytes", &adapter->net_stats.rx_bytes);
+	LIST_ADD_U("Tx_Bytes", &adapter->net_stats.tx_bytes);
+	LIST_ADD_U("Rx_Errors", &adapter->net_stats.rx_errors);
+	LIST_ADD_U("Tx_Errors", &adapter->net_stats.tx_errors);
+	LIST_ADD_U("Rx_Dropped", &adapter->net_stats.rx_dropped);
+	LIST_ADD_U("Tx_Dropped", &adapter->net_stats.tx_dropped);
+
+	LIST_ADD_U("Multicast", &adapter->net_stats.multicast);
+	LIST_ADD_U("Collisions", &adapter->net_stats.collisions);
+
+	LIST_ADD_U("Rx_Length_Errors", &adapter->net_stats.rx_length_errors);
+	LIST_ADD_U("Rx_Over_Errors", &adapter->net_stats.rx_over_errors);
+	LIST_ADD_U("Rx_CRC_Errors", &adapter->net_stats.rx_crc_errors);
+	LIST_ADD_U("Rx_Frame_Errors", &adapter->net_stats.rx_frame_errors);
+	LIST_ADD_U("Rx_FIFO_Errors", &adapter->net_stats.rx_fifo_errors);
+	LIST_ADD_U("Rx_Missed_Errors", &adapter->net_stats.rx_missed_errors);
+
+	LIST_ADD_U("Tx_Aborted_Errors", &adapter->net_stats.tx_aborted_errors);
+	LIST_ADD_U("Tx_Carrier_Errors", &adapter->net_stats.tx_carrier_errors);
+	LIST_ADD_U("Tx_FIFO_Errors", &adapter->net_stats.tx_fifo_errors);
+	LIST_ADD_U("Tx_Heartbeat_Errors", 
+	           &adapter->net_stats.tx_heartbeat_errors);
+	LIST_ADD_U("Tx_Window_Errors", &adapter->net_stats.tx_window_errors);
+
+	/* 8254x-specific stats */
+	LIST_ADD_U("Tx_Abort_Late_Coll", &adapter->stats.latecol);
+	LIST_ADD_U("Tx_Deferred_Ok", &adapter->stats.dc);
+	LIST_ADD_U("Tx_Single_Coll_Ok", &adapter->stats.scc);
+	LIST_ADD_U("Tx_Multi_Coll_Ok", &adapter->stats.mcc);
+	LIST_ADD_U("Rx_Long_Length_Errors", &adapter->stats.roc);
+	LIST_ADD_U("Rx_Short_Length_Errors", &adapter->stats.ruc);
+	
+	/* The 82542 does not have an alignment error count register */
+	if(adapter->shared.mac_type >= e1000_82543)
+		LIST_ADD_U("Rx_Align_Errors", &adapter->stats.algnerrc);
+	
+	LIST_ADD_U("Rx_Flow_Control_XON", &adapter->stats.xonrxc);
+	LIST_ADD_U("Rx_Flow_Control_XOFF", &adapter->stats.xoffrxc);
+	LIST_ADD_U("Tx_Flow_Control_XON", &adapter->stats.xontxc);
+	LIST_ADD_U("Tx_Flow_Control_XOFF", &adapter->stats.xofftxc);
+	LIST_ADD_U("Rx_CSum_Offload_Good", &adapter->hw_csum_good);
+	LIST_ADD_U("Rx_CSum_Offload_Errors", &adapter->hw_csum_err);
+
+	LIST_ADD_BLANK();
+
+	/* Cable diags */
+	LIST_ADD_F("PHY_Media_Type", adapter, e1000_proc_media_type);
+	if(adapter->shared.media_type == e1000_media_type_copper) {
+		LIST_ADD_F("PHY_Cable_Length",
+		           adapter, e1000_proc_cable_length);
+		LIST_ADD_F("PHY_Extended_10Base_T_Distance",
+		           adapter, e1000_proc_extended);
+		LIST_ADD_F("PHY_Cable_Polarity",
+		           adapter, e1000_proc_cable_polarity);
+		LIST_ADD_F("PHY_Disable_Polarity_Correction",
+		           adapter, e1000_proc_polarity_correction);
+		LIST_ADD_U("PHY_Idle_Errors", 
+		           &adapter->phy_stats.idle_errors);
+		LIST_ADD_F("PHY_Link_Reset_Enabled",
+		           adapter, e1000_proc_link_reset_enabled);
+		LIST_ADD_U("PHY_Receive_Errors",
+		           &adapter->phy_stats.receive_errors);
+		LIST_ADD_F("PHY_MDI_X_Enabled",
+		           adapter, e1000_proc_mdi_x_enabled);
+		LIST_ADD_F("PHY_Local_Receiver_Status",
+		           &adapter->phy_info.local_rx, 
+			   e1000_proc_rx_status);
+		LIST_ADD_F("PHY_Remote_Receiver_Status",
+		           &adapter->phy_info.remote_rx, 
+			   e1000_proc_rx_status);
+	}
+
+	return;
+}
+
+/*
+ * e1000_proc_dev_setup - create proc fs nodes and link list
+ * @adapter: board private structure
+ */
+
+void __devinit
+e1000_proc_dev_setup(struct e1000_adapter *adapter)
+{
+	e1000_proc_list_setup(adapter);
+
+	e1000_proc_dirs_create(adapter->netdev->name,&adapter->proc_list_head);
+
+	return;
+}
+
+/*
+ * e1000_proc_dev_free - free proc fs nodes and link list
+ * @adapter: board private structure
+ */
+
+void __devexit
+e1000_proc_dev_free(struct e1000_adapter *adapter)
+{
+	e1000_proc_dirs_free(adapter->netdev->name, &adapter->proc_list_head);
+
+	e1000_proc_list_free(&adapter->proc_list_head);
+
+	return;
+}
+
+#else /* CONFIG_PROC_FS */
+
+void __devinit e1000_proc_dev_setup(struct e1000_adapter *adapter) {}
+void __devexit e1000_proc_dev_free(struct e1000_adapter *adapter) {}
+
+#endif /* CONFIG_PROC_FS */
+
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/eepro100.c	Tue Feb 26 11:57:57 2002
@@ -2288,7 +2288,7 @@
 	name:		"eepro100",
 	id_table:	eepro100_pci_tbl,
 	probe:		eepro100_init_one,
-	remove:		eepro100_remove_one,
+	remove:		__devexit_p(eepro100_remove_one),
 #ifdef CONFIG_PM
 	suspend:	eepro100_suspend,
 	resume:		eepro100_resume,
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/epic100.c	Tue Feb 26 11:57:59 2002
@@ -1533,7 +1533,7 @@
 	name:		DRV_NAME,
 	id_table:	epic_pci_tbl,
 	probe:		epic_init_one,
-	remove:		epic_remove_one,
+	remove:		__devexit_p(epic_remove_one),
 #ifdef CONFIG_PM
 	suspend:	epic_suspend,
 	resume:		epic_resume,
diff -Nru a/drivers/net/fc/Makefile b/drivers/net/fc/Makefile
--- a/drivers/net/fc/Makefile	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/fc/Makefile	Tue Feb 26 11:57:58 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for linux/drivers/net/fc
 #
-# 9 Aug 2000, Christoph Hellwig <hch@caldera.de>
+# 9 Aug 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c
--- a/drivers/net/fealnx.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/fealnx.c	Tue Feb 26 11:58:00 2002
@@ -1929,7 +1929,7 @@
 	name:		"fealnx",
 	id_table:	fealnx_pci_tbl,
 	probe:		fealnx_init_one,
-	remove:		fealnx_remove_one,
+	remove:		__devexit_p(fealnx_remove_one),
 };
 
 static int __init fealnx_init(void)
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/hamachi.c	Tue Feb 26 11:57:59 2002
@@ -1978,7 +1978,7 @@
 }
 
 
-static void __exit hamachi_remove_one (struct pci_dev *pdev)
+static void __devexit hamachi_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -2008,7 +2008,7 @@
 	name:		DRV_NAME,
 	id_table:	hamachi_pci_tbl,
 	probe:		hamachi_init_one,
-	remove:		hamachi_remove_one,
+	remove:		__devexit_p(hamachi_remove_one),
 };
 
 static int __init hamachi_init (void)
diff -Nru a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile
--- a/drivers/net/hamradio/Makefile	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/hamradio/Makefile	Tue Feb 26 11:57:56 2002
@@ -7,7 +7,7 @@
 #               Joerg Reuter DL1BKE <jreuter@yaina.de>
 #
 # 20000806	Rewritten to use lists instead of if-statements.
-#		Christoph Hellwig <hch@caldera.de>
+#		Christoph Hellwig <hch@infradead.org>
 #
 
 
diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
--- a/drivers/net/ioc3-eth.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/ioc3-eth.c	Tue Feb 26 11:57:56 2002
@@ -1516,7 +1516,7 @@
 	name:		"ioc3-eth",
 	id_table:	ioc3_pci_tbl,
 	probe:		ioc3_probe,
-	remove:		ioc3_remove_one,
+	remove:		__devexit_p(ioc3_remove_one),
 };
 
 static int __init ioc3_init_module(void)
diff -Nru a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
--- a/drivers/net/irda/Makefile	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/irda/Makefile	Tue Feb 26 11:57:59 2002
@@ -2,7 +2,7 @@
 #
 # Makefile for the Linux IrDA infrared port device drivers.
 #
-# 9 Aug 2000, Christoph Hellwig <hch@caldera.de>
+# 9 Aug 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
--- a/drivers/net/irda/vlsi_ir.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/irda/vlsi_ir.c	Tue Feb 26 11:57:56 2002
@@ -1291,7 +1291,7 @@
 	name:           drivername,
 	id_table:       vlsi_irda_table,
 	probe:          vlsi_irda_probe,
-	remove:         vlsi_irda_remove,
+	remove:         __devexit_p(vlsi_irda_remove),
 	suspend:        vlsi_irda_suspend,
 	resume:         vlsi_irda_resume,
 };
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/natsemi.c	Tue Feb 26 11:57:56 2002
@@ -1925,6 +1925,8 @@
 	/* get link status */
 	case ETHTOOL_GLINK: {
 		struct ethtool_value edata = {ETHTOOL_GLINK};
+		/* LSTATUS is latched low until a read - so read twice */
+		mdio_read(dev, 1, MII_BMSR);
 		edata.data = (mdio_read(dev, 1, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
 		if (copy_to_user(useraddr, &edata, sizeof(edata)))
 			return -EFAULT;
@@ -2504,7 +2506,7 @@
 	name:		DRV_NAME,
 	id_table:	natsemi_pci_tbl,
 	probe:		natsemi_probe1,
-	remove:		natsemi_remove1,
+	remove:		__devexit_p(natsemi_remove1),
 #ifdef CONFIG_PM
 	suspend:	natsemi_suspend,
 	resume:		natsemi_resume,
diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
--- a/drivers/net/ne2k-pci.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/ne2k-pci.c	Tue Feb 26 11:57:58 2002
@@ -642,7 +642,7 @@
 static struct pci_driver ne2k_driver = {
 	name:		DRV_NAME,
 	probe:		ne2k_pci_init_one,
-	remove:		ne2k_pci_remove_one,
+	remove:		__devexit_p(ne2k_pci_remove_one),
 	id_table:	ne2k_pci_tbl,
 };
 
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/ns83820.c	Tue Feb 26 11:58:00 2002
@@ -1637,7 +1637,7 @@
 	name:		"ns83820",
 	id_table:	ns83820_pci_tbl,
 	probe:		ns83820_init_one,
-	remove:		ns83820_remove_one,
+	remove:		__devexit_p(ns83820_remove_one),
 #if 0	/* FIXME: implement */
 	suspend:	,
 	resume:		,
diff -Nru a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
--- a/drivers/net/pci-skeleton.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/pci-skeleton.c	Tue Feb 26 11:57:56 2002
@@ -1956,7 +1956,7 @@
 	name:		MODNAME,
 	id_table:	netdrv_pci_tbl,
 	probe:		netdrv_init_one,
-	remove:		netdrv_remove_one,
+	remove:		__devexit_p(netdrv_remove_one),
 #ifdef CONFIG_PM
 	suspend:	netdrv_suspend,
 	resume:		netdrv_resume,
diff -Nru a/drivers/net/pcmcia/Config.help b/drivers/net/pcmcia/Config.help
--- a/drivers/net/pcmcia/Config.help	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/pcmcia/Config.help	Tue Feb 26 11:57:58 2002
@@ -133,7 +133,7 @@
 
   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 xircom_tulip_cb.o.  If you want to compile
+  The module will be called xircom_cb.o.  If you want to compile
   it as a module, say M here and read
   <file:Documentation/modules.txt>. If unsure, say N.
 
diff -Nru a/drivers/net/pcmcia/xircom_cb.c b/drivers/net/pcmcia/xircom_cb.c
--- a/drivers/net/pcmcia/xircom_cb.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/pcmcia/xircom_cb.c	Tue Feb 26 11:58:00 2002
@@ -170,7 +170,7 @@
 	name:		"xircom_cb", 
 	id_table:	xircom_pci_table, 
 	probe:		xircom_probe, 
-	remove:		xircom_remove, 
+	remove:		__devexit_p(xircom_remove), 
 };
 
 
diff -Nru a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c
--- a/drivers/net/pcmcia/xircom_tulip_cb.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/pcmcia/xircom_tulip_cb.c	Tue Feb 26 11:57:57 2002
@@ -1709,7 +1709,7 @@
 	name:		DRV_NAME,
 	id_table:	xircom_pci_table,
 	probe:		xircom_init_one,
-	remove:		xircom_remove_one,
+	remove:		__devexit_p(xircom_remove_one),
 #ifdef CONFIG_PM
 	suspend:	xircom_suspend,
 	resume:		xircom_resume
diff -Nru a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
--- a/drivers/net/rcpci45.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/rcpci45.c	Tue Feb 26 11:57:58 2002
@@ -115,7 +115,7 @@
 MODULE_DEVICE_TABLE (pci, rcpci45_pci_table);
 MODULE_LICENSE("GPL");
 
-static void __exit
+static void __devexit
 rcpci45_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
@@ -267,7 +267,7 @@
 	name:		"rcpci45",
 	id_table:	rcpci45_pci_table,
 	probe:		rcpci45_init_one,
-	remove:		rcpci45_remove_one,
+	remove:		__devexit_p(rcpci45_remove_one),
 };
 
 static int __init
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/sis900.c	Tue Feb 26 11:57:59 2002
@@ -2129,7 +2129,7 @@
 	name:		SIS900_MODULE_NAME,
 	id_table:	sis900_pci_tbl,
 	probe:		sis900_probe,
-	remove:		sis900_remove,
+	remove:		__devexit_p(sis900_remove),
 };
 
 static int __init sis900_init_module(void)
diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c
--- a/drivers/net/starfire.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/starfire.c	Tue Feb 26 11:57:58 2002
@@ -1982,7 +1982,7 @@
 static struct pci_driver starfire_driver = {
 	name:		DRV_NAME,
 	probe:		starfire_init_one,
-	remove:		starfire_remove_one,
+	remove:		__devexit_p(starfire_remove_one),
 	id_table:	starfire_pci_tbl,
 };
 
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/sundance.c	Tue Feb 26 11:57:56 2002
@@ -1463,7 +1463,7 @@
 	name:		DRV_NAME,
 	id_table:	sundance_pci_tbl,
 	probe:		sundance_probe1,
-	remove:		sundance_remove1,
+	remove:		__devexit_p(sundance_remove1),
 };
 
 static int __init sundance_init(void)
diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c
--- a/drivers/net/sungem.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/sungem.c	Tue Feb 26 11:58:00 2002
@@ -2835,7 +2835,7 @@
 	name:		GEM_MODULE_NAME,
 	id_table:	gem_pci_tbl,
 	probe:		gem_init_one,
-	remove:		gem_remove_one,
+	remove:		__devexit_p(gem_remove_one),
 #ifdef CONFIG_PM
 	suspend:	gem_suspend,
 	resume:		gem_resume,
diff -Nru a/drivers/net/tlan.c b/drivers/net/tlan.c
--- a/drivers/net/tlan.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/tlan.c	Tue Feb 26 11:57:57 2002
@@ -431,7 +431,7 @@
 	name:		"tlan",
 	id_table:	tlan_pci_tbl,
 	probe:		tlan_init_one,
-	remove:		tlan_remove_one,	
+	remove:		__devexit_p(tlan_remove_one),	
 };
 
 static int __init tlan_probe(void)
diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/tokenring/3c359.c	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1816 @@
+/*
+ *   3c359.c (c) 2000 Mike Phillips (mikep@linuxtr.net) All Rights Reserved
+ *
+ *  Linux driver for 3Com 3c359 Tokenlink Velocity XL PCI NIC
+ *
+ *  Base Driver Olympic:
+ *	Written 1999 Peter De Schrijver & Mike Phillips
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU General Public License, incorporated herein by reference.
+ * 
+ *  7/17/00 - Clean up, version number 0.9.0. Ready to release to the world.
+ *
+ *  2/16/01 - Port up to kernel 2.4.2 ready for submission into the kernel.
+ *  3/05/01 - Last clean up stuff before submission.
+ *  2/15/01 - Finally, update to new pci api. 
+ *
+ *  To Do:
+ */
+
+/* 
+ *	Technical Card Details
+ *
+ *  All access to data is done with 16/8 bit transfers.  The transfer
+ *  method really sucks. You can only read or write one location at a time.
+ *
+ *  Also, the microcode for the card must be uploaded if the card does not have
+ *  the flashrom on board.  This is a 28K bloat in the driver when compiled
+ *  as a module.
+ *
+ *  Rx is very simple, status into a ring of descriptors, dma data transfer,
+ *  interrupts to tell us when a packet is received.
+ *
+ *  Tx is a little more interesting. Similar scenario, descriptor and dma data
+ *  transfers, but we don't have to interrupt the card to tell it another packet
+ *  is ready for transmission, we are just doing simple memory writes, not io or mmio
+ *  writes.  The card can be set up to simply poll on the next
+ *  descriptor pointer and when this value is non-zero will automatically download
+ *  the next packet.  The card then interrupts us when the packet is done.
+ *
+ */
+
+#define XL_DEBUG 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include "3c359.h"
+
+static char version[] __devinitdata  = 
+"3c359.c v1.2.0 2/17/01 - Mike Phillips (mikep@linuxtr.net)" ; 
+
+MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ; 
+MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ;
+
+/* Module paramters */
+
+/* Ring Speed 0,4,16 
+ * 0 = Autosense   
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed.
+ * 
+ * The adapter will _not_ fail to open if there are no
+ * active monitors on the ring, it will simply open up in 
+ * its last known ringspeed if no ringspeed is specified.
+ */
+
+static int ringspeed[XL_MAX_ADAPTERS] = {0,} ;
+
+MODULE_PARM(ringspeed, "1-" __MODULE_STRING(XL_MAX_ADAPTERS) "i");
+MODULE_PARM_DESC(ringspeed,"3c359: Ringspeed selection - 4,16 or 0") ; 
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[XL_MAX_ADAPTERS] = {0,} ;
+ 
+MODULE_PARM(pkt_buf_sz, "1-" __MODULE_STRING(XL_MAX_ADAPTERS) "i") ; 
+MODULE_PARM_DESC(pkt_buf_sz,"3c359: Initial buffer size") ; 
+/* Message Level */
+
+static int message_level[XL_MAX_ADAPTERS] = {0,} ; 
+
+MODULE_PARM(message_level, "1-" __MODULE_STRING(XL_MAX_ADAPTERS) "i") ; 
+MODULE_PARM_DESC(message_level, "3c359: Level of reported messages \n") ; 
+/* 
+ *	This is a real nasty way of doing this, but otherwise you
+ *	will be stuck with 1555 lines of hex #'s in the code.
+ */
+
+#include "3c359_microcode.h" 
+
+static struct pci_device_id xl_pci_tbl[] __devinitdata =
+{
+	{PCI_VENDOR_ID_3COM,PCI_DEVICE_ID_3COM_3C359, PCI_ANY_ID, PCI_ANY_ID, },
+	{ }			/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci,xl_pci_tbl) ; 
+
+static int xl_init(struct net_device *dev);
+static int xl_open(struct net_device *dev);
+static int xl_open_hw(struct net_device *dev) ;  
+static int xl_hw_reset(struct net_device *dev); 
+static int xl_xmit(struct sk_buff *skb, struct net_device *dev);
+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 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);
+static void xl_asb_cmd(struct net_device *dev) ; 
+static void xl_srb_cmd(struct net_device *dev, int srb_cmd) ; 
+static void xl_wait_misr_flags(struct net_device *dev) ; 
+static int xl_change_mtu(struct net_device *dev, int mtu);
+static void xl_srb_bh(struct net_device *dev) ; 
+static void xl_asb_bh(struct net_device *dev) ; 
+static void xl_reset(struct net_device *dev) ;  
+static void xl_freemem(struct net_device *dev) ;  
+
+
+/* EEProm Access Functions */
+static u16  xl_ee_read(struct net_device *dev, int ee_addr) ; 
+static void  xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value) ; 
+
+/* Debugging functions */
+#if XL_DEBUG
+static void print_tx_state(struct net_device *dev) ; 
+static void print_rx_state(struct net_device *dev) ; 
+
+static void print_tx_state(struct net_device *dev)
+{
+
+	struct xl_private *xl_priv = (struct xl_private *)dev->priv ; 
+	struct xl_tx_desc *txd ; 
+	u8 *xl_mmio = xl_priv->xl_mmio ; 
+	int i ; 
+
+	printk("tx_ring_head: %d, tx_ring_tail: %d, free_ent: %d \n",xl_priv->tx_ring_head, 
+		xl_priv->tx_ring_tail, xl_priv->free_ring_entries) ; 
+	printk("Ring    , Address ,   FSH  , DnNextPtr, Buffer, Buffer_Len \n"); 
+	for (i = 0; i < 16; i++) {
+		txd = &(xl_priv->xl_tx_ring[i]) ; 
+		printk("%d, %08lx, %08x, %08x, %08x, %08x \n", i, virt_to_bus(txd), 
+			txd->framestartheader, txd->dnnextptr, txd->buffer, txd->buffer_length ) ; 
+	}
+
+	printk("DNLISTPTR = %04x \n", readl(xl_mmio + MMIO_DNLISTPTR) ); 
+	
+	printk("DmaCtl = %04x \n", readl(xl_mmio + MMIO_DMA_CTRL) ); 
+	printk("Queue status = %0x \n",netif_running(dev) ) ; 
+}
+
+static void print_rx_state(struct net_device *dev)
+{
+
+	struct xl_private *xl_priv = (struct xl_private *)dev->priv ; 
+	struct xl_rx_desc *rxd ; 
+	u8 *xl_mmio = xl_priv->xl_mmio ; 
+	int i ; 
+
+	printk("rx_ring_tail: %d \n", xl_priv->rx_ring_tail) ; 
+	printk("Ring    , Address ,   FrameState  , UPNextPtr, FragAddr, Frag_Len \n"); 
+	for (i = 0; i < 16; i++) { 
+		/* rxd = (struct xl_rx_desc *)xl_priv->rx_ring_dma_addr + (i * sizeof(struct xl_rx_desc)) ; */
+		rxd = &(xl_priv->xl_rx_ring[i]) ; 
+		printk("%d, %08lx, %08x, %08x, %08x, %08x \n", i, virt_to_bus(rxd), 
+			rxd->framestatus, rxd->upnextptr, rxd->upfragaddr, rxd->upfraglen ) ; 
+	}
+
+	printk("UPLISTPTR = %04x \n", readl(xl_mmio + MMIO_UPLISTPTR) ); 
+	
+	printk("DmaCtl = %04x \n", readl(xl_mmio + MMIO_DMA_CTRL) ); 
+	printk("Queue status = %0x \n",netif_running(dev) ) ;
+} 
+#endif
+
+/*
+ *	Read values from the on-board EEProm.  This looks very strange
+ *	but you have to wait for the EEProm to get/set the value before 
+ *	passing/getting the next value from the nic. As with all requests
+ *	on this nic it has to be done in two stages, a) tell the nic which
+ *	memory address you want to access and b) pass/get the value from the nic.
+ *	With the EEProm, you have to wait before and inbetween access a) and b).
+ *	As this is only read at initialization time and the wait period is very 
+ *	small we shouldn't have to worry about scheduling issues.
+ */
+
+static u16 xl_ee_read(struct net_device *dev, int ee_addr)
+{ 
+    	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+	u8 *xl_mmio = xl_priv->xl_mmio ; 
+
+	/* Wait for EEProm to not be busy */
+	writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+	/* Tell EEProm what we want to do and where */
+	writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(EEREAD + ee_addr, xl_mmio + MMIO_MACDATA) ; 
+
+	/* Wait for EEProm to not be busy */
+	writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ; 
+	
+	/* Tell EEProm what we want to do and where */
+	writel(IO_WORD_WRITE | EECONTROL , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(EEREAD + ee_addr, xl_mmio + MMIO_MACDATA) ; 
+
+	/* Finally read the value from the EEProm */
+	writel(IO_WORD_READ | EEDATA , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	return readw(xl_mmio + MMIO_MACDATA) ; 
+}
+
+/* 
+ *	Write values to the onboard eeprom. As with eeprom read you need to 
+ *	set which location to write, wait, value to write, wait, with the 
+ *	added twist of having to enable eeprom writes as well.
+ */
+
+static void  xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value) 
+{
+    	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+	u8 *xl_mmio = xl_priv->xl_mmio ; 
+
+	/* Wait for EEProm to not be busy */
+	writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+	
+	/* Enable write/erase */
+	writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(EE_ENABLE_WRITE, xl_mmio + MMIO_MACDATA) ; 
+
+	/* Wait for EEProm to not be busy */
+	writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+	/* Put the value we want to write into EEDATA */ 
+	writel(IO_WORD_WRITE | EEDATA, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(ee_value, xl_mmio + MMIO_MACDATA) ;
+
+	/* Tell EEProm to write eevalue into ee_addr */
+	writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(EEWRITE + ee_addr, xl_mmio + MMIO_MACDATA) ; 
+
+	/* Wait for EEProm to not be busy, to ensure write gets done */
+	writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+	
+	return ; 
+}
+ 
+int __devinit xl_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 
+{
+	struct net_device *dev ; 
+	struct xl_private *xl_priv ; 
+	static int card_no = -1 ;
+	int i ; 
+
+	card_no++ ; 
+
+	if (pci_enable_device(pdev)) { 
+		return -ENODEV ; 
+	} 
+
+	pci_set_master(pdev);
+
+	if ((i = pci_request_regions(pdev,"3c359"))) { 
+		return i ; 
+	} ; 
+
+	/* 
+	 * Allowing init_trdev to allocate the dev->priv structure will align xl_private
+   	 * on a 32 bytes boundary which we need for the rx/tx descriptors
+	 */
+
+	dev = alloc_trdev(sizeof(struct xl_private)) ; 
+	if (!dev) { 
+		pci_release_regions(pdev) ; 
+		return -ENOMEM ; 
+	} 
+	xl_priv = dev->priv ; 
+
+#if XL_DEBUG  
+	printk("pci_device: %p, dev:%p, dev->priv: %p, ba[0]: %10x, ba[1]:%10x\n", 
+		pdev, dev, dev->priv, (unsigned int)pdev->resource[0].start, (unsigned int)pdev->resource[1].start) ;  
+#endif 
+
+	dev->irq=pdev->irq;
+	dev->base_addr=pci_resource_start(pdev,0) ; 
+	dev->init=NULL ; /* Must be null with new api, otherwise get called twice */
+	xl_priv->xl_card_name = (char *)pdev->name ; 
+	xl_priv->xl_mmio=ioremap(pci_resource_start(pdev,1), XL_IO_SPACE);
+	xl_priv->pdev = pdev ; 
+		
+	if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
+		xl_priv->pkt_buf_sz = PKT_BUF_SZ ; 
+	else
+		xl_priv->pkt_buf_sz = pkt_buf_sz[card_no] ; 
+
+	dev->mtu = xl_priv->pkt_buf_sz - TR_HLEN ; 
+	xl_priv->xl_ring_speed = ringspeed[card_no] ; 
+	xl_priv->xl_message_level = message_level[card_no] ; 
+	xl_priv->xl_functional_addr[0] = xl_priv->xl_functional_addr[1] = xl_priv->xl_functional_addr[2] = xl_priv->xl_functional_addr[3] = 0 ; 
+	xl_priv->xl_copy_all_options = 0 ; 
+		
+	if((i = xl_init(dev))) {
+		iounmap(xl_priv->xl_mmio) ; 
+		kfree(dev) ; 
+		pci_release_regions(pdev) ; 
+		return i ; 
+	}				
+
+	dev->open=&xl_open;
+	dev->hard_start_xmit=&xl_xmit;
+	dev->change_mtu=&xl_change_mtu;
+	dev->stop=&xl_close;
+	dev->do_ioctl=NULL;
+	dev->set_multicast_list=&xl_set_rx_mode;
+	dev->get_stats=&xl_get_stats ;
+	dev->set_mac_address=&xl_set_mac_address ; 
+	SET_MODULE_OWNER(dev); 
+
+	pci_set_drvdata(pdev,dev) ; 
+	if ((i = register_netdev(dev))) { 
+		printk(KERN_ERR "3C359, register netdev failed\n") ;  
+		pci_set_drvdata(pdev,NULL) ; 
+		iounmap(xl_priv->xl_mmio) ; 
+		kfree(dev) ; 
+		pci_release_regions(pdev) ; 
+		return i ; 
+	}
+   
+	printk(KERN_INFO "3C359: %s registered as: %s\n",xl_priv->xl_card_name,dev->name) ; 
+
+	return 0; 
+}
+
+
+static int __init xl_init(struct net_device *dev) 
+{
+    	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+
+	printk(KERN_INFO "%s \n", version);
+	printk(KERN_INFO "%s: I/O at %hx, MMIO at %p, using irq %d\n",
+		xl_priv->xl_card_name, (unsigned int)dev->base_addr ,xl_priv->xl_mmio, dev->irq);
+
+	spin_lock_init(&xl_priv->xl_lock) ; 
+
+	return xl_hw_reset(dev) ; 
+
+}
+
+
+/* 
+ *	Hardware reset.  This needs to be a separate entity as we need to reset the card
+ *	when we change the EEProm settings.
+ */
+
+static int xl_hw_reset(struct net_device *dev) 
+{ 
+    	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+	u8 *xl_mmio = xl_priv->xl_mmio ; 
+	unsigned long t ; 
+	u16 i ; 
+    	u16 result_16 ; 
+	u8 result_8 ;
+	u16 start ; 
+	int j ;
+
+	/*
+	 *  Reset the card.  If the card has got the microcode on board, we have 
+         *  missed the initialization interrupt, so we must always do this.
+	 */
+
+	writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ; 
+
+	/* 
+	 * Must wait for cmdInProgress bit (12) to clear before continuing with
+	 * card configuration.
+	 */
+
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 40*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL  card not responding to global reset.\n", dev->name);
+			return -ENODEV;
+		}
+	}
+
+	/*
+	 *  Enable pmbar by setting bit in CPAttention
+	 */
+
+	writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+	result_8 = readb(xl_mmio + MMIO_MACDATA) ; 
+	result_8 = result_8 | CPA_PMBARVIS ; 
+	writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(result_8, xl_mmio + MMIO_MACDATA) ; 
+	
+	/*
+	 * Read cpHold bit in pmbar, if cleared we have got Flashrom on board.
+ 	 * If not, we need to upload the microcode to the card
+	 */
+
+	writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);  
+
+#if XL_DEBUG
+	printk(KERN_INFO "Read from PMBAR = %04x \n", readw(xl_mmio + MMIO_MACDATA)) ; 
+#endif
+
+	if ( readw( (xl_mmio + MMIO_MACDATA))  & PMB_CPHOLD ) { 
+
+		/* Set PmBar, privateMemoryBase bits (8:2) to 0 */
+
+		writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);  
+		result_16 = readw(xl_mmio + MMIO_MACDATA) ; 
+		result_16 = result_16 & ~((0x7F) << 2) ; 
+		writel( (IO_WORD_WRITE | PMBAR), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writew(result_16,xl_mmio + MMIO_MACDATA) ; 
+	
+		/* Set CPAttention, memWrEn bit */
+
+		writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		result_8 = readb(xl_mmio + MMIO_MACDATA) ; 
+		result_8 = result_8 | CPA_MEMWREN  ; 
+		writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(result_8, xl_mmio + MMIO_MACDATA) ; 
+
+		/* 
+		 * Now to write the microcode into the shared ram 
+	 	 * The microcode must finish at position 0xFFFF, so we must subtract
+		 * to get the start position for the code
+		 */
+
+		start = (0xFFFF - (mc_size) + 1 ) ; /* Looks strange but ensures compiler only uses 16 bit unsigned int for this */ 
+		
+		printk(KERN_INFO "3C359: Uploading Microcode: "); 
+		
+		for (i = start,j=0; (j < mc_size && i <= 0xffff) ; i++,j++) { 
+			writel(MEM_BYTE_WRITE | 0XD0000 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			writeb(microcode[j],xl_mmio + MMIO_MACDATA) ; 
+			if (j % 1024 == 0)
+				printk(".");
+		}
+		printk("\n") ; 
+
+		for (i=0;i < 16; i++) { 
+			writel( (MEM_BYTE_WRITE | 0xDFFF0) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			writeb(microcode[mc_size - 16 + i], xl_mmio + MMIO_MACDATA) ; 
+		}
+
+		/*
+		 * Have to write the start address of the upload to FFF4, but
+                 * the address must be >> 4. You do not want to know how long
+                 * it took me to discover this.
+		 */
+
+		writel(MEM_WORD_WRITE | 0xDFFF4, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writew(start >> 4, xl_mmio + MMIO_MACDATA);
+
+		/* Clear the CPAttention, memWrEn Bit */
+	
+		writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		result_8 = readb(xl_mmio + MMIO_MACDATA) ; 
+		result_8 = result_8 & ~CPA_MEMWREN ; 
+		writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(result_8, xl_mmio + MMIO_MACDATA) ; 
+
+		/* Clear the cpHold bit in pmbar */
+
+		writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);  
+		result_16 = readw(xl_mmio + MMIO_MACDATA) ; 
+		result_16 = result_16 & ~PMB_CPHOLD ; 
+		writel( (IO_WORD_WRITE | PMBAR), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writew(result_16,xl_mmio + MMIO_MACDATA) ; 
+
+
+	} /* If microcode upload required */
+
+	/* 
+	 * The card should now go though a self test procedure and get itself ready
+         * to be opened, we must wait for an srb response with the initialization
+         * information. 
+	 */
+
+#if XL_DEBUG
+	printk(KERN_INFO "%s: Microcode uploaded, must wait for the self test to complete\n", dev->name);
+#endif
+
+	writew(SETINDENABLE | 0xFFF, xl_mmio + MMIO_COMMAND) ; 
+
+	t=jiffies;
+	while ( !(readw(xl_mmio + MMIO_INTSTATUS_AUTO) & INTSTAT_SRB) ) { 
+		schedule();		
+		if(jiffies-t > 15*HZ) {
+			printk(KERN_ERR "3COM 3C359 Velocity XL  card not responding.\n");
+			return -ENODEV; 
+		}
+	}
+
+	/*
+	 * Write the RxBufArea with D000, RxEarlyThresh, TxStartThresh, 
+ 	 * DnPriReqThresh, read the tech docs if you want to know what
+	 * values they need to be.
+	 */
+
+	writel(MMIO_WORD_WRITE | RXBUFAREA, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(0xD000, xl_mmio + MMIO_MACDATA) ; 
+	
+	writel(MMIO_WORD_WRITE | RXEARLYTHRESH, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(0X0020, xl_mmio + MMIO_MACDATA) ; 
+	
+	writew( SETTXSTARTTHRESH | 0x40 , xl_mmio + MMIO_COMMAND) ; 
+
+	writeb(0x04, xl_mmio + MMIO_DNBURSTTHRESH) ; 
+	writeb(0x04, xl_mmio + DNPRIREQTHRESH) ;
+
+	/*
+	 * Read WRBR to provide the location of the srb block, have to use byte reads not word reads. 
+	 * Tech docs have this wrong !!!!
+	 */
+
+	writel(MMIO_BYTE_READ | WRBR, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	xl_priv->srb = readb(xl_mmio + MMIO_MACDATA) << 8 ; 
+	writel( (MMIO_BYTE_READ | WRBR) + 1, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	xl_priv->srb = xl_priv->srb | readb(xl_mmio + MMIO_MACDATA) ;
+
+#if XL_DEBUG
+	writel(IO_WORD_READ | SWITCHSETTINGS, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	if ( readw(xl_mmio + MMIO_MACDATA) & 2) { 
+		printk(KERN_INFO "Default ring speed 4 mbps \n") ;
+	} else {
+		printk(KERN_INFO "Default ring speed 16 mbps \n") ; 
+	} 
+	printk(KERN_INFO "%s: xl_priv->srb = %04x\n",xl_priv->xl_card_name, xl_priv->srb);
+#endif
+
+	return 0;
+}
+
+static int xl_open(struct net_device *dev) 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u8 i ; 
+	u16 hwaddr[3] ; /* Should be u8[6] but we get word return values */
+	int open_err ;
+
+	u16 switchsettings, switchsettings_eeprom  ;
+ 
+	if(request_irq(dev->irq, &xl_interrupt, SA_SHIRQ , "3c359", dev)) {
+		return -EAGAIN;
+	}
+
+	/* 
+	 * Read the information from the EEPROM that we need. I know we
+ 	 * should use ntohs, but the word gets stored reversed in the 16
+	 * bit field anyway and it all works its self out when we memcpy
+	 * it into dev->dev_addr. 
+	 */
+	
+	hwaddr[0] = xl_ee_read(dev,0x10) ; 
+	hwaddr[1] = xl_ee_read(dev,0x11) ; 
+	hwaddr[2] = xl_ee_read(dev,0x12) ; 
+
+	/* Ring speed */
+
+	switchsettings_eeprom = xl_ee_read(dev,0x08) ;
+	switchsettings = switchsettings_eeprom ;  
+
+	if (xl_priv->xl_ring_speed != 0) { 
+		if (xl_priv->xl_ring_speed == 4)  
+			switchsettings = switchsettings | 0x02 ; 
+		else 
+			switchsettings = switchsettings & ~0x02 ; 
+	}
+
+	/* Only write EEProm if there has been a change */
+	if (switchsettings != switchsettings_eeprom) { 
+		xl_ee_write(dev,0x08,switchsettings) ; 
+		/* Hardware reset after changing EEProm */
+		xl_hw_reset(dev) ; 
+	}
+
+	memcpy(dev->dev_addr,hwaddr,dev->addr_len) ; 
+	
+	open_err = xl_open_hw(dev) ; 
+
+	/* 
+	 * This really needs to be cleaned up with better error reporting.
+	 */
+
+	if (open_err != 0) { /* Something went wrong with the open command */
+		if (open_err & 0x07) { /* Wrong speed, retry at different speed */
+			printk(KERN_WARNING "%s: Open Error, retrying at different ringspeed \n", dev->name) ; 
+			switchsettings = switchsettings ^ 2 ; 
+			xl_ee_write(dev,0x08,switchsettings) ; 
+			xl_hw_reset(dev) ; 
+			open_err = xl_open_hw(dev) ; 
+			if (open_err != 0) { 
+				printk(KERN_WARNING "%s: Open error returned a second time, we're bombing out now\n", dev->name); 
+				free_irq(dev->irq,dev) ; 						
+				return -ENODEV ;
+			}  
+		} else { 
+			printk(KERN_WARNING "%s: Open Error = %04x\n", dev->name, open_err) ; 
+			free_irq(dev->irq,dev) ; 
+			return -ENODEV ; 
+		}
+	}
+
+	/*
+	 * Now to set up the Rx and Tx buffer structures
+	 */
+	/* These MUST be on 8 byte boundaries */
+	xl_priv->xl_tx_ring = kmalloc((sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) + 7, GFP_DMA | GFP_KERNEL) ; 
+	xl_priv->xl_rx_ring = kmalloc((sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) +7, GFP_DMA | GFP_KERNEL) ; 
+	memset(xl_priv->xl_tx_ring,0,sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) ; 
+	memset(xl_priv->xl_rx_ring,0,sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) ; 
+
+	 /* Setup Rx Ring */
+	 for (i=0 ; i < XL_RX_RING_SIZE ; i++) { 
+		struct sk_buff *skb ; 
+
+		skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ; 
+		if (skb==NULL) 
+			break ; 
+
+		skb->dev = dev ; 
+		xl_priv->xl_rx_ring[i].upfragaddr = pci_map_single(xl_priv->pdev, skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; 
+		xl_priv->xl_rx_ring[i].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG;
+		xl_priv->rx_ring_skb[i] = skb ; 	
+	}
+
+	if (i==0) { 
+		printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled \n",dev->name) ; 
+		free_irq(dev->irq,dev) ; 
+		return -EIO ; 
+	} 
+
+	xl_priv->rx_ring_no = i ; 
+	xl_priv->rx_ring_tail = 0 ; 
+	xl_priv->rx_ring_dma_addr = pci_map_single(xl_priv->pdev,xl_priv->xl_rx_ring, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_TODEVICE) ; 
+	for (i=0;i<(xl_priv->rx_ring_no-1);i++) { 
+		xl_priv->xl_rx_ring[i].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * (i+1)) ; 
+	} 
+	xl_priv->xl_rx_ring[i].upnextptr = 0 ; 
+
+	writel(xl_priv->rx_ring_dma_addr, xl_mmio + MMIO_UPLISTPTR) ; 
+	
+	/* Setup Tx Ring */
+	
+	xl_priv->tx_ring_dma_addr = pci_map_single(xl_priv->pdev,xl_priv->xl_tx_ring, sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE,PCI_DMA_TODEVICE) ; 
+	
+	xl_priv->tx_ring_head = 1 ; 
+	xl_priv->tx_ring_tail = 255 ; /* Special marker for first packet */
+	xl_priv->free_ring_entries = XL_TX_RING_SIZE ; 
+
+	/*
+ 	 * Setup the first dummy DPD entry for polling to start working.
+	 */
+
+	xl_priv->xl_tx_ring[0].framestartheader = TXDPDEMPTY ; 
+	xl_priv->xl_tx_ring[0].buffer = 0 ; 
+	xl_priv->xl_tx_ring[0].buffer_length = 0 ; 
+	xl_priv->xl_tx_ring[0].dnnextptr = 0 ; 
+
+	writel(xl_priv->tx_ring_dma_addr, xl_mmio + MMIO_DNLISTPTR) ; 
+	writel(DNUNSTALL, xl_mmio + MMIO_COMMAND) ; 
+	writel(UPUNSTALL, xl_mmio + MMIO_COMMAND) ; 
+	writel(DNENABLE, xl_mmio + MMIO_COMMAND) ; 
+	writeb(0x40, xl_mmio + MMIO_DNPOLL) ;	
+
+	/*
+	 * Enable interrupts on the card
+	 */
+
+	writel(SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
+	writel(SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
+
+	netif_start_queue(dev) ; 	
+	return 0;
+	
+}	
+
+static int xl_open_hw(struct net_device *dev) 
+{ 
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u16 vsoff ;
+	char ver_str[33];  
+	int open_err ; 
+	int i ; 
+	unsigned long t ; 
+
+	/*
+	 * Okay, let's build up the Open.NIC srb command
+	 *
+	 */
+		
+	writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(OPEN_NIC, xl_mmio + MMIO_MACDATA) ; 
+	
+	/*
+	 * Use this as a test byte, if it comes back with the same value, the command didn't work
+	 */
+
+	writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb)+ 2, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0xff,xl_mmio + MMIO_MACDATA) ; 
+
+	/* Open options */
+	writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + 8, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0x00, xl_mmio + MMIO_MACDATA) ; 
+	writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + 9, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0x00, xl_mmio + MMIO_MACDATA) ; 
+
+	/* 
+	 * Node address, be careful here, the docs say you can just put zeros here and it will use
+	 * the hardware address, it doesn't, you must include the node address in the open command.
+	 */
+
+	if (xl_priv->xl_laa[0]) {  /* If using a LAA address */
+		for (i=10;i<16;i++) { 
+			writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			writeb(xl_priv->xl_laa[i],xl_mmio + MMIO_MACDATA) ; 
+		}
+		memcpy(dev->dev_addr,xl_priv->xl_laa,dev->addr_len) ; 
+	} else { /* Regular hardware address */ 
+		for (i=10;i<16;i++) { 
+			writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			writeb(dev->dev_addr[i-10], xl_mmio + MMIO_MACDATA) ; 
+		}
+	}
+
+	/* Default everything else to 0 */
+	for (i = 16; i < 34; i++) {
+		writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(0x00,xl_mmio + MMIO_MACDATA) ; 
+	}
+	
+	/*
+	 *  Set the csrb bit in the MISR register
+	 */
+
+	xl_wait_misr_flags(dev) ; 
+	writel(MEM_BYTE_WRITE | MF_CSRB, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0xFF, xl_mmio + MMIO_MACDATA) ; 
+	writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(MISR_CSRB , xl_mmio + MMIO_MACDATA) ; 
+
+	/*
+	 * Now wait for the command to run
+	 */
+
+	t=jiffies;
+	while (! (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_SRB)) { 
+		schedule();		
+		if(jiffies-t > 40*HZ) {
+			printk(KERN_ERR "3COM 3C359 Velocity XL  card not responding.\n");
+			break ; 
+		}
+	}
+
+	/*
+	 * Let's interpret the open response
+	 */
+
+	writel( (MEM_BYTE_READ | 0xD0000 | xl_priv->srb)+2, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	if (readb(xl_mmio + MMIO_MACDATA)!=0) {
+		open_err = readb(xl_mmio + MMIO_MACDATA) << 8 ; 
+		writel( (MEM_BYTE_READ | 0xD0000 | xl_priv->srb) + 7, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		open_err |= readb(xl_mmio + MMIO_MACDATA) ; 
+		return open_err ; 
+	} else { 
+		writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 8, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		xl_priv->asb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; 
+		printk(KERN_INFO "%s: Adapter Opened Details: ",dev->name) ; 
+		printk("ASB: %04x",xl_priv->asb ) ; 
+		writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 10, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		printk(", SRB: %04x",ntohs(readw(xl_mmio + MMIO_MACDATA)) ) ; 
+ 
+		writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 12, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		xl_priv->arb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; 
+		printk(", ARB: %04x \n",xl_priv->arb ) ; 
+		writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 14, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		vsoff = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; 
+
+		/* 
+		 * Interesting, sending the individual characters directly to printk was causing klogd to use
+		 * use 100% of processor time, so we build up the string and print that instead.
+	   	 */
+
+		for (i=0;i<0x20;i++) { 
+			writel( (MEM_BYTE_READ | 0xD0000 | vsoff) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			ver_str[i] = readb(xl_mmio + MMIO_MACDATA) ; 
+		}
+		ver_str[i] = '\0' ; 
+		printk(KERN_INFO "%s: Microcode version String: %s \n",dev->name,ver_str); 
+	} 	
+	
+	/*
+	 * Issue the AckInterrupt
+	 */
+	writew(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+
+	return 0 ; 
+}
+
+/*
+ *	There are two ways of implementing rx on the 359 NIC, either
+ * 	interrupt driven or polling.  We are going to uses interrupts,
+ *	it is the easier way of doing things.
+ *	
+ *	The Rx works with a ring of Rx descriptors.  At initialise time the ring
+ *	entries point to the next entry except for the last entry in the ring 
+ *	which points to 0.  The card is programmed with the location of the first
+ *	available descriptor and keeps reading the next_ptr until next_ptr is set
+ *	to 0.  Hopefully with a ring size of 16 the card will never get to read a next_ptr
+ *	of 0.  As the Rx interrupt is received we copy the frame up to the protocol layers
+ *	and then point the end of the ring to our current position and point our current
+ *	position to 0, therefore making the current position the last position on the ring.
+ *	The last position on the ring therefore loops continually loops around the rx ring.
+ *	
+ *	rx_ring_tail is the position on the ring to process next. (Think of a snake, the head 
+ *	expands as the card adds new packets and we go around eating the tail processing the
+ *	packets.)
+ *
+ *	Undoubtably it could be streamlined and improved upon, but at the moment it works 
+ *	and the fast path through the routine is fine. 
+ *	
+ *	adv_rx_ring could be inlined to increase performance, but its called a *lot* of times
+ *	in xl_rx so would increase the size of the function significantly. 
+ */
+
+static void adv_rx_ring(struct net_device *dev) /* Advance rx_ring, cut down on bloat in xl_rx */ 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	int prev_ring_loc ; 
+
+	prev_ring_loc = (xl_priv->rx_ring_tail + XL_RX_RING_SIZE - 1) & (XL_RX_RING_SIZE - 1);
+	xl_priv->xl_rx_ring[prev_ring_loc].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * xl_priv->rx_ring_tail) ; 
+	xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus = 0 ; 
+	xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upnextptr = 0 ; 	
+	xl_priv->rx_ring_tail++ ; 
+	xl_priv->rx_ring_tail &= (XL_RX_RING_SIZE-1) ; 
+
+	return ; 
+}
+
+static void xl_rx(struct net_device *dev)
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	struct sk_buff *skb, *skb2 ; 
+	int frame_length = 0, copy_len = 0  ; 	
+	int temp_ring_loc ;  
+
+	/*
+	 * Receive the next frame, loop around the ring until all frames
+  	 * have been received.
+	 */ 	 
+	
+	while (xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & (RXUPDCOMPLETE | RXUPDFULL) ) { /* Descriptor to process */
+
+		if (xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & RXUPDFULL ) { /* UpdFull, Multiple Descriptors used for the frame */
+
+			/* 
+			 * This is a pain, you need to go through all the descriptors until the last one 
+			 * for this frame to find the framelength
+			 */
+
+			temp_ring_loc = xl_priv->rx_ring_tail ; 
+
+			while (xl_priv->xl_rx_ring[temp_ring_loc].framestatus & RXUPDFULL ) {
+				temp_ring_loc++ ; 
+				temp_ring_loc &= (XL_RX_RING_SIZE-1) ; 
+			}
+
+			frame_length = xl_priv->xl_rx_ring[temp_ring_loc].framestatus & 0x7FFF ; 
+
+			skb = dev_alloc_skb(frame_length) ;
+ 
+			if (skb==NULL) { /* No memory for frame, still need to roll forward the rx ring */
+				printk(KERN_WARNING "%s: dev_alloc_skb failed - multi buffer !\n", dev->name) ; 
+				while (xl_priv->rx_ring_tail != temp_ring_loc)  
+					adv_rx_ring(dev) ; 
+				
+				adv_rx_ring(dev) ; /* One more time just for luck :) */ 
+				xl_priv->xl_stats.rx_dropped++ ; 
+
+				writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 
+				return ; 				
+			}
+	
+			skb->dev = dev ; 
+
+			while (xl_priv->rx_ring_tail != temp_ring_loc) { 
+				copy_len = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen & 0x7FFF ; 
+				frame_length -= copy_len ;  
+				pci_dma_sync_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; 
+				memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, copy_len) ; 
+				adv_rx_ring(dev) ; 
+			} 
+
+			/* Now we have found the last fragment */
+			pci_dma_sync_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; 
+			memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, frame_length) ; 
+/*			memcpy(skb_put(skb,frame_length), bus_to_virt(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr), frame_length) ; */
+			adv_rx_ring(dev) ; 
+			skb->protocol = tr_type_trans(skb,dev) ; 
+			netif_rx(skb) ; 
+
+		} else { /* Single Descriptor Used, simply swap buffers over, fast path  */
+
+			frame_length = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & 0x7FFF ; 
+			
+			skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ; 
+
+			if (skb==NULL) { /* Still need to fix the rx ring */
+				printk(KERN_WARNING "%s: dev_alloc_skb failed in rx, single buffer \n",dev->name) ; 
+				adv_rx_ring(dev) ; 
+				xl_priv->xl_stats.rx_dropped++ ; 
+				writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 
+				return ; 
+			}
+
+			skb->dev = dev ; 
+
+			skb2 = xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] ; 
+			pci_unmap_single(xl_priv->pdev, xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr, xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ; 
+			skb_put(skb2, frame_length) ; 
+			skb2->protocol = tr_type_trans(skb2,dev) ; 
+
+			xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] = skb ; 	
+			xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr = pci_map_single(xl_priv->pdev,skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; 
+			xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG ; 
+			adv_rx_ring(dev) ; 
+			xl_priv->xl_stats.rx_packets++ ; 
+			xl_priv->xl_stats.rx_bytes += frame_length ; 	
+
+			netif_rx(skb2) ; 		
+		 } /* if multiple buffers */
+		dev->last_rx = jiffies ; 	
+	} /* while packet to do */
+
+	/* Clear the updComplete interrupt */
+	writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 
+	return ; 	
+}
+
+/*
+ * This is ruthless, it doesn't care what state the card is in it will 
+ * completely reset the adapter.
+ */
+
+static void xl_reset(struct net_device *dev) 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	unsigned long t; 
+
+	writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ; 
+
+	/* 
+	 * Must wait for cmdInProgress bit (12) to clear before continuing with
+	 * card configuration.
+	 */
+
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		if(jiffies-t > 40*HZ) {
+			printk(KERN_ERR "3COM 3C359 Velocity XL  card not responding.\n");
+			break ; 
+		}
+	}
+	
+}
+
+static void xl_freemem(struct net_device *dev) 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv ; 
+	int i ; 
+
+	for (i=0;i<XL_RX_RING_SIZE;i++) {
+		dev_kfree_skb_irq(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]) ; 
+		pci_unmap_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ; 
+		xl_priv->rx_ring_tail++ ; 
+		xl_priv->rx_ring_tail &= XL_RX_RING_SIZE-1; 
+	} 
+
+	/* unmap ring */
+	pci_unmap_single(xl_priv->pdev,xl_priv->rx_ring_dma_addr, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_FROMDEVICE) ; 
+	
+	pci_unmap_single(xl_priv->pdev,xl_priv->tx_ring_dma_addr, sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE, PCI_DMA_TODEVICE) ; 
+
+	kfree(xl_priv->xl_rx_ring) ; 
+	kfree(xl_priv->xl_tx_ring) ; 
+
+	return  ; 
+}
+
+static void 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;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u16 intstatus, macstatus  ;
+
+	if (!dev) { 
+		printk(KERN_WARNING "Device structure dead, aaahhhh !\n") ;
+		return ; 
+	}
+
+	intstatus = readw(xl_mmio + MMIO_INTSTATUS) ;  
+
+	if (!(intstatus & 1)) /* We didn't generate the interrupt */
+		return ; 
+
+	spin_lock(&xl_priv->xl_lock) ; 
+
+	/*
+	 * Process the interrupt
+	 */
+	/*
+	 * Something fishy going on here, we shouldn't get 0001 ints, not fatal though.
+	 */
+	if (intstatus == 0x0001) {  
+		writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+		printk(KERN_INFO "%s: 00001 int received \n",dev->name) ;  
+	} else {  
+		if (intstatus &	(HOSTERRINT | SRBRINT | ARBCINT | UPCOMPINT | DNCOMPINT | HARDERRINT | (1<<8) | TXUNDERRUN | ASBFINT)) { 
+			
+			/* 
+			 * Host Error.
+			 * It may be possible to recover from this, but usually it means something
+			 * is seriously fubar, so we just close the adapter.
+			 */
+
+			if (intstatus & HOSTERRINT) {
+				printk(KERN_WARNING "%s: Host Error, performing global reset, intstatus = %04x \n",dev->name,intstatus) ; 
+				writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ;
+				printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name); 
+				netif_stop_queue(dev) ;
+				xl_freemem(dev) ; 
+				free_irq(dev->irq,dev); 	
+				xl_reset(dev) ; 
+				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+				spin_unlock(&xl_priv->xl_lock) ; 
+				return ; 
+			} /* Host Error */
+
+			if (intstatus & SRBRINT ) {  /* Srbc interrupt */
+				writel(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+				if (xl_priv->srb_queued)
+					xl_srb_bh(dev) ; 
+			} /* SRBR Interrupt */
+
+			if (intstatus & TXUNDERRUN) { /* Issue DnReset command */
+				writel(DNRESET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+				while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { /* Wait for command to run */
+					/* !!! FIX-ME !!!! 
+					Must put a timeout check here ! */
+					/* Empty Loop */
+				} 
+				printk(KERN_WARNING "%s: TX Underrun received \n",dev->name) ;
+				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+			} /* TxUnderRun */
+	
+			if (intstatus & ARBCINT ) { /* Arbc interrupt */
+				xl_arb_cmd(dev) ; 
+			} /* Arbc */
+
+			if (intstatus & ASBFINT) { 
+				if (xl_priv->asb_queued == 1) {
+					xl_asb_cmd(dev) ; 
+				} else if (xl_priv->asb_queued == 2) {
+					xl_asb_bh(dev) ; 
+				} else { 
+					writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ; 
+				}  
+			} /* Asbf */
+
+			if (intstatus & UPCOMPINT ) /* UpComplete */
+				xl_rx(dev) ; 
+
+			if (intstatus & DNCOMPINT )  /* DnComplete */
+				xl_dn_comp(dev) ; 
+
+			if (intstatus & HARDERRINT ) { /* Hardware error */
+				writel(MMIO_WORD_READ | MACSTATUS, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+				macstatus = readw(xl_mmio + MMIO_MACDATA) ; 
+				printk(KERN_WARNING "%s: MacStatusError, details: ", dev->name);
+				if (macstatus & (1<<14)) 
+					printk(KERN_WARNING "tchk error: Unrecoverable error \n") ; 
+				if (macstatus & (1<<3))
+					printk(KERN_WARNING "eint error: Internal watchdog timer expired \n") ;
+				if (macstatus & (1<<2))
+					printk(KERN_WARNING "aint error: Host tried to perform illegal operation \n") ; 
+				printk(KERN_WARNING "Instatus = %02x, macstatus = %02x\n",intstatus,macstatus) ; 
+				printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name); 
+				netif_stop_queue(dev) ;
+				xl_freemem(dev) ; 
+				free_irq(dev->irq,dev); 
+				unregister_trdev(dev) ; 
+				kfree(dev) ;  
+				xl_reset(dev) ; 
+				writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+				spin_unlock(&xl_priv->xl_lock) ; 
+				return ; 
+			}
+		} else { 
+			printk(KERN_WARNING "%s: Received Unknown interrupt : %04x \n", dev->name, intstatus) ;
+			writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 	
+		}
+	} 
+
+	/* Turn interrupts back on */
+
+	writel( SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
+	writel( SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ; 
+
+	spin_unlock(&xl_priv->xl_lock) ; 
+}	
+
+/*
+ *	Tx - Polling configuration
+ */
+	
+static int xl_xmit(struct sk_buff *skb, struct net_device *dev) 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	struct xl_tx_desc *txd ; 
+	int tx_head, tx_tail, tx_prev ; 
+	unsigned long flags ; 	
+
+	spin_lock_irqsave(&xl_priv->xl_lock,flags) ; 
+
+	netif_stop_queue(dev) ; 
+
+	if (xl_priv->free_ring_entries > 1 ) { 	
+		/*
+		 * Set up the descriptor for the packet 
+		 */
+		tx_head = xl_priv->tx_ring_head ; 
+		tx_tail = xl_priv->tx_ring_tail ; 
+
+		txd = &(xl_priv->xl_tx_ring[tx_head]) ; 
+		txd->dnnextptr = 0 ; 
+		txd->framestartheader = skb->len | TXDNINDICATE ; 
+		txd->buffer = pci_map_single(xl_priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE) ; 
+		txd->buffer_length = skb->len | TXDNFRAGLAST  ; 
+		xl_priv->tx_ring_skb[tx_head] = skb ; 
+		xl_priv->xl_stats.tx_packets++ ; 
+		xl_priv->xl_stats.tx_bytes += skb->len ;
+
+		/* 
+		 * Set the nextptr of the previous descriptor equal to this descriptor, add XL_TX_RING_SIZE -1 
+		 * to ensure no negative numbers in unsigned locations.
+		 */ 
+	
+		tx_prev = (xl_priv->tx_ring_head + XL_TX_RING_SIZE - 1) & (XL_TX_RING_SIZE - 1) ; 
+
+		xl_priv->tx_ring_head++ ; 
+		xl_priv->tx_ring_head &= (XL_TX_RING_SIZE - 1) ;
+		xl_priv->free_ring_entries-- ; 
+
+		xl_priv->xl_tx_ring[tx_prev].dnnextptr = xl_priv->tx_ring_dma_addr + (sizeof (struct xl_tx_desc) * tx_head) ; 
+
+		/* Sneaky, by doing a read on DnListPtr we can force the card to poll on the DnNextPtr */
+		/* readl(xl_mmio + MMIO_DNLISTPTR) ; */
+
+		netif_wake_queue(dev) ; 
+
+		spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ; 
+ 
+		return 0;
+	} else {
+		spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ; 
+		return 1;
+	}
+
+}
+	
+/* 
+ * The NIC has told us that a packet has been downloaded onto the card, we must
+ * find out which packet it has done, clear the skb and information for the packet
+ * then advance around the ring for all tranmitted packets
+ */
+
+static void xl_dn_comp(struct net_device *dev) 
+{
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	struct xl_tx_desc *txd ; 
+
+
+	if (xl_priv->tx_ring_tail == 255) {/* First time */
+		xl_priv->xl_tx_ring[0].framestartheader = 0 ; 
+		xl_priv->xl_tx_ring[0].dnnextptr = 0 ;  
+		xl_priv->tx_ring_tail = 1 ; 
+	}
+
+	while (xl_priv->xl_tx_ring[xl_priv->tx_ring_tail].framestartheader & TXDNCOMPLETE ) { 
+		txd = &(xl_priv->xl_tx_ring[xl_priv->tx_ring_tail]) ;
+		pci_unmap_single(xl_priv->pdev,txd->buffer, xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]->len, PCI_DMA_TODEVICE) ; 
+		txd->framestartheader = 0 ; 
+		txd->buffer = 0xdeadbeef  ; 
+		txd->buffer_length  = 0 ;  
+		dev_kfree_skb_irq(xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]) ;
+		xl_priv->tx_ring_tail++ ; 
+		xl_priv->tx_ring_tail &= (XL_TX_RING_SIZE - 1) ; 
+		xl_priv->free_ring_entries++ ; 
+	}
+
+	netif_wake_queue(dev) ; 
+
+	writel(ACK_INTERRUPT | DNCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 
+}
+
+/*
+ * Close the adapter properly.
+ * This srb reply cannot be handled from interrupt context as we have
+ * to free the interrupt from the driver. 
+ */
+
+static int xl_close(struct net_device *dev) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	unsigned long t ; 
+
+	netif_stop_queue(dev) ; 
+
+	/*
+	 * Close the adapter, need to stall the rx and tx queues.
+	 */
+
+    	writew(DNSTALL, xl_mmio + MMIO_COMMAND) ; 
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNSTALL not responding.\n", dev->name);
+			break ; 
+		}
+	}
+    	writew(DNDISABLE, xl_mmio + MMIO_COMMAND) ; 
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNDISABLE not responding.\n", dev->name);
+			break ;
+		}
+	}
+    	writew(UPSTALL, xl_mmio + MMIO_COMMAND) ; 
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPSTALL not responding.\n", dev->name);
+			break ; 
+		}
+	}
+
+	/* Turn off interrupts, we will still get the indication though
+ 	 * so we can trap it
+	 */
+
+	writel(SETINTENABLE, xl_mmio + MMIO_COMMAND) ; 
+
+	xl_srb_cmd(dev,CLOSE_NIC) ; 
+
+	t=jiffies;
+	while (!(readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_SRB)) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-CLOSENIC not responding.\n", dev->name);
+			break ; 
+		}
+	}
+	/* Read the srb response from the adapter */
+
+	writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD);
+	if (readb(xl_mmio + MMIO_MACDATA) != CLOSE_NIC) { 
+		printk(KERN_INFO "%s: CLOSE_NIC did not get a CLOSE_NIC response \n",dev->name) ; 
+	} else { 
+		writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+		if (readb(xl_mmio + MMIO_MACDATA)==0) { 
+			printk(KERN_INFO "%s: Adapter has been closed \n",dev->name) ;
+			writew(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+
+			xl_freemem(dev) ; 
+			free_irq(dev->irq,dev) ; 
+		} else { 
+			printk(KERN_INFO "%s: Close nic command returned error code %02x\n",dev->name, readb(xl_mmio + MMIO_MACDATA)) ;
+		} 
+	}
+
+	/* Reset the upload and download logic */
+ 
+    	writew(UPRESET, xl_mmio + MMIO_COMMAND) ; 
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPRESET not responding.\n", dev->name);
+			break ; 
+		}
+	}
+    	writew(DNRESET, xl_mmio + MMIO_COMMAND) ; 
+	t=jiffies;
+	while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { 
+		schedule();		
+		if(jiffies-t > 10*HZ) {
+			printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNRESET not responding.\n", dev->name);
+			break ; 
+		}
+	}
+	xl_hw_reset(dev) ; 
+	return 0 ;
+}
+
+static void xl_set_rx_mode(struct net_device *dev) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	struct dev_mc_list *dmi ; 
+	unsigned char dev_mc_address[4] ; 
+	u16 options ; 
+	int i ; 
+
+	if (dev->flags & IFF_PROMISC)
+		options = 0x0004 ; 
+	else
+		options = 0x0000 ; 
+
+	if (options ^ xl_priv->xl_copy_all_options) { /* Changed, must send command */
+		xl_priv->xl_copy_all_options = options ; 
+		xl_srb_cmd(dev, SET_RECEIVE_MODE) ;
+		return ;  
+	}
+
+	dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ;
+
+        for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) {
+                dev_mc_address[0] |= dmi->dmi_addr[2] ;
+                dev_mc_address[1] |= dmi->dmi_addr[3] ;
+                dev_mc_address[2] |= dmi->dmi_addr[4] ;
+                dev_mc_address[3] |= dmi->dmi_addr[5] ;
+        }
+
+	if (memcmp(xl_priv->xl_functional_addr,dev_mc_address,4) != 0) { /* Options have changed, run the command */
+		memcpy(xl_priv->xl_functional_addr, dev_mc_address,4) ; 
+		xl_srb_cmd(dev, SET_FUNC_ADDRESS) ; 
+	}
+	return ; 
+}
+
+
+/*
+ *	We issued an srb command and now we must read
+ *	the response from the completed command.
+ */
+
+static void xl_srb_bh(struct net_device *dev) 
+{ 
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u8 srb_cmd, ret_code ; 
+	int i ; 
+
+	writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+	srb_cmd = readb(xl_mmio + MMIO_MACDATA) ; 
+	writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+	ret_code = readb(xl_mmio + MMIO_MACDATA) ; 
+
+	/* Ret_code is standard across all commands */
+
+	switch (ret_code) { 
+	case 1:
+		printk(KERN_INFO "%s: Command: %d - Invalid Command code\n",dev->name,srb_cmd) ; 
+		break ; 
+	case 4:
+		printk(KERN_INFO "%s: Command: %d - Adapter is closed, must be open for this command \n",dev->name,srb_cmd) ; 
+		break ;
+	
+	case 6:
+		printk(KERN_INFO "%s: Command: %d - Options Invalid for command \n",dev->name,srb_cmd) ;
+		break ;
+
+	case 0: /* Successful command execution */ 
+		switch (srb_cmd) { 
+		case READ_LOG: /* Returns 14 bytes of data from the NIC */
+			if(xl_priv->xl_message_level)
+				printk(KERN_INFO "%s: READ.LOG 14 bytes of data ",dev->name) ; 
+			/* 
+			 * We still have to read the log even if message_level = 0 and we don't want
+			 * to see it
+			 */
+			for (i=0;i<14;i++) { 
+				writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+				if(xl_priv->xl_message_level) 
+					printk("%02x:",readb(xl_mmio + MMIO_MACDATA)) ; 	
+			} 
+			printk("\n") ; 
+			break ; 
+		case SET_FUNC_ADDRESS:
+			if(xl_priv->xl_message_level) 
+				printk(KERN_INFO "%s: Functional Address Set \n",dev->name) ;  
+			break ; 
+		case CLOSE_NIC:
+			if(xl_priv->xl_message_level)
+				printk(KERN_INFO "%s: Received CLOSE_NIC interrupt in interrupt handler \n",dev->name) ; 	
+			break ; 
+		case SET_MULTICAST_MODE:
+			if(xl_priv->xl_message_level)
+				printk(KERN_INFO "%s: Multicast options successfully changed\n",dev->name) ; 
+			break ;
+		case SET_RECEIVE_MODE:
+			if(xl_priv->xl_message_level) {  
+				if (xl_priv->xl_copy_all_options == 0x0004) 
+					printk(KERN_INFO "%s: Entering promiscuous mode \n", dev->name) ; 
+				else
+					printk(KERN_INFO "%s: Entering normal receive mode \n",dev->name) ; 
+			}
+			break ; 
+ 
+		} /* switch */
+		break ; 
+	} /* switch */
+	return ; 	
+} 
+
+static struct net_device_stats * xl_get_stats(struct net_device *dev)
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+	return (struct net_device_stats *) &xl_priv->xl_stats; 
+}
+
+static int xl_set_mac_address (struct net_device *dev, void *addr) 
+{
+	struct sockaddr *saddr = addr ; 
+	struct xl_private *xl_priv = (struct xl_private *)dev->priv ; 
+
+	if (netif_running(dev)) { 
+		printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ; 
+		return -EIO ; 
+	}
+
+	memcpy(xl_priv->xl_laa, saddr->sa_data,dev->addr_len) ; 
+	
+	if (xl_priv->xl_message_level) { 
+ 		printk(KERN_INFO "%s: MAC/LAA Set to  = %x.%x.%x.%x.%x.%x\n",dev->name, xl_priv->xl_laa[0],
+		xl_priv->xl_laa[1], xl_priv->xl_laa[2],
+		xl_priv->xl_laa[3], xl_priv->xl_laa[4],
+		xl_priv->xl_laa[5]);
+	} 
+
+	return 0 ; 
+}
+
+static void xl_arb_cmd(struct net_device *dev)
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv;
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u8 arb_cmd ; 
+	u16 lan_status, lan_status_diff ; 
+
+	writel( ( MEM_BYTE_READ | 0xD0000 | xl_priv->arb), xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	arb_cmd = readb(xl_mmio + MMIO_MACDATA) ; 
+	
+	if (arb_cmd == RING_STATUS_CHANGE) { /* Ring.Status.Change */
+		writel( ( (MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+		 
+		printk(KERN_INFO "%s: Ring Status Change: New Status = %04x\n", dev->name, ntohs(readw(xl_mmio + MMIO_MACDATA) )) ; 
+
+		lan_status = ntohs(readw(xl_mmio + MMIO_MACDATA));
+	
+		/* Acknowledge interrupt, this tells nic we are done with the arb */
+		writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+			
+		lan_status_diff = xl_priv->xl_lan_status ^ lan_status ; 
+
+		if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) { 
+			if (lan_status_diff & LSC_LWF) 
+				printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name);
+			if (lan_status_diff & LSC_ARW) 
+				printk(KERN_WARNING "%s: Auto removal error\n",dev->name);
+			if (lan_status_diff & LSC_FPE)
+				printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name);
+			if (lan_status_diff & LSC_RR) 
+				printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name);
+		
+			/* Adapter has been closed by the hardware */
+
+			netif_stop_queue(dev);
+			xl_freemem(dev) ; 
+			free_irq(dev->irq,dev);
+			
+			printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; 
+		} /* If serious error */
+		
+		if (xl_priv->xl_message_level) { 
+			if (lan_status_diff & LSC_SIG_LOSS) 
+					printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ; 
+			if (lan_status_diff & LSC_HARD_ERR)
+					printk(KERN_INFO "%s: Beaconing \n",dev->name);
+			if (lan_status_diff & LSC_SOFT_ERR)
+					printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name);
+			if (lan_status_diff & LSC_TRAN_BCN) 
+					printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+			if (lan_status_diff & LSC_SS) 
+					printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+			if (lan_status_diff & LSC_RING_REC)
+					printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name);
+			if (lan_status_diff & LSC_FDX_MODE)
+					printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name);
+		} 	
+		
+		if (lan_status_diff & LSC_CO) { 
+				if (xl_priv->xl_message_level) 
+					printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+				/* Issue READ.LOG command */
+				xl_srb_cmd(dev, READ_LOG) ; 	
+		}
+
+		/* There is no command in the tech docs to issue the read_sr_counters */
+		if (lan_status_diff & LSC_SR_CO) { 
+			if (xl_priv->xl_message_level)
+				printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+		}
+
+		xl_priv->xl_lan_status = lan_status ; 
+	
+	}  /* Lan.change.status */
+	else if ( arb_cmd == RECEIVE_DATA) { /* Received.Data */
+#if XL_DEBUG
+		printk(KERN_INFO "Received.Data \n") ; 
+#endif 		
+		writel( ((MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+		xl_priv->mac_buffer = ntohs(readw(xl_mmio + MMIO_MACDATA)) ;
+		
+		/* Now we are going to be really basic here and not do anything
+		 * with the data at all. The tech docs do not give me enough
+		 * information to calculate the buffers properly so we're
+		 * just going to tell the nic that we've dealt with the frame
+		 * anyway.
+		 */
+
+		dev->last_rx = jiffies ; 
+		/* Acknowledge interrupt, this tells nic we are done with the arb */
+		writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; 
+
+		/* Is the ASB free ? */ 	
+			
+		xl_priv->asb_queued = 0 ; 			
+		writel( ((MEM_BYTE_READ | 0xD0000 | xl_priv->asb) + 2), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+		if (readb(xl_mmio + MMIO_MACDATA) != 0xff) { 
+			xl_priv->asb_queued = 1 ;
+
+			xl_wait_misr_flags(dev) ;  
+
+			writel(MEM_BYTE_WRITE | MF_ASBFR, xl_mmio + MMIO_MAC_ACCESS_CMD); 
+			writeb(0xff, xl_mmio + MMIO_MACDATA) ;
+			writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			writeb(MISR_ASBFR, xl_mmio + MMIO_MACDATA) ; 
+			return ; 	
+			/* Drop out and wait for the bottom half to be run */
+		}
+	
+		xl_asb_cmd(dev) ; 
+		
+	} else {
+		printk(KERN_WARNING "%s: Received unknown arb (xl_priv) command: %02x \n",dev->name,arb_cmd) ; 
+	}
+
+	/* Acknowledge the arb interrupt */
+
+	writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; 
+
+	return ; 
+}
+
+
+/*
+ *	There is only one asb command, but we can get called from different
+ *	places.
+ */
+
+static void xl_asb_cmd(struct net_device *dev)
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+
+	if (xl_priv->asb_queued == 1) 
+		writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ; 
+		
+	writel(MEM_BYTE_WRITE | 0xd0000 | xl_priv->asb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0x81, xl_mmio + MMIO_MACDATA) ; 
+
+	writel(MEM_WORD_WRITE | 0xd0000 | xl_priv->asb | 6, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writew(ntohs(xl_priv->mac_buffer), xl_mmio + MMIO_MACDATA) ; 
+
+	xl_wait_misr_flags(dev) ; 	
+
+	writel(MEM_BYTE_WRITE | MF_RASB, xl_mmio + MMIO_MAC_ACCESS_CMD); 
+	writeb(0xff, xl_mmio + MMIO_MACDATA) ;
+
+	writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(MISR_RASB, xl_mmio + MMIO_MACDATA) ; 
+
+	xl_priv->asb_queued = 2 ; 
+
+	return ; 
+}
+
+/*
+ * 	This will only get called if there was an error
+ *	from the asb cmd.
+ */
+static void xl_asb_bh(struct net_device *dev) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	u8 ret_code ; 
+
+	writel(MMIO_BYTE_READ | 0xd0000 | xl_priv->asb | 2, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	ret_code = readb(xl_mmio + MMIO_MACDATA) ; 
+	switch (ret_code) { 
+		case 0x01:
+			printk(KERN_INFO "%s: ASB Command, unrecognized command code \n",dev->name) ;
+			break ;
+		case 0x26:
+			printk(KERN_INFO "%s: ASB Command, unexpected receive buffer \n", dev->name) ; 
+			break ; 
+		case 0x40:
+			printk(KERN_INFO "%s: ASB Command, Invalid Station ID \n", dev->name) ; 
+			break ;  
+	}
+	xl_priv->asb_queued = 0 ; 
+	writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ;
+	return ;  
+}
+
+/* 	
+ *	Issue srb commands to the nic 
+ */
+
+static void xl_srb_cmd(struct net_device *dev, int srb_cmd) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+
+	switch (srb_cmd) { 
+	case READ_LOG:
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(READ_LOG, xl_mmio + MMIO_MACDATA) ; 
+		break; 
+
+	case CLOSE_NIC:
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(CLOSE_NIC, xl_mmio + MMIO_MACDATA) ; 
+		break ;
+
+	case SET_RECEIVE_MODE:
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(SET_RECEIVE_MODE, xl_mmio + MMIO_MACDATA) ; 
+		writel(MEM_WORD_WRITE | 0xD0000 | xl_priv->srb | 4, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writew(xl_priv->xl_copy_all_options, xl_mmio + MMIO_MACDATA) ; 
+		break ;
+
+	case SET_FUNC_ADDRESS:
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(SET_FUNC_ADDRESS, xl_mmio + MMIO_MACDATA) ; 
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 6 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(xl_priv->xl_functional_addr[0], xl_mmio + MMIO_MACDATA) ; 
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 7 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(xl_priv->xl_functional_addr[1], xl_mmio + MMIO_MACDATA) ; 
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 8 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(xl_priv->xl_functional_addr[2], xl_mmio + MMIO_MACDATA) ; 
+		writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 9 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+		writeb(xl_priv->xl_functional_addr[3], xl_mmio + MMIO_MACDATA) ;
+		break ;  
+	} /* switch */
+
+
+	xl_wait_misr_flags(dev)  ; 
+
+	/* Write 0xff to the CSRB flag */
+	writel(MEM_BYTE_WRITE | MF_CSRB , xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0xFF, xl_mmio + MMIO_MACDATA) ; 
+	/* Set csrb bit in MISR register to process command */
+	writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(MISR_CSRB, xl_mmio + MMIO_MACDATA) ; 
+	xl_priv->srb_queued = 1 ; 
+
+	return ; 
+}
+
+/*
+ * This is nasty, to use the MISR command you have to wait for 6 memory locations
+ * to be zero. This is the way the driver does on other OS'es so we should be ok with 
+ * the empty loop.
+ */
+
+static void xl_wait_misr_flags(struct net_device *dev) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv ; 
+	u8 * xl_mmio = xl_priv->xl_mmio ; 
+	
+	int i  ; 
+	
+	writel(MMIO_BYTE_READ | MISR_RW, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	if (readb(xl_mmio + MMIO_MACDATA) != 0) {  /* Misr not clear */
+		for (i=0; i<6; i++) { 
+			writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+			while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+		} 
+	}
+
+	writel(MMIO_BYTE_WRITE | MISR_AND, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
+	writeb(0x80, xl_mmio + MMIO_MACDATA) ; 
+
+	return ; 
+} 
+
+/*
+ *	Change mtu size, this should work the same as olympic
+ */
+
+static int xl_change_mtu(struct net_device *dev, int mtu) 
+{
+	struct xl_private *xl_priv = (struct xl_private *) dev->priv;
+	u16 max_mtu ; 
+
+	if (xl_priv->xl_ring_speed == 4)
+		max_mtu = 4500 ; 
+	else
+		max_mtu = 18000 ; 
+	
+	if (mtu > max_mtu)
+		return -EINVAL ; 
+	if (mtu < 100) 
+		return -EINVAL ; 
+
+	dev->mtu = mtu ; 
+	xl_priv->pkt_buf_sz = mtu + TR_HLEN ; 
+
+	return 0 ; 
+}
+
+static void __devexit xl_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pdev->driver_data;
+	struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+	
+	unregister_trdev(dev);
+	iounmap(xl_priv->xl_mmio) ; 
+	pci_release_regions(pdev) ; 
+	pci_set_drvdata(pdev,NULL) ; 
+	kfree(dev);
+	return ; 
+}
+
+static struct pci_driver xl_3c359_driver = {
+	name:		"3c359",
+	id_table:	xl_pci_tbl,
+	probe:		xl_probe,
+	remove:		__devexit_p(xl_remove_one),
+};
+
+static int __init xl_pci_init (void)
+{
+	return pci_module_init (&xl_3c359_driver);
+}
+
+
+static void __exit xl_pci_cleanup (void)
+{
+	pci_unregister_driver (&xl_3c359_driver);
+}
+
+module_init(xl_pci_init);
+module_exit(xl_pci_cleanup);
+
+MODULE_LICENSE("GPL") ; 
diff -Nru a/drivers/net/tokenring/3c359.h b/drivers/net/tokenring/3c359.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/tokenring/3c359.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,290 @@
+/*
+ *  3c359.h (c) 2000 Mike Phillips (mikep@linuxtr.net) All Rights Reserved
+ *
+ *  Linux driver for 3Com 3C359 Token Link PCI XL cards.
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU General Public License Version 2 or (at your option) 
+ *  any later verion, incorporated herein by reference.
+ */
+
+/* Memory Access Commands */
+#define IO_BYTE_READ 0x28 << 24
+#define IO_BYTE_WRITE 0x18 << 24 
+#define IO_WORD_READ 0x20 << 24
+#define IO_WORD_WRITE 0x10 << 24
+#define MMIO_BYTE_READ 0x88 << 24
+#define MMIO_BYTE_WRITE 0x48 << 24
+#define MMIO_WORD_READ 0x80 << 24
+#define MMIO_WORD_WRITE 0x40 << 24
+#define MEM_BYTE_READ 0x8C << 24
+#define MEM_BYTE_WRITE 0x4C << 24
+#define MEM_WORD_READ 0x84 << 24
+#define MEM_WORD_WRITE 0x44 << 24
+
+#define PMBAR 0x1C80
+#define PMB_CPHOLD (1<<10)
+
+#define CPATTENTION 0x180D
+#define CPA_PMBARVIS (1<<7)
+#define CPA_MEMWREN (1<<6)
+
+#define SWITCHSETTINGS 0x1C88
+#define EECONTROL 0x1C8A
+#define EEDATA 0x1C8C
+#define EEREAD 0x0080 
+#define EEWRITE 0x0040
+#define EEERASE 0x0060
+#define EE_ENABLE_WRITE 0x0030
+#define EEBUSY (1<<15)
+
+#define WRBR 0xCDE02
+#define WWOR 0xCDE04
+#define WWCR 0xCDE06
+#define MACSTATUS 0xCDE08 
+#define MISR_RW 0xCDE0B
+#define MISR_AND 0xCDE2B
+#define MISR_SET 0xCDE4B
+#define RXBUFAREA 0xCDE10
+#define RXEARLYTHRESH 0xCDE12
+#define TXSTARTTHRESH 0x58
+#define DNPRIREQTHRESH 0x2C
+
+#define MISR_CSRB (1<<5)
+#define MISR_RASB (1<<4)
+#define MISR_SRBFR (1<<3)
+#define MISR_ASBFR (1<<2)
+#define MISR_ARBF (1<<1) 
+
+/* MISR Flags memory locations */
+#define MF_SSBF 0xDFFE0 
+#define MF_ARBF 0xDFFE1
+#define MF_ASBFR 0xDFFE2
+#define MF_SRBFR 0xDFFE3
+#define MF_RASB 0xDFFE4
+#define MF_CSRB 0xDFFE5
+
+#define MMIO_MACDATA 0x10 
+#define MMIO_MAC_ACCESS_CMD 0x14
+#define MMIO_TIMER 0x1A
+#define MMIO_DMA_CTRL 0x20
+#define MMIO_DNLISTPTR 0x24
+#define MMIO_HASHFILTER 0x28
+#define MMIO_CONFIG 0x29
+#define MMIO_DNPRIREQTHRESH 0x2C
+#define MMIO_DNPOLL 0x2D
+#define MMIO_UPPKTSTATUS 0x30
+#define MMIO_FREETIMER 0x34
+#define MMIO_COUNTDOWN 0x36
+#define MMIO_UPLISTPTR 0x38
+#define MMIO_UPPOLL 0x3C
+#define MMIO_UPBURSTTHRESH 0x40
+#define MMIO_DNBURSTTHRESH 0x41
+#define MMIO_INTSTATUS_AUTO 0x56
+#define MMIO_TXSTARTTHRESH 0x58
+#define MMIO_INTERRUPTENABLE 0x5A
+#define MMIO_INDICATIONENABLE 0x5C
+#define MMIO_COMMAND 0x5E  /* These two are meant to be the same */
+#define MMIO_INTSTATUS 0x5E /* Makes the code more readable this way */
+#define INTSTAT_CMD_IN_PROGRESS (1<<12) 
+#define INTSTAT_SRB (1<<14)
+#define INTSTAT_INTLATCH (1<<0)
+
+/* Indication / Interrupt Mask 
+ * Annoyingly the bits to be set in the indication and interrupt enable
+ * do not match with the actual bits received in the interrupt, although
+ * they are in the same order. 
+ * The mapping for the indication / interrupt are:
+ * Bit	Indication / Interrupt
+ *   0	HostError
+ *   1	txcomplete
+ *   2	updneeded
+ *   3	rxcomplete
+ *   4	intrequested
+ *   5	macerror
+ *   6  dncomplete
+ *   7	upcomplete
+ *   8	txunderrun
+ *   9	asbf
+ *  10	srbr
+ *  11	arbc
+ *
+ *  The only ones we don't want to receive are txcomplete and rxcomplete
+ *  we use dncomplete and upcomplete instead.
+ */
+
+#define INT_MASK 0xFF5
+
+/* Note the subtle difference here, IND and INT */
+
+#define SETINDENABLE (8<<12)
+#define SETINTENABLE (7<<12)
+#define SRBBIT (1<<10)
+#define ASBBIT (1<<9)
+#define ARBBIT (1<<11)
+
+#define SRB 0xDFE90
+#define ASB 0xDFED0
+#define ARB 0xD0000
+#define SCRATCH 0xDFEF0
+
+#define INT_REQUEST 0x6000 /* (6 << 12) */
+#define ACK_INTERRUPT 0x6800 /* (13 <<11) */
+#define GLOBAL_RESET 0x00 
+#define DNDISABLE 0x5000 
+#define DNENABLE 0x4800 
+#define DNSTALL 0x3002
+#define DNRESET 0x5800
+#define DNUNSTALL 0x3003
+#define UPRESET 0x2800
+#define UPSTALL 0x3000
+#define UPUNSTALL 0x3001
+#define SETCONFIG 0x4000
+#define SETTXSTARTTHRESH 0x9800 
+
+/* Received Interrupts */
+#define ASBFINT (1<<13)
+#define SRBRINT (1<<14)
+#define ARBCINT (1<<15)
+#define TXUNDERRUN (1<<11)
+
+#define UPCOMPINT (1<<10)
+#define DNCOMPINT (1<<9)
+#define HARDERRINT (1<<7)
+#define RXCOMPLETE (1<<4)
+#define TXCOMPINT (1<<2)
+#define HOSTERRINT (1<<1)
+
+/* Receive descriptor bits */
+#define RXOVERRUN (1<<19)
+#define RXFC (1<<21)
+#define RXAR (1<<22)
+#define RXUPDCOMPLETE (1<<23)
+#define RXUPDFULL (1<<24)
+#define RXUPLASTFRAG (1<<31)
+
+/* Transmit descriptor bits */
+#define TXDNCOMPLETE (1<<16)
+#define TXTXINDICATE (1<<27)
+#define TXDPDEMPTY (1<<29)
+#define TXDNINDICATE (1<<31)
+#define TXDNFRAGLAST (1<<31)
+
+/* Interrupts to Acknowledge */
+#define LATCH_ACK 1 
+#define TXCOMPACK (1<<1)
+#define INTREQACK (1<<2)
+#define DNCOMPACK (1<<3)
+#define UPCOMPACK (1<<4)
+#define ASBFACK (1<<5)
+#define SRBRACK (1<<6)
+#define ARBCACK (1<<7)
+
+#define XL_IO_SPACE 128
+#define SRB_COMMAND_SIZE 50
+
+/* Adapter Commands */
+#define REQUEST_INT 0x00
+#define MODIFY_OPEN_PARMS 0x01
+#define RESTORE_OPEN_PARMS 0x02
+#define OPEN_NIC 0x03
+#define CLOSE_NIC 0x04
+#define SET_SLEEP_MODE 0x05
+#define SET_GROUP_ADDRESS 0x06
+#define SET_FUNC_ADDRESS 0x07
+#define READ_LOG 0x08
+#define SET_MULTICAST_MODE 0x0C
+#define CHANGE_WAKEUP_PATTERN 0x0D
+#define GET_STATISTICS 0x13
+#define SET_RECEIVE_MODE 0x1F
+
+/* ARB Commands */
+#define RECEIVE_DATA 0x81
+#define RING_STATUS_CHANGE 0x84
+
+/* ASB Commands */
+#define ASB_RECEIVE_DATE 0x81 
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF      0x0800
+#define LSC_ARW      0x0400
+#define LSC_FPE      0x0200
+#define LSC_RR       0x0100
+#define LSC_CO       0x0080
+#define LSC_SS       0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO    0x0010
+#define LSC_FDX_MODE 0x0004
+
+#define XL_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* 3c359 defaults for buffers */
+ 
+#define XL_RX_RING_SIZE 16 /* must be a power of 2 */
+#define XL_TX_RING_SIZE 16 /* must be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* 3c359 data structures */
+
+struct xl_tx_desc {
+	u32 dnnextptr ; 
+	u32 framestartheader ; 
+	u32 buffer ;
+	u32 buffer_length ;
+};
+
+struct xl_rx_desc {
+	u32 upnextptr ; 
+	u32 framestatus ; 
+	u32 upfragaddr ; 
+	u32 upfraglen ; 
+};
+
+struct xl_private {
+	
+
+	/* These two structures must be aligned on 8 byte boundaries */
+
+	/* struct xl_rx_desc xl_rx_ring[XL_RX_RING_SIZE]; */
+	/* struct xl_tx_desc xl_tx_ring[XL_TX_RING_SIZE]; */
+	struct xl_rx_desc *xl_rx_ring ; 
+	struct xl_tx_desc *xl_tx_ring ; 
+	struct sk_buff *tx_ring_skb[XL_TX_RING_SIZE], *rx_ring_skb[XL_RX_RING_SIZE];	
+	int tx_ring_head, tx_ring_tail ;  
+	int rx_ring_tail, rx_ring_no ; 
+	int free_ring_entries ; 
+
+	u16 srb;
+	u16 arb;
+	u16 asb;
+
+	u8 *xl_mmio;
+	char *xl_card_name;
+	struct pci_dev *pdev ; 
+	
+	spinlock_t xl_lock ; 
+
+	volatile int srb_queued;    
+	struct wait_queue *srb_wait;
+	volatile int asb_queued;   
+
+	struct net_device_stats xl_stats ;
+
+	u16 mac_buffer ; 	
+	u16 xl_lan_status ;
+	u8 xl_ring_speed ;
+	u16 pkt_buf_sz ; 
+	u8 xl_message_level; 
+	u16 xl_copy_all_options ;  
+	unsigned char xl_functional_addr[4] ; 
+	u16 xl_addr_table_addr, xl_parms_addr ; 
+	u8 xl_laa[6] ; 
+	u32 rx_ring_dma_addr ; 
+	u32 tx_ring_dma_addr ; 
+};
+
diff -Nru a/drivers/net/tokenring/3c359_microcode.h b/drivers/net/tokenring/3c359_microcode.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/tokenring/3c359_microcode.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,1585 @@
+
+/*
+ * The firmware this driver downloads into the tokenring card is a
+ * separate program and is not GPL'd source code, even though the Linux
+ * side driver and the routine that loads this data into the card are.
+ *
+ * This firmware is licensed to you strictly for use in conjunction
+ * with the use of 3Com 3C359 TokenRing adapters. There is no
+ * waranty expressed or implied about its fitness for any purpose.
+ */
+
+/* 3c359_microcode.mac: 3Com 3C359 Tokenring microcode.
+ *
+ * Notes:
+ *  - Loaded from xl_init upon adapter initialization.
+ *
+ * Available from 3Com as part of their standard 3C359 driver. 
+ *
+ * mc_size *must* must match the microcode being used, each version is a 
+ * different length.
+ */
+
+
+#if defined(CONFIG_3C359) || defined(CONFIG_3C359_MODULE) 
+
+static int mc_size = 24880 ; 
+
+u8 microcode[] = { 
+ 0xfe,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x33,0x2f,0x30,0x32,0x2f,0x39,0x39,0x20,0x31
+,0x37,0x3a,0x31,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46
+,0x00,0x00,0x07,0xff,0x02,0x00,0xfe,0x9f,0x06,0x00,0x00,0x7c,0x48,0x00,0x00,0x70
+,0x82,0x00,0xff,0xff,0x86,0x00,0xff,0xff,0x88,0x00,0xff,0xff,0x9a,0x00,0xff,0xff
+,0xff,0xff,0x11,0x00,0xc0,0x00,0xff,0xff,0xff,0xff,0x11,0x22,0x33,0x44,0x55,0x66
+,0x33,0x43,0x4f,0x4d,0x20,0x42,0x41,0x42,0x45,0x11,0x40,0xc0,0x00,0xff,0xff,0xff
+,0xff,0x11,0x22,0x33,0x44,0x55,0x66,0x53,0x74,0x61,0x72,0x74,0x20,0x6f,0x66,0x20
+,0x4c,0x4c,0x43,0x20,0x66,0x72,0x61,0x6d,0x65,0x2e,0x20,0x20,0x54,0x6f,0x74,0x61
+,0x6c,0x20,0x64,0x61,0x74,0x61,0x20,0x73,0x69,0x7a,0x65,0x20,0x69,0x73,0x20,0x78
+,0x78,0x78,0x20,0x20,0x20,0x42,0x41,0x42,0x45,0xe8,0xd2,0x01,0x83,0x3e,0xf7,0x34
+,0x00,0x75,0x21,0xe8,0x41,0x00,0x83,0x3e,0xf7,0x34,0x00,0x75,0x17,0xe8,0x82,0x00
+,0x83,0x3e,0xf7,0x34,0x00,0x75,0x0d,0xe8,0xbf,0x00,0x83,0x3e,0xf7,0x34,0x00,0x75
+,0x03,0xe8,0x41,0x02,0xc3,0x1e,0xb8,0x00,0xf0,0x8e,0xd8,0x33,0xf6,0xb9,0x00,0x80
+,0x33,0xdb,0xad,0x03,0xd8,0xe2,0xfb,0x1f,0xb8,0x00,0x00,0x83,0xfb,0x00,0x74,0x03
+,0xb8,0x22,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0xba,0x56,0x00,0xb0,0xff,0xee,0x33,0xc0
+,0x8e,0xc0,0x33,0xf6,0xb9,0xff,0x7f,0x83,0x3e,0xff,0x34,0x00,0x74,0x08,0x8d,0x3e
+,0x30,0x61,0xd1,0xef,0x2b,0xcf,0x26,0x8b,0x1c,0x26,0xc7,0x04,0xff,0xff,0x26,0x83
+,0x3c,0xff,0x75,0x17,0x26,0xc7,0x04,0x00,0x00,0x26,0x83,0x3c,0x00,0x75,0x0c,0x26
+,0x89,0x1c,0x46,0x46,0xe2,0xe0,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x24,0x00,0xa3,0xf7
+,0x34,0xc3,0xfa,0xb4,0xd7,0x9e,0x73,0x3a,0x75,0x38,0x79,0x36,0x7b,0x34,0x9f,0xb1
+,0x05,0xd2,0xec,0x73,0x2d,0xb0,0x40,0xd0,0xe0,0x71,0x27,0x79,0x25,0xd0,0xe0,0x73
+,0x21,0x7b,0x1f,0x32,0xc0,0x75,0x1b,0x32,0xe4,0x9e,0x72,0x16,0x74,0x14,0x78,0x12
+,0x7a,0x10,0x9f,0xd2,0xec,0x72,0x0b,0xd0,0xe4,0x70,0x07,0x75,0x05,0xb8,0x00,0x00
+,0xeb,0x03,0xb8,0x26,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0xba,0x5a,0x00,0x33,0xc0,0xef
+,0xef,0xef,0xef,0xb0,0x00,0xe6,0x56,0xb0,0x00,0xe6,0x54,0xba,0x52,0x00,0xb8,0x01
+,0x01,0xef,0xe8,0xca,0x00,0x3c,0x01,0x75,0x7f,0xe8,0x83,0x00,0xba,0x52,0x00,0xb8
+,0x02,0x02,0xef,0xe8,0xb9,0x00,0x3c,0x02,0x75,0x6e,0xe8,0x7a,0x00,0xba,0x52,0x00
+,0xb8,0x04,0x04,0xef,0xe8,0xa8,0x00,0x3c,0x04,0x75,0x5d,0xe8,0x71,0x00,0xba,0x52
+,0x00,0xb8,0x08,0x08,0xef,0xe8,0x97,0x00,0x3c,0x08,0x75,0x4c,0xe8,0x68,0x00,0xba
+,0x52,0x00,0xb8,0x10,0x10,0xef,0xe8,0x86,0x00,0x3c,0x10,0x75,0x3b,0xe8,0x5f,0x00
+,0xba,0x52,0x00,0xb8,0x20,0x20,0xef,0xe8,0x75,0x00,0x3c,0x20,0x75,0x2a,0xe8,0x56
+,0x00,0xba,0x52,0x00,0xb8,0x40,0x40,0xef,0xe8,0x64,0x00,0x3c,0x40,0x75,0x19,0xe8
+,0x4d,0x00,0xba,0x52,0x00,0xb8,0x80,0x80,0xef,0xe8,0x53,0x00,0x3c,0x80,0x75,0x08
+,0xe8,0x44,0x00,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x28,0x00,0xa3,0xf7,0x34,0xc3,0xba
+,0x5a,0x00,0xb8,0x00,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x01,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x02,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x03,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x04,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x05,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x06,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x07,0x80,0xef,0xc3,0xb9
+,0xff,0xff,0xe4,0x58,0xe4,0x54,0x3c,0x00,0x75,0x03,0x49,0x75,0xf7,0xc3,0xfa,0x32
+,0xc0,0xe6,0x56,0xe4,0x56,0x3c,0x00,0x74,0x03,0xe9,0x82,0x00,0xb0,0xff,0xe6,0x56
+,0xe4,0x56,0x3c,0xff,0x75,0x78,0xba,0x52,0x00,0xb8,0xff,0xff,0xef,0xed,0x3c,0xff
+,0x75,0x6c,0xb8,0x00,0xff,0xef,0xed,0x3c,0x00,0x75,0x63,0xb0,0xff,0xe6,0x54,0xe4
+,0x54,0x3c,0xff,0x75,0x59,0x32,0xc0,0xe6,0x54,0xe4,0x54,0x3c,0x00,0x75,0x4f,0xb0
+,0x0f,0xe6,0x50,0xe4,0x50,0x24,0x0f,0x3c,0x0f,0x75,0x43,0xb0,0x00,0xe6,0x50,0xe4
+,0x50,0x24,0x0f,0x3c,0x00,0x75,0x37,0x8c,0xc8,0x8e,0xc0,0xbe,0x70,0x00,0x26,0x8b
+,0x14,0x26,0x8b,0x5c,0x02,0xb8,0x00,0x00,0xef,0xed,0x23,0xc3,0x3d,0x00,0x00,0x75
+,0x1d,0xb8,0xff,0xff,0x23,0xc3,0xef,0x8b,0xc8,0xed,0x23,0xc3,0x3b,0xc1,0x75,0x0e
+,0x83,0xc6,0x04,0x26,0x83,0x3c,0xff,0x75,0xd5,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x2a
+,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0x33,0xc0,0xbf,0x00,0x20,0xb9,0x17,0x00,0xf3,0xab
+,0xbf,0x00,0x30,0xb9,0x17,0x00,0xf3,0xab,0xbf,0x00,0x22,0xb9,0x40,0x00,0xf3,0xab
+,0xbf,0x00,0x32,0xb9,0x40,0x00,0xf3,0xab,0xfc,0x1e,0x8c,0xc8,0x8e,0xd8,0x33,0xc0
+,0x8e,0xc0,0xbe,0x92,0x00,0xbf,0x00,0x20,0xb9,0x17,0x00,0xf3,0xa4,0xbe,0xa9,0x00
+,0xbf,0x00,0x22,0xb9,0x40,0x00,0xf3,0xa4,0x1f,0xc7,0x06,0xfb,0x34,0x64,0x00,0xba
+,0x08,0x00,0xb8,0x0f,0x00,0xef,0xe8,0x82,0x01,0xe8,0x9b,0x01,0x72,0x0d,0xc7,0x06
+,0xf7,0x34,0x2c,0x00,0xc7,0x06,0xf9,0x34,0x04,0x00,0xc3,0xba,0x0a,0x00,0x33,0xc0
+,0xef,0xe8,0x98,0x01,0xe8,0xb5,0x01,0xb8,0x17,0x00,0xba,0x9c,0x00,0xef,0xb8,0x00
+,0x10,0xba,0x9a,0x00,0xef,0xb8,0x17,0x00,0xa9,0x01,0x00,0x74,0x01,0x40,0xba,0x8c
+,0x00,0xef,0xb8,0x00,0x18,0xba,0x86,0x00,0xef,0xb8,0x0c,0x00,0xba,0x82,0x00,0xef
+,0xba,0x02,0x00,0xed,0x25,0xf9,0xff,0x0d,0x02,0x00,0xef,0xba,0x06,0x00,0x33,0xc0
+,0xef,0xba,0x04,0x00,0xb8,0x60,0x00,0xef,0xba,0x00,0x00,0xb8,0x18,0x00,0xef,0xba
+,0x80,0x00,0xb9,0xff,0xff,0xed,0xa9,0x01,0x00,0x75,0x04,0xe2,0xf8,0xeb,0x3e,0xba
+,0x0a,0x00,0xed,0xa9,0x00,0x40,0x74,0x35,0xa9,0x00,0x20,0x74,0x30,0x33,0xc0,0xef
+,0x51,0xb9,0xc8,0x00,0xe2,0xfe,0x59,0x1e,0x06,0x1f,0x26,0x8b,0x0e,0x02,0x30,0x83
+,0xf9,0x17,0x75,0x18,0x49,0x49,0xbe,0x02,0x20,0xbf,0x06,0x30,0xf3,0xa6,0x1f,0x23
+,0xc9,0x75,0x0a,0xff,0x0e,0xfb,0x34,0x74,0x12,0xe9,0x4d,0xff,0x1f,0xb8,0x2c,0x00
+,0xbb,0x00,0x00,0xa3,0xf7,0x34,0x89,0x1e,0xf9,0x34,0xc3,0xc7,0x06,0xfb,0x34,0x64
+,0x00,0xe8,0xd3,0x00,0x72,0x0d,0xc7,0x06,0xf7,0x34,0x2c,0x00,0xc7,0x06,0xf9,0x34
+,0x04,0x00,0xc3,0xe8,0xd6,0x00,0xe8,0xf3,0x00,0xb8,0x03,0x00,0xba,0x82,0x00,0xef
+,0xb8,0x40,0x80,0xba,0x98,0x00,0xef,0xb8,0x00,0x11,0xba,0x96,0x00,0xef,0xb8,0x40
+,0x00,0xa9,0x01,0x00,0x74,0x01,0x40,0xba,0x92,0x00,0xef,0xb8,0x00,0x19,0xba,0x8e
+,0x00,0xef,0xba,0x02,0x00,0xed,0x25,0xf9,0xff,0x0d,0x06,0x00,0xef,0xba,0x06,0x00
+,0x33,0xc0,0xef,0xba,0x00,0x00,0xb8,0x18,0x00,0xef,0xba,0x80,0x00,0xb9,0xff,0xff
+,0xed,0xa9,0x20,0x00,0x75,0x04,0xe2,0xf8,0xeb,0x43,0xba,0x0a,0x00,0xed,0xa9,0x00
+,0x40,0x74,0x3a,0xa9,0x00,0x20,0x74,0x35,0x33,0xc0,0xef,0x51,0xb9,0xc8,0x00,0xe2
+,0xfe,0x59,0x1e,0x06,0x1f,0x26,0x8b,0x0e,0x02,0x32,0x83,0xf9,0x40,0x75,0x1d,0x49
+,0x49,0xbe,0x02,0x22,0xbf,0x06,0x32,0xf3,0xa6,0x1f,0x23,0xc9,0x75,0x0f,0xff,0x0e
+,0xfb,0x34,0x74,0x03,0xe9,0x5a,0xff,0xb8,0x00,0x00,0xeb,0x0b,0x1f,0xb8,0x2c,0x00
+,0xbb,0x02,0x00,0x89,0x1e,0xf9,0x34,0xa3,0xf7,0x34,0xc3,0xba,0x02,0x00,0xb8,0x00
+,0x9c,0xef,0xba,0x00,0x00,0xb8,0x00,0x84,0xef,0x33,0xc0,0xef,0xba,0x0a,0x00,0xef
+,0xba,0x0e,0x00,0x33,0xc0,0xef,0xc3,0xba,0x0a,0x00,0xb9,0xff,0xff,0xed,0x25,0x00
+,0x60,0x3d,0x00,0x60,0x74,0x04,0xe2,0xf5,0xf8,0xc3,0xf9,0xc3,0xb0,0x00,0xe6,0x56
+,0xb8,0x00,0xff,0xba,0x52,0x00,0xef,0xb9,0xff,0xff,0xba,0x58,0x00,0xed,0x25,0xef
+,0x00,0x74,0x08,0xba,0x5a,0x00,0x33,0xc0,0xef,0xe2,0xef,0xc3,0xba,0x80,0x00,0xed
+,0xba,0x84,0x00,0xef,0xba,0x80,0x00,0xed,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xc6,0x06,0xec,0x34,0x15,0x33,0xc0,0x8e,0xd8,0x8e,0xc0,0x1e,0x8c,0xc8,0xbe,0x40
+,0x54,0xbf,0x60,0xfe,0x8e,0xd8,0xb9,0x10,0x00,0xf3,0xa4,0x1f,0xc7,0x06,0x80,0x36
+,0x10,0x35,0xc7,0x06,0x8c,0x36,0x30,0x35,0x8d,0x06,0x38,0x35,0xa3,0x30,0x35,0xa3
+,0x32,0x35,0x05,0x33,0x01,0xa3,0x34,0x35,0xc7,0x06,0x36,0x35,0x50,0x01,0xc7,0x06
+,0x84,0x36,0x80,0xfe,0xc7,0x06,0x88,0x36,0xc0,0xfe,0xc6,0x06,0xc2,0xfe,0xff,0xc6
+,0x06,0x93,0x36,0x80,0xc6,0x06,0x92,0x36,0x00,0xc6,0x06,0x80,0xfe,0x80,0xc7,0x06
+,0x82,0xfe,0x54,0x50,0xc7,0x06,0x84,0xfe,0x2b,0x4d,0xe5,0xce,0xa9,0x02,0x00,0x75
+,0x08,0xc6,0x06,0x81,0xfe,0x23,0xe9,0x05,0x00,0xc6,0x06,0x81,0xfe,0x22,0xa1,0xf7
+,0x34,0xa3,0x86,0xfe,0xb8,0x48,0x34,0x86,0xe0,0xa3,0x88,0xfe,0x8d,0x06,0x4e,0x34
+,0x86,0xe0,0xa3,0x8a,0xfe,0xb8,0x58,0x34,0x86,0xe0,0xa3,0x8c,0xfe,0xb8,0x9c,0x34
+,0x86,0xe0,0xa3,0x8e,0xfe,0x8d,0x06,0x20,0x03,0x86,0xe0,0xa3,0x90,0xfe,0x33,0xc0
+,0xba,0x72,0x00,0xef,0x33,0xc0,0xba,0x74,0x00,0xef,0xba,0x76,0x00,0xef,0xb8,0x80
+,0xfe,0x86,0xe0,0xba,0x72,0x00,0xef,0xe8,0xbf,0x07,0xba,0x0c,0x01,0xb8,0x40,0x40
+,0xef,0xed,0xba,0x6a,0x00,0xb8,0x03,0x00,0xc1,0xe0,0x08,0x0d,0x03,0x00,0xef,0xb9
+,0x0a,0x00,0xe8,0x94,0x00,0xba,0x6a,0x00,0xb8,0x03,0x00,0xc1,0xe0,0x08,0xef,0xa1
+,0x32,0x34,0xa3,0xa2,0x33,0xc7,0x06,0xa6,0x33,0x04,0x00,0x8d,0x06,0xa0,0x33,0xc1
+,0xe8,0x04,0xcd,0x39,0xc7,0x06,0x90,0x36,0xff,0xff,0xe9,0xe3,0x00,0x63,0x0d,0x66
+,0x0d,0x66,0x0d,0x8a,0x0d,0xe6,0x0e,0x75,0x12,0x2e,0x0f,0x03,0x0f,0x50,0x0f,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0xed,0x0f,0xe9,0x12,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x60,0x0d,0x22,0x10,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0xfe,0x10,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0xaf,0x0f,0x32,0x10,0x37
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x64,0x0e,0x00,0x0f,0x95,0x09,0x60,0x0a,0x49,0xbb,0xff,0xff,0xba,0x6a,0x00
+,0xed,0xa9,0x00,0x20,0x74,0x38,0x80,0x3e,0x80,0xfe,0x12,0x75,0x31,0xe8,0x4a,0x00
+,0xa1,0x32,0x34,0xa3,0xa2,0x33,0xc7,0x06,0xa6,0x33,0x04,0x00,0x8d,0x06,0xa0,0x33
+,0xc1,0xe8,0x04,0xcd,0x39,0xe8,0x22,0x00,0xc7,0x06,0xf3,0x34,0x46,0x00,0xc7,0x06
+,0xf5,0x34,0xff,0xff,0xc7,0x06,0x90,0x36,0xff,0xff,0x58,0xe9,0x32,0x00,0x4b,0x83
+,0xfb,0x00,0x75,0xb9,0x83,0xf9,0x00,0x75,0xb0,0xc3,0x52,0xba,0x6a,0x00,0xb8,0x03
+,0x00,0xc1,0xe0,0x08,0x0d,0x03,0x00,0xef,0x5a,0xc3,0x52,0xba,0x6a,0x00,0xb8,0x03
+,0x00,0xc1,0xe0,0x08,0xef,0x5a,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x68,0x80,0x07,0xa1,0x90,0x36,0xcd,0x35,0x8b,0x36,0x24,0x02,0x2e,0xff,0xa4,0x35
+,0x0a,0xfa,0x8a,0x26,0x94,0x36,0x88,0x26,0xe8,0x34,0xc6,0x06,0x94,0x36,0x00,0xfb
+,0x22,0xe4,0x75,0x01,0xc3,0xf6,0xc4,0x20,0x74,0x7d,0xf6,0xc4,0x08,0x74,0x05,0x80
+,0x0e,0x92,0x36,0x04,0x80,0x26,0xe8,0x34,0xd7,0xc4,0x1e,0x84,0x36,0x26,0x8b,0x37
+,0x81,0xe6,0xff,0x00,0x83,0xfe,0x20,0x76,0x05,0xb0,0x01,0xe9,0x28,0x00,0x53,0x06
+,0xd1,0xe6,0x2e,0xff,0x94,0x9d,0x06,0x07,0x5b,0x26,0x88,0x47,0x02,0x3c,0xff,0x74
+,0x07,0x3c,0xfe,0x75,0x11,0xe9,0x3b,0x00,0xf6,0x06,0x92,0x36,0x08,0x75,0x34,0xf6
+,0x06,0x92,0x36,0x04,0x74,0x2d,0x80,0x26,0x92,0x36,0xf3,0x80,0x3e,0x95,0x36,0x00
+,0x75,0x21,0x26,0x80,0x3f,0x05,0x75,0x13,0xc6,0x06,0x95,0x36,0x00,0x26,0x80,0x7f
+,0x06,0x00,0x74,0x07,0x26,0x8b,0x47,0x04,0xa2,0x95,0x36,0xba,0x0c,0x01,0xb8,0x40
+,0x40,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x10,0x75,0x03,0xe9,0x5b,0x00,0xf6
+,0xc4,0x04,0x74,0x05,0x80,0x0e,0x92,0x36,0x01,0x80,0x26,0xe8,0x34,0xeb,0xc4,0x3e
+,0x88,0x36,0x26,0x8b,0x35,0x83,0xe6,0x7f,0x83,0xfe,0x12,0x72,0x08,0x26,0xc6,0x45
+,0x02,0x01,0xe9,0x24,0x00,0x83,0xc6,0x20,0xd1,0xe6,0x2e,0xff,0x94,0x9d,0x06,0xc4
+,0x3e,0x88,0x36,0x26,0x88,0x45,0x02,0x3c,0xff,0x75,0x0e,0xf6,0x06,0x92,0x36,0x01
+,0x74,0x14,0xf6,0x06,0x92,0x36,0x02,0x75,0x0d,0x80,0x26,0x92,0x36,0xfc,0xba,0x0c
+,0x01,0xb8,0x20,0x20,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x08,0x74,0x22,0x80
+,0x26,0xe8,0x34,0xf7,0x80,0x0e,0x92,0x36,0x04,0xf6,0x06,0x92,0x36,0x08,0x74,0x11
+,0x80,0x26,0x92,0x36,0xf3,0xba,0x0c,0x01,0xb8,0x40,0x40,0xef,0xed,0x8a,0x26,0xe8
+,0x34,0xf6,0xc4,0x04,0x74,0x22,0x80,0x26,0xe8,0x34,0xfb,0x80,0x0e,0x92,0x36,0x01
+,0xf6,0x06,0x92,0x36,0x02,0x75,0x11,0x80,0x26,0x92,0x36,0xfe,0xba,0x0c,0x01,0xb8
+,0x20,0x20,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x01,0x74,0x67,0x80,0x26,0xe8
+,0x34,0xfe,0x80,0x3e,0xe8,0xff,0x00,0x74,0x39,0x80,0x3e,0xe8,0xff,0x04,0x74,0x32
+,0x80,0x3e,0xe8,0xff,0x01,0x75,0x21,0xe5,0x80,0xa9,0x00,0x07,0x74,0x0a,0xba,0x9e
+,0x00,0xb8,0x00,0x02,0xef,0xe9,0xef,0xff,0xc6,0x06,0xe8,0xff,0x03,0xba,0x0c,0x01
+,0xb8,0x08,0x08,0xef,0xed,0xe9,0x28,0x00,0x80,0x3e,0xe8,0xff,0x03,0x74,0x06,0xe9
+,0x1e,0x00,0xe9,0x00,0x00,0xba,0x10,0x01,0xb8,0x02,0x02,0xef,0xed,0xe5,0x00,0x0d
+,0x18,0x00,0xe7,0x00,0xe5,0x82,0x0d,0x02,0x00,0xe7,0x82,0xc6,0x06,0xe8,0xff,0x04
+,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x02,0x74,0x0d,0x80,0x26,0xe8,0x34,0xfd,0x80,0x26
+,0x92,0x36,0xbf,0xe8,0x4f,0x0b,0xfa,0xa0,0xe8,0x34,0x08,0x06,0x94,0x36,0xc6,0x06
+,0xe8,0x34,0x00,0xfb,0xc3,0xe8,0xe7,0x0f,0xc4,0x1e,0x84,0x36,0x2e,0xff,0x16,0x01
+,0x07,0x26,0x88,0x47,0x02,0xe9,0x7e,0xfe,0xe8,0x2d,0x10,0xc4,0x1e,0x84,0x36,0x2e
+,0xff,0x16,0x03,0x07,0x26,0x88,0x47,0x02,0xe9,0x6b,0xfe,0x8e,0x06,0x26,0x02,0x2e
+,0xff,0x16,0x07,0x07,0xc3,0xc3,0x83,0x3e,0xf5,0x34,0x00,0x74,0x0f,0xff,0x0e,0xf3
+,0x34,0x75,0x09,0xe8,0xc4,0xfd,0xc7,0x06,0xf5,0x34,0x00,0x00,0xf6,0x06,0x93,0x36
+,0x20,0x74,0x30,0xa1,0xc2,0x34,0x3b,0x06,0xe9,0x34,0xa3,0xe9,0x34,0x74,0x24,0x80
+,0x3e,0x95,0x36,0x00,0x75,0x1d,0xf7,0x06,0xe6,0x34,0x20,0x00,0x74,0x12,0xa9,0x20
+,0x00,0x74,0x0d,0x83,0x26,0xc2,0x34,0xdf,0x83,0x26,0xe9,0x34,0xdf,0xe9,0x03,0x00
+,0xe8,0xdd,0x09,0xba,0x06,0x01,0xed,0x8b,0xd0,0x81,0xe2,0x00,0xc0,0xc1,0xea,0x0e
+,0x03,0x16,0x74,0x34,0xc1,0xe0,0x02,0x11,0x06,0x72,0x34,0x73,0x04,0xff,0x06,0x74
+,0x34,0xba,0x02,0x01,0xed,0x8b,0xd0,0x81,0xe2,0x00,0xc0,0xc1,0xea,0x0e,0x03,0x16
+,0x70,0x34,0xc1,0xe0,0x02,0x11,0x06,0x6e,0x34,0x73,0x04,0xff,0x06,0x70,0x34,0xc7
+,0x06,0xa6,0x33,0x04,0x00,0xc7,0x06,0xaa,0x33,0x00,0x00,0x8d,0x06,0xa0,0x33,0xc1
+,0xe8,0x04,0xcd,0x39,0xc3,0x95,0x09,0x95,0x09,0x65,0x09,0x78,0x09,0x95,0x09,0x95
+,0x09,0x91,0x07,0x95,0x09,0x96,0x09,0x8b,0x09,0x95,0x09,0x95,0x09,0x95,0x09,0x95
+,0x09,0x95,0x09,0x95,0x09,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x90
+,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xe9,0xcc,0x00,0x8c,0xc0,0x40,0x8e,0xc0,0x26
+,0x8b,0x0e,0x06,0x00,0x86,0xe9,0x26,0x89,0x0e,0x06,0x00,0x8c,0xc2,0xc1,0xe2,0x04
+,0xbe,0x0e,0x00,0x26,0xa1,0x04,0x00,0xd0,0xe0,0x24,0xc0,0x8a,0xe0,0xc0,0xec,0x04
+,0x0a,0xc4,0x26,0xa2,0x05,0x00,0x26,0xa1,0x08,0x00,0xa9,0x00,0xc0,0x74,0x03,0xe9
+,0x9e,0x00,0x26,0xf6,0x06,0x10,0x00,0x80,0x75,0x03,0xe9,0x0a,0x00,0x26,0xa0,0x16
+,0x00,0x24,0x1f,0x32,0xe4,0x03,0xf0,0x80,0x3e,0xec,0x34,0x06,0x72,0x5c,0x80,0x3e
+,0x95,0x36,0x00,0x75,0x66,0x8b,0xfa,0x33,0xdb,0x8e,0xc3,0x26,0x89,0x1d,0x26,0x88
+,0x5d,0x04,0x51,0x50,0xc4,0x1e,0x8c,0x36,0xb9,0x0f,0x00,0x33,0xc0,0xe8,0x21,0x09
+,0x58,0x59,0x0b,0xdb,0x74,0x34,0xfe,0x0e,0xe6,0x3a,0x26,0xc6,0x07,0x81,0x26,0xc6
+,0x47,0x01,0x00,0x26,0xc6,0x47,0x02,0xff,0x26,0xc7,0x47,0x04,0x00,0x00,0x26,0x89
+,0x4f,0x0a,0x86,0xf2,0x26,0x89,0x57,0x06,0x26,0x89,0x77,0x08,0x26,0xc6,0x47,0x09
+,0x00,0x26,0xc6,0x47,0x0c,0x02,0xe8,0x8c,0x09,0xc3,0xff,0x06,0xec,0x33,0x8c,0xc0
+,0x48,0x8e,0xc0,0xfa,0xe8,0x97,0x10,0xfb,0xe9,0xeb,0xff,0x8c,0xc0,0x48,0x8e,0xc0
+,0xfa,0xe8,0x8a,0x10,0xfb,0xc3,0x8c,0xc0,0x8e,0xc0,0xfa,0xe8,0x80,0x10,0xfb,0xc3
+,0x80,0x3e,0x95,0x36,0x00,0x75,0x03,0xe9,0xc2,0x00,0xbf,0x08,0x00,0x26,0xf6,0x06
+,0x10,0x00,0x80,0x75,0x05,0x03,0xfe,0xe9,0x0c,0x00,0x26,0xa0,0x16,0x00,0x24,0x1f
+,0x32,0xe4,0x03,0xf0,0x03,0xfe,0xa0,0x95,0x36,0x3c,0x00,0x75,0x03,0xe9,0x9c,0x00
+,0x3c,0x01,0x74,0x0b,0x3c,0x02,0x74,0x14,0x3c,0x03,0x74,0x1d,0xe9,0x8d,0x00,0xc6
+,0x06,0x96,0x36,0x01,0xe8,0x3c,0x01,0x72,0x27,0xe9,0x80,0x00,0xc6,0x06,0x96,0x36
+,0x02,0xe8,0x83,0x00,0x72,0x1a,0xe9,0x73,0x00,0xc6,0x06,0x96,0x36,0x01,0xe8,0x22
+,0x01,0x72,0x0d,0xc6,0x06,0x96,0x36,0x02,0xe8,0x6c,0x00,0x72,0x03,0xe9,0x5c,0x00
+,0x53,0x06,0x50,0xc4,0x1e,0x8c,0x36,0xb9,0x0b,0x00,0x33,0xc0,0xe8,0x42,0x08,0x58
+,0x26,0xc6,0x07,0x82,0x26,0xc6,0x47,0x02,0xff,0x8d,0x06,0xe0,0xfe,0x86,0xc4,0x26
+,0x89,0x47,0x06,0xa0,0x96,0x36,0x26,0x88,0x47,0x08,0xe8,0xc8,0x08,0x07,0x5b,0x83
+,0x26,0xad,0x36,0xfe,0xa1,0xad,0x36,0xe7,0x04,0xba,0x10,0x01,0xb8,0x80,0x80,0xef
+,0xed,0xba,0x10,0x01,0xb8,0x02,0x02,0xef,0xed,0x52,0xba,0xe0,0x00,0xb8,0x41,0x10
+,0xef,0x5a,0xb8,0x9c,0x03,0xcd,0x39,0xc6,0x06,0x95,0x36,0x00,0x8c,0xc0,0x48,0x8e
+,0xc0,0xfa,0xe8,0xa9,0x0f,0xfb,0xc3,0x1e,0x06,0x1f,0x06,0x33,0xc0,0x8e,0xc0,0x8b
+,0xf0,0x8d,0x3e,0x20,0xf3,0x51,0xb1,0x0a,0x26,0x83,0x7d,0x0c,0x01,0x75,0x2a,0x57
+,0x26,0x83,0x7d,0x0e,0x00,0x74,0x06,0xe8,0x2f,0x00,0xe9,0x03,0x00,0xe8,0x66,0x07
+,0x5f,0x73,0x16,0x33,0xc0,0x8e,0xd8,0x26,0x8b,0x4d,0x12,0x8d,0x75,0x20,0x8d,0x3e
+,0xe0,0xfe,0xf3,0xa4,0x59,0x07,0x1f,0xf9,0xc3,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20
+,0x01,0xe9,0xc4,0xff,0x59,0x07,0x1f,0xf8,0xc3,0x51,0x50,0x53,0x56,0x52,0x57,0x33
+,0xdb,0x26,0x8a,0x5d,0x0e,0x26,0x8b,0x4d,0x12,0x8d,0x7d,0x20,0x5a,0x87,0xd7,0x26
+,0x8a,0x45,0x14,0x87,0xd7,0x42,0x32,0xff,0x80,0xff,0x08,0x75,0x08,0xfe,0xcb,0x22
+,0xdb,0x75,0xea,0x33,0xdb,0x23,0xdb,0x74,0x06,0xfe,0xc7,0xd0,0xc8,0x73,0x0c,0x50
+,0x26,0x8a,0x05,0x38,0x04,0x58,0x74,0x03,0xe9,0x0a,0x00,0x49,0x46,0x47,0x23,0xc9
+,0x74,0x0a,0xe9,0xd3,0xff,0x5a,0x5e,0x5b,0x58,0x59,0xf8,0xc3,0x5a,0x5e,0x5b,0x58
+,0x59,0xf9,0xc3,0x1e,0x06,0x1f,0x06,0x33,0xc0,0x8e,0xc0,0x86,0xcd,0x2b,0xce,0x8b
+,0xf7,0x8b,0xc1,0x33,0xc9,0x80,0x3c,0xff,0x74,0x16,0x80,0xf9,0x06,0x73,0x09,0x32
+,0xc9,0x46,0x48,0x74,0x2e,0xe9,0xed,0xff,0x3d,0x60,0x00,0x73,0x0c,0xe9,0x23,0x00
+,0xfe,0xc1,0x46,0x48,0x74,0x1d,0xe9,0xdc,0xff,0xb8,0x10,0x00,0x8d,0x3e,0x18,0x34
+,0x32,0xed,0xb1,0x06,0xf3,0xa6,0x74,0x03,0xe9,0x08,0x00,0x48,0x23,0xc0,0x74,0x07
+,0xe9,0xe9,0xff,0x07,0x1f,0xf8,0xc3,0x8d,0x36,0x18,0x34,0x33,0xc0,0x8e,0xd8,0x8d
+,0x3e,0xe0,0xfe,0xb8,0x10,0x00,0xb9,0x06,0x00,0x56,0xf3,0xa4,0x5e,0x48,0x3d,0x00
+,0x00,0x75,0xf3,0x07,0x1f,0xf9,0xc3,0xff,0x06,0xe4,0x33,0xc6,0x06,0xeb,0x34,0x00
+,0x26,0x8b,0x45,0x06,0x86,0xe0,0xc1,0xe8,0x04,0x48,0x06,0x8e,0xc0,0xfe,0x06,0xe6
+,0x3a,0xfa,0xe8,0x69,0x0e,0xfb,0x07,0xb0,0xff,0xc3,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb0,0x01,0xc3,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3
+,0x8b,0x0e,0x97,0x36,0x81,0xe1,0x80,0x30,0x26,0x8b,0x47,0x04,0x25,0x7f,0xcf,0x0b
+,0xc1,0xa3,0x97,0x36,0xa3,0xe6,0x34,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x74
+,0x03,0xb0,0x03,0xc3,0x26,0x8b,0x47,0x08,0xa3,0x97,0x36,0xa3,0xe6,0x34,0x26,0x8a
+,0x47,0x20,0xa2,0xfd,0x34,0x3c,0x01,0x75,0x06,0xc7,0x06,0xa1,0x36,0x00,0x00,0x26
+,0x8a,0x47,0x21,0xa2,0xfe,0x34,0x26,0x8b,0x47,0x0a,0xa3,0x18,0x34,0xa3,0x58,0x34
+,0x26,0x8b,0x47,0x0c,0xa3,0x1a,0x34,0xa3,0x5a,0x34,0x26,0x8b,0x47,0x0e,0xa3,0x1c
+,0x34,0xa3,0x5c,0x34,0xc6,0x06,0x2a,0x34,0xc0,0x26,0x8b,0x47,0x14,0x25,0x7f,0xff
+,0x09,0x06,0x2c,0x34,0x26,0x8b,0x47,0x16,0x25,0xff,0xfe,0x25,0xff,0xfc,0x09,0x06
+,0x2e,0x34,0xc6,0x06,0x00,0x34,0xc0,0x26,0x8b,0x47,0x10,0xa3,0x02,0x34,0x26,0x8b
+,0x47,0x12,0xa3,0x04,0x34,0x06,0x53,0xe8,0x84,0x0a,0x5b,0x07,0x3d,0x00,0x00,0x75
+,0x07,0x80,0x0e,0x92,0x36,0x08,0xb0,0xfe,0xc3,0xb9,0x00,0x01,0xa1,0xac,0x33,0x33
+,0xd2,0xf7,0xf9,0xa3,0xae,0x33,0x91,0x49,0x33,0xd2,0xf7,0xe9,0x05,0x00,0x3b,0xa3
+,0x46,0x34,0xbf,0x00,0x3b,0x89,0x3e,0x44,0x34,0xba,0x68,0x00,0xb8,0xe0,0xe0,0xef
+,0xa1,0xae,0x33,0xe7,0x62,0xa1,0xae,0x33,0xba,0x08,0x01,0xef,0xa1,0x44,0x34,0xe7
+,0x64,0xa1,0x44,0x34,0xba,0x0a,0x01,0xef,0xb8,0x00,0x01,0x2d,0x04,0x00,0x0d,0x00
+,0x10,0xe7,0x92,0xc3,0x3d,0x00,0x00,0x74,0x0a,0x26,0x89,0x47,0x07,0xe8,0x83,0x3a
+,0xb0,0x07,0xc3,0xa1,0xae,0x33,0x26,0x89,0x47,0x2b,0xa1,0x44,0x34,0x26,0x89,0x47
+,0x2d,0xa1,0x46,0x34,0x26,0x89,0x47,0x2f,0x80,0x0e,0x93,0x36,0x20,0xa1,0x88,0x36
+,0x86,0xe0,0x26,0x89,0x47,0x08,0xa1,0x84,0x36,0x86,0xe0,0x26,0x89,0x47,0x0a,0xa1
+,0x80,0x36,0x86,0xe0,0x26,0x89,0x47,0x0c,0xb8,0x60,0xfe,0x86,0xe0,0x26,0x89,0x47
+,0x0e,0xa0,0xa1,0x36,0x26,0x88,0x47,0x10,0x8b,0x36,0x88,0x36,0x26,0xc6,0x44,0x02
+,0xff,0xe5,0x9e,0xa9,0x00,0x08,0x74,0x0c,0xba,0x84,0x00,0xed,0x0d,0x08,0x00,0xef
+,0xba,0x8e,0x00,0xef,0xe5,0x02,0x25,0xf9,0xff,0xe7,0x02,0xba,0x10,0x01,0xb8,0x02
+,0x02,0xef,0xed,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x01,0xc3
+,0x80,0x26,0x93,0x36,0x9f,0xe8,0x8d,0x0a,0x80,0x0e,0x92,0x36,0x08,0xb0,0xfe,0xc3
+,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xc6,0x06,0x2a
+,0x34,0xc0,0x26,0x8b,0x47,0x06,0x25,0x7f,0xff,0xa3,0x2c,0x34,0x26,0x8b,0x47,0x08
+,0x25,0xff,0xfe,0x25,0xff,0xfc,0xa3,0x2e,0x34,0xcd,0x52,0xb0,0x00,0xc3,0xf6,0x06
+,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xc6,0x06,0x00,0x34,0xc0,0x26,0x8b,0x47
+,0x06,0xa3,0x02,0x34,0x26,0x8b,0x47,0x08,0xa3,0x04,0x34,0xcd,0x52,0xb0,0x00,0xc3
+,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x57,0x8d,0x7f,0x06,0x51,0xb9
+,0x07,0x00,0x33,0xc0,0xf3,0xab,0x59,0x8d,0x7f,0x06,0xa1,0x7a,0x34,0x03,0x06,0x39
+,0x37,0x26,0x88,0x05,0xa1,0x95,0x37,0x26,0x88,0x45,0x02,0xa1,0x80,0x34,0x03,0x06
+,0x76,0x34,0x26,0x88,0x45,0x07,0xa1,0xc6,0x34,0x26,0x88,0x45,0x09,0xa1,0xd8,0x33
+,0x26,0x88,0x45,0x0a,0x33,0xc0,0xa3,0x7a,0x34,0xa3,0x39,0x37,0xa3,0x95,0x37,0xa3
+,0x80,0x34,0xa3,0x76,0x34,0xa3,0xc6,0x34,0xa3,0xd8,0x33,0x5f,0xb0,0x00,0xc3,0xf6
+,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x26,0x8b,0x4f,0x04,0x83,0xf9,0x06
+,0x74,0x12,0x83,0xf9,0x04,0x74,0x0d,0x83,0xf9,0x00,0x74,0x08,0x83,0xf9,0x02,0x74
+,0x03,0xb0,0x01,0xc3,0x89,0x0e,0xe8,0x3a,0x83,0x26,0xab,0x36,0xf9,0x09,0x0e,0xab
+,0x36,0xe5,0x02,0x25,0xf9,0xff,0x0b,0xc1,0xe7,0x02,0xb0,0x00,0xc3,0xf6,0x06,0x93
+,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x26,0x8b,0x4f,0x04,0x80,0xf9,0xff,0x74,0x08
+,0x80,0xf9,0x00,0x74,0x10,0xb0,0x01,0xc3,0x83,0x0e,0xad,0x36,0x02,0xa1,0xad,0x36
+,0xe7,0x04,0xe9,0x0a,0x00,0x83,0x26,0xad,0x36,0xfd,0xa1,0xad,0x36,0xe7,0x04,0xb0
+,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xe8,0xd5,0x04,0xb0
+,0x00,0xc3,0xf6,0x06,0x93,0x36,0x80,0x75,0x03,0xb0,0x01,0xc3,0x26,0x83,0x7f,0x06
+,0x05,0x75,0x03,0xe9,0x9d,0x00,0x26,0x8b,0x57,0x04,0x26,0x8b,0x47,0x08,0x26,0x81
+,0x7f,0x06,0x00,0x80,0x75,0x08,0xed,0x26,0x89,0x47,0x0a,0xe9,0x9d,0x00,0x26,0x83
+,0x7f,0x06,0x01,0x75,0x04,0xef,0xe9,0x92,0x00,0x26,0x81,0x7f,0x06,0x01,0x80,0x75
+,0x09,0xef,0xed,0x26,0x89,0x47,0x0a,0xe9,0x81,0x00,0x26,0x83,0x7f,0x06,0x02,0x75
+,0x07,0x26,0x21,0x47,0x04,0xe9,0x73,0x00,0x26,0x81,0x7f,0x06,0x02,0x80,0x75,0x0c
+,0x26,0x21,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x5f,0x00,0x26,0x83,0x7f,0x06
+,0x03,0x75,0x07,0x26,0x09,0x47,0x04,0xe9,0x51,0x00,0x26,0x81,0x7f,0x06,0x03,0x80
+,0x75,0x0c,0x26,0x09,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x3d,0x00,0x26,0x83
+,0x7f,0x06,0x04,0x75,0x07,0x26,0x31,0x47,0x04,0xe9,0x2f,0x00,0x26,0x81,0x7f,0x06
+,0x04,0x80,0x75,0x0c,0x26,0x31,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x1b,0x00
+,0xb0,0x01,0xc3,0xfa,0x53,0x26,0x8b,0x4f,0x08,0x0b,0xc9,0x74,0x0c,0x8d,0x1e,0xe0
+,0xfe,0xe8,0x52,0xff,0x83,0xc3,0x08,0xe2,0xf8,0x5b,0xfb,0xb0,0x00,0xc3,0xf6,0x06
+,0x93,0x36,0x80,0x75,0x0a,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x01,0xc3,0x8d
+,0x3e,0xe0,0xfe,0xe5,0x00,0x26,0x89,0x05,0xe5,0x02,0x26,0x89,0x45,0x02,0xa1,0xad
+,0x36,0x26,0x89,0x45,0x04,0xe5,0x06,0x26,0x89,0x45,0x06,0xe5,0x08,0x26,0x89,0x45
+,0x08,0xe5,0x0a,0x26,0x89,0x45,0x0a,0xe5,0x0e,0x26,0x89,0x45,0x0c,0xe5,0x48,0x26
+,0x89,0x45,0x0e,0xe5,0x4a,0x26,0x89,0x45,0x10,0xe5,0x4c,0x26,0x89,0x45,0x12,0xa1
+,0xb7,0x36,0x26,0x89,0x45,0x14,0xe5,0x50,0x26,0x89,0x45,0x16,0xe5,0x52,0x26,0x89
+,0x45,0x18,0xe5,0x54,0x26,0x89,0x45,0x1a,0xe5,0x56,0x26,0x89,0x45,0x1c,0xe5,0x58
+,0x26,0x89,0x45,0x1e,0xe5,0x62,0x26,0x89,0x45,0x20,0xe5,0x64,0x26,0x89,0x45,0x22
+,0xe5,0x66,0x26,0x89,0x45,0x24,0xe5,0x68,0x26,0x89,0x45,0x26,0xe5,0x6a,0x26,0x89
+,0x45,0x28,0xe5,0x6c,0x26,0x89,0x45,0x2a,0xe5,0x70,0x26,0x89,0x45,0x2c,0xe5,0x72
+,0x26,0x89,0x45,0x2e,0xe5,0x74,0x26,0x89,0x45,0x30,0xe5,0x76,0x26,0x89,0x45,0x32
+,0xe5,0x7c,0x26,0x89,0x45,0x34,0xe5,0x7e,0x26,0x89,0x45,0x36,0xe5,0x80,0x26,0x89
+,0x45,0x38,0xe5,0x82,0x26,0x89,0x45,0x3a,0xe5,0x86,0x26,0x89,0x45,0x3c,0xe5,0x88
+,0x26,0x89,0x45,0x3e,0xe5,0x9a,0x26,0x89,0x45,0x40,0xe5,0x9e,0x26,0x89,0x45,0x42
+,0xe5,0xcc,0x26,0x89,0x45,0x44,0xe5,0xce,0x26,0x89,0x45,0x46,0xe5,0xd0,0x26,0x89
+,0x45,0x48,0xe5,0xd2,0x26,0x89,0x45,0x4a,0xba,0x00,0x01,0xed,0x11,0x06,0x66,0x34
+,0x73,0x04,0xff,0x06,0x68,0x34,0x26,0x89,0x45,0x4c,0xba,0x02,0x01,0xed,0xc1,0xe0
+,0x02,0x11,0x06,0x6e,0x34,0x73,0x04,0xff,0x06,0x70,0x34,0x26,0x89,0x45,0x4e,0xba
+,0x04,0x01,0xed,0x11,0x06,0x6a,0x34,0x73,0x04,0xff,0x06,0x6c,0x34,0x26,0x89,0x45
+,0x50,0xba,0x06,0x01,0xed,0xc1,0xe0,0x02,0x11,0x06,0x72,0x34,0x73,0x04,0xff,0x06
+,0x74,0x34,0x26,0x89,0x45,0x52,0xba,0x08,0x01,0xed,0x26,0x89,0x45,0x54,0xba,0x0a
+,0x01,0xed,0x26,0x89,0x45,0x56,0xba,0x0c,0x01,0xed,0x26,0x89,0x45,0x58,0xba,0x0e
+,0x01,0xed,0x01,0x06,0x7a,0x34,0x26,0x89,0x45,0x5e,0xba,0x10,0x01,0xed,0x26,0x89
+,0x45,0x5c,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x80,0x74,0x07,0xf6,0x06,0x93,0x36
+,0x20,0x75,0x03,0xb0,0x01,0xc3,0x26,0x80,0x7f,0x06,0x00,0x75,0x30,0x80,0x3e,0x95
+,0x36,0x00,0x74,0x52,0xc6,0x06,0x95,0x36,0x00,0x83,0x26,0xad,0x36,0xfe,0xa1,0xad
+,0x36,0xe7,0x04,0xba,0x10,0x01,0xb8,0x80,0x80,0xef,0xed,0xba,0x10,0x01,0xb8,0x02
+,0x02,0xef,0xed,0xba,0xe0,0x00,0xb8,0x00,0x10,0xef,0xb0,0x00,0xc3,0x26,0x8b,0x47
+,0x04,0x3d,0x00,0x00,0x74,0x20,0x3d,0x03,0x00,0x77,0x1b,0xba,0x10,0x01,0xb8,0x02
+,0x00,0xef,0xba,0xe0,0x00,0xb8,0x01,0x10,0xef,0x83,0x0e,0xad,0x36,0x01,0xa1,0xad
+,0x36,0xe7,0x04,0xb0,0x00,0xc3,0xb0,0x06,0xc3,0xf6,0x06,0x93,0x36,0x80,0x75,0x03
+,0xb0,0x01,0xc3,0x26,0x83,0x7f,0x04,0x01,0x74,0x0a,0x26,0x83,0x7f,0x04,0x02,0x74
+,0x19,0xb0,0x06,0xc3,0x26,0x83,0x7f,0x06,0x0c,0x77,0xf6,0x26,0x83,0x7f,0x0a,0x60
+,0x77,0xef,0xe8,0x10,0x00,0x72,0x0b,0xb0,0x46,0xc3,0xe8,0x4e,0x00,0x72,0x03,0xb0
+,0x46,0xc3,0xb0,0x00,0xc3,0x51,0xb1,0x0a,0x8b,0x3e,0x20,0xf3,0x26,0x83,0x7d,0x0c
+,0x02,0x75,0x03,0xe9,0x0e,0x00,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20,0x01,0xe9,0xeb
+,0xff,0x59,0xf8,0xc3,0x57,0x8d,0x7d,0x0e,0x8d,0x77,0x06,0xb9,0x12,0x00,0xf3,0xa4
+,0x8d,0x7d,0x20,0x8d,0x36,0xe0,0xfe,0x26,0x8b,0x4d,0x12,0xf3,0xa4,0xff,0x06,0x01
+,0x35,0x5f,0x26,0xc7,0x45,0x0c,0x01,0x00,0x59,0xf9,0xc3,0x51,0xb1,0x0a,0x8d,0x3e
+,0x20,0xf3,0x8d,0x36,0xe0,0xfe,0x26,0x83,0x7d,0x0c,0x01,0x75,0x1b,0x57,0xe8,0x25
+,0x00,0x5f,0x73,0x14,0x33,0xc0,0xb9,0x20,0x01,0xf3,0xaa,0x26,0xc7,0x45,0x0c,0x02
+,0x00,0xff,0x0e,0x01,0x35,0x59,0xf9,0xc3,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20,0x01
+,0xe9,0xd3,0xff,0x59,0xf8,0xc3,0x51,0x26,0x8b,0x4d,0x12,0x8d,0x7d,0x20,0xf3,0xa6
+,0x74,0x03,0x59,0xf8,0xc3,0x59,0xf9,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x80,0x3e,0xec,0x34,0x06,0x72,0x33,0xff,0x06,0xf0,0x33,0x50,0xc4,0x1e,0x8c,0x36
+,0xb9,0x0f,0x00,0x33,0xc0,0xe8,0x29,0x00,0x58,0x81,0x26,0xc2,0x34,0xdf,0x7f,0x81
+,0x26,0xe9,0x34,0xdf,0x7f,0x0b,0xdb,0x74,0x11,0x26,0xc6,0x07,0x84,0x26,0xc6,0x47
+,0x02,0xff,0x26,0x89,0x47,0x06,0xe8,0xac,0x00,0xc3,0xff,0x06,0xea,0x33,0xe9,0xf5
+,0xff,0x57,0x26,0x8b,0x3f,0x03,0xf9,0x26,0x3b,0x7f,0x02,0x74,0x16,0x26,0x3b,0x7f
+,0x04,0x7c,0x2a,0x3d,0x00,0x00,0x75,0x13,0x8d,0x7f,0x08,0x03,0xf9,0x26,0x3b,0x7f
+,0x02,0x7c,0x14,0xff,0x06,0xde,0x33,0x33,0xdb,0x5f,0xc3,0x26,0x8b,0x7f,0x02,0x26
+,0x89,0x3f,0x03,0xf9,0xe9,0x06,0x00,0x26,0x89,0x3f,0x26,0x29,0x0f,0x26,0xc7,0x05
+,0xff,0xff,0x26,0x87,0x3f,0x26,0x89,0x0d,0x8d,0x5d,0x02,0x50,0x8b,0xfb,0x83,0xe9
+,0x02,0x33,0xc0,0xf3,0xaa,0x58,0xfe,0x0e,0xec,0x34,0x5f,0xc3,0x8b,0x7c,0x02,0x3b
+,0x3c,0x74,0x2f,0x83,0x3d,0xff,0x75,0x0b,0x8d,0x7c,0x08,0x89,0x7c,0x02,0x83,0x3d
+,0xff,0x74,0x1e,0x8a,0x45,0x02,0x3c,0x81,0x75,0x0c,0x80,0x3e,0xeb,0x34,0x00,0x74
+,0x05,0x33,0xc0,0xe9,0x0b,0x00,0x8b,0x0d,0x01,0x4c,0x02,0x8d,0x75,0x02,0x83,0xe9
+,0x02,0xc3,0x80,0x3e,0xec,0x34,0x06,0x72,0x05,0x33,0xc0,0xe9,0xf3,0xff,0xff,0x06
+,0xee,0x33,0xe9,0xbe,0xff,0xf6,0x06,0x92,0x36,0x40,0x74,0x01,0xc3,0x57,0x56,0x51
+,0x52,0x8b,0x36,0x8c,0x36,0xe8,0xa4,0xff,0x75,0x03,0xe9,0x1a,0x00,0xe9,0x1c,0x00
+,0xfe,0x06,0xec,0x34,0xc4,0x3e,0x80,0x36,0xf3,0xa4,0x80,0x0e,0x92,0x36,0x40,0xba
+,0x0c,0x01,0xb8,0x80,0x80,0xef,0xed,0x5a,0x59,0x5e,0x5f,0xc3,0xff,0x06,0xe0,0x33
+,0x80,0x3c,0x81,0x75,0x0c,0xff,0x06,0xe2,0x33,0xc6,0x06,0xeb,0x34,0x01,0xe9,0xcf
+,0xff,0x80,0x3c,0x84,0x75,0x07,0xff,0x06,0xe6,0x33,0xe9,0xc3,0xff,0xff,0x06,0xe8
+,0x33,0xe9,0xbc,0xff,0x8d,0x3e,0xe0,0xfe,0xa1,0x72,0x34,0xc7,0x06,0x72,0x34,0x00
+,0x00,0x89,0x05,0xa1,0x74,0x34,0xc7,0x06,0x74,0x34,0x00,0x00,0x89,0x45,0x02,0xba
+,0x04,0x01,0xed,0x89,0x45,0x04,0xc7,0x45,0x06,0x00,0x00,0xa1,0x6e,0x34,0xc7,0x06
+,0x6e,0x34,0x00,0x00,0x89,0x45,0x08,0xa1,0x70,0x34,0xc7,0x06,0x70,0x34,0x00,0x00
+,0x89,0x45,0x0a,0xba,0x00,0x01,0xed,0x89,0x45,0x0c,0xc7,0x45,0x0e,0x00,0x00,0x32
+,0xe4,0xba,0x0e,0x01,0xec,0x89,0x45,0x10,0xa1,0x7e,0x34,0xc7,0x06,0x7e,0x34,0x00
+,0x00,0x89,0x45,0x12,0xa1,0x8c,0x34,0xc7,0x06,0x8c,0x34,0x00,0x00,0x89,0x45,0x14
+,0xa1,0x8a,0x34,0xc7,0x06,0x8a,0x34,0x00,0x00,0x89,0x45,0x16,0xa1,0x7c,0x34,0xc7
+,0x06,0x7c,0x34,0x00,0x00,0x89,0x45,0x18,0xa1,0x88,0x34,0xc7,0x06,0x88,0x34,0x00
+,0x00,0x89,0x45,0x1a,0xa1,0xca,0x33,0xc7,0x06,0xca,0x33,0x00,0x00,0x89,0x45,0x1c
+,0xa1,0x78,0x34,0xc7,0x06,0x78,0x34,0x00,0x00,0x89,0x45,0x1e,0xa1,0xc6,0x34,0xc7
+,0x06,0xc6,0x34,0x00,0x00,0x89,0x45,0x20,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xfa,0x33,0xc0,0x8e,0xd8,0x8e,0xc0,0xb8,0xa0,0x01,0xc1,0xe8,0x04,0x8e,0xd0,0x8d
+,0x26,0x80,0x00,0xe8,0x00,0x01,0xe8,0x10,0xeb,0x8b,0x1e,0xf7,0x34,0x8b,0x16,0xf9
+,0x34,0x8b,0x36,0xff,0x34,0x33,0xc0,0xb9,0xef,0xff,0x8d,0x3e,0x14,0x00,0x2b,0xcf
+,0x2b,0xce,0xd1,0xe9,0xf3,0xab,0x89,0x1e,0xf7,0x34,0x89,0x16,0xf9,0x34,0x83,0xfe
+,0x00,0x74,0x0c,0xb9,0xef,0xff,0xbf,0x80,0xfe,0x2b,0xcf,0xd1,0xe9,0xf3,0xab,0xb9
+,0xff,0xff,0x81,0xe9,0x00,0x3b,0x83,0xfe,0x00,0x74,0x03,0xe9,0x1b,0x00,0x51,0x1e
+,0xb8,0x00,0xe0,0x8e,0xd8,0x33,0xf6,0x8d,0x3e,0x00,0xd8,0xb9,0x00,0x0c,0xf3,0xa5
+,0x1f,0x59,0xbe,0xff,0xff,0x81,0xee,0x00,0xd8,0x2b,0xce,0x81,0xe1,0x00,0xff,0x89
+,0x0e,0xac,0x33,0x8d,0x06,0x20,0x02,0xc1,0xe8,0x04,0xa3,0x32,0x34,0x8e,0xd0,0x36
+,0xc7,0x06,0x1e,0x00,0x80,0x18,0x36,0xc7,0x06,0x22,0x00,0xff,0x7f,0x36,0xc7,0x06
+,0x0a,0x00,0xff,0xff,0x36,0xc7,0x06,0x1c,0x00,0x80,0x00,0x8d,0x06,0xa0,0x02,0xc1
+,0xe8,0x04,0xa3,0x30,0x34,0x8e,0xd0,0x36,0xc7,0x06,0x1e,0x00,0x50,0x28,0x36,0xc7
+,0x06,0x0a,0x00,0xff,0xff,0x36,0xc7,0x06,0x1c,0x00,0x80,0x00,0xb8,0xa0,0x01,0xc1
+,0xe8,0x04,0xa3,0x34,0x34,0xa3,0xf2,0x33,0x8e,0xd0,0x8d,0x26,0x80,0x00,0xb8,0x00
+,0x90,0xe7,0x02,0x8d,0x3e,0x70,0x01,0x8b,0xc7,0xc1,0xe8,0x04,0xb9,0x03,0x00,0x89
+,0x45,0x0e,0x89,0x45,0x02,0xc7,0x05,0xff,0xff,0x83,0xc7,0x10,0x05,0x01,0x00,0xe2
+,0xee,0xe8,0x5b,0x01,0xe5,0xce,0xa3,0xb5,0x36,0xe8,0x21,0x00,0xe8,0x45,0x01,0xa1
+,0x32,0x34,0x8c,0xcb,0xcd,0x37,0x0e,0x58,0xa9,0x00,0xf0,0x74,0x07,0x33,0xf6,0x89
+,0x36,0xff,0x34,0xc3,0x8d,0x36,0x30,0x61,0x89,0x36,0xff,0x34,0xc3,0x33,0xc0,0x8b
+,0xd0,0x8b,0xf2,0xb9,0x68,0x00,0x2e,0x80,0xbc,0xac,0x17,0x80,0x75,0x01,0xef,0x83
+,0xc2,0x02,0x46,0xe2,0xf1,0xb8,0x02,0x00,0xe7,0x50,0xb9,0x5a,0x00,0x33,0xff,0xc7
+,0x05,0x65,0x18,0x8c,0x4d,0x02,0x83,0xc7,0x04,0xe2,0xf4,0x33,0xc0,0x8e,0xc0,0x8c
+,0xc8,0x8e,0xd8,0x8d,0x3e,0x80,0x00,0x8d,0x36,0x9c,0x17,0xb9,0x08,0x00,0xe8,0x37
+,0x00,0x8d,0x36,0x20,0x21,0x8d,0x3e,0xc0,0x00,0xb9,0x0d,0x00,0xe8,0x29,0x00,0x8d
+,0x3e,0x40,0x01,0xb9,0x0a,0x00,0xe8,0x1f,0x00,0xe8,0x4b,0x0e,0x33,0xc0,0x8e,0xd8
+,0xc7,0x06,0x4e,0x37,0x6f,0x17,0xe7,0x48,0xe7,0x4c,0xb8,0x40,0x9c,0xe7,0x4a,0xe5
+,0x48,0x90,0xb8,0x00,0x70,0xe7,0x48,0xc3,0xa5,0x83,0xc7,0x02,0xe2,0xfa,0xc3,0xe5
+,0x4c,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe5,0x58,0xd1
+,0xe0,0x73,0x11,0x8b,0xf0,0xd1,0xe6,0x33,0xc0,0x8e,0xd8,0x8b,0xb4,0x80,0x00,0x83
+,0xc6,0x0b,0xff,0xe6,0x1f,0x07,0x5a,0x5f,0x5e,0x59,0x58,0xcf,0x58,0x1c,0xe4,0x1c
+,0x6c,0x1c,0x8e,0x1a,0xc0,0x1f,0x40,0x1a,0x44,0x1c,0x65,0x18,0x80,0x80,0x80,0xff
+,0x80,0x03,0x02,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0x80,0x03,0x03,0x43,0x80,0x80,0x02,0x80,0x42,0x03,0x02,0xff,0x03,0x01,0x03,0x01
+,0x01,0x03,0x02,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x02,0x03,0x01,0x03
+,0x03,0xff,0x01,0x01,0xff,0x01,0xff,0x01,0x01,0x03,0x03,0x03,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0x02,0xb8,0x0f,0x00,0xe7,0x84,0xb8,0x0f,0xf8,0xe7,0x82,0xc3,0xb9
+,0x08,0x00,0x89,0x0e,0xe6,0x3a,0x8d,0x06,0x20,0x03,0x8b,0xd0,0xc1,0xe8,0x04,0xa3
+,0x90,0x01,0x8b,0xc2,0x8b,0xd8,0xc1,0xe8,0x04,0x8e,0xc0,0x05,0x61,0x00,0x26,0xa3
+,0x00,0x00,0xa1,0x30,0x34,0x26,0xa3,0x02,0x00,0x83,0xc3,0x14,0xd1,0xeb,0x26,0x89
+,0x1e,0x08,0x00,0x81,0xc2,0x10,0x06,0xe2,0xd9,0x26,0xc7,0x06,0x00,0x00,0xff,0xff
+,0x8c,0x06,0x92,0x01,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8
+,0xe7,0x5a,0xff,0x06,0xbe,0x33,0xba,0xd2,0x00,0xed,0xcf,0x00,0x00,0x00,0x00,0x00
+,0x8c,0xcb,0xa1,0x30,0x34,0xcd,0x37,0xe9,0x06,0xed,0xb8,0x32,0x00,0xc3,0xe8,0x8c
+,0x01,0xfe,0x06,0xe2,0x34,0xe8,0x21,0x01,0x75,0xf0,0xe8,0x53,0x0e,0x81,0x0e,0xaf
+,0x36,0x00,0xc0,0xc7,0x06,0xad,0x36,0x60,0x00,0xf7,0x06,0xe6,0x34,0x80,0x00,0x75
+,0x1a,0xf7,0x06,0xe6,0x34,0x00,0x08,0x74,0x09,0xc7,0x06,0xab,0x36,0x0b,0x00,0xe9
+,0x0f,0x00,0xc7,0x06,0xab,0x36,0x03,0x00,0xe9,0x06,0x00,0xc7,0x06,0xab,0x36,0x11
+,0x9c,0xc7,0x06,0xa9,0x36,0x18,0x00,0xf7,0x06,0xe6,0x34,0x80,0x00,0x75,0x0d,0xf7
+,0x06,0xb5,0x36,0x02,0x00,0x74,0x05,0x83,0x0e,0xa9,0x36,0x20,0xa1,0xa9,0x36,0xe7
+,0x00,0xa1,0xab,0x36,0xe7,0x02,0xf7,0x06,0xe6,0x34,0x80,0x00,0x74,0x2e,0xe8,0xf2
+,0x2f,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56,0xa1,0xb1,0x36,0x0d,0x00,0x10,0xe7,0x08
+,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xb8,0x40,0x00,0xe7,0x4e,0x33
+,0xc0,0xe7,0x0e,0xc7,0x06,0x26,0x02,0x00,0x00,0xe9,0x23,0x00,0xc7,0x06,0x4e,0x37
+,0x3f,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x80,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x80,0xc6,0x06,0xe0,0x34,0x01,0xb8,0x00,0x00,0xc3,0xfe
+,0x06,0xe1,0x34,0xc6,0x06,0xe0,0x34,0x00,0xa1,0x26,0x02,0x0b,0xc0,0x74,0x01,0xc3
+,0xe8,0x04,0x00,0xb8,0x00,0x00,0xc3,0xa1,0xa9,0x36,0xe7,0x00,0x8b,0x1e,0xab,0x36
+,0x83,0xe3,0x06,0xe5,0x02,0x25,0xf9,0xff,0x0b,0xc3,0x0d,0x10,0x00,0xe7,0x02,0xa1
+,0xad,0x36,0xe7,0x04,0xc3,0xb8,0x0a,0x00,0xe7,0x84,0xfe,0x06,0xe5,0x34,0xc6,0x06
+,0xe3,0x34,0x01,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x40,0x74,0x07
+,0x26,0x81,0x0e,0x08,0x00,0x00,0x40,0xc3,0xc7,0x06,0x4e,0x37,0x6f,0x17,0xfe,0x06
+,0xe4,0x34,0xc6,0x06,0xe3,0x34,0x00,0xc3,0xc3,0xf6,0x06,0x18,0x34,0x80,0x75,0x0d
+,0xa1,0x18,0x34,0x0b,0x06,0x1a,0x34,0x0b,0x06,0x1c,0x34,0x75,0x01,0xc3,0xa1,0x2e
+,0x34,0x25,0xff,0xfe,0x8b,0x16,0xe7,0x36,0x81,0xe2,0x00,0x01,0x0b,0xc2,0xa3,0x2e
+,0x34,0x8d,0x16,0x10,0x00,0xbf,0x00,0x00,0xb9,0x08,0x00,0x8b,0x85,0x00,0x34,0xef
+,0x83,0xc2,0x10,0x8b,0x85,0x02,0x34,0xef,0x83,0xc2,0x10,0x8b,0x85,0x04,0x34,0xef
+,0x83,0xc2,0xe2,0x83,0xc7,0x06,0x49,0x75,0xe2,0xb8,0x00,0x00,0x8e,0xc0,0xbe,0x00
+,0x34,0xbf,0xb9,0x36,0xb9,0x18,0x00,0xf3,0xa5,0xb8,0x00,0x00,0xc3,0x33,0xc0,0x8e
+,0xc0,0x8d,0x3e,0xb0,0x33,0xb9,0x08,0x00,0xf3,0xab,0x8d,0x3e,0x3e,0x34,0xb9,0x03
+,0x00,0xf3,0xab,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xba
+,0x33,0xe5,0x56,0x0d,0x20,0x00,0xe7,0x56,0xba,0x7a,0x00,0xed,0x08,0x26,0x94,0x36
+,0x33,0xc0,0xb1,0x08,0x32,0xed,0x06,0x8e,0xc0,0x8d,0x3e,0xe0,0xff,0xf3,0xaa,0x8e
+,0x06,0x32,0x34,0x26,0x81,0x0e,0x08,0x00,0x00,0x02,0x07,0xe5,0x56,0x25,0xdf,0xff
+,0xe7,0x56,0xe9,0xf8,0xfc,0x00,0xbd,0x1b,0x10,0x1b,0xd9,0x1a,0xf3,0x1a,0x50,0x51
+,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb6,0x33,0x53
+,0x06,0x51,0xe5,0x80,0xa3,0xb4,0x33,0x8b,0xd8,0x8b,0xc8,0x25,0x10,0x00,0xa3,0xed
+,0x34,0x0b,0xc0,0x74,0x14,0xff,0x06,0x80,0x34,0x80,0x3e,0xfe,0x34,0x00,0x74,0x03
+,0xe9,0x06,0x00,0xb8,0x80,0x00,0xe8,0x9d,0x04,0x83,0xe3,0x03,0xd1,0xe3,0x2e,0xff
+,0x97,0x86,0x1a,0x59,0x07,0x5b,0xe9,0xa4,0xfc,0xba,0x20,0x00,0x8e,0x06,0x3c,0x34
+,0x83,0x3e,0x3c,0x34,0x00,0x75,0x03,0xe9,0xf0,0x00,0xc7,0x06,0x3c,0x34,0x00,0x00
+,0xe9,0x2a,0x00,0xba,0x10,0x00,0x8e,0x06,0x3a,0x34,0x83,0x3e,0x3a,0x34,0x00,0x75
+,0x03,0xe9,0xd5,0xff,0xc7,0x06,0x3a,0x34,0x00,0x00,0xe8,0x10,0x00,0xe9,0xc9,0xff
+,0xba,0x10,0x00,0x8e,0x06,0x3a,0x34,0xc7,0x06,0x3a,0x34,0x00,0x00,0x26,0xa1,0x14
+,0x00,0x26,0xa3,0x0c,0x00,0x26,0xa1,0x16,0x00,0x26,0xa3,0x0e,0x00,0x26,0xc6,0x06
+,0x0a,0x00,0x00,0xc1,0xea,0x02,0x23,0xd1,0x74,0x1c,0xba,0x20,0x00,0x26,0xc7,0x06
+,0x0e,0x00,0xea,0x05,0x26,0x0b,0x16,0x0c,0x00,0x26,0x89,0x16,0x0c,0x00,0xff,0x06
+,0x86,0x34,0xff,0x06,0xdc,0x33,0x26,0xa1,0x0c,0x00,0xa9,0x00,0x37,0x74,0x16,0x26
+,0xc6,0x06,0x0a,0x00,0x02,0xa9,0x00,0x30,0x74,0x04,0xff,0x06,0x7a,0x34,0xff,0x06
+,0xda,0x33,0xe9,0x49,0x00,0xc0,0xec,0x07,0x83,0x16,0x8a,0x34,0x00,0x24,0x07,0x3c
+,0x07,0x75,0x04,0xff,0x06,0x8c,0x34,0xff,0x06,0x7e,0x34,0xa1,0x30,0x34,0x8c,0xc3
+,0x8e,0xc0,0x8e,0xdb,0x26,0x83,0x0e,0x08,0x00,0x40,0x8c,0xd8,0x26,0x87,0x06,0x16
+,0x00,0x26,0x83,0x3e,0x14,0x00,0xff,0x74,0x0a,0x8e,0xc0,0x26,0x8c,0x1e,0x00,0x00
+,0xe9,0x05,0x00,0x26,0x8c,0x1e,0x14,0x00,0x33,0xc0,0x8e,0xd8,0xc3,0xc3,0x8c,0xc0
+,0x87,0x06,0x92,0x01,0x3d,0xff,0xff,0x74,0x0d,0x8e,0xd8,0x8c,0x06,0x00,0x00,0x33
+,0xc0,0x8e,0xd8,0xe9,0x04,0x00,0x8c,0x06,0x90,0x01,0xe8,0x01,0x00,0xc3,0x06,0x83
+,0x3e,0x90,0x01,0xff,0x74,0x29,0x83,0x3e,0x3a,0x34,0x00,0x75,0x11,0xba,0x86,0x00
+,0xe8,0x1e,0x00,0x8c,0x06,0x3a,0x34,0x83,0x3e,0x90,0x01,0xff,0x74,0x11,0x83,0x3e
+,0x3c,0x34,0x00,0x75,0x0a,0xba,0x88,0x00,0xe8,0x06,0x00,0x8c,0x06,0x3c,0x34,0x07
+,0xc3,0xa1,0x90,0x01,0x8e,0xc0,0x26,0xa1,0x08,0x00,0xef,0x26,0xa1,0x00,0x00,0x26
+,0xc7,0x06,0x00,0x00,0xff,0xff,0xa3,0x90,0x01,0x3d,0xff,0xff,0x75,0x03,0xa3,0x92
+,0x01,0x83,0x3e,0xed,0x34,0x00,0x74,0x0b,0xb8,0x10,0x00,0xe7,0x84,0xc7,0x06,0xed
+,0x34,0x00,0x00,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7
+,0x5a,0xff,0x06,0xbc,0x33,0xe9,0x25,0xfb,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33
+,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb0,0x33,0xe9,0x11,0xfb,0x50,0x51,0x56,0x57
+,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb4,0x33,0x06,0xff,0x06
+,0x76,0x34,0x80,0x3e,0xfe,0x34,0x00,0x74,0x04,0x07,0xe9,0xf0,0xfa,0xb8,0x80,0x00
+,0xe8,0xd3,0x02,0x07,0xe9,0xe6,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xc6,0x1d,0x08,0x1d,0x91,0x1e,0x5d,0x1e,0x73,0x1e,0x89,0x1e,0x91,0x1e,0xa8,0x1d
+,0x91,0x1e,0x91,0x1e,0xaf,0x1e,0xaf,0x1e,0x15,0x1d,0x15,0x1d,0x91,0x1e,0x99,0x1f
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00
+,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00
+,0x07,0xe9,0x99,0xfa,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7
+,0x5a,0xff,0x06,0xb2,0x33,0x06,0x68,0xf6,0x1c,0xe5,0x06,0xa3,0xb2,0x33,0x8b,0xf0
+,0x83,0xe6,0x1e,0x2e,0xff,0xa4,0xa0,0x1c,0xe5,0x0c,0xa9,0x80,0x00,0x74,0x06,0xe8
+,0xa4,0x01,0xe5,0x06,0xc3,0x53,0xe5,0x0c,0x8b,0xd8,0xa9,0x01,0x00,0x74,0x14,0x83
+,0x3e,0xe0,0x3a,0x00,0x74,0x0d,0x8e,0x06,0x38,0x34,0xe8,0xbf,0x06,0xc7,0x06,0xe0
+,0x3a,0x00,0x00,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7
+,0x02,0x8b,0xc3,0x5b,0xa9,0x01,0x00,0x74,0x01,0xc3,0x8b,0xd0,0xb8,0x00,0x08,0xe7
+,0x84,0x8b,0xc2,0x8e,0x06,0x38,0x34,0x26,0xa3,0x0c,0x00,0x8b,0xd0,0xc1,0xe0,0x03
+,0x83,0x16,0x88,0x34,0x00,0xff,0x06,0x7c,0x34,0x26,0x83,0x3e,0x06,0x00,0x0a,0x75
+,0x21,0x8b,0xc2,0x25,0x40,0x18,0x3d,0x40,0x00,0x74,0x0c,0x3d,0x00,0x10,0x75,0x12
+,0x26,0xfe,0x0e,0x0a,0x00,0x74,0x0b,0xf7,0x06,0xef,0x34,0x20,0x00,0x75,0x03,0xe9
+,0x5a,0x06,0x8c,0xc0,0x26,0x8e,0x06,0x02,0x00,0x26,0x83,0x0e,0x08,0x00,0x20,0x26
+,0xa3,0x12,0x00,0x26,0xa3,0x10,0x00,0xc3,0xff,0x06,0xc4,0x33,0xe5,0x0c,0xa9,0x01
+,0x00,0x75,0x01,0xc3,0xa9,0xf0,0x07,0x74,0x01,0xc3,0xff,0x06,0xd4,0x33,0xe5,0x00
+,0x0d,0x18,0x00,0xe7,0x00,0xc3,0xff,0x06,0xca,0x33,0x80,0x3e,0xa0,0x36,0x08,0x75
+,0x14,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x08,0x74,0x07,0x26,0x81
+,0x0e,0x08,0x00,0x00,0x08,0xe5,0x82,0x25,0xfd,0xff,0xe7,0x82,0xe5,0x0c,0x50,0xe5
+,0x80,0x25,0x00,0x07,0xa3,0xe4,0x3a,0xe5,0x8c,0x25,0x00,0x80,0xa3,0xe2,0x3a,0x58
+,0xa9,0x02,0x00,0x75,0x25,0x83,0x3e,0xe2,0x3a,0x00,0x75,0x1e,0x83,0x3e,0xe4,0x3a
+,0x00,0x75,0x17,0xe5,0x08,0x0d,0x00,0x04,0x25,0xff,0x04,0xe7,0x08,0xe8,0x6a,0x01
+,0xe5,0x82,0x0d,0x02,0x00,0xe7,0x82,0xe9,0x21,0x00,0xe8,0x1a,0x06,0x80,0x3e,0xe8
+,0xff,0x00,0x74,0x0a,0x80,0x3e,0xe8,0xff,0x04,0x74,0x03,0xe9,0x0d,0x00,0xc6,0x06
+,0xe8,0xff,0x01,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0x80,0x3e,0x9f,0x36,0x06
+,0x75,0x05,0x83,0x0e,0x99,0x36,0x40,0xb8,0x00,0x01,0xe9,0x09,0x01,0xff,0x06,0xcc
+,0x33,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36,0xe7,0x06,0xff,0x06,0xc6,0x34
+,0xe9,0x1e,0x00,0xff,0x06,0xce,0x33,0xff,0x06,0x95,0x37,0x81,0x26,0xaf,0x36,0xff
+,0xef,0xa1,0xaf,0x36,0xe7,0x06,0xe9,0x08,0x00,0xff,0x06,0xd0,0x33,0xff,0x06,0x7a
+,0x34,0xff,0x06,0xd2,0x33,0xd1,0xe6,0x8e,0x06,0x30,0x34,0x2e,0x8b,0x84,0xc0,0x1c
+,0x26,0x09,0x06,0x08,0x00,0x2e,0x8b,0x84,0xc2,0x1c,0x09,0x06,0x66,0x37,0xc3,0xe5
+,0x0c,0xa9,0x80,0x00,0x74,0x56,0x50,0xe8,0xf0,0x00,0x58,0xa9,0x00,0x01,0x75,0x07
+,0xff,0x06,0xc6,0x33,0xe9,0x08,0x00,0xff,0x06,0x78,0x34,0xff,0x06,0xc8,0x33,0xe5
+,0x82,0x25,0xfd,0xff,0xe7,0x82,0xe8,0x6e,0x05,0xba,0x10,0x01,0xed,0x80,0x3e,0xe8
+,0xff,0x00,0x74,0x0a,0x80,0x3e,0xe8,0xff,0x04,0x74,0x03,0xe9,0x1d,0x00,0xc6,0x06
+,0xe8,0xff,0x01,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0xe9,0x0d,0x00,0xc6,0x06
+,0xe8,0xff,0x03,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0xc3,0xa9,0x01,0x00,0x74
+,0x1c,0xe8,0x2c,0x00,0x83,0x3e,0xe0,0x3a,0x00,0x74,0x0f,0x06,0x8e,0x06,0x38,0x34
+,0xe8,0xc9,0x04,0xc7,0x06,0xe0,0x3a,0x00,0x00,0x07,0xe9,0x5d,0x00,0x8b,0xd0,0x8e
+,0x06,0x38,0x34,0x26,0xa3,0x0c,0x00,0xe8,0x06,0x00,0x68,0x69,0x1d,0xe9,0x4a,0x00
+,0xa9,0x00,0x04,0x74,0x0a,0xb8,0x00,0x04,0xff,0x06,0xd8,0x33,0xe9,0x17,0x00,0xa9
+,0x00,0x01,0x74,0x0a,0xff,0x06,0x39,0x37,0xb8,0x00,0x01,0xe9,0x08,0x00,0xa9,0x10
+,0x00,0xb8,0x10,0x00,0x74,0x1d,0x09,0x06,0x66,0x37,0x8c,0xc0,0x8e,0x06,0x30,0x34
+,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x01
+,0x8e,0xc0,0xc3,0xff,0x06,0xc2,0x33,0xe9,0xf8,0xff,0xe5,0x00,0x0d,0x18,0x00,0xe7
+,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7,0x02,0xc3,0x58,0xe9,0x43,0xfd,0xe5,0x08,0x0d
+,0x00,0x04,0x25,0xff,0x04,0xe7,0x08,0xe9,0xe0,0xff,0xe5,0x0e,0xa9,0x00,0x08,0x75
+,0x01,0xc3,0xe9,0xf5,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb8
+,0x33,0xe5,0x48,0x06,0x53,0x57,0xff,0x16,0x4e,0x37,0x5f,0x5b,0x83,0x3e,0x80,0x01
+,0xff,0x74,0x58,0x8e,0x06,0x80,0x01,0x26,0xff,0x0e,0x08,0x00,0x75,0x4d,0x26,0xa1
+,0x00,0x00,0xa3,0x80,0x01,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x8c,0xc0,0x26,0x8e
+,0x06,0x02,0x00,0x26,0x81,0x0e,0x08,0x00,0x80,0x00,0x8b,0xd0,0x26,0x87,0x06,0x1a
+,0x00,0x26,0x83,0x3e,0x18,0x00,0xff,0x74,0x0a,0x8e,0xc0,0x26,0x89,0x16,0x00,0x00
+,0xe9,0x05,0x00,0x26,0x89,0x16,0x18,0x00,0x83,0x3e,0x80,0x01,0xff,0x74,0x0c,0x8e
+,0x06,0x80,0x01,0x26,0x83,0x3e,0x08,0x00,0x00,0x74,0xb3,0x07,0xe9,0x3e,0xf7,0xe5
+,0x4c,0x90,0xe5,0x02,0xa9,0x00,0x20,0x74,0x0d,0x25,0xff,0xdf,0x0d,0x01,0x00,0xe7
+,0x02,0x0d,0x00,0x20,0xe7,0x02,0xe5,0x0a,0x8b,0xd8,0xa3,0xf4,0x33,0x25,0xc3,0x57
+,0x0d,0x00,0x10,0xe7,0x0a,0xf7,0x06,0x9b,0x36,0x00,0x80,0x74,0x37,0xf7,0xc3,0x00
+,0x80,0x74,0x06,0xf7,0xc3,0x00,0x08,0x74,0x5d,0x81,0x26,0xc2,0x34,0x7f,0xff,0xc7
+,0x06,0x35,0x37,0x05,0x00,0xb8,0x80,0x03,0xcd,0x39,0x81,0x26,0x9b,0x36,0xff,0x7f
+,0xc7,0x06,0x0f,0x37,0x04,0x00,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06
+,0x0f,0x37,0x03,0x00,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x2a,0xf7,0xc3,0x00,0x08
+,0x74,0x24,0x80,0x3e,0x9d,0x36,0x06,0x7c,0x1d,0xff,0x06,0x94,0x34,0x83,0x0e,0x66
+,0x37,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x01,0xf7,0xc3,0x00,0x20,0x75,0x3b,0xf7,0x06,0x9a,0x37
+,0x80,0x00,0x74,0x0b,0xff,0x06,0x89,0x37,0x33,0xc0,0xe7,0x0e,0xe9,0x04,0x00,0xff
+,0x06,0x3b,0x37,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x1c,0x80,0x26,0x9e,0x36,0xff
+,0x75,0x15,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x08,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x08,0xc3,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x02,0x23,0x02,0x23,0x02,0x23,0x02,0x23,0x03,0x23,0xdd,0x22,0x02,0x23,0xfd,0x21
+,0x02,0x23,0xa4,0x24,0xf3,0x24,0x02,0x23,0x8d,0x22,0x7a,0x23,0x02,0x23,0x97,0x24
+,0x1b,0x24,0x75,0x24,0x02,0x23,0x02,0x23,0x8e,0x25,0xfb,0x8e,0x06,0x7e,0x01,0xfb
+,0x26,0x83,0x3e,0x00,0x00,0xff,0x74,0xf2,0x26,0x8e,0x06,0x00,0x00,0xfa,0x26,0x8b
+,0x1e,0x08,0x00,0x26,0x23,0x1e,0x0a,0x00,0x74,0xe5,0x8c,0xc0,0x8e,0xd0,0x26,0x8b
+,0x26,0x02,0x00,0x8c,0x16,0xf2,0x33,0x22,0xff,0x75,0x6a,0x26,0xa1,0x1c,0x00,0x8a
+,0xe3,0x8a,0xdc,0x22,0xd8,0x75,0x0d,0xd0,0xe8,0x24,0xf8,0x0a,0xc0,0x75,0xf2,0xb0
+,0x80,0xe9,0xed,0xff,0xd0,0xe8,0x24,0xf8,0x0a,0xc0,0x75,0x02,0xb0,0x80,0x32,0xe4
+,0x26,0xa3,0x1c,0x00,0xf7,0xc3,0x08,0x00,0x75,0x47,0x2e,0x8a,0x9f,0xc5,0x25,0x2e
+,0x8b,0xbf,0xc5,0x26,0x80,0xc3,0x10,0x26,0x8e,0x1d,0x26,0x8c,0x1e,0x06,0x00,0x8b
+,0x16,0x00,0x00,0xc7,0x06,0x00,0x00,0xff,0xff,0x26,0x89,0x15,0x83,0xfa,0xff,0x75
+,0x0a,0x2e,0x8b,0x97,0xcd,0x26,0x26,0x21,0x16,0x08,0x00,0x33,0xc0,0x8e,0xd8,0x26
+,0x89,0x1e,0x04,0x00,0xc3,0x8a,0xdf,0xb7,0x00,0x2e,0x8a,0x9f,0xc5,0x25,0xe9,0xe0
+,0xff,0x26,0x83,0x26,0x08,0x00,0xf7,0x83,0xc3,0x10,0xe9,0xde,0xff,0x60,0x06,0x1e
+,0x68,0x87,0x25,0x6a,0x00,0x1f,0x8e,0x06,0xf2,0x33,0x8b,0x0e,0x34,0x34,0x39,0x0e
+,0xf2,0x33,0x74,0x0e,0x26,0x81,0x0e,0x0a,0x00,0x00,0x02,0x26,0x81,0x0e,0x08,0x00
+,0x00,0x02,0x26,0x89,0x26,0x02,0x00,0xa3,0xf2,0x33,0x8e,0xd0,0x8d,0x26,0x80,0x00
+,0x36,0x89,0x26,0x02,0x00,0x36,0x89,0x1e,0x20,0x00,0x36,0xc7,0x06,0x08,0x00,0x00
+,0x00,0xb9,0x04,0x00,0xbe,0x00,0x00,0x2e,0x8b,0xbc,0xc5,0x26,0x36,0xc7,0x05,0xff
+,0xff,0x36,0xc7,0x45,0x02,0xff,0xff,0x83,0xc6,0x02,0xe2,0xeb,0x8e,0x06,0x7e,0x01
+,0x36,0x8b,0x0e,0x22,0x00,0x8c,0xc0,0x26,0x83,0x3e,0x00,0x00,0xff,0x26,0x8e,0x06
+,0x00,0x00,0x74,0x07,0x26,0x3b,0x0e,0x22,0x00,0x7d,0xea,0x36,0x8c,0x06,0x00,0x00
+,0x8e,0xc0,0x26,0x8c,0x16,0x00,0x00,0xfb,0x36,0xff,0x2e,0x1e,0x00,0x06,0x1e,0x68
+,0x8b,0x25,0x6a,0x00,0x1f,0x26,0x09,0x36,0x08,0x00,0xf7,0xc6,0x00,0xff,0x74,0x01
+,0xc3,0x56,0x52,0x2e,0x8b,0xb4,0xc5,0x25,0x81,0xe6,0xff,0x00,0x2e,0x8b,0xb4,0xc5
+,0x26,0x8c,0xc2,0x8e,0xc0,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x8e,0xc2,0x26,0x83
+,0x3c,0xff,0x74,0x0f,0x8b,0xd0,0x26,0x87,0x54,0x02,0x8e,0xc2,0x26,0xa3,0x00,0x00
+,0xe9,0x07,0x00,0x26,0x89,0x44,0x02,0x26,0x89,0x04,0x5a,0x5e,0xc3,0x06,0x1e,0x68
+,0x8b,0x25,0x6a,0x00,0x1f,0x8e,0x06,0xf2,0x33,0x26,0xa3,0x0a,0x00,0x26,0x89,0x26
+,0x02,0x00,0xa1,0x34,0x34,0x8e,0xd0,0x8d,0x26,0x80,0x00,0x8c,0x16,0xf2,0x33,0xe9
+,0x4d,0xfe,0xcf,0x50,0x1e,0x52,0x53,0x33,0xc0,0x8e,0xd8,0x26,0x83,0x3e,0x04,0x00
+,0xff,0x26,0xc7,0x06,0x04,0x00,0x00,0x00,0x74,0x03,0xe9,0x1a,0x00,0x83,0x3e,0xe6
+,0x3a,0x02,0x76,0x13,0xff,0x06,0xd6,0x33,0x8c,0xc0,0x8e,0x06,0x32,0x34,0xbe,0x40
+,0x00,0x68,0x3a,0x23,0xe9,0x5e,0xff,0xe8,0x84,0xf8,0x5b,0x5a,0x1f,0x58,0xcf,0xe8
+,0xe1,0x00,0x26,0xc6,0x06,0x18,0x00,0x10,0x26,0x8a,0x1e,0x29,0x00,0x88,0x1e,0x1b
+,0x37,0x26,0xc7,0x06,0x0c,0x00,0xff,0x7f,0x26,0xa1,0x0e,0x00,0xe7,0x9c,0x26,0xa1
+,0x08,0x00,0xe7,0x9a,0xe5,0x00,0x80,0xfb,0x08,0x74,0x09,0x0d,0x18,0xac,0xe7,0x00
+,0x07,0x1f,0x58,0xcf,0x0d,0x18,0x00,0xe9,0xf4,0xff,0x50,0x1e,0x06,0x33,0xc0,0x8e
+,0xd8,0x83,0x3e,0xa1,0x36,0x00,0x75,0xb7,0x26,0x8b,0x36,0x06,0x00,0x2e,0xff,0x94
+,0xdc,0x23,0x07,0x1f,0x58,0xcf,0xe8,0x8a,0x00,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00
+,0xe8,0x49,0x00,0xc3,0x53,0xf7,0x06,0xef,0x34,0x20,0x00,0x75,0x2d,0xe5,0x8c,0x25
+,0x00,0x70,0x8b,0xd8,0xe5,0x8c,0x25,0x00,0x70,0x3b,0xc3,0x74,0x05,0x8b,0xd8,0xe9
+,0xf2,0xff,0x3d,0x00,0x30,0x75,0x10,0xe5,0x02,0x25,0xef,0xff,0xe7,0x02,0xc7,0x06
+,0xe0,0x3a,0xff,0xff,0xe9,0x03,0x00,0xe8,0x12,0x00,0x5b,0xc3,0xa3,0x23,0x96,0x23
+,0xa4,0x23,0xa4,0x23,0x96,0x23,0xa4,0x23,0x96,0x23,0x96,0x23,0x26,0xa0,0x29,0x00
+,0xa2,0x1b,0x37,0x26,0xc7,0x06,0x0c,0x00,0xff,0x7f,0x26,0xa1,0x0e,0x00,0xe7,0x9c
+,0x26,0xa1,0x08,0x00,0xe7,0x9a,0xe5,0x00,0x25,0xff,0x53,0x26,0x8b,0x36,0x06,0x00
+,0x83,0xe6,0x0e,0x2e,0x0b,0x84,0xad,0x25,0xe7,0x00,0xc3,0x06,0x1e,0x68,0x8b,0x25
+,0x6a,0x00,0x1f,0x83,0x0e,0xef,0x34,0x20,0x83,0x0e,0x9b,0x36,0x08,0xe5,0x00,0x25
+,0xef,0xff,0x0d,0x08,0x00,0xe7,0x00,0xe5,0x00,0xa9,0x10,0x00,0x75,0x01,0xc3,0xe5
+,0x00,0xa9,0x10,0x00,0x75,0xf9,0xc3,0x50,0x53,0x51,0x56,0x06,0x1e,0x33,0xc0,0x8e
+,0xd8,0xb8,0x05,0x00,0xe7,0x84,0xe5,0x08,0x0d,0x00,0x04,0x25,0xff,0x04,0xe7,0x08
+,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7,0x02,0x1f,0x07
+,0x5e,0x59,0x5b,0x58,0xc3,0x50,0x1e,0x33,0xc0,0x8e,0xd8,0xc7,0x06,0xef,0x34,0x00
+,0x00,0x83,0x26,0x9b,0x36,0xf7,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d
+,0x11,0x00,0xe7,0x02,0x1f,0x58,0xcf,0x60,0x06,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f
+,0xe8,0x16,0xf5,0xc3,0x06,0x1e,0x68,0x8b,0x25,0x6a,0x00,0x1f,0x8e,0xc0,0x26,0x83
+,0x3e,0x0a,0x00,0x00,0x74,0x03,0xe8,0x43,0x00,0x26,0xc7,0x06,0x0a,0x00,0xff,0xff
+,0x26,0x8b,0x16,0x06,0x00,0x8e,0x1e,0x8e,0x01,0x8c,0xd8,0x8b,0xca,0x83,0x3e,0x00
+,0x00,0xff,0x8e,0x1e,0x00,0x00,0x74,0x0a,0x2b,0x16,0x08,0x00,0x73,0xeb,0x29,0x0e
+,0x08,0x00,0x26,0x89,0x0e,0x08,0x00,0x26,0x8c,0x1e,0x00,0x00,0x8e,0xd8,0x8c,0x06
+,0x00,0x00,0xc3,0x60,0x06,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f,0x8e,0xc0,0x8b,0xc8
+,0x8e,0x1e,0x8e,0x01,0x26,0xc7,0x06,0x0a,0x00,0x00,0x00,0x8c,0xd8,0x83,0x3e,0x00
+,0x00,0xff,0x74,0x25,0x3b,0x0e,0x00,0x00,0x8e,0x1e,0x00,0x00,0x75,0xed,0x8e,0xd8
+,0x26,0xa1,0x00,0x00,0xa3,0x00,0x00,0x3d,0xff,0xff,0x74,0x56,0x8e,0xd8,0x26,0xa1
+,0x08,0x00,0x01,0x06,0x08,0x00,0xe9,0x49,0x00,0x26,0x8e,0x1e,0x02,0x00,0xbe,0x18
+,0x00,0x83,0x3c,0xff,0x74,0x3c,0x39,0x0c,0x74,0x19,0x8e,0x1c,0xbe,0x00,0x00,0x83
+,0x3e,0x00,0x00,0xff,0x74,0x2c,0x39,0x0e,0x00,0x00,0x74,0x07,0x8e,0x1e,0x00,0x00
+,0xe9,0xec,0xff,0x26,0xa1,0x00,0x00,0x89,0x04,0x33,0xc9,0x8e,0xd9,0x3d,0xff,0xff
+,0x75,0x10,0x83,0xfe,0x18,0x75,0x0b,0x26,0x8e,0x1e,0x02,0x00,0x81,0x26,0x08,0x00
+,0x7f,0xff,0x33,0xc0,0x8e,0xd8,0xc3,0x1f,0x07,0x61,0xcf,0x1f,0x07,0xcf,0x60,0x06
+,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f,0xe5,0x06,0x25,0x1e,0x00,0x3d,0x1e,0x00,0x75
+,0xf6,0xb9,0x08,0x00,0xe5,0x58,0xe7,0x5a,0x23,0xc0,0xe0,0xf8,0xc3,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0xa8,0x00,0x8c,0x02,0x04,0x00
+,0x00,0x08,0x10,0x20,0x00,0xff,0x0e,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08
+,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06
+,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+,0x04,0x04,0x04,0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x14,0x00,0x10,0x00,0x0c,0x00,0xff,0x7f,0xff
+,0xbf,0xff,0xdf,0xff,0xef,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0x7f,0xff,0xbf
+,0xff,0xdf,0xff,0xef,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0xff,0x00,0x00,0x00
+,0x80,0x3e,0xe2,0x34,0x01,0x76,0x03,0xe9,0xa5,0x00,0xb8,0x00,0x00,0xe7,0x4e,0xb9
+,0x28,0x00,0xe2,0xfe,0xc6,0x06,0x45,0x37,0x02,0xbf,0x3f,0x28,0x2e,0x8b,0x45,0x08
+,0xe7,0x4e,0xb9,0x28,0x00,0xe2,0xfe,0x2e,0x8b,0x1d,0xc7,0x06,0xb3,0x36,0x40,0x11
+,0xc7,0x06,0xb1,0x36,0x27,0x00,0xc7,0x06,0x46,0x37,0x02,0x00,0xc7,0x06,0x48,0x37
+,0x64,0x00,0xf7,0x06,0xb5,0x36,0x02,0x00,0x75,0x1c,0x2e,0x0b,0x5d,0x02,0x81,0x26
+,0xb3,0x36,0xff,0xfe,0xc7,0x06,0xb1,0x36,0x9c,0x00,0xc7,0x06,0x46,0x37,0x08,0x00
+,0xc7,0x06,0x48,0x37,0x90,0x01,0x89,0x1e,0xb7,0x36,0x89,0x1e,0xfe,0x33,0xbe,0x20
+,0x00,0x8b,0xc3,0xe7,0x4e,0xb9,0x28,0x00,0xe2,0xfe,0x2e,0x8b,0x45,0x04,0xe7,0x4e
+,0xb9,0x28,0x00,0xe2,0xfe,0xe5,0x4e,0x8b,0xcb,0x2e,0x23,0x45,0x06,0x2e,0x23,0x4d
+,0x06,0x3a,0xc1,0x74,0x36,0x4e,0x75,0xd9,0x80,0x3e,0x45,0x37,0x00,0x74,0x0b,0xc6
+,0x06,0x45,0x37,0x00,0xbf,0x2f,0x28,0xe9,0x72,0xff,0xc6,0x06,0x45,0x37,0x01,0xf7
+,0x06,0xb5,0x36,0x02,0x00,0x74,0x14,0xe5,0xce,0x25,0xfd,0xff,0xe7,0xce,0xe8,0x43
+,0x00,0xe5,0xce,0x0d,0x02,0x00,0xe7,0xce,0xe8,0x39,0x00,0x80,0x3e,0xe2,0x34,0x01
+,0x76,0x01,0xc3,0xb8,0xea,0x05,0xe7,0x8c,0xfa,0xe8,0x12,0xf4,0xfb,0x8d,0x06,0xd0
+,0x39,0x8b,0xd8,0xc1,0xe8,0x04,0xa3,0x38,0x34,0x8e,0xc0,0xa1,0x30,0x34,0x26,0xa3
+,0x02,0x00,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x83,0xc3,0x18,0xd1,0xeb,0x26,0x89
+,0x1e,0x08,0x00,0xc3,0xe5,0x02,0x0d,0x00,0x40,0xe7,0x02,0xe5,0x00,0x0d,0x04,0x00
+,0xe7,0x00,0xb8,0x00,0x00,0xe7,0x0a,0xe5,0x0a,0xa9,0x00,0x80,0x75,0x14,0xe5,0x08
+,0x0d,0x00,0x10,0xe7,0x08,0xe5,0x0a,0x0d,0x00,0x08,0xb9,0x05,0x00,0xe7,0x0a,0xe2
+,0xfc,0xc3,0xe5,0x08,0x0d,0x00,0x10,0xb9,0x05,0x00,0xe7,0x08,0xe2,0xfc,0xc3,0x04
+,0x0c,0x20,0x00,0x01,0x0c,0x7e,0xff,0x00,0x0c,0x02,0x00,0x10,0x00,0x40,0x00,0x0c
+,0xc6,0x01,0x00,0x00,0xc0,0xf7,0xff,0x00,0xc0,0x02,0x00,0x10,0x00,0x40,0x00,0x00
+,0x33,0xc0,0x8e,0xd8,0x8d,0x3e,0x72,0x49,0x8d,0x36,0xb0,0x37,0xb9,0x14,0x00,0x8b
+,0x1e,0x30,0x34,0x89,0x5c,0x02,0x2e,0x8b,0x45,0x02,0x89,0x44,0x06,0x2e,0x8b,0x05
+,0x89,0x44,0x04,0x83,0xc7,0x04,0x83,0xc6,0x10,0xe2,0xe8,0xc6,0x06,0x9e,0x36,0x0e
+,0xe8,0xfd,0x26,0x68,0x83,0x28,0xa1,0xaa,0x02,0xcd,0x35,0x83,0x3e,0xa1,0x36,0x00
+,0x74,0x03,0xe9,0x3b,0x27,0x33,0xff,0x8e,0x06,0xa6,0x02,0x8b,0x36,0xa4,0x02,0x2e
+,0xff,0xa4,0x2e,0x30,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37,0x37,0x01,0x00,0xc6
+,0x06,0xca,0x34,0x01,0xe9,0x7d,0x19,0x80,0x3e,0xa0,0x36,0x08,0x74,0xe6,0x80,0x26
+,0x9e,0x36,0xff,0x75,0x1a,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x12,0xf7,0x06,0x9b
+,0x36,0x03,0x00,0x75,0x0a,0x83,0x0e,0x66,0x37,0x10,0xc6,0x06,0xa0,0x36,0x08,0xe9
+,0xfb,0x01,0x80,0x3e,0x9e,0x36,0x02,0x75,0xce,0xc6,0x06,0xa0,0x36,0x06,0xe9,0xec
+,0x01,0xc3,0xe9,0xe8,0x01,0x26,0xc7,0x06,0x0a,0x00,0x00,0x00,0x26,0xff,0x26,0x04
+,0x00,0xa1,0xd1,0x36,0x26,0x39,0x06,0x1a,0x00,0x75,0x22,0xa1,0xd3,0x36,0x26,0x39
+,0x06,0x1c,0x00,0x75,0x18,0xa1,0xd5,0x36,0x26,0x39,0x06,0x1e,0x00,0x75,0x0e,0x26
+,0xf7,0x06,0x0c,0x00,0x40,0x00,0x74,0x05,0x83,0x0e,0x66,0x37,0x40,0x81,0x0e,0xaf
+,0x36,0x00,0x10,0xa1,0xaf,0x36,0xe7,0x06,0x80,0x3e,0x9d,0x36,0x02,0x75,0x06,0xcd
+,0x34,0xe9,0xa2,0x1a,0xc3,0xf7,0x06,0x9b,0x36,0x10,0x00,0x75,0x54,0x26,0xf6,0x06
+,0x0a,0x00,0xff,0x75,0x4c,0x26,0xa0,0x19,0x00,0x24,0xc0,0x3c,0x40,0x75,0x11,0x80
+,0x3e,0x95,0x36,0x00,0x74,0x3b,0x26,0xc7,0x06,0x04,0x00,0xff,0xff,0xe9,0x31,0x00
+,0xe8,0xf1,0x04,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74,0x2f,0x8b,0xd8,0xb8,0x7d,0x03
+,0xcd,0x3a,0x8b,0xc3,0xc6,0x06,0xa0,0x36,0x06,0xf7,0x06,0x9b,0x36,0x02,0x00,0x75
+,0x05,0xc6,0x06,0xa0,0x36,0x04,0x81,0x0e,0x9b,0x36,0x80,0x00,0x83,0x26,0x9b,0x36
+,0xfc,0xe9,0x23,0x01,0xe8,0x87,0x1d,0xe9,0x33,0x01,0x50,0x26,0xa1,0x0c,0x00,0x25
+,0x07,0x00,0x3d,0x07,0x00,0x75,0x03,0xe9,0x84,0x00,0x3d,0x05,0x00,0x75,0x03,0xe9
+,0x7c,0x00,0x83,0x3e,0xe8,0x3a,0x04,0x74,0x75,0x83,0x3e,0xe8,0x3a,0x02,0x74,0x6e
+,0xf7,0x06,0xe6,0x34,0x18,0x80,0x75,0x03,0xe9,0x6a,0x00,0xf7,0x06,0xe6,0x34,0x00
+,0x80,0x74,0x35,0x26,0x80,0x3e,0x29,0x00,0x02,0x75,0x2d,0x51,0x56,0x57,0x8d,0x36
+,0x3e,0x34,0x8d,0x3e,0x20,0x00,0xb9,0x06,0x00,0xf3,0xa6,0x5f,0x5e,0x59,0x74,0x45
+,0x26,0xa1,0x20,0x00,0xa3,0x3e,0x34,0x26,0xa1,0x22,0x00,0xa3,0x40,0x34,0x26,0xa1
+,0x24,0x00,0xa3,0x42,0x34,0xe9,0x26,0x00,0xf7,0x06,0xe6,0x34,0x08,0x00,0x74,0x0b
+,0x26,0x80,0x3e,0x19,0x00,0x00,0x74,0x03,0xe9,0x13,0x00,0xf7,0x06,0xe6,0x34,0x10
+,0x00,0x74,0x12,0x26,0xa0,0x28,0x00,0xc0,0xe8,0x04,0x22,0xc0,0x74,0x07,0x26,0xc7
+,0x06,0x04,0x00,0xff,0xff,0x58,0x23,0xc0,0x74,0x03,0xe9,0x57,0xff,0x81,0x26,0x9b
+,0x36,0xff,0xfe,0x83,0xfe,0x06,0x7f,0x24,0x26,0xa1,0x20,0x00,0x3b,0x06,0xd1,0x36
+,0x75,0x1a,0x26,0xa1,0x22,0x00,0x3b,0x06,0xd3,0x36,0x75,0x10,0x26,0xa1,0x24,0x00
+,0x3b,0x06,0xd5,0x36,0x75,0x06,0x81,0x0e,0x9b,0x36,0x00,0x01,0x26,0xa1,0x20,0x00
+,0x25,0x7f,0xff,0xa3,0xb8,0x34,0x26,0xa1,0x22,0x00,0xa3,0xba,0x34,0x26,0xa1,0x24
+,0x00,0xa3,0xbc,0x34,0x8b,0xc6,0x86,0xc4,0xa3,0xc0,0x34,0xd1,0xe6,0x80,0xfc,0x09
+,0x74,0x03,0xe8,0xaa,0x1c,0x8b,0xc6,0x2e,0xff,0xa4,0x30,0x49,0x26,0xa1,0x0c,0x00
+,0x3d,0xff,0x7f,0x74,0x0f,0x26,0xff,0x26,0x04,0x00,0x8e,0x06,0x38,0x34,0xe8,0x36
+,0x06,0xcd,0x50,0xc3,0xe9,0x16,0x00,0xcd,0x34,0xe9,0x11,0x00,0xcd,0x34,0x89,0x36
+,0x3d,0x37,0xa1,0x9d,0x36,0xa3,0x3f,0x37,0xc6,0x06,0xa0,0x36,0x0c,0xe8,0x8e,0x00
+,0xa1,0x9f,0x36,0x22,0xe4,0x75,0x32,0xf7,0x06,0x4c,0x37,0x01,0x00,0x75,0x2a,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x07,0x88,0x26,0x9e,0x36,0xe9,0x31,0x00,0x3a,0x06,0x9d
+,0x36,0xa3,0x9d,0x36,0x74,0x28,0x8b,0xf0,0x2e,0xff,0xa4,0x0d,0x2b,0x44,0x29,0xee
+,0x42,0x19,0x44,0xcd,0x44,0x2f,0x45,0x5a,0x45,0x3a,0x26,0x9e,0x36,0x75,0x01,0xc3
+,0x32,0xc0,0x86,0xc4,0x8b,0xf0,0xa2,0x9e,0x36,0x2e,0xff,0xa4,0x20,0x49,0x8b,0x2e
+,0x99,0x36,0x23,0xed,0x75,0x01,0xc3,0xbf,0x01,0x00,0xbe,0x00,0x00,0x85,0xfd,0x75
+,0x1a,0x46,0xd1,0xe7,0xe9,0xf6,0xff,0x2a,0x00,0x29,0x00,0x28,0x00,0x27,0x00,0x25
+,0x00,0x05,0x00,0x07,0x00,0x26,0x00,0x06,0x00,0x20,0x00,0xf7,0xd7,0x21,0x3e,0x99
+,0x36,0xd1,0xe6,0x2e,0x8b,0xb4,0x47,0x2b,0xe9,0x4f,0xff,0xe9,0x56,0xff,0x80,0x26
+,0x9e,0x36,0xff,0x75,0x17,0xf7,0x06,0x4c,0x37,0x01,0x00,0x75,0x0f,0xf6,0x06,0x9d
+,0x36,0x80,0x74,0x08,0xf7,0x06,0x66,0x37,0xff,0xff,0x75,0x07,0xc7,0x06,0x66,0x37
+,0x00,0x00,0xc3,0xf7,0x06,0x41,0x37,0x01,0x00,0x75,0x0b,0xb8,0x7f,0x03,0xcd,0x39
+,0xc7,0x06,0x41,0x37,0x01,0x00,0x33,0xf6,0xb8,0x00,0x40,0x85,0x06,0x66,0x37,0x74
+,0x21,0x80,0xbc,0x54,0x37,0xff,0x74,0x04,0xfe,0x84,0x54,0x37,0x80,0xbc,0x96,0x34
+,0xff,0x74,0x04,0xfe,0x84,0x96,0x34,0x31,0x06,0x66,0x37,0x83,0x3e,0x66,0x37,0x00
+,0x74,0x05,0x46,0xd1,0xe8,0x73,0xd4,0xc3,0xa1,0xf4,0x33,0xa9,0x00,0x88,0x74,0x0b
+,0xa9,0x00,0x10,0x75,0x09,0x8b,0x1e,0x43,0x37,0xff,0xe3,0xe9,0xd7,0x00,0xc7,0x06
+,0x35,0x37,0x05,0x00,0xc7,0x06,0x43,0x37,0x1e,0x2c,0xf7,0x06,0xf4,0x33,0x00,0x08
+,0x74,0x06,0xc7,0x06,0x43,0x37,0x10,0x2c,0xb8,0x80,0x03,0xcd,0x39,0xe9,0xcd,0xfe
+,0xa9,0x00,0x08,0x74,0xd9,0xff,0x0e,0x35,0x37,0x75,0xed,0xe9,0x66,0x00,0xa9,0x00
+,0x08,0x75,0xcb,0xff,0x0e,0x35,0x37,0x75,0xdf,0x81,0x0e,0xc2,0x34,0xc0,0x00,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x48,0x81,0x0e,0x9b,0x36,0x00,0x80,0xf7,0x06,0x9b,0x36
+,0x01,0x00,0x74,0x1e,0xb8,0x7d,0x03,0xcd,0x3a,0x81,0x0e,0x9b,0x36,0x80,0x00,0x83
+,0x26,0x9b,0x36,0xfe,0xc7,0x06,0x0f,0x37,0x02,0x00,0xc6,0x06,0xa0,0x36,0x04,0xe9
+,0x7b,0xfe,0x80,0x3e,0xa0,0x36,0x04,0x75,0x07,0x83,0x3e,0x0f,0x37,0x01,0x75,0x05
+,0xc6,0x06,0xa0,0x36,0x06,0xc7,0x06,0x0f,0x37,0x02,0x00,0xe9,0x5f,0xfe,0xbe,0x02
+,0x00,0xe9,0x4a,0xfe,0x80,0x26,0x9e,0x36,0xff,0x75,0x3a,0xf6,0x06,0x9d,0x36,0x80
+,0x74,0x2d,0xf7,0x06,0x9b,0x36,0x00,0x20,0x75,0x2b,0xc6,0x06,0xa0,0x36,0x06,0xff
+,0x06,0x94,0x34,0x83,0x0e,0x66,0x37,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a
+,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x01,0xe9,0x06,0x00,0xbe
+,0x04,0x00,0xe9,0x09,0xfe,0x81,0x0e,0xaf,0x36,0x00,0x08,0xa1,0xaf,0x36,0xe7,0x06
+,0xe5,0x0a,0xa9,0x00,0x80,0x74,0x0e,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36
+,0xe7,0x06,0xe9,0x09,0xff,0xe9,0xf5,0xfd,0xc7,0x06,0x41,0x37,0x00,0x00,0x83,0x0e
+,0x99,0x36,0x02,0xe9,0xe7,0xfd,0x80,0x26,0x9e,0x36,0xff,0x75,0x1d,0xf7,0x06,0x9b
+,0x36,0x00,0x40,0x75,0x05,0x83,0x0e,0x99,0x36,0x08,0x83,0x0e,0x99,0x36,0x20,0x81
+,0x26,0x9b,0x36,0xff,0xbf,0xb8,0x85,0x03,0xcd,0x39,0xe9,0xc0,0xfd,0x80,0x3e,0x9e
+,0x36,0x06,0x74,0x07,0x80,0x3e,0x9e,0x36,0x0a,0x75,0x34,0xf6,0x06,0x9d,0x36,0x80
+,0x75,0x06,0xbe,0x07,0x00,0xe9,0x96,0xfd,0xc6,0x06,0xa0,0x36,0x04,0x83,0x3e,0x0f
+,0x37,0x02,0x74,0x1b,0xc7,0x06,0x0f,0x37,0x04,0x00,0x80,0x3e,0x9e,0x36,0x06,0x75
+,0x0e,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06,0x0f,0x37,0x03,0x00,0xe9
+,0x7b,0xfd,0x80,0x3e,0x9d,0x36,0x04,0x75,0x12,0x81,0x0e,0xc2,0x34,0x00,0x40,0xff
+,0x06,0x92,0x34,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x62,0xfd,0xbe,0x05,0x00,0xe9,0x4d
+,0xfd,0xf6,0x06,0x9d,0x36,0x80,0x75,0x19,0x83,0x0e,0xc2,0x34,0x04,0xbe,0x06,0x00
+,0xe9,0x3b,0xfd,0x80,0x26,0x9e,0x36,0xff,0x75,0xc5,0xff,0x06,0x31,0x37,0xe9,0x00
+,0x00,0x83,0x26,0xc2,0x34,0xbf,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x2f,0xfd,0xe5,0x0a
+,0x50,0x25,0xc3,0xbf,0xe7,0x0a,0x58,0x80,0x26,0x9e,0x36,0xff,0x75,0x0d,0xa9,0x00
+,0x40,0x75,0x08,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x12,0xfd,0xb8,0x83,0x03,0xcd,0x39
+,0xc3,0xb8,0x7c,0x03,0xcd,0x39,0xf7,0x06,0xf4,0x33,0x00,0x10,0x75,0x09,0xc7,0x06
+,0x33,0x37,0x02,0x00,0xe9,0xf6,0xfc,0xff,0x0e,0x33,0x37,0x74,0x03,0xe9,0xed,0xfc
+,0xff,0x06,0x8e,0x34,0xe8,0xf7,0x19,0x83,0x0e,0xc2,0x34,0x08,0xbe,0x03,0x00,0xe9
+,0xcc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x04,0x05
+,0x04,0x04,0x04,0x00,0x03,0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x04,0x00,0x08,0x08,0x05,0x08,0x08,0x08,0x00,0x03,0x00,0x03,0x03,0x00,0x00
+,0x02,0x04,0x04,0x04,0x04,0x00,0x00,0x08,0x00,0x00,0x0a,0x14,0x00,0x00,0x1a,0x00
+,0x1c,0x00,0x1e,0x20,0x00,0x00,0x04,0x41,0x06,0x0b,0x08,0xc2,0xff,0xe7,0x04,0x03
+,0x06,0x04,0x04,0x05,0x04,0x06,0x04,0x87,0x04,0x03,0x06,0x04,0x04,0x85,0x4e,0xa2
+,0x04,0xcf,0x04,0xcd,0xc7,0x06,0xa2,0x37,0x00,0x00,0xc7,0x06,0xa6,0x37,0x00,0x00
+,0x26,0xa1,0x20,0x00,0x25,0x7f,0xff,0xa3,0xf5,0x36,0x26,0xa1,0x22,0x00,0xa3,0xf7
+,0x36,0x26,0xa1,0x24,0x00,0xa3,0xf9,0x36,0xe8,0x3b,0x19,0x8b,0xf0,0x26,0x8b,0x0e
+,0x0e,0x00,0x2b,0xc8,0x83,0xe9,0x0e,0xb8,0x01,0x80,0x83,0xf9,0x04,0x7c,0x51,0x26
+,0x8a,0x54,0x28,0x88,0x16,0x1c,0x37,0x40,0x26,0x8b,0x6c,0x26,0x86,0xcd,0x3b,0xcd
+,0x86,0xcd,0x89,0x0e,0xa4,0x37,0x75,0x38,0x40,0x32,0xff,0x26,0x8a,0x5c,0x29,0x80
+,0xfb,0x15,0x77,0x25,0x80,0xfb,0x0a,0x74,0x20,0x80,0xfb,0x01,0x74,0x1b,0xb8,0x04
+,0x80,0x2e,0x3a,0x97,0x02,0x2e,0x74,0x07,0x2e,0x3a,0x97,0x18,0x2e,0x75,0x11,0x33
+,0xc0,0x80,0xfb,0x09,0x75,0x4f,0x8b,0xf3,0xc3,0x26,0xc7,0x06,0x04,0x00,0xff,0xff
+,0x50,0x52,0xa1,0xa4,0x37,0x86,0xc4,0x26,0x3b,0x06,0x26,0x00,0x7c,0x32,0x26,0x81
+,0x3e,0x26,0x00,0x00,0x04,0x7e,0x29,0x8d,0x74,0x2a,0x26,0x8b,0x14,0x22,0xd2,0x74
+,0x1f,0x80,0xe6,0xbf,0x80,0xfe,0x09,0x75,0x17,0xc7,0x06,0xa2,0x37,0x01,0x00,0x80
+,0xfa,0x04,0x75,0x0c,0x26,0x8b,0x44,0x02,0xa3,0x03,0x37,0x86,0xc4,0xa3,0xd0,0x34
+,0x5a,0x58,0xe9,0xb1,0xff,0xbd,0x72,0x37,0x2e,0x8a,0x87,0x2e,0x2e,0x22,0xc0,0x74
+,0x16,0x05,0x44,0x2e,0x8b,0xf8,0x2e,0x8b,0x05,0x3e,0x89,0x46,0x00,0x83,0xc5,0x02
+,0x83,0xc7,0x02,0x22,0xe4,0x7d,0xef,0x8d,0x74,0x2a,0x83,0xe9,0x04,0x75,0x03,0xe9
+,0xa1,0x00,0x26,0x8b,0x14,0x22,0xd2,0x75,0x03,0xe9,0x7c,0x00,0xc7,0x06,0xa6,0x37
+,0x01,0x00,0xbf,0x72,0x37,0x8b,0x05,0x83,0xc7,0x02,0x80,0xe6,0xbf,0x80,0xe4,0x3f
+,0x80,0xfe,0x09,0x75,0x22,0x80,0xfa,0x04,0x75,0x5e,0xc7,0x06,0xa2,0x37,0x01,0x00
+,0x26,0x8b,0x44,0x02,0xa3,0x03,0x37,0x86,0xc4,0xa3,0xd0,0x34,0x86,0xc4,0xc7,0x06
+,0xa6,0x37,0x00,0x00,0xe9,0x47,0x00,0x3b,0xfd,0x7e,0x15,0x26,0x8b,0x04,0xa8,0x40
+,0x74,0x06,0xb8,0x07,0x80,0xe9,0x38,0xff,0x32,0xc0,0x26,0x8b,0x04,0xe9,0x2e,0x00
+,0x3a,0xf4,0x75,0xb1,0xc7,0x45,0xfe,0x00,0x00,0x80,0xfe,0x22,0x75,0x0d,0x3a,0xd0
+,0x77,0x16,0xc7,0x06,0xa6,0x37,0x00,0x00,0xe9,0x13,0x00,0x3a,0xd0,0x75,0x09,0xc7
+,0x06,0xa6,0x37,0x00,0x00,0xe9,0x06,0x00,0xb8,0x05,0x80,0xe9,0x02,0xff,0x32,0xf6
+,0x03,0xf2,0x2b,0xca,0xb8,0x05,0x80,0x23,0xc9,0x76,0x03,0xe9,0x64,0xff,0x74,0x03
+,0xe9,0xed,0xfe,0x33,0xc0,0xbf,0x72,0x37,0x8b,0x15,0x47,0x47,0x3b,0xfd,0x7f,0x1b
+,0xf6,0xc6,0x80,0x74,0x16,0xf7,0x06,0xa6,0x37,0x01,0x00,0x74,0x06,0xb8,0x08,0x80
+,0xe9,0xc3,0xfe,0xf6,0xc6,0x40,0x74,0xe0,0xb8,0x07,0x80,0xe9,0xb8,0xfe,0x7d,0x42
+,0xa3,0x45,0x44,0x29,0x44,0x29,0xb7,0x28,0xe2,0x28,0xee,0x2b,0xf2,0x28,0xf5,0x28
+,0x01,0x29,0xac,0x2a,0x44,0x29,0x44,0x29,0x44,0x29,0x44,0x29,0x44,0x29,0x00,0x00
+,0x73,0x36,0x00,0x00,0x03,0x36,0xc5,0x35,0x83,0x35,0x45,0x35,0x07,0x35,0xd2,0x34
+,0x45,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0xa6,0x38,0x00,0x00,0xe0,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xf2,0x33,0x00,0x00,0xa6,0x33,0x60,0x33,0xfd,0x32,0xbc,0x32,0x77,0x32,0x3c,0x32
+,0xfb,0x31,0x6a,0x31,0x0a,0x31,0xe0,0xe0,0x10,0x10,0x10,0xe0,0xe0,0xe0,0xe0,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0
+,0xe0,0x33,0xff,0x26,0xf6,0x06,0x1a,0x00,0x80,0x74,0x1b,0x26,0x80,0x26,0x1a,0x00
+,0x7f,0x26,0x8b,0x3e,0x26,0x00,0x83,0xe7,0x1f,0x74,0x0b,0x26,0x80,0x0e,0x20,0x00
+,0x80,0x26,0x01,0x3e,0x0e,0x00,0xc3,0x60,0x2e,0x8b,0x84,0xa6,0x30,0x26,0xa3,0x18
+,0x00,0xd1,0xe6,0x2e,0xff,0x94,0x50,0x30,0x61,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4
+,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x16,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26
+,0xc6,0x06,0x19,0x00,0x00,0xe8,0xbf,0x05,0xe8,0x98,0x05,0x26,0xc7,0x06,0x26,0x00
+,0x00,0x08,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29,0x00,0x2a,0xbf,0x2a
+,0x00,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x2a,0xa1,0x93,0x37,0x33,0xdb,0xa9
+,0x40,0x00,0x75,0x02,0xb3,0x01,0xa9,0x00,0x10,0x74,0x02,0xb7,0x88,0xa9,0x00,0x08
+,0x74,0x03,0x80,0xcf,0x44,0x26,0x89,0x5d,0x02,0xc3,0x83,0x0e,0xc2,0x34,0x20,0x26
+,0xc7,0x06,0x04,0x00,0x6b,0x2b,0x26,0xc7,0x06,0x0e,0x00,0x30,0x00,0x26,0xc7,0x06
+,0x06,0x00,0x0a,0x00,0x26,0xc7,0x06,0x0a,0x00,0x04,0x00,0x26,0xc6,0x06,0x19,0x00
+,0x00,0xe8,0x69,0x05,0xe8,0x2c,0x05,0x26,0xc7,0x06,0x26,0x00,0x00,0x22,0x26,0xc6
+,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x29,0xbf,0x2a,0x00,0x26,0xc6,0x05
+,0x08,0x26,0xc6,0x45,0x01,0x2d,0x8d,0x7d,0x02,0xbe,0x54,0x37,0xb9,0x03,0x00,0xf3
+,0xa5,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x2e,0x8d,0x7d,0x02,0xbe,0x5a,0x37
+,0xb9,0x03,0x00,0xf3,0xa5,0xe8,0xd4,0x05,0xe8,0x64,0x05,0xb9,0x06,0x00,0xbe,0x54
+,0x37,0x8d,0x2e,0x2c,0x00,0x26,0x8b,0x46,0x00,0x29,0x04,0x83,0xc6,0x02,0x83,0xc5
+,0x02,0x83,0xf9,0x04,0x75,0x02,0x45,0x45,0xe2,0xeb,0xc3,0x26,0xc7,0x06,0x04,0x00
+,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x24,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00
+,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0xe4,0x04,0xe8,0xa7,0x04,0x26,0xc7,0x06,0x26
+,0x00,0x00,0x16,0x26,0xc6,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x28,0xbf
+,0x2a,0x00,0xe8,0x5b,0x06,0xe8,0x74,0x05,0xe8,0x04,0x05,0xc3,0x26,0xc7,0x06,0x04
+,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x1a,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0xa3,0x04,0xe8,0x66,0x04,0x26,0xc7,0x06
+,0x26,0x00,0x00,0x0c,0x26,0xc6,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x27
+,0xbf,0x2a,0x00,0xe8,0x21,0x05,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x0a,0x00,0x26,0xc7,0x06,0x0a
+,0x00,0x04,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x4b,0x04,0xe8,0x24,0x04,0x26
+,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29
+,0x00,0x26,0xbf,0x2a,0x00,0xe8,0xf4,0x04,0xe8,0x84,0x04,0xc3,0x26,0xc7,0x06,0x04
+,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x0d,0x04,0xe8,0xe6,0x03,0x26,0xc7,0x06
+,0x26,0x00,0x00,0x26,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29,0x00,0x25
+,0xbf,0x2a,0x00,0xe8,0xb6,0x04,0xe8,0x46,0x04,0xe8,0xfa,0x04,0xc3,0x26,0xc7,0x06
+,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x38,0x00,0xa1,0xa2,0x37,0x50,0x0b
+,0xc0,0x75,0x07,0x26,0xc7,0x06,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x99,0x03,0xe8,0xa4,0xfd,0x26,0xc7,0x45
+,0x26,0x00,0x2a,0x58,0x0b,0xc0,0x75,0x06,0x26,0xc7,0x45,0x26,0x00,0x26,0xa1,0x1c
+,0x37,0xc1,0xe0,0x04,0x26,0x88,0x45,0x28,0x26,0xc6,0x45,0x29,0x24,0x83,0xc7,0x2a
+,0xe8,0x29,0x04,0xe8,0xa0,0x04,0xe8,0x22,0x05,0xe8,0xf8,0x03,0xe8,0x09,0x04,0xc3
+,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x32,0x00,0x26,0xc7
+,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x45,0x03,0xe8,0x50
+,0xfd,0x26,0xc7,0x45,0x26,0x00,0x24,0xa1,0x1c,0x37,0xc1,0xe0,0x04,0x26,0x88,0x45
+,0x28,0x26,0xc6,0x45,0x29,0x23,0x83,0xc7,0x2a,0xe8,0xe0,0x03,0xe8,0x6c,0x04,0xe8
+,0x8a,0x04,0xe8,0x9c,0x04,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06
+,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00
+,0x00,0xe8,0xff,0x02,0xe8,0x0a,0xfd,0x26,0xc7,0x45,0x26,0x00,0x26,0xa1,0x1c,0x37
+,0xc1,0xe0,0x04,0x26,0x88,0x45,0x28,0x26,0xc6,0x45,0x29,0x22,0x83,0xc7,0x2a,0xe8
+,0x9a,0x03,0xe8,0xc7,0x03,0xe8,0x57,0x03,0xe8,0xf8,0x03,0xe8,0x78,0x04,0xe8,0x8a
+,0x04,0xc3,0x26,0xc7,0x06,0x04,0x00,0x74,0x45,0x26,0xc7,0x06,0x0e,0x00,0x3e,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc7,0x06,0x0a,0x00,0x04,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0xe8,0xfc,0x02,0xe8,0xa9,0x02,0x83,0x3e,0x8d,0x37,0x03,0x75
+,0x01,0x90,0x26,0xc7,0x06,0x26,0x00,0x00,0x30,0x26,0xc6,0x06,0x28,0x00,0x50,0x26
+,0xc6,0x06,0x29,0x00,0x20,0xbf,0x2a,0x00,0xe8,0xd0,0x03,0xe8,0x01,0x03,0xe8,0xb5
+,0x03,0xe8,0x9f,0x03,0xc3,0x26,0xc7,0x06,0x04,0x00,0x61,0x43,0xb9,0xf0,0x00,0x83
+,0xe9,0x02,0x26,0x89,0x0e,0x0e,0x00,0x26,0xc7,0x06,0x06,0x00,0x02,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0x26,0xc7,0x06,0x1a,0x00,0x00,0x00,0x26,0xc7,0x06,0x1c,0x00
+,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x00,0xe8,0x47,0x02,0x83,0xe9,0x0e,0x86
+,0xcd,0x26,0x89,0x0e,0x26,0x00,0x86,0xcd,0x26,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6
+,0x06,0x29,0x00,0x08,0xbf,0x2a,0x00,0x83,0xe9,0x04,0x26,0x89,0x0d,0x26,0xc6,0x45
+,0x01,0x26,0x8d,0x7d,0x02,0x83,0xe9,0x02,0xbb,0x01,0x00,0xb8,0x30,0x30,0x4b,0x75
+,0x17,0xbb,0x0a,0x00,0x8a,0xc4,0x26,0x88,0x05,0xb0,0x31,0x80,0xc4,0x01,0x80,0xfc
+,0x3a,0x75,0x0a,0xb4,0x61,0xe9,0x05,0x00,0x26,0x88,0x05,0x04,0x01,0x47,0x49,0x75
+,0xdd,0xc3,0x26,0xc7,0x06,0x04,0x00,0x04,0x45,0x26,0xc7,0x06,0x0e,0x00,0x12,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x01,0xe8,0xe5,0x01
+,0xe8,0xd0,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x04,0x26,0xc6,0x06,0x28,0x00,0x00
+,0x26,0xc6,0x06,0x29,0x00,0x07,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x06,0xe8,0x04,0x02,0xe8,0x9b,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x06,0xbf,0x2a,0x00,0xe8,0x6b
+,0x02,0xe8,0xfb,0x01,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e
+,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x05
+,0xe8,0xc6,0x01,0xe8,0x5d,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06
+,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x05,0xbf,0x2a,0x00,0xe8,0x2d,0x02,0xe8
+,0xbd,0x01,0xc3,0xff,0x06,0x82,0x34,0x26,0xc7,0x06,0x04,0x00,0x3d,0x41,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x0e,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x04,0xe8,0x84,0x01,0xe8,0x1b,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x04,0xbf,0x2a,0x00,0xe8,0xeb
+,0x01,0xe8,0x7b,0x01,0xc3,0x26,0xc7,0x06,0x04,0x00,0x67,0x42,0x26,0xc7,0x06,0x0e
+,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x08,0x00,0x26,0xc6,0x06,0x19,0x00,0x03
+,0xe8,0x46,0x01,0xe8,0xdd,0x00,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06
+,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x03,0xbf,0x2a,0x00,0xe8,0xad,0x01,0xe8
+,0x3d,0x01,0xc3,0xff,0x06,0x84,0x34,0x26,0xc7,0x06,0x04,0x00,0x67,0x42,0x26,0xc7
+,0x06,0x0e,0x00,0x24,0x00,0x26,0xc7,0x06,0x06,0x00,0x08,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x02,0xe8,0x04,0x01,0xe8,0x9b,0x00,0x26,0xc7,0x06,0x26,0x00,0x00,0x16,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x02,0xbf,0x2a,0x00,0x26,0xc6
+,0x05,0x04,0x26,0xc6,0x45,0x01,0x01,0xa1,0x0f,0x37,0x86,0xe0,0xf6,0x06,0x6f,0x37
+,0x01,0x75,0x0f,0x39,0x06,0xcc,0x34,0x74,0x09,0x8b,0xd8,0xb8,0x89,0x03,0xcd,0x39
+,0x8b,0xc3,0xa3,0xcc,0x34,0x26,0x89,0x45,0x02,0x8d,0x7d,0x04,0xe8,0x3d,0x01,0xe8
+,0xcd,0x00,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x1c
+,0x00,0xa1,0xa2,0x37,0x50,0x0b,0xc0,0x75,0x07,0x26,0xc7,0x06,0x0e,0x00,0x18,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x23,0x00
+,0xe8,0x2e,0xfa,0x26,0xc7,0x45,0x26,0x00,0x0e,0x58,0x0b,0xc0,0x75,0x06,0x26,0xc7
+,0x45,0x26,0x00,0x0a,0x26,0xc6,0x45,0x29,0x00,0x83,0xc7,0x2a,0xe8,0xbd,0x00,0xe8
+,0xff,0x00,0xc3,0x56,0x57,0x51,0xb9,0x03,0x00,0xbe,0xd1,0x36,0xbf,0x20,0x00,0xf3
+,0xa5,0x59,0x5f,0x5e,0xc3,0x56,0x57,0x51,0xb9,0x03,0x00,0xbe,0xd1,0x36,0xbf,0x1a
+,0x00,0xf3,0xa5,0x59,0x5f,0x5e,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00,0x26,0xc7
+,0x06,0x1c,0x00,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x10,0xc3,0x26,0xc7,0x06
+,0x1a,0x00,0xc0,0x00,0x26,0xc7,0x06,0x1c,0x00,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00
+,0x00,0x08,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00,0x26,0xc7,0x06,0x1c,0x00,0x00
+,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x02,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00
+,0x26,0xc7,0x06,0x1c,0x00,0xff,0xff,0x26,0xc7,0x06,0x1e,0x00,0xff,0xff,0xc3,0x26
+,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x02,0x8d,0x7d,0x02,0xbe,0x05,0x37,0xb9,0x03
+,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x06,0xa1,0x0d,0x37
+,0x26,0x89,0x45,0x02,0x8d,0x7d,0x04,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01
+,0x07,0xa1,0x0b,0x37,0x26,0x89,0x45,0x02,0x83,0xc7,0x04,0xc3,0xa1,0xa2,0x37,0x0b
+,0xc0,0x74,0x13,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x09,0xa1,0x03,0x37,0x26
+,0x89,0x45,0x02,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x02
+,0x8d,0x7d,0x02,0xbe,0x05,0x37,0xb9,0x03,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x06
+,0x26,0xc6,0x45,0x01,0x0b,0x8d,0x7d,0x02,0xbe,0xef,0x36,0xb9,0x02,0x00,0xf3,0xa5
+,0xc3,0x26,0xc6,0x05,0x06,0x26,0xc6,0x45,0x01,0x20,0xa1,0x68,0x37,0x26,0x89,0x45
+,0x02,0xa1,0x6a,0x37,0x26,0x88,0x65,0x05,0xc1,0xe0,0x04,0x26,0x88,0x45,0x04,0x83
+,0xc7,0x06,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x21,0x26,0xc7,0x45,0x02
+,0x00,0x00,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x14,0x26,0xc6,0x45,0x01,0x22,0x8d
+,0x7d,0x02,0xbe,0x1f,0x37,0xb9,0x09,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x0c,0x26
+,0xc6,0x45,0x01,0x23,0x8d,0x7d,0x02,0x1e,0x0e,0x1f,0x8d,0x36,0x40,0x54,0xb9,0x03
+,0x00,0xf3,0xa5,0x33,0xc0,0xb9,0x02,0x00,0xf3,0xab,0x1f,0xc3,0x26,0xc6,0x05,0x08
+,0x26,0xc6,0x45,0x01,0x28,0x8d,0x7d,0x02,0xbe,0xd1,0x36,0xb9,0x03,0x00,0xf3,0xa5
+,0xc3,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x29,0xa1,0xc2,0x34,0x86,0xe0,0x26
+,0x89,0x45,0x02,0xa1,0x9b,0x36,0x26,0x89,0x45,0x04,0x26,0x88,0x45,0x06,0x26,0x88
+,0x45,0x07,0x8d,0x7d,0x08,0xc3,0x26,0xc6,0x05,0x06,0x26,0xc6,0x45,0x01,0x2b,0x8d
+,0x7d,0x02,0xbe,0xbb,0x36,0xb9,0x02,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x06,0x26
+,0xc6,0x45,0x01,0x2c,0x8d,0x7d,0x02,0xbe,0xe5,0x36,0xb9,0x02,0x00,0xf3,0xa5,0xc3
+,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x30,0xa1,0x37,0x37,0x86,0xe0,0x26,0x89
+,0x45,0x02,0x8d,0x7d,0x04,0xc3,0x26,0xc7,0x06,0x0e,0x00,0x1e,0x00,0x26,0xc7,0x06
+,0x06,0x00,0x02,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x6c,0xfe,0xe8,0x03,0xfe
+,0x26,0xc7,0x06,0x26,0x00,0x00,0x10,0x26,0xc6,0x06,0x28,0x00,0x30,0x26,0xc6,0x06
+,0x29,0x00,0x11,0xbf,0x2a,0x00,0xe8,0x35,0x00,0xe8,0x45,0x00,0xe8,0x55,0x00,0xc3
+,0x26,0xc7,0x06,0x0e,0x00,0x12,0x00,0x26,0xc7,0x06,0x06,0x00,0x02,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0xe8,0x32,0xfe,0xe8,0xc9,0xfd,0x26,0xc7,0x06,0x26,0x00,0x00
+,0x04,0x26,0xc6,0x06,0x28,0x00,0x30,0x26,0xc6,0x06,0x29,0x00,0x13,0xc3,0x26,0xc6
+,0x05,0x04,0x26,0xc6,0x45,0x01,0x0c,0x26,0xc7,0x45,0x02,0x00,0x01,0x83,0xc7,0x04
+,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x0e,0x26,0xc7,0x45,0x02,0x00,0x02
+,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x21,0x26,0xc7,0x45
+,0x02,0x00,0x00,0x83,0xc7,0x04,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb3,0x39,0xc9,0x39,0x83,0x3a,0xb3,0x39,0xb3,0x39,0xb3,0x39,0x1c,0x3a,0x1c,0x3a
+,0xa3,0xb6,0x34,0xa1,0xe9,0x36,0xa3,0x11,0x37,0xa3,0xd2,0x34,0xa1,0xeb,0x36,0xa3
+,0x13,0x37,0xa3,0xd4,0x34,0xa1,0xed,0x36,0xa3,0x15,0x37,0xa3,0xd6,0x34,0xa1,0x01
+,0x37,0xa3,0xce,0x34,0xa1,0xf7,0x36,0xa3,0x17,0x37,0xa3,0xdc,0x34,0xa1,0xf9,0x36
+,0xa3,0x19,0x37,0xa3,0xde,0x34,0xf7,0x06,0x9b,0x36,0x02,0x00,0x75,0x0c,0x33,0xc0
+,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0x50,0x39,0xe9,0x0f,0x01,0xbe,0x07,0x00
+,0xe9,0x19,0xf1,0xf6,0x06,0x9d,0x36,0x80,0x74,0xf3,0xc6,0x06,0xa0,0x36,0x02,0xc6
+,0x06,0x6e,0x37,0x08,0xc6,0x06,0x70,0x37,0x02,0xb8,0x88,0x03,0xcd,0x39,0xf6,0x06
+,0x6f,0x37,0x01,0x75,0x4a,0xa1,0xd1,0x36,0x3a,0x06,0xe9,0x36,0x75,0x41,0x3a,0x26
+,0xea,0x36,0x75,0x3b,0xa1,0xd3,0x36,0x3a,0x06,0xeb,0x36,0x75,0x32,0x3a,0x26,0xec
+,0x36,0x75,0x2c,0xa1,0xd5,0x36,0x3a,0x06,0xed,0x36,0x75,0x23,0x3a,0x26,0xee,0x36
+,0x75,0x1d,0xc6,0x06,0x70,0x37,0x02,0xfe,0x0e,0x6e,0x37,0x75,0x0f,0xb8,0x88,0x03
+,0xcd,0x3a,0x83,0x0e,0x9b,0x36,0x12,0xc6,0x06,0xa0,0x36,0x0c,0xe9,0xa8,0xf0,0xa1
+,0x05,0x37,0x26,0x3b,0x06,0x20,0x00,0x75,0x40,0xa1,0x07,0x37,0x26,0x3b,0x06,0x22
+,0x00,0x75,0x36,0xa1,0x09,0x37,0x26,0x3b,0x06,0x24,0x00,0x75,0x2c,0xa0,0x9e,0x36
+,0x3c,0x02,0x75,0x08,0x26,0xf6,0x06,0x18,0x00,0x08,0x75,0x47,0xc6,0x06,0x6e,0x37
+,0x08,0xfe,0x0e,0x70,0x37,0x75,0x1c,0xc6,0x06,0x70,0x37,0x02,0xe5,0x02,0x0d,0x01
+,0x04,0x25,0xef,0xff,0xe7,0x02,0xe9,0x5e,0xf0,0xc6,0x06,0x70,0x37,0x02,0xc6,0x06
+,0x6e,0x37,0x08,0xe5,0x02,0x25,0xff,0xfb,0x0d,0x01,0x00,0x25,0xef,0xff,0xe7,0x02
+,0xe9,0x44,0xf0,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x25,0x26,0xf6,0x06,0x18,0x00
+,0x08,0x75,0xed,0x81,0x26,0x9b,0x36,0x7f,0xff,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x84
+,0x03,0xcd,0x3a,0xc6,0x06,0xa0,0x36,0x06,0x83,0x26,0xc2,0x34,0xaf,0xe9,0x17,0xf0
+,0xa1,0x01,0x37,0x3a,0x26,0x0f,0x37,0x7f,0xc7,0xe9,0xf7,0xfe,0x83,0x26,0x9b,0x36
+,0xec,0xe8,0x2a,0x0d,0x81,0x0e,0x9b,0x36,0x80,0x00,0xbb,0xff,0x7f,0xcd,0x53,0xc6
+,0x06,0xa0,0x36,0x02,0xe9,0xf0,0xef,0x83,0x0e,0x9b,0x36,0x11,0xc6,0x06,0xa0,0x36
+,0x0c,0xe9,0xf9,0xef,0x44,0x3b,0x2c,0x3b,0xc7,0x2a,0x6b,0x3b,0x44,0x3b,0xc7,0x2a
+,0xc7,0x2a,0xc7,0x2a,0xa3,0xb6,0x34,0x81,0x0e,0xc2,0x34,0x00,0x20,0xf7,0x06,0x41
+,0x37,0x01,0x00,0x74,0x1b,0x8c,0xc3,0xc7,0x06,0x41,0x37,0x00,0x00,0xb8,0x7f,0x03
+,0xcd,0x3a,0x33,0xc0,0x8e,0xc0,0xbf,0x54,0x37,0xb9,0x06,0x00,0xf3,0xab,0x8e,0xc3
+,0x33,0xc0,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0xe4,0x3a,0xf7,0x06,0x9b,0x36
+,0x00,0x01,0x75,0x21,0x83,0x26,0xc2,0x34,0xbf,0xa1,0xa9,0x36,0xe7,0x00,0xa1,0x9b
+,0x36,0xe9,0x09,0x00,0xa1,0x9b,0x36,0x81,0x26,0x9b,0x36,0xff,0xdf,0xa9,0x00,0x20
+,0x75,0x06,0xe9,0x6e,0x00,0xe9,0x6f,0xef,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37
+,0x37,0x01,0x00,0xc6,0x06,0xca,0x34,0x01,0xe9,0x58,0x00,0x83,0x0e,0x9b,0x36,0x40
+,0xe8,0x58,0x00,0xa1,0x05,0x37,0x3b,0x06,0xe9,0x36,0x75,0x37,0xa1,0x07,0x37,0x3b
+,0x06,0xeb,0x36,0x75,0x2e,0xa1,0x09,0x37,0x3b,0x06,0xed,0x36,0x75,0x25,0xfe,0x0e
+,0x71,0x37,0x75,0x1c,0xb8,0x87,0x03,0xcd,0x3a,0x83,0x0e,0x99,0x36,0x10,0xa1,0x50
+,0x37,0xc7,0x06,0x50,0x37,0x00,0x00,0x09,0x06,0x99,0x36,0xc6,0x06,0xa0,0x36,0x08
+,0xe9,0x14,0xef,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37,0x37,0x03,0x00,0xc6,0x06
+,0xca,0x34,0x03,0xc6,0x06,0xa0,0x36,0x0a,0xe9,0xfc,0xee,0xa1,0xd1,0x36,0x26,0x3b
+,0x06,0x20,0x00,0x75,0x15,0xa1,0xd3,0x36,0x26,0x3b,0x06,0x22,0x00,0x75,0x12,0xa1
+,0xd5,0x36,0x26,0x3b,0x06,0x24,0x00,0x75,0x0f,0xc3,0x8d,0x36,0x20,0x00,0xe9,0x0b
+,0x00,0x8d,0x36,0x22,0x00,0xe9,0x04,0x00,0x8d,0x36,0x24,0x00,0x83,0xc4,0x02,0xf7
+,0x06,0xe6,0x34,0x01,0x00,0x74,0x15,0x26,0x3a,0x04,0x77,0x08,0x72,0x0e,0x26,0x3a
+,0x64,0x01,0x72,0x08,0xc6,0x06,0xa0,0x36,0x06,0xe9,0xab,0xee,0xe8,0x7c,0x0a,0x8c
+,0xc0,0x3d,0xff,0xff,0x74,0x1b,0x26,0xc6,0x06,0x18,0x00,0x10,0x26,0xc7,0x06,0x04
+,0x00,0x49,0x3c,0x26,0xc7,0x06,0x06,0x00,0x0c,0x00,0xcd,0x50,0xb9,0x4e,0x00,0xe2
+,0xfe,0xc6,0x06,0xa0,0x36,0x0a,0xe9,0x94,0xee,0xe9,0x7b,0xee,0x8f,0x3c,0x06,0x3d
+,0x06,0x3d,0x06,0x3d,0xd2,0x3c,0xea,0x3c,0x06,0x3d,0x06,0x3d,0xa3,0xb6,0x34,0x81
+,0x26,0xc2,0x34,0xaf,0xdf,0xc7,0x06,0x4c,0x37,0x00,0x00,0xb8,0x8a,0x03,0xcd,0x3a
+,0x80,0x3e,0x9d,0x36,0x04,0x75,0x0c,0x80,0x3e,0x9e,0x36,0x06,0x74,0x05,0xc6,0x06
+,0x9f,0x36,0x06,0x33,0xc0,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0x4c,0x3c,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x0e,0x81,0x26,0x9b,0x36,0xff,0xbf,0xb8,0x8b,0x03
+,0xcd,0x3a,0xe9,0x54,0x00,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x03,0xe9,0x17,0xee
+,0xc7,0x06,0x37,0x37,0x02,0x00,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04
+,0x83,0x0e,0x50,0x37,0x04,0xf6,0x06,0x9d,0x36,0x80,0x75,0x2a,0xe8,0x1f,0x0b,0xe9
+,0x27,0x00,0xf7,0x06,0x9b,0x36,0x00,0x01,0x75,0xd3,0xc7,0x06,0x37,0x37,0x02,0x00
+,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04,0xc6,0x06,0xa0,0x36,0x00,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x03,0xe8,0xde,0x0a,0x81,0x26,0x9b,0x36,0x7c,0xff,0xbb
+,0xff,0xff,0xcd,0x53,0xcd,0x54,0xe9,0xbe,0xed,0xa3,0xb6,0x34,0xe8,0xad,0x01,0xb8
+,0x86,0x03,0xcd,0x39,0xc7,0x06,0x4c,0x37,0x00,0x00,0x81,0x26,0xc2,0x34,0xaf,0xdf
+,0xf6,0x06,0x9d,0x36,0x80,0x74,0x34,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x56,0xf7
+,0x06,0x9b,0x36,0x00,0x01,0x74,0x27,0xe8,0x35,0x01,0x72,0x1c,0xbe,0x00,0x40,0x85
+,0x36,0xc2,0x34,0x75,0x08,0x09,0x36,0xc2,0x34,0xff,0x06,0x92,0x34,0xe8,0x8b,0x01
+,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00,0xe9,0x6c,0xed,0xe9,0xb5,0x00,0xc7,0x06
+,0x37,0x37,0x02,0x00,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04,0x83,0x0e
+,0x50,0x37,0x04,0x80,0x3e,0x9e,0x36,0x08,0x74,0x03,0xe8,0x5a,0x0a,0xe8,0xef,0x00
+,0x72,0xd6,0xe9,0xc8,0xff,0x80,0x3e,0x9e,0x36,0x0a,0x75,0x12,0xc6,0x06,0xa0,0x36
+,0x00,0xf7,0x06,0x9b,0x36,0x08,0x00,0x74,0x02,0xcd,0x54,0xe8,0x39,0x0a,0x81,0x26
+,0x9b,0x36,0xff,0xbf,0xe8,0xc8,0x00,0x72,0xaf,0xb8,0x8b,0x03,0xcd,0x39,0xe9,0x9c
+,0xff,0xf6,0x06,0x9e,0x36,0xff,0x75,0x58,0xa3,0xb6,0x34,0xe8,0xfe,0x00,0x81,0x26
+,0xc2,0x34,0xff,0xbf,0xf6,0x06,0x9d,0x36,0x80,0x74,0x48,0xf7,0x06,0x9b,0x36,0x00
+,0x20,0x74,0x22,0xf7,0x06,0x9b,0x36,0x00,0x40,0x75,0x08,0xe8,0x91,0x00,0x72,0x30
+,0xe9,0x22,0x00,0x26,0xa1,0x0c,0x00,0xa9,0x60,0x00,0x75,0x24,0x81,0x0e,0x66,0x37
+,0x00,0x08,0xe9,0xd2,0xec,0xc7,0x06,0x4c,0x37,0x00,0x00,0xe8,0x71,0x00,0x72,0x10
+,0xb8,0x8b,0x03,0xcd,0x39,0xe8,0xd3,0x00,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00
+,0xe9,0xb4,0xec,0x80,0x3e,0x9d,0x36,0x04,0x75,0x0c,0x80,0x3e,0x9e,0x36,0x06,0x74
+,0x46,0xc6,0x06,0x9f,0x36,0x06,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x0c,0x80,0x3e
+,0x9d,0x36,0x08,0x75,0x05,0xc6,0x06,0x9f,0x36,0x0a,0xe8,0x32,0x00,0x72,0xd1,0xe8
+,0x99,0x00,0x80,0x3e,0x9d,0x36,0x08,0x75,0x13,0x81,0x0e,0x99,0x36,0x80,0x00,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x08,0xb8,0x8b,0x03,0xcd,0x39,0xe9,0x68,0xec,0xc6
+,0x06,0x9f,0x36,0x0a,0xe9,0x60,0xec,0xb8,0x86,0x03,0xcd,0x3a,0xe9,0x58,0xec,0x26
+,0xa1,0x0c,0x00,0xa9,0x60,0x00,0x74,0x08,0x81,0x26,0xc2,0x34,0xff,0xbf,0xf9,0xc3
+,0xf7,0x06,0x9b,0x36,0x00,0x40,0x74,0x13,0x81,0x0e,0x66,0x37,0x00,0x08,0xe8,0x4a
+,0x00,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00,0xf9,0xc3,0x81,0x0e,0x9b,0x36,0x00
+,0x40,0x80,0x26,0x6f,0x37,0xfe,0x81,0x26,0x9b,0x36,0x7f,0xff,0xc6,0x06,0xa0,0x36
+,0x00,0xf8,0xc3,0x81,0x0e,0x99,0x36,0x00,0x01,0xe9,0x21,0xec,0x26,0xa1,0x20,0x00
+,0xa3,0xfb,0x36,0xa3,0xaa,0x34,0x26,0xa1,0x22,0x00,0xa3,0xfd,0x36,0xa3,0xac,0x34
+,0x26,0xa1,0x24,0x00,0xa3,0xff,0x36,0xa3,0xae,0x34,0xc3,0xa1,0x05,0x37,0x26,0x3b
+,0x06,0x20,0x00,0x75,0x19,0xa1,0x07,0x37,0x26,0x3b,0x06,0x22,0x00,0x75,0x0f,0xa1
+,0x09,0x37,0x26,0x3b,0x06,0x24,0x00,0x75,0x05,0xe8,0x02,0x00,0xf8,0xc3,0x51,0x1e
+,0x06,0x8b,0xc7,0x8d,0x36,0x20,0x00,0xbf,0x05,0x37,0xb9,0x03,0x00,0x1e,0x06,0x1f
+,0x07,0xf3,0xa5,0x8b,0xf8,0x8d,0x36,0x20,0x00,0xbf,0xa0,0x34,0xb9,0x03,0x00,0xf3
+,0xa5,0x07,0x1f,0x59,0x8b,0xf8,0xa1,0x07,0x37,0xa3,0xa6,0x34,0xa1,0x09,0x37,0xa3
+,0xa8,0x34,0xf9,0xc3,0xc6,0x06,0xb6,0x34,0x01,0xe9,0x8b,0xeb,0xe8,0x87,0x08,0x8b
+,0xf0,0x05,0x12,0x00,0x26,0x29,0x06,0x0e,0x00,0x26,0x8b,0x44,0x2a,0x26,0x3a,0x06
+,0x0e,0x00,0x75,0x5b,0x26,0x83,0x2e,0x0e,0x00,0x02,0x80,0xfc,0x27,0x75,0x50,0x26
+,0x8b,0x44,0x2c,0xa9,0xff,0xff,0x75,0x47,0x8b,0xfe,0x33,0xc0,0x26,0xf6,0x45,0x3c
+,0x80,0x74,0x06,0x26,0x8a,0x45,0x3a,0x24,0x1f,0x03,0xf8,0x26,0x80,0x7d,0x45,0x09
+,0x75,0x2d,0x8c,0xc2,0x8e,0x06,0x38,0x34,0x8e,0xda,0x8b,0x0e,0x0e,0x00,0x26,0x89
+,0x0e,0x0e,0x00,0x8d,0x74,0x2c,0xbf,0x18,0x00,0xf3,0xa4,0x33,0xc0,0x8e,0xd8,0x26
+,0xc7,0x06,0x04,0x00,0xb5,0x3f,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0xcd,0x50,0xb8
+,0x06,0x80,0xe9,0xef,0xe9,0x26,0xa1,0x0c,0x00,0xa3,0x93,0x37,0x83,0x0e,0x99,0x36
+,0x01,0xe9,0x00,0xeb,0x26,0x80,0x3e,0x1c,0x00,0xff,0x75,0x2f,0x26,0x80,0x3e,0x1e
+,0x00,0xff,0x75,0x27,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00,0x75,0x1b,0xa1,0xd1,0x36
+,0x26,0xa3,0x1a,0x00,0xa1,0xd3,0x36,0x26,0xa3,0x1c,0x00,0xa1,0xd5,0x36,0x26,0xa3
+,0x1e,0x00,0xb8,0x0a,0x80,0xe8,0x36,0x07,0xe9,0xe2,0xea,0xff,0x06,0x90,0x34,0xbe
+,0x0a,0x00,0xc6,0x06,0xb6,0x34,0x01,0xf6,0x06,0x9d,0x36,0x80,0x75,0x05,0x83,0x0e
+,0xc2,0x34,0x01,0xe9,0xb6,0xea,0x80,0x3e,0x9d,0x36,0x0a,0x75,0x0f,0x26,0xa1,0x0c
+,0x00,0x25,0x07,0x00,0x3d,0x04,0x00,0x75,0x03,0xe8,0x79,0x00,0xa1,0xf3,0x36,0x86
+,0xe0,0xe7,0x1e,0xa3,0xe3,0x36,0x81,0x26,0x0b,0x37,0x00,0x03,0x81,0x26,0x0d,0x37
+,0x7b,0x7f,0x83,0x0e,0x0d,0x37,0x48,0xe8,0x1e,0x00,0x26,0xa1,0x0c,0x00,0x25,0x07
+,0x00,0x3d,0x04,0x00,0x74,0x09,0x26,0xf7,0x06,0x0c,0x00,0x20,0x00,0x75,0x06,0xb8
+,0x01,0x00,0xe9,0x3f,0xe9,0xe9,0x5f,0xea,0xc7,0x06,0x41,0x37,0x00,0x00,0xb8,0x7f
+,0x03,0xcd,0x3a,0xa1,0x1d,0x37,0xa3,0xc4,0x34,0x86,0xe0,0x68,0x7f,0x03,0x1f,0xa3
+,0x06,0x00,0x33,0xc0,0x8e,0xd8,0xa1,0x0b,0x37,0xa3,0xb2,0x34,0xa1,0x0d,0x37,0xa3
+,0xb4,0x34,0xa1,0xf3,0x36,0xa3,0xc8,0x34,0xa1,0xef,0x36,0xa3,0x9c,0x34,0xa1,0xf1
+,0x36,0xa3,0x9e,0x34,0xc3,0x80,0x0e,0x9d,0x36,0x80,0xbe,0x00,0x00,0xe8,0xb4,0x07
+,0xb8,0x7b,0x03,0xcd,0x3a,0xb8,0x7c,0x03,0xcd,0x39,0xc7,0x06,0x33,0x37,0x02,0x00
+,0xa1,0xe5,0x36,0xe7,0x2e,0xa1,0xe7,0x36,0xe7,0x3e,0xb8,0x82,0x03,0xcd,0x3a,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x03,0xe8,0xfd,0x06,0xa1,0xd3,0x36,0xa3,0xef,0x36
+,0xa3,0x9c,0x34,0xa1,0xd5,0x36,0xa3,0xf1,0x36,0xa3,0x9e,0x34,0xc3,0xf6,0x06,0x9d
+,0x36,0x80,0x74,0x31,0xbe,0x22,0x00,0xe9,0x17,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74
+,0x24,0xbe,0x23,0x00,0xe9,0x0a,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74,0x17,0xbe,0x24
+,0x00,0x56,0xe8,0xa8,0x05,0x8c,0xc0,0x3d,0xff,0xff,0x5e,0x74,0x05,0xe8,0xd7,0xef
+,0xcd,0x50,0xe9,0x1f,0xe8,0xe9,0x9f,0xe9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb8,0x84,0x03,0xcd,0x3a,0xb8,0x8a,0x03,0xcd,0x39,0xe9,0xf7,0x00,0x80,0x3e,0xa0
+,0x36,0x08,0x75,0x2e,0xa9,0xd0,0x07,0x75,0x2c,0xa1,0xb1,0x36,0x0d,0x00,0x04,0xe7
+,0x08,0xe5,0x00,0x25,0xff,0x73,0xe7,0x00,0xb8,0x8a,0x03,0xcd,0x3a,0xe8,0xc3,0x06
+,0x33,0xc0,0xe7,0x0e,0xe5,0x0a,0x25,0xc3,0x17,0xe7,0x0a,0xcd,0x54,0xc6,0x06,0xa0
+,0x36,0x00,0xe9,0x68,0xe9,0xbe,0x04,0x00,0xe9,0x3f,0xe9,0x83,0x26,0x9b,0x36,0xbf
+,0xc6,0x06,0x71,0x37,0x03,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x88,0x03,0xcd,0x3a,0xb8
+,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x39,0x81,0x0e,0xc2,0x34,0x00,0x20,0xe9
+,0x92,0x00,0xe8,0x49,0x06,0xb8,0x87,0x03,0xcd,0x39,0xbb,0xff,0x7f,0xcd,0x53,0xb8
+,0x84,0x03,0xcd,0x3a,0xb8,0x88,0x03,0xcd,0x3a,0xb8,0x8b,0x03,0xcd,0x3a,0xb8,0x83
+,0x03,0xcd,0x3a,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd,0x3a,0xc3,0xe5,0x00
+,0x25,0xff,0x53,0xe7,0x00,0x83,0x0e,0xc2,0x34,0x40,0x83,0x26,0xc2,0x34,0xef,0xe8
+,0x0c,0x06,0xbb,0xff,0x7f,0xcd,0x53,0xb8,0x8a,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd
+,0x3a,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x3a
+,0xb8,0x8b,0x03,0xcd,0x3a,0xb8,0x84,0x03,0xcd,0x3a,0xb8,0x89,0x03,0xcd,0x3a,0xc3
+,0x83,0x0e,0xc2,0x34,0x50,0xe8,0x18,0x04,0xe8,0xd3,0x05,0xf6,0x06,0x6f,0x37,0x01
+,0x75,0x12,0xb8,0x89,0x03,0xcd,0x39,0x83,0x3e,0x0f,0x37,0x00,0x75,0x06,0xc7,0x06
+,0x0f,0x37,0x04,0x00,0xa1,0x9d,0x36,0x80,0xfc,0x08,0x74,0x05,0xb8,0x84,0x03,0xcd
+,0x39,0xe5,0x02,0x0d,0x01,0x08,0x25,0xef,0xff,0xe7,0x02,0xa1,0x9d,0x36,0x86,0xe0
+,0x32,0xe4,0x8b,0xf0,0xd1,0xee,0x33,0xc0,0x0d,0x20,0x00,0x09,0x06,0xad,0x36,0xa1
+,0xad,0x36,0xe7,0x04,0xe9,0x53,0xe8,0xe9,0x5a,0xe8,0x33,0xc0,0xa0,0x1b,0x37,0xd1
+,0xe0,0x3a,0x06,0xa0,0x36,0x75,0x03,0xe9,0xba,0xff,0xe9,0x60,0xe8,0xc7,0x06,0x41
+,0x37,0x00,0x00,0xe8,0xc1,0xe1,0xe8,0x6a,0x06,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56
+,0xa1,0xb1,0x36,0x0d,0x00,0x10,0xe7,0x08,0xe5,0x02,0x25,0xf9,0xff,0x0d,0x03,0x00
+,0xe7,0x02,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xa1,0xad,0x36,0xe7
+,0x04,0xe8,0x7c,0x03,0xe8,0x9f,0x03,0xc7,0x06,0x1d,0x37,0x00,0xc8,0xc7,0x06,0x0b
+,0x37,0x00,0x03,0xc7,0x06,0x0d,0x37,0x7b,0x7f,0x33,0xc0,0xa3,0x99,0x36,0xa3,0x9b
+,0x36,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xa3,0x4c,0x37,0xa3,0xf3,0x36,0xa3,0xef,0x36
+,0xa3,0xf1,0x36,0xe8,0x82,0xfd,0xc6,0x06,0x9f,0x36,0x02,0xe9,0xef,0xe7,0xe5,0x02
+,0x0d,0x01,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02,0xe8,0xf2
+,0x05,0xe5,0x0a,0x0d,0x40,0x00,0xe7,0x0a,0x33,0xc0,0xa3,0x81,0x37,0xa3,0x85,0x37
+,0xa3,0x83,0x37,0xa3,0x87,0x37,0xa3,0x89,0x37,0xe5,0x00,0x0d,0x00,0x84,0xe7,0x00
+,0xb8,0x8c,0x03,0xcd,0x39,0xb8,0x80,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff
+,0xe5,0x00,0x25,0xff,0x7b,0xe7,0x00,0x81,0x0e,0x9a,0x37,0x80,0x00,0xb8,0x7e,0x03
+,0xcd,0x39,0x33,0xc0,0xe7,0x0e,0xbe,0x08,0x00,0x8e,0x06,0x38,0x34,0xe8,0xa7,0xed
+,0x83,0x26,0xef,0x34,0xdf,0xff,0x06,0x81,0x37,0xcd,0x50,0x83,0x0e,0xef,0x34,0x20
+,0xc3,0xf7,0x06,0x9a,0x37,0x80,0x00,0x74,0x3d,0xa9,0xd0,0x07,0x74,0x10,0xa9,0x00
+,0x04,0x74,0x12,0x33,0xc0,0xe7,0x0e,0xff,0x06,0x87,0x37,0xe9,0xd2,0xff,0xff,0x06
+,0x85,0x37,0xe9,0xcb,0xff,0xff,0x06,0x83,0x37,0xe9,0xc4,0xff,0x83,0x26,0x9a,0x37
+,0x7f,0xa1,0x89,0x37,0x03,0x06,0x87,0x37,0x3d,0x05,0x00,0x7f,0x01,0xc3,0xbb,0xff
+,0x7f,0xcd,0x53,0xe9,0x00,0x00,0xe5,0x02,0x25,0xff,0xfb,0x25,0xef,0xff,0x0d,0x01
+,0x00,0xe7,0x02,0xa1,0x83,0x37,0x3b,0x06,0x46,0x37,0x7f,0x2a,0xa1,0x85,0x37,0x3b
+,0x06,0x48,0x37,0x7c,0x21,0xa1,0x89,0x37,0x03,0x06,0x87,0x37,0x3d,0x05,0x00,0x7f
+,0x15,0xc6,0x06,0x9f,0x36,0x04,0xe5,0x02,0x25,0xff,0xf7,0x0d,0x01,0x00,0x25,0xef
+,0xff,0xe7,0x02,0xe9,0xf7,0xe6,0xbe,0x01,0x00,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74
+,0x0a,0x83,0x26,0x9b,0x36,0xfc,0x83,0x0e,0xc2,0x34,0x04,0xe9,0xd0,0xe6,0xb8,0x7b
+,0x03,0xcd,0x39,0xe5,0x02,0x0d,0x01,0x60,0x25,0xef,0xff,0xe7,0x02,0xc7,0x06,0xf1
+,0x34,0x20,0x03,0xb8,0x8e,0x03,0xcd,0x39,0xc3,0x81,0x26,0xc2,0x34,0x7f,0xff,0x80
+,0x0e,0x6f,0x37,0x01,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74,0xd2,0xb8,0x7b,0x03,0xcd
+,0x3a,0xb8,0x7d,0x03,0xcd,0x39,0x83,0x26,0x9b,0x36,0xef,0x33,0xc0,0xb0,0x8a,0xa2
+,0x9f,0x36,0xa2,0x9d,0x36,0xc7,0x06,0x4c,0x37,0x01,0x00,0xc7,0x06,0x0f,0x37,0x04
+,0x00,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06,0x0f,0x37,0x03,0x00,0xb8
+,0x8d,0x03,0xcd,0x39,0xe8,0x00,0xd5,0xe5,0x02,0x0d,0x01,0x40,0x25,0xef,0xff,0x8b
+,0xd8,0xb8,0x7c,0x03,0xcd,0x39,0xc7,0x06,0x33,0x37,0x02,0x00,0x8b,0xc3,0x0d,0x00
+,0x20,0x25,0xf9,0xff,0x0b,0x06,0xe8,0x3a,0xe7,0x02,0xc3,0xff,0x0e,0xf1,0x34,0x75
+,0x01,0xc3,0xe5,0x4e,0xa9,0x01,0x00,0x75,0x12,0xe5,0x00,0xa9,0x00,0x04,0x75,0x05
+,0x0d,0x00,0x04,0xe7,0x00,0xb8,0x8e,0x03,0xcd,0x39,0xc3,0xe5,0x00,0xa9,0x00,0x04
+,0x74,0xf3,0x25,0xff,0xfb,0xe7,0x00,0xe9,0xeb,0xff,0xc6,0x06,0xa0,0x36,0x04,0x83
+,0x26,0x9b,0x36,0xfc,0x81,0x0e,0x9b,0x36,0x80,0x00,0xe9,0x10,0xe6,0xb8,0x8e,0x03
+,0xcd,0x3a,0xcd,0x54,0x81,0x0e,0xaf,0x36,0x00,0x18,0xa1,0xaf,0x36,0xe7,0x06,0xb8
+,0x7b,0x03,0xcd,0x39,0xa1,0xd3,0x36,0xa3,0x8f,0x37,0xa1,0xd5,0x36,0xa3,0x91,0x37
+,0xc7,0x06,0x8b,0x37,0x02,0x00,0xc7,0x06,0x8d,0x37,0x02,0x00,0x83,0x0e,0x99,0x36
+,0x40,0xe9,0xd9,0xe5,0x80,0x3e,0x9f,0x36,0x06,0x75,0x15,0xa9,0xd0,0x07,0x75,0xec
+,0x25,0x00,0x18,0x75,0x0e,0xff,0x0e,0x8b,0x37,0x75,0xe1,0xc6,0x06,0x9f,0x36,0x08
+,0xe9,0xba,0xe5,0xff,0x0e,0x8d,0x37,0x75,0xd3,0xbe,0x08,0x00,0xe9,0x9f,0xe5,0xb8
+,0x7b,0x03,0xcd,0x39,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x08,0xc6,0x06,0x9f,0x36
+,0x0a,0xe9,0x0d,0x00,0xf7,0x06,0x9b,0x36,0x00,0x40,0x74,0x0b,0xb8,0x8b,0x03,0xcd
+,0x39,0x81,0x0e,0x99,0x36,0x80,0x00,0xe9,0x83,0xe5,0xb8,0x7b,0x03,0xcd,0x39,0xc7
+,0x06,0x8b,0x37,0x04,0x00,0xc7,0x06,0x8d,0x37,0x04,0x00,0x81,0x0e,0x99,0x36,0x00
+,0x02,0xe9,0x69,0xe5,0xf6,0x06,0x9d,0x36,0x80,0x75,0x1b,0xa9,0xd0,0x07,0x75,0xeb
+,0xa9,0x00,0x18,0x75,0x0c,0xff,0x0e,0x8d,0x37,0x75,0xe0,0xe8,0x17,0xfb,0xe9,0x4c
+,0xe5,0xb8,0x82,0x03,0xcd,0x39,0xc3,0xff,0x0e,0x8b,0x37,0x75,0xce,0xbe,0x09,0x00
+,0xe9,0x2b,0xe5,0xc7,0x06,0x3d,0x37,0x00,0x00,0xc7,0x06,0x9b,0x36,0x00,0x00,0xe8
+,0x3c,0x02,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0x81,0x26,0x9b
+,0x36,0xff,0x7f,0xe5,0x02,0x0d,0x01,0x00,0x25,0xef,0xff,0x25,0xff,0xdf,0xe7,0x02
+,0xbb,0xff,0x7f,0xcd,0x53,0x33,0xc0,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xe8,0x50,0x00
+,0xe8,0x73,0x00,0xb8,0x81,0x03,0xcd,0x39,0xc3,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74
+,0x0d,0xc6,0x06,0x9f,0x36,0x02,0xc6,0x06,0xa0,0x36,0x00,0xe9,0xdf,0xe4,0x83,0x0e
+,0x9b,0x36,0x10,0xc7,0x06,0x99,0x36,0x00,0x00,0xe8,0xe7,0x02,0xe5,0x56,0x0d,0x02
+,0x00,0xe7,0x56,0xc7,0x06,0xa8,0x02,0x00,0x00,0x8b,0x36,0x3d,0x37,0xe8,0x44,0x02
+,0xc6,0x06,0xa0,0x36,0x0e,0xe9,0xb5,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x06,0xb8,0x8a,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd,0x3a,0xb8,0x86,0x03,0xcd,0x3a
+,0xb8,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x3a,0xb8,0x8b,0x03,0xcd,0x3a,0xb8
+,0x88,0x03,0xcd,0x3a,0x07,0xc3,0x06,0xb8,0x88,0x03,0xcd,0x3a,0xb8,0x7b,0x03,0xcd
+,0x3a,0xb8,0x82,0x03,0xcd,0x3a,0xb8,0x7f,0x03,0xcd,0x3a,0xb8,0x7c,0x03,0xcd,0x3a
+,0xb8,0x7e,0x03,0xcd,0x3a,0xb8,0x80,0x03,0xcd,0x3a,0xb8,0x81,0x03,0xcd,0x3a,0xb8
+,0x84,0x03,0xcd,0x3a,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x7d,0x03,0xcd,0x3a,0xb8,0x8d
+,0x03,0xcd,0x3a,0xc7,0x06,0x41,0x37,0x00,0x00,0x07,0xc3,0x06,0x8e,0x06,0x38,0x34
+,0x1f,0x8b,0x0e,0x0e,0x00,0x26,0x89,0x0e,0x0e,0x00,0xbe,0x18,0x00,0xbf,0x18,0x00
+,0xf3,0xa4,0x06,0x1e,0x07,0xcd,0x34,0x07,0x33,0xc0,0x8e,0xd8,0xc3,0x26,0xf6,0x06
+,0x20,0x00,0x80,0x74,0x44,0x33,0xc0,0x26,0xa0,0x26,0x00,0x24,0x1f,0x8b,0xf0,0x26
+,0x8b,0x5c,0x28,0x89,0x1e,0x6a,0x37,0x06,0x8e,0x06,0x38,0x34,0x1f,0xc0,0xe3,0x04
+,0x26,0x88,0x5c,0x28,0x8b,0xc6,0xb9,0x06,0x00,0xbe,0x20,0x00,0xbf,0x1a,0x00,0xf3
+,0xa4,0x8b,0xc8,0x83,0xc7,0x06,0xf3,0xa4,0x26,0x81,0x26,0x26,0x00,0x1f,0x80,0x26
+,0x81,0x36,0x26,0x00,0x00,0x80,0xe9,0xa9,0xff,0x26,0x8b,0x1e,0x28,0x00,0x89,0x1e
+,0x6a,0x37,0x06,0x8e,0x06,0x38,0x34,0x1f,0xc0,0xe3,0x04,0x26,0x88,0x1e,0x28,0x00
+,0xb9,0x06,0x00,0xbe,0x20,0x00,0xbf,0x1a,0x00,0xf3,0xa4,0xe9,0x84,0xff,0x86,0xc4
+,0xa3,0x68,0x37,0xe8,0x87,0xff,0xf7,0x06,0x6a,0x37,0x0f,0x00,0x74,0x10,0x80,0x3e
+,0x9e,0x36,0x00,0x75,0x09,0xbe,0x00,0x00,0xe8,0xac,0xe9,0xcd,0x50,0xc3,0xc3,0x50
+,0x56,0x06,0x33,0xc0,0x26,0xf6,0x06,0x20,0x00,0x80,0x74,0x06,0x26,0xa0,0x26,0x00
+,0x24,0x1f,0x8b,0xf0,0x26,0x8b,0x5c,0x26,0x86,0xfb,0x83,0xeb,0x04,0x74,0x4f,0x83
+,0xc6,0x2a,0x8c,0xc0,0x8e,0xd8,0xb9,0x07,0x00,0x33,0xc0,0x8e,0xc0,0xbf,0x72,0x37
+,0xf3,0xab,0x33,0xc9,0x8a,0x0c,0x80,0xf9,0x00,0x75,0x03,0xe9,0x30,0x00,0x3b,0xd9
+,0x73,0x03,0xe9,0x29,0x00,0x2b,0xd9,0x8a,0x44,0x01,0x25,0x3f,0x00,0x74,0x19,0x3d
+,0x0b,0x00,0x7d,0x14,0xd1,0xe0,0x8b,0xf8,0x2e,0x8b,0xbd,0x5c,0x49,0x8d,0x74,0x02
+,0x83,0xe9,0x02,0xf3,0xa4,0xe9,0x02,0x00,0x03,0xf1,0x23,0xdb,0x75,0xc4,0x33,0xc0
+,0x8e,0xd8,0x07,0x5e,0x58,0xc3,0x33,0xc0,0x26,0xf6,0x06,0x20,0x00,0x80,0x74,0x06
+,0x26,0xa0,0x26,0x00,0x24,0x1f,0xc3,0xe5,0x0a,0x25,0xc3,0xbf,0xe7,0x0a,0xb8,0x86
+,0x03,0xcd,0x39,0xb8,0x83,0x03,0xcd,0x39,0x81,0x26,0x9b,0x36,0x7c,0xdf,0xb8,0x85
+,0x03,0xcd,0x3a,0xe5,0x02,0x25,0xff,0xf3,0x0d,0x01,0x00,0x25,0xef,0xff,0xe7,0x02
+,0xe5,0x00,0x25,0xff,0x53,0xe7,0x00,0xa1,0xe7,0x36,0x25,0xff,0xfe,0xa3,0xe7,0x36
+,0xe7,0x3e,0x83,0x26,0x99,0x36,0xcf,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1,0xaf,0x36
+,0xe7,0x06,0xc3,0xe5,0x02,0x0d,0x01,0x0c,0x25,0xef,0xff,0xe7,0x02,0xa1,0xe7,0x36
+,0x0d,0x00,0x01,0xe7,0x3e,0xa3,0xe7,0x36,0x81,0x0e,0x9b,0x36,0x00,0x20,0x83,0x0e
+,0x99,0x36,0x20,0x81,0x26,0x9b,0x36,0x7c,0xbf,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1
+,0xaf,0x36,0xe7,0x06,0xb8,0x86,0x03,0xcd,0x39,0xb8,0x85,0x03,0xcd,0x39,0xb8,0x83
+,0x03,0xcd,0x3a,0xc3,0x0b,0xf6,0x75,0x49,0x06,0x8e,0x06,0x32,0x34,0x80,0x3e,0xe0
+,0x34,0x01,0x75,0x1b,0x26,0x89,0x36,0x06,0x00,0x8e,0x06,0x32,0x34,0x26,0xf7,0x06
+,0x0a,0x00,0x00,0x20,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x20,0x07,0xc3,0x80
+,0x3e,0xe3,0x34,0x01,0x75,0x19,0x26,0x89,0x36,0x06,0x00,0x8e,0x06,0x32,0x34,0x26
+,0xf7,0x06,0x0a,0x00,0x00,0x10,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x10,0x07
+,0xc3,0xe9,0xb4,0xff,0x50,0x51,0x57,0x33,0xc0,0xb9,0x06,0x00,0x8e,0xc0,0xbf,0xd1
+,0x36,0xf3,0xae,0x5f,0x74,0x0c,0x26,0xf6,0x06,0x00,0x00,0xc0,0x75,0x04,0xf8,0x59
+,0x58,0xc3,0xf9,0xe9,0xf9,0xff,0x8b,0x05,0x0b,0x45,0x02,0x0b,0x45,0x04,0xc3,0x52
+,0x50,0xe5,0x06,0x25,0x1e,0x00,0x3d,0x1e,0x00,0x75,0xf6,0xb8,0x01,0x80,0xe7,0x5a
+,0x58,0x5a,0xc3,0xe8,0xe9,0xff,0x50,0xe5,0x02,0x25,0xff,0x7f,0x0d,0x01,0x00,0x25
+,0xef,0xff,0xe7,0x02,0x0d,0x00,0x80,0xe7,0x02,0xa1,0xad,0x36,0xe7,0x04,0xa1,0xaf
+,0x36,0xe7,0x06,0x58,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x2e,0x2b,0xce,0x41,0x10,0x42,0x7b,0x41,0x30,0x41,0xa2,0x41,0xaf,0x45,0x44,0x29
+,0xc7,0x2a,0xc7,0x2a,0x60,0x39,0xf4,0x3a,0x5c,0x3c,0x09,0x3d,0xb1,0x3d,0x34,0x3f
+,0xc7,0x2a,0x3c,0x3f,0xc7,0x2a,0xc4,0x3f,0x16,0x40,0x16,0x40,0xed,0x40,0xfa,0x40
+,0x07,0x41,0xc7,0x2a,0xc7,0x2a,0xc7,0x2a,0xc7,0x2a,0xd6,0x52,0x00,0x00,0x01,0x37
+,0xe9,0x36,0xf3,0x36,0xef,0x36,0x1d,0x37,0x0d,0x37,0x0b,0x37,0x9c,0x37,0x03,0x37
+,0xfb,0x36,0x62,0x2d,0x40,0x06,0xd1,0x2d,0xf4,0x01,0xba,0x44,0x40,0x06,0x8c,0x43
+,0x64,0x00,0xe8,0x2c,0xc8,0x00,0xd8,0x2b,0x05,0x00,0xe9,0x45,0x50,0x00,0x97,0x45
+,0xfa,0x00,0xae,0x2d,0x04,0x01,0x6a,0x42,0x02,0x00,0xf6,0x2c,0xbc,0x02,0x93,0x2d
+,0xdc,0x05,0x1d,0x2d,0x64,0x00,0xa1,0x2d,0x14,0x00,0xd7,0x3a,0x08,0x07,0x81,0x2d
+,0x64,0x00,0xb3,0x3e,0x02,0x00,0x30,0x43,0x64,0x00,0xc5,0x2c,0xf4,0x01,0x8b,0x44
+,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x80,0x3e,0xfd,0x34,0x02,0x74,0x0c,0xe8,0x20,0x05,0xc7,0x06,0xa1,0x36,0x00,0x00
+,0xe9,0x9a,0xf8,0xff,0x06,0xc0,0x33,0xe8,0x10,0x05,0x8b,0x36,0x3d,0x37,0xe8,0x73
+,0xfe,0xc3,0xcd,0x34,0xe9,0xe8,0x05,0xc7,0x06,0xa3,0x36,0x00,0x00,0xc7,0x06,0x41
+,0x37,0x00,0x00,0xe8,0xed,0xfe,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56,0xa1,0xb1,0x36
+,0x0d,0x00,0x10,0xe7,0x08,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xa1
+,0xad,0x36,0xe7,0x04,0xe8,0x2b,0x09,0xc7,0x06,0x1d,0x37,0x00,0xc8,0xc7,0x06,0x0b
+,0x37,0x00,0x03,0xc7,0x06,0x0d,0x37,0x7b,0x7f,0x33,0xc0,0xa3,0x9b,0x36,0xa3,0x9d
+,0x36,0xc7,0x06,0x4c,0x37,0x01,0x00,0xc6,0x06,0x9e,0x36,0xff,0xc7,0x06,0x05,0x37
+,0x00,0x00,0xc7,0x06,0x07,0x37,0x00,0x00,0xc7,0x06,0x09,0x37,0x00,0x00,0xa3,0xf3
+,0x36,0xa3,0xef,0x36,0xa3,0xf1,0x36,0xe8,0xfe,0xf5,0xe5,0x02,0x25,0xf9,0xff,0x0d
+,0x03,0x00,0x0d,0x00,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02
+,0xb8,0x8f,0x03,0xcd,0x39,0xb8,0x80,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff
+,0xa1,0xa9,0x36,0xa3,0xa7,0x36,0x0d,0x00,0xa4,0x0d,0x00,0x08,0xe7,0x00,0xa3,0xa9
+,0x36,0xc7,0x06,0xa3,0x36,0x01,0x00,0xc7,0x06,0xa5,0x36,0x0c,0x00,0x83,0x3e,0xa5
+,0x36,0x00,0x75,0x09,0xc7,0x06,0x3d,0x37,0x05,0x00,0xe9,0x13,0xff,0xff,0x0e,0xa5
+,0x36,0xbe,0x11,0x00,0xe8,0x22,0x05,0xb8,0x90,0x03,0xcd,0x39,0xc3,0x83,0x3e,0xa3
+,0x36,0x01,0x74,0xd9,0xc3,0xb8,0x90,0x03,0xcd,0x3a,0x26,0xa0,0x2b,0x00,0x26,0x8b
+,0x1e,0x2c,0x00,0xcd,0x34,0x83,0x3e,0xa3,0x36,0x01,0x74,0x03,0xe9,0xf0,0x04,0x3c
+,0x0f,0x75,0x1e,0x81,0xfb,0x00,0x02,0x75,0x18,0x26,0xa1,0x20,0x00,0xa3,0x05,0x37
+,0x26,0xa1,0x22,0x00,0xa3,0x07,0x37,0x26,0xa1,0x24,0x00,0xa3,0x09,0x37,0xe9,0x09
+,0x00,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xb6,0xfe,0xc7,0x06,0xa3,0x36,0x02,0x00
+,0xc6,0x06,0x9e,0x36,0xff,0xe8,0xcb,0xfd,0xe8,0x1c,0xd9,0x33,0xc0,0xa3,0x85,0x37
+,0xa3,0x83,0x37,0xa3,0x87,0x37,0xa3,0x89,0x37,0xb8,0x91,0x03,0xcd,0x39,0xb8,0x80
+,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff,0xe5,0x00,0x25,0xff,0x53,0xe7,0x00
+,0x81,0x0e,0x9a,0x37,0x80,0x00,0xb8,0x92,0x03,0xcd,0x39,0x33,0xc0,0xe7,0x0e,0xbe
+,0x08,0x00,0x8e,0x06,0x38,0x34,0xe8,0x8e,0xe5,0x26,0xc7,0x06,0x04,0x00,0x7d,0x4b
+,0x83,0x26,0xef,0x34,0xdf,0xcd,0x50,0x83,0x0e,0xef,0x34,0x20,0xc3,0xf7,0x06,0x9a
+,0x37,0x80,0x00,0x74,0x32,0xa9,0xd0,0x07,0x74,0x0c,0xa9,0x00,0x04,0x74,0x0e,0x33
+,0xc0,0xe7,0x0e,0xe9,0xda,0xff,0xff,0x06,0x85,0x37,0xe9,0xd3,0xff,0xff,0x06,0x83
+,0x37,0xe9,0xcc,0xff,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0x36,0xfe,0x83,0x26,0x9a
+,0x37,0x7f,0xbb,0xff,0x7f,0xcd,0x53,0xe5,0x00,0x0d,0x00,0xac,0xe7,0x00,0xe5,0x02
+,0x25,0xff,0xfb,0x25,0xef,0xff,0x25,0xff,0xf7,0x0d,0x01,0x00,0xe7,0x02,0xa1,0x83
+,0x37,0x3b,0x06,0x46,0x37,0x7f,0xcd,0xa1,0x85,0x37,0x3b,0x06,0x48,0x37,0x7c,0xc4
+,0xc7,0x06,0xa3,0x36,0x03,0x00,0xbe,0x13,0x00,0xe8,0xfd,0x03,0xb8,0x93,0x03,0xcd
+,0x39,0xb8,0x94,0x03,0xcd,0x39,0xb8,0x96,0x03,0xcd,0x39,0xb8,0x95,0x03,0xcd,0x39
+,0xbe,0x06,0x00,0xe8,0xe3,0x03,0xe9,0xd6,0x03,0x83,0x3e,0xa3,0x36,0x03,0x74,0x01
+,0xc3,0xbe,0x13,0x00,0xe8,0xd2,0x03,0xb8,0x94,0x03,0xcd,0x39,0xc3,0xb8,0x94,0x03
+,0xcd,0x3a,0x26,0xa0,0x2b,0x00,0x26,0x8b,0x1e,0x2c,0x00,0xcd,0x34,0x83,0x3e,0xa3
+,0x36,0x03,0x74,0x03,0xe9,0xa8,0x03,0x3c,0x0d,0x75,0x3e,0x83,0xfb,0x00,0x75,0x39
+,0xe5,0x02,0x0d,0x00,0x20,0xe7,0x02,0xb8,0x93,0x03,0xcd,0x3a,0xc7,0x06,0xa3,0x36
+,0x04,0x00,0xbe,0x00,0x00,0xe8,0x0c,0xfc,0xc6,0x06,0x9d,0x36,0x80,0xc6,0x06,0x9e
+,0x36,0x00,0xc7,0x06,0x33,0x37,0x02,0x00,0xb8,0x9a,0x03,0xcd,0x39,0xe8,0xfc,0x00
+,0xc7,0x06,0x4c,0x37,0x00,0x00,0xe9,0x66,0x03,0xc7,0x06,0x3d,0x37,0x08,0x00,0xe9
+,0x61,0xfd,0x83,0x3e,0xa3,0x36,0x03,0x75,0x09,0xc7,0x06,0x3d,0x37,0x05,0x00,0xe9
+,0x51,0xfd,0xe9,0x4a,0x03,0x83,0x3e,0xa3,0x36,0x04,0x74,0x12,0x83,0x3e,0xa3,0x36
+,0x05,0x74,0x0b,0xcd,0x34,0xc7,0x06,0x3d,0x37,0x07,0x00,0xe9,0x35,0xfd,0xc7,0x06
+,0xa3,0x36,0x06,0x00,0xc6,0x06,0x9e,0x36,0xff,0xb8,0x9a,0x03,0xcd,0x3a,0xb8,0x99
+,0x03,0xcd,0x3a,0xb8,0x96,0x03,0xcd,0x3a,0xb8,0x97,0x03,0xcd,0x39,0xb8,0x98,0x03
+,0xcd,0x39,0xb8,0x9b,0x03,0xcd,0x39,0xe9,0x18,0xfd,0xcd,0x34,0x83,0x3e,0xa3,0x36
+,0x04,0x77,0x18,0x83,0x3e,0xa3,0x36,0x03,0x75,0x08,0xf7,0x06,0x9b,0x36,0x00,0x01
+,0x75,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xe8,0xfc,0xe9,0xe1,0x02,0xcd,0x34
+,0x83,0x3e,0xa3,0x36,0x02,0x77,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xd3,0xfc
+,0x83,0x3e,0xa3,0x36,0x04,0x77,0x05,0xb8,0x96,0x03,0xcd,0x39,0xe9,0xc0,0x02,0x83
+,0x3e,0xa3,0x36,0x03,0x75,0x10,0x26,0xa1,0x0c,0x00,0x25,0x07,0x00,0x50,0x3d,0x04
+,0x00,0x75,0x03,0xe8,0x36,0x00,0xa1,0xf3,0x36,0x86,0xe0,0xe7,0x1e,0xa3,0xe3,0x36
+,0x81,0x26,0x0b,0x37,0x00,0x03,0x81,0x26,0x0d,0x37,0x7b,0x7f,0x83,0x0e,0x0d,0x37
+,0x48,0xe8,0x14,0xf3,0x58,0x3d,0x04,0x00,0x74,0x09,0x26,0xf7,0x06,0x0c,0x00,0x20
+,0x00,0x75,0x06,0xb8,0x01,0x00,0xe9,0x7a,0x02,0xe9,0x86,0xfc,0xa1,0xe5,0x36,0xe7
+,0x2e,0xa1,0xe7,0x36,0xe7,0x3e,0xa1,0xd3,0x36,0xa3,0x9c,0x34,0xa1,0xd5,0x36,0xa3
+,0x9e,0x34,0xc3,0x26,0x80,0x3e,0x1c,0x00,0xff,0x75,0x2f,0x26,0x80,0x3e,0x1e,0x00
+,0xff,0x75,0x27,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00,0x75,0x1b,0xa1,0xd1,0x36,0x26
+,0xa3,0x1a,0x00,0xa1,0xd3,0x36,0x26,0xa3,0x1c,0x00,0xa1,0xd5,0x36,0x26,0xa3,0x1e
+,0x00,0xb8,0x0a,0x80,0xe9,0x2c,0x02,0xe9,0x38,0xfc,0xff,0x06,0x90,0x34,0xbe,0x0a
+,0x00,0xc6,0x06,0xb6,0x34,0x01,0xf6,0x06,0x9d,0x36,0x80,0x75,0x05,0x83,0x0e,0xc2
+,0x34,0x01,0xcd,0x34,0xe9,0x0c,0xfc,0x83,0x3e,0xa3,0x36,0x03,0x75,0x09,0xc7,0x06
+,0x3d,0x37,0x05,0x00,0xe9,0xfc,0xfb,0xe5,0x02,0x0d,0x03,0x00,0x0d,0x00,0x88,0x0d
+,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02,0xc7,0x06,0xa3,0x36,0x05,0x00,0xc6,0x06,0x9e
+,0x36,0xff,0xbe,0x02,0x00,0xe8,0xe1,0x01,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x9a,0x03
+,0xcd,0x3a,0xb8,0x99,0x03,0xcd,0x39,0xb8,0x97,0x03,0xcd,0x39,0xb8,0x98,0x03,0xcd
+,0x39,0xe9,0xbb,0x01,0x83,0x3e,0xa3,0x36,0x03,0x74,0x0a,0x83,0x3e,0xa3,0x36,0x04
+,0x74,0x03,0xe9,0xaa,0x01,0xbe,0x06,0x00,0xe8,0xae,0x01,0xb8,0x95,0x03,0xcd,0x39
+,0xe9,0x9c,0x01,0x83,0x3e,0xa3,0x36,0x05,0x74,0x03,0xe9,0x92,0x01,0xbe,0x02,0x00
+,0xe8,0x96,0x01,0xb8,0x99,0x03,0xcd,0x39,0xe9,0x84,0x01,0xc7,0x06,0x0f,0x37,0x05
+,0x00,0xe9,0x7b,0x01,0xe5,0x02,0x25,0xff,0xdf,0xe7,0x02,0xc7,0x06,0xa3,0x36,0x07
+,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xe9,0x65,0x01,0xe8,0xd5,0x04,0xc6,0x06,0x9d
+,0x36,0x00,0xc7,0x06,0x9b,0x36,0x00,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xc7,0x06
+,0xa8,0x02,0x00,0x00,0xc7,0x06,0x4c,0x37,0x01,0x00,0xe5,0x02,0x25,0xf9,0xff,0x0d
+,0x03,0x00,0x0d,0x00,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02
+,0xe9,0x67,0xfc,0xb8,0x9a,0x03,0xcd,0x39,0xf7,0x06,0xf4,0x33,0x00,0x10,0x75,0x09
+,0xc7,0x06,0x33,0x37,0x02,0x00,0xe9,0x16,0x01,0xff,0x0e,0x33,0x37,0x74,0x03,0xe9
+,0x0d,0x01,0xff,0x06,0x8e,0x34,0x83,0x0e,0xc2,0x34,0x08,0xc7,0x06,0x3d,0x37,0x03
+,0x00,0xe9,0xff,0xfa,0xc3,0x52,0x50,0xba,0xe0,0x00,0xb8,0x00,0x10,0xef,0x58,0x5a
+,0xc3,0xc7,0x06,0x3d,0x37,0x00,0x00,0xe9,0xe9,0xfa,0xfa,0xe8,0x54,0x04,0xb8,0x80
+,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04,0x00,0xd8,0x2b,0xb8,0x7f,0x03,0x8e,0xc0,0x26
+,0xc7,0x06,0x04,0x00,0xe8,0x2c,0x33,0xc0,0x8e,0xc0,0xa1,0xa7,0x36,0xa3,0xa9,0x36
+,0xa1,0xa9,0x36,0xe7,0x00,0xa1,0xab,0x36,0xe7,0x02,0xc7,0x06,0x05,0x37,0x00,0x00
+,0xc7,0x06,0x07,0x37,0x00,0x00,0xc7,0x06,0x09,0x37,0x00,0x00,0xc6,0x06,0x9d,0x36
+,0x00,0xc6,0x06,0x9e,0x36,0xff,0xc7,0x06,0x9b,0x36,0x00,0x00,0xc7,0x06,0xa3,0x36
+,0x00,0x00,0xc7,0x06,0x0f,0x37,0x00,0x00,0xc7,0x06,0xa8,0x02,0x00,0x00,0xc7,0x06
+,0x4c,0x37,0x01,0x00,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0xbb
+,0xff,0x7f,0xcd,0x53,0xe8,0x7c,0xf9,0xe5,0x56,0x0d,0x02,0x00,0xe7,0x56,0xfb,0xc3
+,0x8d,0x3e,0xc0,0x53,0x8d,0x36,0xf0,0x38,0xb9,0x0e,0x00,0x8b,0x1e,0x30,0x34,0x89
+,0x5c,0x02,0x2e,0x8b,0x45,0x02,0x89,0x44,0x06,0x2e,0x8b,0x05,0x89,0x44,0x04,0x83
+,0xc7,0x04,0x83,0xc6,0x10,0xe2,0xe8,0xb8,0x80,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04
+,0x00,0xe2,0x51,0xb8,0x7f,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04,0x00,0xb2,0x52,0x33
+,0xc0,0x8e,0xc0,0xc7,0x06,0xa1,0x36,0x01,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xc3
+,0x33,0xff,0x8e,0x06,0xa6,0x02,0x8b,0x36,0xa4,0x02,0x2e,0xff,0xa4,0xa0,0x53,0xe8
+,0x8c,0xdb,0xc3,0xe8,0x48,0xf7,0xe9,0xf6,0xff,0x8e,0x06,0x38,0x34,0xe8,0x07,0xe1
+,0x26,0xc7,0x06,0x04,0x00,0xdf,0x4f,0xcd,0x50,0xc3,0x26,0xc7,0x06,0x0a,0x00,0x00
+,0x00,0x26,0xff,0x26,0x04,0x00,0xcd,0x34,0xe9,0xd4,0xff,0xa1,0xd1,0x36,0x26,0x39
+,0x06,0x1a,0x00,0x75,0x22,0xa1,0xd3,0x36,0x26,0x39,0x06,0x1c,0x00,0x75,0x18,0xa1
+,0xd5,0x36,0x26,0x39,0x06,0x1e,0x00,0x75,0x0e,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00
+,0x74,0x05,0x83,0x0e,0x66,0x37,0x40,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1,0xaf,0x36
+,0xe7,0x06,0x83,0x3e,0xa3,0x36,0x02,0x75,0x05,0xcd,0x34,0xe9,0x56,0xfb,0x83,0x3e
+,0xa3,0x36,0x00,0x74,0xb1,0x83,0x3e,0xa3,0x36,0x05,0x77,0xaa,0x26,0xf6,0x06,0x0a
+,0x00,0xff,0x75,0xa2,0xe8,0xfd,0xdd,0x50,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xe9
+,0x8c,0x00,0x26,0xa1,0x0c,0x00,0x25,0x07,0x00,0x3d,0x07,0x00,0x75,0x03,0xe9,0x76
+,0x00,0x3d,0x05,0x00,0x75,0x03,0xe9,0x6e,0x00,0xf7,0x06,0xe6,0x34,0x18,0x80,0x75
+,0x03,0xe9,0x6a,0x00,0xf7,0x06,0xe6,0x34,0x00,0x80,0x74,0x35,0x26,0x80,0x3e,0x29
+,0x00,0x02,0x75,0x2d,0x51,0x56,0x57,0x8d,0x36,0x3e,0x34,0x8d,0x3e,0x20,0x00,0xb9
+,0x06,0x00,0xf3,0xa6,0x5f,0x5e,0x59,0x75,0x45,0x26,0xa1,0x20,0x00,0xa3,0x3e,0x34
+,0x26,0xa1,0x22,0x00,0xa3,0x40,0x34,0x26,0xa1,0x24,0x00,0xa3,0x42,0x34,0xe9,0x26
+,0x00,0xf7,0x06,0xe6,0x34,0x08,0x00,0x74,0x0b,0x26,0x80,0x3e,0x19,0x00,0x00,0x74
+,0x03,0xe9,0x13,0x00,0xf7,0x06,0xe6,0x34,0x10,0x00,0x74,0x12,0x26,0xa0,0x28,0x00
+,0xc0,0xe8,0x04,0x22,0xc0,0x74,0x07,0x26,0xc7,0x06,0x04,0x00,0xff,0xff,0x58,0x23
+,0xc0,0x74,0x03,0xe9,0xdd,0xfe,0x81,0x26,0x9b,0x36,0xff,0xfe,0x26,0xa1,0x20,0x00
+,0x3b,0x06,0xd1,0x36,0x75,0x1a,0x26,0xa1,0x22,0x00,0x3b,0x06,0xd3,0x36,0x75,0x10
+,0x26,0xa1,0x24,0x00,0x3b,0x06,0xd5,0x36,0x75,0x06,0x81,0x0e,0x9b,0x36,0x00,0x01
+,0x26,0xa1,0x20,0x00,0x25,0x7f,0xff,0xa3,0xb8,0x34,0x26,0xa1,0x22,0x00,0xa3,0xba
+,0x34,0x26,0xa1,0x24,0x00,0xa3,0xbc,0x34,0x8b,0xc6,0x86,0xc4,0xa3,0xc0,0x34,0xd1
+,0xe6,0x80,0xfc,0x09,0x74,0x03,0xe8,0xf6,0xf5,0xa1,0x05,0x37,0x0b,0x06,0x07,0x37
+,0x0b,0x06,0x09,0x37,0x74,0x3e,0x26,0xa1,0x20,0x00,0x3b,0x06,0x05,0x37,0x75,0x17
+,0x26,0xa1,0x22,0x00,0x3b,0x06,0x07,0x37,0x75,0x0d,0x26,0xa1,0x24,0x00,0x3b,0x06
+,0x09,0x37,0x75,0x03,0xe9,0x1d,0x00,0x26,0xa0,0x28,0x00,0x24,0x0f,0x3c,0x03,0x74
+,0x1b,0x3c,0x00,0x75,0x0f,0x83,0x3e,0xa3,0x36,0x04,0x74,0x10,0xf7,0x06,0x9b,0x36
+,0x00,0x01,0x74,0x08,0x2e,0xff,0x94,0xf8,0x53,0xe9,0x33,0xfe,0xcd,0x34,0xc7,0x06
+,0x3d,0x37,0x01,0x00,0xe9,0x2c,0xf8,0x83,0x3e,0xa3,0x36,0x05,0x74,0x10,0x83,0x3e
+,0xa3,0x36,0x01,0x7e,0x09,0x83,0xee,0x16,0x2e,0xff,0x94,0x24,0x54,0xc3,0xcd,0x34
+,0xc3,0x26,0xa1,0x0c,0x00,0x3d,0xff,0x7f,0x74,0x05,0x26,0xff,0x26,0x04,0x00,0xe9
+,0xfd,0xfd,0xa1,0xf4,0x33,0xa9,0x00,0x88,0x74,0x0b,0xa9,0x00,0x10,0x75,0x09,0x8b
+,0x1e,0x43,0x37,0xff,0xe3,0xe9,0x97,0x00,0xc7,0x06,0x35,0x37,0x05,0x00,0xc7,0x06
+,0x43,0x37,0x28,0x52,0xf7,0x06,0xf4,0x33,0x00,0x08,0x74,0x06,0xc7,0x06,0x43,0x37
+,0x1a,0x52,0xb8,0x80,0x03,0xcd,0x39,0xe9,0xc5,0xfd,0xa9,0x00,0x08,0x74,0xd9,0xff
+,0x0e,0x35,0x37,0x75,0xed,0xe9,0x30,0x00,0xa9,0x00,0x08,0x75,0xcb,0xff,0x0e,0x35
+,0x37,0x75,0xdf,0x81,0x0e,0xc2,0x34,0xc0,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74,0x0f
+,0x81,0x0e,0x9b,0x36,0x00,0x80,0xc7,0x06,0x0f,0x37,0x02,0x00,0xe9,0x90,0xfd,0xc7
+,0x06,0x3d,0x37,0x02,0x00,0xe9,0x8b,0xf7,0x80,0x26,0x9e,0x36,0xff,0x75,0x30,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x20,0xff,0x06,0x94,0x34,0x83,0x0e,0x66,0x37,0x20,0x8e
+,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08
+,0x00,0x00,0x01,0xe9,0x09,0x00,0xc7,0x06,0x3d,0x37,0x04,0x00,0xe9,0x54,0xf7,0x81
+,0x0e,0xaf,0x36,0x00,0x08,0xa1,0xaf,0x36,0xe7,0x06,0xe5,0x0a,0xa9,0x00,0x80,0x74
+,0x0e,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36,0xe7,0x06,0xe9,0x49,0xff,0xe9
+,0x2d,0xfd,0xc7,0x06,0x41,0x37,0x00,0x00,0xbe,0x29,0x00,0xe8,0x2b,0xfd,0xe9,0x1e
+,0xfd,0xcd,0x34,0x83,0x3e,0xa3,0x36,0x04,0x77,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00
+,0xe9,0x10,0xf7,0xe9,0x09,0xfd,0xcd,0x34,0xc3,0xc7,0x06,0x9b,0x36,0x00,0x00,0xe8
+,0x0c,0xf5,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0x81,0x26,0x9b
+,0x36,0xff,0x7f,0xe5,0x02,0x0d,0x01,0x00,0x25,0xef,0xff,0x25,0xff,0xdf,0xe7,0x02
+,0xbb,0xff,0x7f,0xcd,0x53,0x33,0xc0,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xe8,0x20,0xf3
+,0xe8,0x43,0xf3,0x83,0x0e,0x9b,0x36,0x10,0xc7,0x06,0x99,0x36,0x00,0x00,0xe8,0xd2
+,0xf5,0xe5,0x56,0x0d,0x02,0x00,0xe7,0x56,0xc7,0x06,0xa8,0x02,0x00,0x00,0xbe,0x00
+,0x00,0xe8,0x30,0xf5,0xc6,0x06,0xa0,0x36,0x0e,0xb8,0x9c,0x03,0xcd,0x39,0xb8,0x80
+,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff,0xc7,0x06,0xa1,0x36,0x01,0x00,0xe9
+,0xa5,0xf6,0x06,0xb8,0x8f,0x03,0xcd,0x3a,0xb8,0x90,0x03,0xcd,0x3a,0xb8,0x91,0x03
+,0xcd,0x3a,0xb8,0x92,0x03,0xcd,0x3a,0xb8,0x93,0x03,0xcd,0x3a,0xb8,0x94,0x03,0xcd
+,0x3a,0xb8,0x95,0x03,0xcd,0x3a,0xb8,0x96,0x03,0xcd,0x3a,0xb8,0x97,0x03,0xcd,0x3a
+,0xb8,0x98,0x03,0xcd,0x3a,0xb8,0x99,0x03,0xcd,0x3a,0xb8,0x9a,0x03,0xcd,0x3a,0xb8
+,0x9b,0x03,0xcd,0x3a,0xb8,0x7f,0x03,0xcd,0x3a,0xb8,0x80,0x03,0xcd,0x3a,0x07,0xc3
+,0xf7,0x49,0xf1,0x4e,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xf8,0x51,0xdf,0x4f
+,0xfa,0x4f,0x0b,0x50,0xd1,0x51,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f
+,0xe4,0x4e,0x06,0x00,0xcd,0x4a,0x04,0x00,0xe4,0x4e,0x19,0x00,0xad,0x4b,0xfa,0x00
+,0x82,0x4c,0x08,0x07,0x09,0x4c,0x14,0x00,0x24,0x4e,0x64,0x00,0xd7,0x4d,0xf4,0x01
+,0x64,0x4e,0xbc,0x02,0x7a,0x4e,0xe8,0x03,0x43,0x4e,0x02,0x00,0xb3,0x4e,0xf4,0x01
+,0x5b,0x4e,0xf4,0x01,0xe5,0x4e,0x14,0x00,0x06,0x50,0x06,0x50,0x95,0x4c,0xc1,0x52
+,0xc1,0x52,0xfe,0x4c,0xda,0x4c,0x06,0x50,0x06,0x50,0x06,0x50,0x06,0x50,0xb7,0x51
+,0xb7,0x51,0xb7,0x51,0xb7,0x51,0xb7,0x51,0xb7,0x51,0x06,0x50,0xd5,0x4a,0x06,0x50
+,0x1d,0x4c,0x06,0x50,0x83,0x4d,0x1f,0x4d,0x1f,0x4d,0xed,0x40,0xfa,0x40,0x07,0x41
+,0x37,0x37,0x2e,0x37,0x37,0x20,0x20,0x79,0x79,0x2f,0x79,0x79,0x2f,0x79,0x79,0x20
+,0x30,0x31,0x2e,0x39,0x30,0x20,0x20,0x30,0x32,0x2f,0x31,0x37,0x2f,0x39,0x39,0x20
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x90,0xea,0xc0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x06
+} ;  
+#endif 
diff -Nru a/drivers/net/tokenring/Config.help b/drivers/net/tokenring/Config.help
--- a/drivers/net/tokenring/Config.help	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/tokenring/Config.help	Tue Feb 26 11:57:59 2002
@@ -129,3 +129,21 @@
   The module will be called smctr.o. If you want to compile it
   as a module, say M here and read <file:Documentation/modules.txt>.
 
+3COM 3C359 Token Link Velocity XL PCI adapter support
+CONFIG_3C359
+  This is support for the 3Com PCI Velocity XL cards, specifically
+  the 3Com 3C359, please note this is not for the 3C339 cards, you
+  should use the tms380 driver instead.
+
+  If you have such an adapter, say Y and read the Token-Ring
+  mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
+
+  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 will be called 3c359.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+
+  Also read the file <file:Documentation/networking/3c359.txt> or check the 
+  Linux Token Ring Project site for the latest information at
+  <http://www.linuxtr.net>
+
diff -Nru a/drivers/net/tokenring/Config.in b/drivers/net/tokenring/Config.in
--- a/drivers/net/tokenring/Config.in	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/tokenring/Config.in	Tue Feb 26 11:57:58 2002
@@ -18,6 +18,7 @@
    fi
    dep_tristate '  IBM Olympic chipset PCI adapter support' CONFIG_IBMOL $CONFIG_TR $CONFIG_PCI
    dep_tristate '  IBM Lanstreamer chipset PCI adapter support' CONFIG_IBMLS $CONFIG_TR $CONFIG_PCI
+   dep_tristate '  3Com 3C359 Token Link Velocity XL adapter support' CONFIG_3C359 $CONFIG_TR $CONFIG_PCI
    tristate '  Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR
    if [ "$CONFIG_TMS380TR" != "n" ]; then
       dep_tristate '    Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_PCI
diff -Nru a/drivers/net/tokenring/Makefile b/drivers/net/tokenring/Makefile
--- a/drivers/net/tokenring/Makefile	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/tokenring/Makefile	Tue Feb 26 11:57:57 2002
@@ -21,6 +21,7 @@
 obj-$(CONFIG_TMSPCI) 	+= tmspci.o
 obj-$(CONFIG_TMSISA) 	+= tmsisa.o
 obj-$(CONFIG_SMCTR) 	+= smctr.o
+obj-$(CONFIG_3C359)	+= 3c359.o
 
 O_TARGET := tr.o
 
diff -Nru a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
--- a/drivers/net/tokenring/abyss.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/tokenring/abyss.c	Tue Feb 26 11:57:58 2002
@@ -433,7 +433,7 @@
 	return 0;
 }
 
-static void __exit abyss_detach (struct pci_dev *pdev)
+static void __devexit abyss_detach (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	
@@ -451,7 +451,7 @@
 	name:		"abyss",
 	id_table:	abyss_pci_tbl,
 	probe:		abyss_attach,
-	remove:		abyss_detach,
+	remove:		__devexit_p(abyss_detach),
 };
 
 static int __init abyss_init (void)
diff -Nru a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
--- a/drivers/net/tokenring/lanstreamer.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/tokenring/lanstreamer.c	Tue Feb 26 11:57:59 2002
@@ -1812,7 +1812,7 @@
   name:       "lanstreamer",
   id_table:   streamer_pci_tbl,
   probe:      streamer_init_one,
-  remove:     streamer_remove_one,
+  remove:     __devexit_p(streamer_remove_one),
 };
 
 static int __init streamer_init_module(void) {
diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
--- a/drivers/net/tokenring/olympic.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/tokenring/olympic.c	Tue Feb 26 11:57:58 2002
@@ -433,8 +433,6 @@
 	do {
 		int i;
 
-		save_flags(flags);
-		cli();
 		for(i=0;i<SRB_COMMAND_SIZE;i+=4)
 			writel(0,init_srb+i);
 		if(SRB_COMMAND_SIZE & 2)
@@ -465,10 +463,12 @@
 			memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ;  
 		} 	
 		writeb(1,init_srb+30);
-	
+
+		spin_lock_irqsave(&olympic_priv->olympic_lock,flags);	
 		olympic_priv->srb_queued=1;
 
 		writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 
 		t = jiffies ; 
 	
@@ -496,7 +496,6 @@
 		remove_wait_queue(&olympic_priv->srb_wait,&wait) ; 
 		set_current_state(TASK_RUNNING) ; 
 
-		restore_flags(flags);
 #if OLYMPIC_DEBUG
 		printk("init_srb(%p): ",init_srb);
 		for(i=0;i<20;i++)
@@ -1058,12 +1057,11 @@
 	writeb(0,srb+1);
 	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
 
-	save_flags(flags);
-	cli();	
-
+	spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
 	olympic_priv->srb_queued=1;
 
 	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+	spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 	
 	t = jiffies ; 
 
@@ -1088,7 +1086,6 @@
 	remove_wait_queue(&olympic_priv->srb_wait,&wait) ; 
 	set_current_state(TASK_RUNNING) ; 
 
-	restore_flags(flags) ; 
 	olympic_priv->rx_status_last_received++;
 	olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
 
@@ -1760,7 +1757,7 @@
 	name:		"olympic",
 	id_table:	olympic_pci_tbl,
 	probe:		olympic_probe,
-	remove:		olympic_remove_one
+	remove:		__devexit_p(olympic_remove_one)
 };
 
 static int __init olympic_pci_init(void) 
diff -Nru a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
--- a/drivers/net/tokenring/tmspci.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/tokenring/tmspci.c	Tue Feb 26 11:58:00 2002
@@ -220,7 +220,7 @@
 	return val;
 }
 
-static void __exit tms_pci_detach (struct pci_dev *pdev)
+static void __devexit tms_pci_detach (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -238,7 +238,7 @@
 	name:		"tmspci",
 	id_table:	tmspci_pci_tbl,
 	probe:		tms_pci_attach,
-	remove:		tms_pci_detach,
+	remove:		__devexit_p(tms_pci_detach),
 };
 
 static int __init tms_pci_init (void)
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/via-rhine.c	Tue Feb 26 11:57:59 2002
@@ -321,6 +321,7 @@
 	VT86C100A = 0,
 	VT6102,
 	VT3043,
+	VT6105,
 };
 
 struct via_rhine_chip_info {
@@ -349,7 +350,7 @@
 	{ "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256,
 	  CanHaveMII | HasWOL },
 	{ "VIA VT3043 Rhine",    RHINE_IOTYPE, 128,
-	  CanHaveMII | ReqTxAlign }
+	  CanHaveMII | ReqTxAlign },
 	{ "VIA VT6105 Rhine-III", RHINE_IOTYPE, 256,
 	  CanHaveMII | HasWOL },
 };
@@ -1753,7 +1754,7 @@
 	name:		"via-rhine",
 	id_table:	via_rhine_pci_tbl,
 	probe:		via_rhine_init_one,
-	remove:		via_rhine_remove_one,
+	remove:		__devexit_p(via_rhine_remove_one),
 };
 
 
diff -Nru a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
--- a/drivers/net/wan/Makefile	Tue Feb 26 11:57:56 2002
+++ b/drivers/net/wan/Makefile	Tue Feb 26 11:57:56 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the Linux network (wan) device drivers.
 #
-# 3 Aug 2000, Christoph Hellwig <hch@caldera.de>
+# 3 Aug 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
--- a/drivers/net/wan/farsync.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/wan/farsync.c	Tue Feb 26 11:57:57 2002
@@ -1810,7 +1810,7 @@
         name:           FST_NAME,
         id_table:       fst_pci_dev_id,
         probe:          fst_add_one,
-        remove:         fst_remove_one,
+        remove:         __devexit_p(fst_remove_one),
         suspend:        NULL,
         resume:         NULL,
 };
diff -Nru a/drivers/net/winbond-840.c b/drivers/net/winbond-840.c
--- a/drivers/net/winbond-840.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/winbond-840.c	Tue Feb 26 11:57:57 2002
@@ -1732,7 +1732,7 @@
 	name:		DRV_NAME,
 	id_table:	w840_pci_tbl,
 	probe:		w840_probe1,
-	remove:		w840_remove1,
+	remove:		__devexit_p(w840_remove1),
 #ifdef CONFIG_PM
 	suspend:	w840_suspend,
 	resume:		w840_resume,
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/net/wireless/airo.c	Tue Feb 26 11:57:57 2002
@@ -63,7 +63,7 @@
 	name:     "airo",
 	id_table: card_ids,
 	probe:    airo_pci_probe,
-	remove:   airo_pci_remove,
+	remove:   __devexit_p(airo_pci_remove),
 };
 #endif /* CONFIG_PCI */
 
diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
--- a/drivers/net/wireless/netwave_cs.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/wireless/netwave_cs.c	Tue Feb 26 11:57:59 2002
@@ -63,6 +63,9 @@
 
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif	/* WIRELESS_EXT > 12 */
 #endif
 
 #include <pcmcia/version.h>
@@ -269,6 +272,16 @@
    because they generally can't be allocated dynamically.
 */
 
+#if WIRELESS_EXT <= 12
+/* Wireless extensions backward compatibility */
+
+/* Part of iw_handler prototype we need */
+struct iw_request_info
+{
+	__u16		cmd;		/* Wireless Extension command */
+	__u16		flags;		/* More to come ;-) */
+};
+
 /* Wireless Extension Backward compatibility - Jean II
  * If the new wireless device private ioctl range is not defined,
  * default to standard device private ioctl range */
@@ -276,8 +289,11 @@
 #define SIOCIWFIRSTPRIV	SIOCDEVPRIVATE
 #endif /* SIOCIWFIRSTPRIV */
 
-#define SIOCGIPSNAP	SIOCIWFIRSTPRIV		/* Site Survey Snapshot */
-/*#define SIOCGIPQTHR	SIOCIWFIRSTPRIV + 1*/
+#else	/* WIRELESS_EXT <= 12 */
+static const struct iw_handler_def	netwave_handler_def;
+#endif	/* WIRELESS_EXT <= 12 */
+
+#define SIOCGIPSNAP	SIOCIWFIRSTPRIV	+ 1	/* Site Survey Snapshot */
 
 #define MAX_ESA 10
 
@@ -483,7 +499,10 @@
     /* wireless extensions */
 #ifdef WIRELESS_EXT
     dev->get_wireless_stats = &netwave_get_wireless_stats;
-#endif
+#if WIRELESS_EXT > 12
+    dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
+#endif /* WIRELESS_EXT > 12 */
+#endif /* WIRELESS_EXT */
     dev->do_ioctl = &netwave_ioctl;
 
     dev->tx_timeout = &netwave_watchdog;
@@ -596,6 +615,303 @@
 } /* netwave_flush_stale_links */
 
 /*
+ * Wireless Handler : get protocol name
+ */
+static int netwave_get_name(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	strcpy(wrqu->name, "Netwave");
+	return 0;
+}
+
+/*
+ * Wireless Handler : set Network ID
+ */
+static int netwave_set_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long flags;
+	ioaddr_t iobase = dev->base_addr;
+	netwave_private *priv = (netwave_private *) dev->priv;
+	u_char *ramBase = priv->ramBase;
+
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+
+#if WIRELESS_EXT > 8
+	if(!wrqu->nwid.disabled) {
+	    domain = wrqu->nwid.value;
+#else	/* WIRELESS_EXT > 8 */
+	if(wrqu->nwid.on) {
+	    domain = wrqu->nwid.nwid;
+#endif	/* WIRELESS_EXT > 8 */
+	    printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", 
+		    (domain >> 8) & 0x01, domain & 0xff);
+	    wait_WOC(iobase);
+	    writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0);
+	    writeb( domain & 0xff, ramBase + NETWAVE_EREG_CB + 1);
+	    writeb((domain >>8 ) & 0x01,ramBase + NETWAVE_EREG_CB+2);
+	    writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+	}
+
+	/* ReEnable interrupts & restore flags */
+	restore_flags(flags);
+    
+	return 0;
+}
+
+/*
+ * Wireless Handler : get Network ID
+ */
+static int netwave_get_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+#if WIRELESS_EXT > 8
+	wrqu->nwid.value = domain;
+	wrqu->nwid.disabled = 0;
+	wrqu->nwid.fixed = 1;
+#else	/* WIRELESS_EXT > 8 */
+	wrqu->nwid.nwid = domain;
+	wrqu->nwid.on = 1;
+#endif	/* WIRELESS_EXT > 8 */
+
+	return 0;
+}
+
+/*
+ * Wireless Handler : set scramble key
+ */
+static int netwave_set_scramble(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu,
+				char *key)
+{
+	unsigned long flags;
+	ioaddr_t iobase = dev->base_addr;
+	netwave_private *priv = (netwave_private *) dev->priv;
+	u_char *ramBase = priv->ramBase;
+
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+
+	scramble_key = (key[0] << 8) | key[1];
+	wait_WOC(iobase);
+	writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
+	writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
+	writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
+	writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+
+	/* ReEnable interrupts & restore flags */
+	restore_flags(flags);
+    
+	return 0;
+}
+
+/*
+ * Wireless Handler : get scramble key
+ */
+static int netwave_get_scramble(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu,
+				char *key)
+{
+	key[1] = scramble_key & 0xff;
+	key[0] = (scramble_key>>8) & 0xff;
+#if WIRELESS_EXT > 8
+	wrqu->encoding.flags = IW_ENCODE_ENABLED;
+	wrqu->encoding.length = 2;
+#else /* WIRELESS_EXT > 8 */
+	wrqu->encoding.method = 1;
+#endif	/* WIRELESS_EXT > 8 */
+
+	return 0;
+}
+
+#if WIRELESS_EXT > 8
+/*
+ * Wireless Handler : get mode
+ */
+static int netwave_get_mode(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	if(domain & 0x100)
+		wrqu->mode = IW_MODE_INFRA;
+	else
+		wrqu->mode = IW_MODE_ADHOC;
+
+	return 0;
+}
+#endif	/* WIRELESS_EXT > 8 */
+
+/*
+ * Wireless Handler : get range info
+ */
+static int netwave_get_range(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	struct iw_range *range = (struct iw_range *) extra;
+	int ret = 0;
+
+	/* Set the length (very important for backward compatibility) */
+	wrqu->data.length = sizeof(struct iw_range);
+
+	/* Set all the info we don't care or don't know about to zero */
+	memset(range, 0, sizeof(struct iw_range));
+
+#if WIRELESS_EXT > 10
+	/* Set the Wireless Extension versions */
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 9;	/* Nothing for us in v10 and v11 */
+#endif /* WIRELESS_EXT > 10 */
+		   
+	/* Set information in the range struct */
+	range->throughput = 450 * 1000;	/* don't argue on this ! */
+	range->min_nwid = 0x0000;
+	range->max_nwid = 0x01FF;
+
+	range->num_channels = range->num_frequency = 0;
+		   
+	range->sensitivity = 0x3F;
+	range->max_qual.qual = 255;
+	range->max_qual.level = 255;
+	range->max_qual.noise = 0;
+		   
+#if WIRELESS_EXT > 7
+	range->num_bitrates = 1;
+	range->bitrate[0] = 1000000;	/* 1 Mb/s */
+#endif /* WIRELESS_EXT > 7 */
+
+#if WIRELESS_EXT > 8
+	range->encoding_size[0] = 2;		/* 16 bits scrambling */
+	range->num_encoding_sizes = 1;
+	range->max_encoding_tokens = 1;	/* Only one key possible */
+#endif /* WIRELESS_EXT > 8 */
+
+	return ret;
+}
+
+/*
+ * Wireless Private Handler : get snapshot
+ */
+static int netwave_get_snap(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long flags;
+	ioaddr_t iobase = dev->base_addr;
+	netwave_private *priv = (netwave_private *) dev->priv;
+	u_char *ramBase = priv->ramBase;
+
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+
+	/* Take snapshot of environment */
+	netwave_snapshot( priv, ramBase, iobase);
+	wrqu->data.length = priv->nss.length;
+	memcpy(extra, (u_char *) &priv->nss, sizeof( struct site_survey));
+
+	priv->lastExec = jiffies;
+
+	/* ReEnable interrupts & restore flags */
+	restore_flags(flags);
+    
+	return(0);
+}
+
+/*
+ * Structures to export the Wireless Handlers
+ *     This is the stuff that are treated the wireless extensions (iwconfig)
+ */
+
+static const struct iw_priv_args netwave_private_args[] = {
+/*{ cmd,         set_args,                            get_args, name } */
+  { SIOCGIPSNAP, 0, 
+    IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(struct site_survey), 
+    "getsitesurvey" },
+};
+
+#if WIRELESS_EXT > 12
+
+static const iw_handler		netwave_handler[] =
+{
+	NULL,				/* SIOCSIWNAME */
+	netwave_get_name,		/* SIOCGIWNAME */
+	netwave_set_nwid,		/* SIOCSIWNWID */
+	netwave_get_nwid,		/* SIOCGIWNWID */
+	NULL,				/* SIOCSIWFREQ */
+	NULL,				/* SIOCGIWFREQ */
+	NULL,				/* SIOCSIWMODE */
+	netwave_get_mode,		/* SIOCGIWMODE */
+	NULL,				/* SIOCSIWSENS */
+	NULL,				/* SIOCGIWSENS */
+	NULL,				/* SIOCSIWRANGE */
+	netwave_get_range,		/* SIOCGIWRANGE */
+	NULL,				/* SIOCSIWPRIV */
+	NULL,				/* SIOCGIWPRIV */
+	NULL,				/* SIOCSIWSTATS */
+	NULL,				/* SIOCGIWSTATS */
+	NULL,				/* SIOCSIWSPY */
+	NULL,				/* SIOCGIWSPY */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWAP */
+	NULL,				/* SIOCGIWAP */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCGIWAPLIST */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWESSID */
+	NULL,				/* SIOCGIWESSID */
+	NULL,				/* SIOCSIWNICKN */
+	NULL,				/* SIOCGIWNICKN */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWRATE */
+	NULL,				/* SIOCGIWRATE */
+	NULL,				/* SIOCSIWRTS */
+	NULL,				/* SIOCGIWRTS */
+	NULL,				/* SIOCSIWFRAG */
+	NULL,				/* SIOCGIWFRAG */
+	NULL,				/* SIOCSIWTXPOW */
+	NULL,				/* SIOCGIWTXPOW */
+	NULL,				/* SIOCSIWRETRY */
+	NULL,				/* SIOCGIWRETRY */
+	netwave_set_scramble,		/* SIOCSIWENCODE */
+	netwave_get_scramble,		/* SIOCGIWENCODE */
+};
+
+static const iw_handler		netwave_private_handler[] =
+{
+	NULL,				/* SIOCIWFIRSTPRIV */
+	netwave_get_snap,		/* SIOCIWFIRSTPRIV + 1 */
+};
+
+static const struct iw_handler_def	netwave_handler_def =
+{
+	num_standard:	sizeof(netwave_handler)/sizeof(iw_handler),
+	num_private:	sizeof(netwave_private_handler)/sizeof(iw_handler),
+	num_private_args: sizeof(netwave_private_args)/sizeof(struct iw_priv_args),
+	standard:	(iw_handler *) netwave_handler,
+	private:	(iw_handler *) netwave_private_handler,
+	private_args:	(struct iw_priv_args *) netwave_private_args,
+};
+#endif /* WIRELESS_EXT > 12 */
+
+/*
  * Function netwave_ioctl (dev, rq, cmd)
  *
  *     Perform ioctl : config & info stuff
@@ -606,56 +922,28 @@
 			 struct ifreq *rq,	 /* Data passed */
 			 int	cmd)	     /* Ioctl number */
 {
-    unsigned long flags;
     int			ret = 0;
 #ifdef WIRELESS_EXT
-    ioaddr_t iobase = dev->base_addr;
-    netwave_private *priv = (netwave_private *) dev->priv;
-    u_char *ramBase = priv->ramBase;
+#if WIRELESS_EXT <= 12
     struct iwreq *wrq = (struct iwreq *) rq;
 #endif
+#endif
 	
     DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
 	
-    /* Disable interrupts & save flags */
-    save_flags(flags);
-    cli();
-
     /* Look what is the request */
     switch(cmd) {
 	/* --------------- WIRELESS EXTENSIONS --------------- */
 #ifdef WIRELESS_EXT
+#if WIRELESS_EXT <= 12
     case SIOCGIWNAME:
-	/* Get name */
-	strcpy(wrq->u.name, "Netwave");
+	netwave_get_name(dev, NULL, &(wrq->u), NULL);
 	break;
     case SIOCSIWNWID:
-	/* Set domain */
-#if WIRELESS_EXT > 8
-	if(!wrq->u.nwid.disabled) {
-	    domain = wrq->u.nwid.value;
-#else	/* WIRELESS_EXT > 8 */
-	if(wrq->u.nwid.on) {
-	    domain = wrq->u.nwid.nwid;
-#endif	/* WIRELESS_EXT > 8 */
-	    printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", 
-		    (domain >> 8) & 0x01, domain & 0xff);
-	    wait_WOC(iobase);
-	    writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0);
-	    writeb( domain & 0xff, ramBase + NETWAVE_EREG_CB + 1);
-	    writeb((domain >>8 ) & 0x01,ramBase + NETWAVE_EREG_CB+2);
-	    writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
-	} break;
+	ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
+	break;
     case SIOCGIWNWID:
-	/* Read domain*/
-#if WIRELESS_EXT > 8
-	wrq->u.nwid.value = domain;
-	wrq->u.nwid.disabled = 0;
-	wrq->u.nwid.fixed = 1;
-#else	/* WIRELESS_EXT > 8 */
-	wrq->u.nwid.nwid = domain;
-	wrq->u.nwid.on = 1;
-#endif	/* WIRELESS_EXT > 8 */
+	ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
 	break;
 #if WIRELESS_EXT > 8	/* Note : The API did change... */
     case SIOCGIWENCODE:
@@ -663,10 +951,7 @@
 	if(wrq->u.encoding.pointer != (caddr_t) 0)
 	  {
 	    char	key[2];
-	    key[1] = scramble_key & 0xff;
-	    key[0] = (scramble_key>>8) & 0xff;
-	    wrq->u.encoding.flags = IW_ENCODE_ENABLED;
-	    wrq->u.encoding.length = 2;
+	    ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
 	    if(copy_to_user(wrq->u.encoding.pointer, key, 2))
 	      ret = -EFAULT;
 	  }
@@ -681,127 +966,68 @@
 		ret = -EFAULT;
 		break;
 	      }
-	    scramble_key = (key[0] << 8) | key[1];
-	    wait_WOC(iobase);
-	    writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
-	    writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
-	    writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
-	    writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+	    ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
 	  }
 	break;
     case SIOCGIWMODE:
-      /* Mode of operation */
-	if(domain & 0x100)
-	  wrq->u.mode = IW_MODE_INFRA;
-	else
-	  wrq->u.mode = IW_MODE_ADHOC;
-      break;
+	/* Mode of operation */
+	ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
+	break;
 #else /* WIRELESS_EXT > 8 */
     case SIOCGIWENCODE:
 	/* Get scramble key */
-	wrq->u.encoding.code = scramble_key;
-	wrq->u.encoding.method = 1;
+	ret = netwave_get_scramble(dev, NULL, &(wrq->u),
+				   (char *) &wrq->u.encoding.code);
 	break;
     case SIOCSIWENCODE:
 	/* Set  scramble key */
-	scramble_key = wrq->u.encoding.code;
-	wait_WOC(iobase);
-	writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
-	writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
-	writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
-	writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+	ret = netwave_set_scramble(dev, NULL, &(wrq->u),
+				   (char *) &wrq->u.encoding.code);
 	break;
 #endif /* WIRELESS_EXT > 8 */
    case SIOCGIWRANGE:
        /* Basic checking... */
        if(wrq->u.data.pointer != (caddr_t) 0) {
-	   struct iw_range	range;
-		   
-	   /* Set the length (very important for backward compatibility) */
-	   wrq->u.data.length = sizeof(struct iw_range);
-
-	   /* Set all the info we don't care or don't know about to zero */
-	   memset(&range, 0, sizeof(range));
-
-#if WIRELESS_EXT > 10
-	   /* Set the Wireless Extension versions */
-	   range.we_version_compiled = WIRELESS_EXT;
-	   range.we_version_source = 9;	/* Nothing for us in v10 and v11 */
-#endif /* WIRELESS_EXT > 10 */
-		   
-	   /* Set information in the range struct */
-	   range.throughput = 450 * 1000;	/* don't argue on this ! */
-	   range.min_nwid = 0x0000;
-	   range.max_nwid = 0x01FF;
-
-	   range.num_channels = range.num_frequency = 0;
-		   
-	   range.sensitivity = 0x3F;
-	   range.max_qual.qual = 255;
-	   range.max_qual.level = 255;
-	   range.max_qual.noise = 0;
-		   
-#if WIRELESS_EXT > 7
-	   range.num_bitrates = 1;
-	   range.bitrate[0] = 1000000;	/* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
-
-#if WIRELESS_EXT > 8
-	   range.encoding_size[0] = 2;		/* 16 bits scrambling */
-	   range.num_encoding_sizes = 1;
-	   range.max_encoding_tokens = 1;	/* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
-
-	   /* Copy structure to the user buffer */
-	   if(copy_to_user(wrq->u.data.pointer, &range,
-			sizeof(struct iw_range)))
-	     ret = -EFAULT;
+           struct iw_range range;
+	   ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
+	   if (copy_to_user(wrq->u.data.pointer, &range,
+			    sizeof(struct iw_range)))
+	       ret = -EFAULT;
        }
        break;
     case SIOCGIWPRIV:
 	/* Basic checking... */
 	if(wrq->u.data.pointer != (caddr_t) 0) {
-	    struct iw_priv_args	priv[] =
-	    {	/* cmd,		set_args,	get_args,	name */
-		{ SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, 
-		  sizeof(struct site_survey), 
-		  "getsitesurvey" },
-	    };
-			
 	    /* Set the number of ioctl available */
-	    wrq->u.data.length = 1;
+	    wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
 			
 	    /* Copy structure to the user buffer */
-	    if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
-			 sizeof(priv)))
+	    if(copy_to_user(wrq->u.data.pointer,
+			    (u_char *) netwave_private_args,
+			    sizeof(netwave_private_args)))
 	      ret = -EFAULT;
 	} 
 	break;
     case SIOCGIPSNAP:
 	if(wrq->u.data.pointer != (caddr_t) 0) {
-	    /* Take snapshot of environment */
-	    netwave_snapshot( priv, ramBase, iobase);
-	    wrq->u.data.length = priv->nss.length;
+	    char buffer[sizeof( struct site_survey)];
+	    ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
 	    /* Copy structure to the user buffer */
 	    if(copy_to_user(wrq->u.data.pointer, 
-			 (u_char *) &priv->nss,
-			 sizeof( struct site_survey)))
+			    buffer,
+			    sizeof( struct site_survey)))
 	      {
 		printk(KERN_DEBUG "Bad buffer!\n");
 		break;
 	      }
-
-	    priv->lastExec = jiffies;
 	}
 	break;
-#endif
+#endif /* WIRELESS_EXT <= 12 */
+#endif /* WIRELESS_EXT */
     default:
 	ret = -EOPNOTSUPP;
     }
 	
-    /* ReEnable interrupts & restore flags */
-    restore_flags(flags);
-    
     return ret;
 }
 
diff -Nru a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
--- a/drivers/net/wireless/orinoco_plx.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/wireless/orinoco_plx.c	Tue Feb 26 11:58:00 2002
@@ -279,7 +279,7 @@
 	name:"orinoco_plx",
 	id_table:orinoco_plx_pci_id_table,
 	probe:orinoco_plx_init_one,
-	remove:orinoco_plx_remove_one,
+	remove:__devexit_p(orinoco_plx_remove_one),
 	suspend:0,
 	resume:0
 };
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/wireless/wavelan.c	Tue Feb 26 11:57:58 2002
@@ -24,28 +24,6 @@
 
 /*------------------------------------------------------------------*/
 /*
- * Wrapper for disabling interrupts and locking the driver.
- * (note : inline, so optimised away)
- */
-static inline void wv_splhi(net_local *		lp,
-			    unsigned long *	pflags)
-{
-	spin_lock_irqsave(&lp->spinlock, *pflags);
-	/* Note : above does the cli(); itself */
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wrapper for re-enabling interrupts and un-locking the driver.
- */
-static inline void wv_splx(net_local *		lp,
-			   unsigned long *	pflags)
-{
-	spin_unlock_irqrestore(&lp->spinlock, *pflags);
-}
-
-/*------------------------------------------------------------------*/
-/*
  * Translate irq number to PSA irq parameter
  */
 static u8 wv_irq_to_psa(int irq)
@@ -870,10 +848,10 @@
 
 	/* Check if we can do it now ! */
 	if((netif_running(dev)) && !(netif_queue_stopped(dev))) {
-		wv_splhi(lp, &flags);
+		spin_lock_irqsave(&lp->spinlock, flags);
 		/* May fail */
 		wv_82586_config(dev);
-		wv_splx(lp, &flags);
+		spin_unlock_irqrestore(&lp->spinlock, flags);
 	}
 	else {
 #ifdef DEBUG_CONFIG_INFO
@@ -1786,170 +1764,287 @@
 
 /*------------------------------------------------------------------*/
 /*
- * Perform ioctl for configuration and information.
- * It is here that the wireless extensions are treated (iwconfig).
+ * Wireless Handler : get protocol name
  */
-static int wavelan_ioctl(struct net_device *dev,	/* device on which the ioctl is applied */
-			 struct ifreq *rq,	/* data passed */
-			 int cmd)
-{				/* ioctl number */
+static int wavelan_get_name(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	strcpy(wrqu->name, "WaveLAN");
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set NWID
+ */
+static int wavelan_set_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
 	unsigned long ioaddr = dev->base_addr;
 	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
-	struct iwreq *wrq = (struct iwreq *) rq;
 	psa_t psa;
 	mm_t m;
 	unsigned long flags;
 	int ret = 0;
-	int err = 0;
 
-#ifdef DEBUG_IOCTL_TRACE
-	printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name,
-	       cmd);
-#endif
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Set NWID in WaveLAN. */
+	if (!wrqu->nwid.disabled) {
+		/* Set NWID in psa */
+		psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;
+		psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;
+		psa.psa_nwid_select = 0x01;
+		psa_write(ioaddr, lp->hacr,
+			  (char *) psa.psa_nwid - (char *) &psa,
+			  (unsigned char *) psa.psa_nwid, 3);
+
+		/* Set NWID in mmc. */
+		m.w.mmw_netw_id_l = psa.psa_nwid[1];
+		m.w.mmw_netw_id_h = psa.psa_nwid[0];
+		mmc_write(ioaddr,
+			  (char *) &m.w.mmw_netw_id_l -
+			  (char *) &m,
+			  (unsigned char *) &m.w.mmw_netw_id_l, 2);
+		mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
+	} else {
+		/* Disable NWID in the psa. */
+		psa.psa_nwid_select = 0x00;
+		psa_write(ioaddr, lp->hacr,
+			  (char *) &psa.psa_nwid_select -
+			  (char *) &psa,
+			  (unsigned char *) &psa.psa_nwid_select,
+			  1);
+
+		/* Disable NWID in the mmc (no filtering). */
+		mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
+			MMW_LOOPT_SEL_DIS_NWID);
+	}
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev, ioaddr, lp->hacr);
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get NWID 
+ */
+static int wavelan_get_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
 
 	/* Disable interrupts and save flags. */
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 	
-	/* Look what is the request */
-	switch (cmd) {
-		/* --------------- WIRELESS EXTENSIONS --------------- */
-
-	case SIOCGIWNAME:
-		strcpy(wrq->u.name, "WaveLAN");
-		break;
-
-	case SIOCSIWNWID:
-		/* Set NWID in WaveLAN. */
-		if (!wrq->u.nwid.disabled) {
-			/* Set NWID in psa */
-			psa.psa_nwid[0] =
-			    (wrq->u.nwid.value & 0xFF00) >> 8;
-			psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
-			psa.psa_nwid_select = 0x01;
-			psa_write(ioaddr, lp->hacr,
-				  (char *) psa.psa_nwid - (char *) &psa,
-				  (unsigned char *) psa.psa_nwid, 3);
+	/* Read the NWID. */
+	psa_read(ioaddr, lp->hacr,
+		 (char *) psa.psa_nwid - (char *) &psa,
+		 (unsigned char *) psa.psa_nwid, 3);
+	wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+	wrqu->nwid.disabled = !(psa.psa_nwid_select);
+	wrqu->nwid.fixed = 1;	/* Superfluous */
 
-			/* Set NWID in mmc. */
-			m.w.mmw_netw_id_l = psa.psa_nwid[1];
-			m.w.mmw_netw_id_h = psa.psa_nwid[0];
-			mmc_write(ioaddr,
-				  (char *) &m.w.mmw_netw_id_l -
-				  (char *) &m,
-				  (unsigned char *) &m.w.mmw_netw_id_l, 2);
-			mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
-		} else {
-			/* Disable NWID in the psa. */
-			psa.psa_nwid_select = 0x00;
-			psa_write(ioaddr, lp->hacr,
-				  (char *) &psa.psa_nwid_select -
-				  (char *) &psa,
-				  (unsigned char *) &psa.psa_nwid_select,
-				  1);
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-			/* Disable NWID in the mmc (no filtering). */
-			mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
-				MMW_LOOPT_SEL_DIS_NWID);
-		}
-		/* update the Wavelan checksum */
-		update_psa_checksum(dev, ioaddr, lp->hacr);
-		break;
+	return ret;
+}
 
-	case SIOCGIWNWID:
-		/* Read the NWID. */
-		psa_read(ioaddr, lp->hacr,
-			 (char *) psa.psa_nwid - (char *) &psa,
-			 (unsigned char *) psa.psa_nwid, 3);
-		wrq->u.nwid.value =
-		    (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
-		wrq->u.nwid.disabled = !(psa.psa_nwid_select);
-		wrq->u.nwid.fixed = 1;	/* Superfluous */
-		break;
-
-	case SIOCSIWFREQ:
-		/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
-		if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-		      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-			ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
-		else
-			ret = -EOPNOTSUPP;
-		break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int wavelan_set_freq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	int ret;
 
-	case SIOCGIWFREQ:
-		/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
-		 * Does it work for everybody, especially old cards? */
-		if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-		      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
-			unsigned short freq;
-
-			/* Ask the EEPROM to read the frequency from the first area. */
-			fee_read(ioaddr, 0x00, &freq, 1);
-			wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
-			wrq->u.freq.e = 1;
-		} else {
-			psa_read(ioaddr, lp->hacr,
-				 (char *) &psa.psa_subband - (char *) &psa,
-				 (unsigned char *) &psa.psa_subband, 1);
-
-			if (psa.psa_subband <= 4) {
-				wrq->u.freq.m =
-				    fixed_bands[psa.psa_subband];
-				wrq->u.freq.e = (psa.psa_subband != 0);
-			} else
-				ret = -EOPNOTSUPP;
-		}
-		break;
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+	if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+		ret = wv_set_frequency(ioaddr, &(wrqu->freq));
+	else
+		ret = -EOPNOTSUPP;
 
-	case SIOCSIWSENS:
-		/* Set the level threshold. */
-		/* We should complain loudly if wrq->u.sens.fixed = 0, because we
-		 * can't set auto mode... */
-		psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
-		psa_write(ioaddr, lp->hacr,
-			  (char *) &psa.psa_thr_pre_set - (char *) &psa,
-			  (unsigned char *) &psa.psa_thr_pre_set, 1);
-		/* update the Wavelan checksum */
-		update_psa_checksum(dev, ioaddr, lp->hacr);
-		mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
-			psa.psa_thr_pre_set);
-		break;
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
 
-	case SIOCGIWSENS:
-		/* Read the level threshold. */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int wavelan_get_freq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+	 * Does it work for everybody, especially old cards? */
+	if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+		unsigned short freq;
+
+		/* Ask the EEPROM to read the frequency from the first area. */
+		fee_read(ioaddr, 0x00, &freq, 1);
+		wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+		wrqu->freq.e = 1;
+	} else {
 		psa_read(ioaddr, lp->hacr,
-			 (char *) &psa.psa_thr_pre_set - (char *) &psa,
-			 (unsigned char *) &psa.psa_thr_pre_set, 1);
-		wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
-		wrq->u.sens.fixed = 1;
-		break;
-
-	case SIOCSIWENCODE:
-		/* Set encryption key */
-		if (!mmc_encr(ioaddr)) {
+			 (char *) &psa.psa_subband - (char *) &psa,
+			 (unsigned char *) &psa.psa_subband, 1);
+
+		if (psa.psa_subband <= 4) {
+			wrqu->freq.m = fixed_bands[psa.psa_subband];
+			wrqu->freq.e = (psa.psa_subband != 0);
+		} else
 			ret = -EOPNOTSUPP;
-			break;
-		}
+	}
 
-		/* Basic checking... */
-		if (wrq->u.encoding.pointer != (caddr_t) 0) {
-			/* Check the size of the key */
-			if (wrq->u.encoding.length != 8) {
-				ret = -EINVAL;
-				break;
-			}
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-			/* Copy the key in the driver */
-			wv_splx(lp, &flags);
-			err = copy_from_user(psa.psa_encryption_key,
-					     wrq->u.encoding.pointer,
-					     wrq->u.encoding.length);
-			wv_splhi(lp, &flags);
-			if (err) {
-				ret = -EFAULT;
-				break;
-			}
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set level threshold
+ */
+static int wavelan_set_sens(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Set the level threshold. */
+	/* We should complain loudly if wrqu->sens.fixed = 0, because we
+	 * can't set auto mode... */
+	psa.psa_thr_pre_set = wrqu->sens.value & 0x3F;
+	psa_write(ioaddr, lp->hacr,
+		  (char *) &psa.psa_thr_pre_set - (char *) &psa,
+		  (unsigned char *) &psa.psa_thr_pre_set, 1);
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev, ioaddr, lp->hacr);
+	mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
+		psa.psa_thr_pre_set);
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get level threshold
+ */
+static int wavelan_get_sens(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Read the level threshold. */
+	psa_read(ioaddr, lp->hacr,
+		 (char *) &psa.psa_thr_pre_set - (char *) &psa,
+		 (unsigned char *) &psa.psa_thr_pre_set, 1);
+	wrqu->sens.value = psa.psa_thr_pre_set & 0x3F;
+	wrqu->sens.fixed = 1;
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set encryption key
+ */
+static int wavelan_set_encode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	psa_t psa;
+	int ret = 0;
 
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+
+	/* Check if capable of encryption */
+	if (!mmc_encr(ioaddr)) {
+		ret = -EOPNOTSUPP;
+	}
+
+	/* Check the size of the key */
+	if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) {
+		ret = -EINVAL;
+	}
+
+	if(!ret) {
+		/* Basic checking... */
+		if (wrqu->encoding.length == 8) {
+			/* Copy the key in the driver */
+			memcpy(psa.psa_encryption_key, extra,
+			       wrqu->encoding.length);
 			psa.psa_encryption_select = 1;
+
 			psa_write(ioaddr, lp->hacr,
 				  (char *) &psa.psa_encryption_select -
 				  (char *) &psa,
@@ -1963,7 +2058,8 @@
 				  psa_encryption_key, 8);
 		}
 
-		if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) {	/* disable encryption */
+		/* disable encryption */
+		if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
 			psa.psa_encryption_select = 0;
 			psa_write(ioaddr, lp->hacr,
 				  (char *) &psa.psa_encryption_select -
@@ -1975,350 +2071,430 @@
 		}
 		/* update the Wavelan checksum */
 		update_psa_checksum(dev, ioaddr, lp->hacr);
-		break;
+	}
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
 
-	case SIOCGIWENCODE:
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get encryption key
+ */
+static int wavelan_get_encode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Check if encryption is available */
+	if (!mmc_encr(ioaddr)) {
+		ret = -EOPNOTSUPP;
+	} else {
 		/* Read the encryption key */
-		if (!mmc_encr(ioaddr)) {
-			ret = -EOPNOTSUPP;
-			break;
-		}
+		psa_read(ioaddr, lp->hacr,
+			 (char *) &psa.psa_encryption_select -
+			 (char *) &psa,
+			 (unsigned char *) &psa.
+			 psa_encryption_select, 1 + 8);
+
+		/* encryption is enabled ? */
+		if (psa.psa_encryption_select)
+			wrqu->encoding.flags = IW_ENCODE_ENABLED;
+		else
+			wrqu->encoding.flags = IW_ENCODE_DISABLED;
+		wrqu->encoding.flags |= mmc_encr(ioaddr);
 
-		/* only super-user can see encryption key */
-		if (!capable(CAP_NET_ADMIN)) {
-			ret = -EPERM;
-			break;
-		}
+		/* Copy the key to the user buffer */
+		wrqu->encoding.length = 8;
+		memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length);
+	}
 
-		/* Basic checking... */
-		if (wrq->u.encoding.pointer != (caddr_t) 0) {
-			/* Verify the user buffer */
-			ret =
-			    verify_area(VERIFY_WRITE,
-					wrq->u.encoding.pointer, 8);
-			if (ret)
-				break;
-
-			psa_read(ioaddr, lp->hacr,
-				 (char *) &psa.psa_encryption_select -
-				 (char *) &psa,
-				 (unsigned char *) &psa.
-				 psa_encryption_select, 1 + 8);
-
-			/* encryption is enabled ? */
-			if (psa.psa_encryption_select)
-				wrq->u.encoding.flags = IW_ENCODE_ENABLED;
-			else
-				wrq->u.encoding.flags = IW_ENCODE_DISABLED;
-			wrq->u.encoding.flags |= mmc_encr(ioaddr);
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-			/* Copy the key to the user buffer */
-			wrq->u.encoding.length = 8;
-			wv_splx(lp, &flags);
-			if (copy_to_user(wrq->u.encoding.pointer,
-					 psa.psa_encryption_key, 8))
-				ret = -EFAULT;
-			wv_splhi(lp, &flags);
-		}
-		break;
+	return ret;
+}
 
-	case SIOCGIWRANGE:
-		/* basic checking */
-		if (wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_range range;
-
-			/* Set the length (very important for backward
-			 * compatibility) */
-			wrq->u.data.length = sizeof(struct iw_range);
-
-			/* Set all the info we don't care or don't know
-			 * about to zero */
-			memset(&range, 0, sizeof(range));
-
-			/* Set the Wireless Extension versions */
-			range.we_version_compiled = WIRELESS_EXT;
-			range.we_version_source = 9;
-
-			/* Set information in the range struct.  */
-			range.throughput = 1.6 * 1000 * 1000;	/* don't argue on this ! */
-			range.min_nwid = 0x0000;
-			range.max_nwid = 0xFFFF;
-
-			/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
-			if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
-			      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
-				range.num_channels = 10;
-				range.num_frequency =
-				    wv_frequency_list(ioaddr, range.freq,
-						      IW_MAX_FREQUENCIES);
-			} else
-				range.num_channels = range.num_frequency =
-				    0;
-
-			range.sensitivity = 0x3F;
-			range.max_qual.qual = MMR_SGNL_QUAL;
-			range.max_qual.level = MMR_SIGNAL_LVL;
-			range.max_qual.noise = MMR_SILENCE_LVL;
-			range.avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
-			/* Need to get better values for those two */
-			range.avg_qual.level = 30;
-			range.avg_qual.noise = 8;
-
-			range.num_bitrates = 1;
-			range.bitrate[0] = 2000000;	/* 2 Mb/s */
-
-			/* Encryption supported ? */
-			if (mmc_encr(ioaddr)) {
-				range.encoding_size[0] = 8;	/* DES = 64 bits key */
-				range.num_encoding_sizes = 1;
-				range.max_encoding_tokens = 1;	/* Only one key possible */
-			} else {
-				range.num_encoding_sizes = 0;
-				range.max_encoding_tokens = 0;
-			}
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int wavelan_get_range(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct iw_range *range = (struct iw_range *) extra;
+	unsigned long flags;
+	int ret = 0;
 
-			/* Copy structure to the user buffer. */
-			wv_splx(lp, &flags);
-			if (copy_to_user(wrq->u.data.pointer,
-					 &range,
-					 sizeof(struct iw_range)))
-				ret = -EFAULT;
-			wv_splhi(lp, &flags);
-		}
-		break;
+	/* Set the length (very important for backward compatibility) */
+	wrqu->data.length = sizeof(struct iw_range);
 
-	case SIOCGIWPRIV:
-		/* Basic checking */
-		if (wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_priv_args priv[] = {
-				/* { cmd,
-				     set_args,
-				     get_args,
-				     name } */
-				{ SIOCSIPQTHR,
-				  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
-				  0,
-				  "setqualthr" },
-				{ SIOCGIPQTHR,
-				  0,
-				  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
-				  "getqualthr" },
-				{ SIOCSIPHISTO,
-				  IW_PRIV_TYPE_BYTE | 16,
-				  0,
-				  "sethisto" },
-				{ SIOCGIPHISTO,
-				  0,
-				  IW_PRIV_TYPE_INT | 16,
-				 "gethisto" },
-			};
-
-			/* Set the number of available ioctls. */
-			wrq->u.data.length = 4;
-
-			/* Copy structure to the user buffer. */
-			wv_splx(lp, &flags);
-			if (copy_to_user(wrq->u.data.pointer,
-					      (u8 *) priv,
-					      sizeof(priv)))
-				ret = -EFAULT;
-			wv_splhi(lp, &flags);
-		}
-		break;
+	/* Set all the info we don't care or don't know about to zero */
+	memset(range, 0, sizeof(struct iw_range));
 
-#ifdef WIRELESS_SPY
-	case SIOCSIWSPY:
-		/* Set the spy list */
+	/* Set the Wireless Extension versions */
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 9;
+
+	/* Set information in the range struct.  */
+	range->throughput = 1.6 * 1000 * 1000;	/* don't argue on this ! */
+	range->min_nwid = 0x0000;
+	range->max_nwid = 0xFFFF;
+
+	range->sensitivity = 0x3F;
+	range->max_qual.qual = MMR_SGNL_QUAL;
+	range->max_qual.level = MMR_SIGNAL_LVL;
+	range->max_qual.noise = MMR_SILENCE_LVL;
+	range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
+	/* Need to get better values for those two */
+	range->avg_qual.level = 30;
+	range->avg_qual.noise = 8;
 
-		/* Check the number of addresses. */
-		if (wrq->u.data.length > IW_MAX_SPY) {
-			ret = -E2BIG;
-			break;
-		}
-		lp->spy_number = wrq->u.data.length;
+	range->num_bitrates = 1;
+	range->bitrate[0] = 2000000;	/* 2 Mb/s */
 
-		/* Are there are addresses to copy? */
-		if (lp->spy_number > 0) {
-			struct sockaddr address[IW_MAX_SPY];
-			int i;
-
-			/* Copy addresses to the driver. */
-			wv_splx(lp, &flags);
-			err = copy_from_user(address,
-					     wrq->u.data.pointer,
-					     sizeof(struct sockaddr)
-					     * lp->spy_number);
-			wv_splhi(lp, &flags);
-			if (err) {
-				ret = -EFAULT;
-				break;
-			}
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+	if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+		range->num_channels = 10;
+		range->num_frequency = wv_frequency_list(ioaddr, range->freq,
+							IW_MAX_FREQUENCIES);
+	} else
+		range->num_channels = range->num_frequency = 0;
 
-			/* Copy addresses to the lp structure. */
-			for (i = 0; i < lp->spy_number; i++) {
-				memcpy(lp->spy_address[i],
-				       address[i].sa_data,
-				       WAVELAN_ADDR_SIZE);
-			}
+	/* Encryption supported ? */
+	if (mmc_encr(ioaddr)) {
+		range->encoding_size[0] = 8;	/* DES = 64 bits key */
+		range->num_encoding_sizes = 1;
+		range->max_encoding_tokens = 1;	/* Only one key possible */
+	} else {
+		range->num_encoding_sizes = 0;
+		range->max_encoding_tokens = 0;
+	}
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+#ifdef WIRELESS_SPY
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set spy list
+ */
+static int wavelan_set_spy(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct sockaddr *address = (struct sockaddr *) extra;
+	int i;
+	int ret = 0;
 
-			/* Reset structure. */
-			memset(lp->spy_stat, 0x00,
-			       sizeof(iw_qual) * IW_MAX_SPY);
+	/* Disable spy while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this */
+	lp->spy_number = 0;
+
+	/* Are there are addresses to copy? */
+	if (wrqu->data.length > 0) {
+		/* Copy addresses to the lp structure. */
+		for (i = 0; i < wrqu->data.length; i++) {
+			memcpy(lp->spy_address[i], address[i].sa_data,
+			       WAVELAN_ADDR_SIZE);
+		}
+
+		/* Reset structure. */
+		memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
 
 #ifdef DEBUG_IOCTL_INFO
+		printk(KERN_DEBUG
+		       "SetSpy:  set of new addresses is: \n");
+		for (i = 0; i < wrqu->data.length; i++)
 			printk(KERN_DEBUG
-			       "SetSpy:  set of new addresses is: \n");
-			for (i = 0; i < wrq->u.data.length; i++)
-				printk(KERN_DEBUG
-				       "%02X:%02X:%02X:%02X:%02X:%02X \n",
-				       lp->spy_address[i][0],
-				       lp->spy_address[i][1],
-				       lp->spy_address[i][2],
-				       lp->spy_address[i][3],
-				       lp->spy_address[i][4],
-				       lp->spy_address[i][5]);
-#endif				/* DEBUG_IOCTL_INFO */
-		}
+			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
+			       lp->spy_address[i][0],
+			       lp->spy_address[i][1],
+			       lp->spy_address[i][2],
+			       lp->spy_address[i][3],
+			       lp->spy_address[i][4],
+			       lp->spy_address[i][5]);
+#endif			/* DEBUG_IOCTL_INFO */
+	}
+
+	/* Now we can set the number of addresses */
+	lp->spy_number = wrqu->data.length;
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get spy list
+ */
+static int wavelan_get_spy(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct sockaddr *address = (struct sockaddr *) extra;
+	int i;
 
-		break;
+	/* Set the number of addresses */
+	wrqu->data.length = lp->spy_number;
 
-	case SIOCGIWSPY:
-		/* Get the spy list and spy stats. */
+	/* Copy addresses from the lp structure. */
+	for (i = 0; i < lp->spy_number; i++) {
+		memcpy(address[i].sa_data,
+		       lp->spy_address[i],
+		       WAVELAN_ADDR_SIZE);
+		address[i].sa_family = AF_UNIX;
+	}
+	/* Copy stats to the user buffer (just after). */
+	if(lp->spy_number > 0)
+		memcpy(extra  + (sizeof(struct sockaddr) * lp->spy_number),
+		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
 
-		/* Set the number of addresses */
-		wrq->u.data.length = lp->spy_number;
+	/* Reset updated flags. */
+	for (i = 0; i < lp->spy_number; i++)
+		lp->spy_stat[i].updated = 0x0;
 
-		/* Does the user want to have the addresses back? */
-		if ((lp->spy_number > 0)
-		    && (wrq->u.data.pointer != (caddr_t) 0)) {
-			struct sockaddr address[IW_MAX_SPY];
-			int i;
-
-			/* Copy addresses from the lp structure. */
-			for (i = 0; i < lp->spy_number; i++) {
-				memcpy(address[i].sa_data,
-				       lp->spy_address[i],
-				       WAVELAN_ADDR_SIZE);
-				address[i].sa_family = AF_UNIX;
-			}
+	return(0);
+}
+#endif			/* WIRELESS_SPY */
 
-			/* Copy addresses to the user buffer. */
-			wv_splx(lp, &flags);
-			err = copy_to_user(wrq->u.data.pointer,
-					   address,
-					   sizeof(struct sockaddr)
-					   * lp->spy_number);
-
-			/* Copy stats to the user buffer (just after). */
-			err |= copy_to_user(wrq->u.data.pointer
-					    + (sizeof(struct sockaddr)
-					       * lp->spy_number),
-					    lp->spy_stat,
-					    sizeof(iw_qual) * lp->spy_number);
-			wv_splhi(lp, &flags);
-			if (err) {
-				ret = -EFAULT;
-				break;
-			}
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set quality threshold
+ */
+static int wavelan_set_qthr(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
 
-			/* Reset updated flags. */
-			for (i = 0; i < lp->spy_number; i++)
-				lp->spy_stat[i].updated = 0x0;
-		}
-		/* if(pointer != NULL) */
-		break;
-#endif				/* WIRELESS_SPY */
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	psa.psa_quality_thr = *(extra) & 0x0F;
+	psa_write(ioaddr, lp->hacr,
+		  (char *) &psa.psa_quality_thr - (char *) &psa,
+		  (unsigned char *) &psa.psa_quality_thr, 1);
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev, ioaddr, lp->hacr);
+	mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
+		psa.psa_quality_thr);
 
-		/* ------------------ PRIVATE IOCTL ------------------ */
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-	case SIOCSIPQTHR:
-		if (!capable(CAP_NET_ADMIN)) {
-			ret = -EPERM;
-			break;
-		}
-		psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
-		psa_write(ioaddr, lp->hacr,
-			  (char *) &psa.psa_quality_thr - (char *) &psa,
-			  (unsigned char *) &psa.psa_quality_thr, 1);
-		/* update the Wavelan checksum */
-		update_psa_checksum(dev, ioaddr, lp->hacr);
-		mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
-			psa.psa_quality_thr);
-		break;
+	return 0;
+}
 
-	case SIOCGIPQTHR:
-		psa_read(ioaddr, lp->hacr,
-			 (char *) &psa.psa_quality_thr - (char *) &psa,
-			 (unsigned char *) &psa.psa_quality_thr, 1);
-		*(wrq->u.name) = psa.psa_quality_thr & 0x0F;
-		break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_qthr(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	unsigned long ioaddr = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	psa_read(ioaddr, lp->hacr,
+		 (char *) &psa.psa_quality_thr - (char *) &psa,
+		 (unsigned char *) &psa.psa_quality_thr, 1);
+	*(extra) = psa.psa_quality_thr & 0x0F;
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return 0;
+}
 
 #ifdef HISTOGRAM
-	case SIOCSIPHISTO:
-		/* Verify that the user is root. */
-		if (!capable(CAP_NET_ADMIN)) {
-			ret = -EPERM;
-			break;
-		}
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set histogram
+ */
+static int wavelan_set_histo(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
 
-		/* Check the number of intervals. */
-		if (wrq->u.data.length > 16) {
-			ret = -E2BIG;
-			break;
-		}
-		lp->his_number = wrq->u.data.length;
+	/* Check the number of intervals. */
+	if (wrqu->data.length > 16) {
+		return(-E2BIG);
+	}
 
-		/* Are there addresses to copy? */
-		if (lp->his_number > 0) {
-			/* Copy interval ranges to the driver */
-			wv_splx(lp, &flags);
-			err = copy_from_user(lp->his_range,
-					     wrq->u.data.pointer,
-					     sizeof(char) * lp->his_number);
-			wv_splhi(lp, &flags);
-			if (err) {
-				ret = -EFAULT;
-				break;
-			}
+	/* Disable histo while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this */
+	lp->his_number = 0;
+
+	/* Are there ranges to copy? */
+	if (wrqu->data.length > 0) {
+		/* Copy interval ranges to the driver */
+		memcpy(lp->his_range, extra, wrqu->data.length);
 
-			/* Reset structure. */
-			memset(lp->his_sum, 0x00, sizeof(long) * 16);
+		{
+		  int i;
+		  printk(KERN_DEBUG "Histo :");
+		  for(i = 0; i < wrqu->data.length; i++)
+		    printk(" %d", lp->his_range[i]);
+		  printk("\n");
 		}
-		break;
 
-	case SIOCGIPHISTO:
-		/* Set the number of intervals. */
-		wrq->u.data.length = lp->his_number;
-
-		/* Give back the distribution statistics */
-		if ((lp->his_number > 0)
-		    && (wrq->u.data.pointer != (caddr_t) 0)) {
-			/* Copy data to the user buffer. */
-			wv_splx(lp, &flags);
-			if (copy_to_user(wrq->u.data.pointer,
-					 lp->his_sum,
-					 sizeof(long) * lp->his_number);
-				ret = -EFAULT;
-			wv_splhi(lp, &flags);
+		/* Reset result structure. */
+		memset(lp->his_sum, 0x00, sizeof(long) * 16);
+	}
 
-		}		/* if(pointer != NULL) */
-		break;
-#endif				/* HISTOGRAM */
+	/* Now we can set the number of ranges */
+	lp->his_number = wrqu->data.length;
+
+	return(0);
+}
 
-		/* ------------------- OTHER IOCTL ------------------- */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get histogram
+ */
+static int wavelan_get_histo(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
 
-	default:
-		ret = -EOPNOTSUPP;
-	}	/* switch (cmd) */
+	/* Set the number of intervals. */
+	wrqu->data.length = lp->his_number;
 
-	/* Enable interrupts and restore flags. */
-	wv_splx(lp, &flags);
+	/* Give back the distribution statistics */
+	if(lp->his_number > 0)
+		memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number);
 
-#ifdef DEBUG_IOCTL_TRACE
-	printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
-#endif
-	return ret;
+	return(0);
 }
+#endif			/* HISTOGRAM */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const iw_handler		wavelan_handler[] =
+{
+	NULL,				/* SIOCSIWNAME */
+	wavelan_get_name,		/* SIOCGIWNAME */
+	wavelan_set_nwid,		/* SIOCSIWNWID */
+	wavelan_get_nwid,		/* SIOCGIWNWID */
+	wavelan_set_freq,		/* SIOCSIWFREQ */
+	wavelan_get_freq,		/* SIOCGIWFREQ */
+	NULL,				/* SIOCSIWMODE */
+	NULL,				/* SIOCGIWMODE */
+	wavelan_set_sens,		/* SIOCSIWSENS */
+	wavelan_get_sens,		/* SIOCGIWSENS */
+	NULL,				/* SIOCSIWRANGE */
+	wavelan_get_range,		/* SIOCGIWRANGE */
+	NULL,				/* SIOCSIWPRIV */
+	NULL,				/* SIOCGIWPRIV */
+	NULL,				/* SIOCSIWSTATS */
+	NULL,				/* SIOCGIWSTATS */
+#ifdef WIRELESS_SPY
+	wavelan_set_spy,		/* SIOCSIWSPY */
+	wavelan_get_spy,		/* SIOCGIWSPY */
+#else	/* WIRELESS_SPY */
+	NULL,				/* SIOCSIWSPY */
+	NULL,				/* SIOCGIWSPY */
+#endif	/* WIRELESS_SPY */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWAP */
+	NULL,				/* SIOCGIWAP */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCGIWAPLIST */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWESSID */
+	NULL,				/* SIOCGIWESSID */
+	NULL,				/* SIOCSIWNICKN */
+	NULL,				/* SIOCGIWNICKN */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWRATE */
+	NULL,				/* SIOCGIWRATE */
+	NULL,				/* SIOCSIWRTS */
+	NULL,				/* SIOCGIWRTS */
+	NULL,				/* SIOCSIWFRAG */
+	NULL,				/* SIOCGIWFRAG */
+	NULL,				/* SIOCSIWTXPOW */
+	NULL,				/* SIOCGIWTXPOW */
+	NULL,				/* SIOCSIWRETRY */
+	NULL,				/* SIOCGIWRETRY */
+	/* Bummer ! Why those are only at the end ??? */
+	wavelan_set_encode,		/* SIOCSIWENCODE */
+	wavelan_get_encode,		/* SIOCGIWENCODE */
+};
+
+static const iw_handler		wavelan_private_handler[] =
+{
+	wavelan_set_qthr,		/* SIOCIWFIRSTPRIV */
+	wavelan_get_qthr,		/* SIOCIWFIRSTPRIV + 1 */
+#ifdef HISTOGRAM
+	wavelan_set_histo,		/* SIOCIWFIRSTPRIV + 2 */
+	wavelan_get_histo,		/* SIOCIWFIRSTPRIV + 3 */
+#endif	/* HISTOGRAM */
+};
+
+static const struct iw_priv_args wavelan_private_args[] = {
+/*{ cmd,         set_args,                            get_args, name } */
+  { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
+  { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
+  { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,                    0, "sethisto" },
+  { SIOCGIPHISTO, 0,                     IW_PRIV_TYPE_INT | 16, "gethisto" },
+};
+
+static const struct iw_handler_def	wavelan_handler_def =
+{
+	num_standard:	sizeof(wavelan_handler)/sizeof(iw_handler),
+	num_private:	sizeof(wavelan_private_handler)/sizeof(iw_handler),
+	num_private_args: sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
+	standard:	(iw_handler *) wavelan_handler,
+	private:	(iw_handler *) wavelan_private_handler,
+	private_args:	(struct iw_priv_args *) wavelan_private_args,
+};
 
 /*------------------------------------------------------------------*/
 /*
@@ -2343,7 +2519,7 @@
 		return (iw_stats *) NULL;
 	
 	/* Disable interrupts and save flags. */
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 	
 	wstats = &lp->wstats;
 
@@ -2371,7 +2547,7 @@
 	wstats->discard.misc = 0L;
 
 	/* Enable interrupts and restore flags. */
-	wv_splx(lp, &flags);
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
 #ifdef DEBUG_IOCTL_TRACE
 	printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n",
@@ -2705,7 +2881,7 @@
 	if (clen < ETH_ZLEN)
 		clen = ETH_ZLEN;
 
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 
 	/* Check nothing bad has happened */
 	if (lp->tx_n_in_use == (NTXBLOCKS - 1)) {
@@ -2713,7 +2889,7 @@
 		printk(KERN_INFO "%s: wv_packet_write(): Tx queue full.\n",
 		       dev->name);
 #endif
-		wv_splx(lp, &flags);
+		spin_unlock_irqrestore(&lp->spinlock, flags);
 		return 1;
 	}
 
@@ -2791,7 +2967,7 @@
 	if (lp->tx_n_in_use < NTXBLOCKS - 1)
 		netif_wake_queue(dev);
 
-	wv_splx(lp, &flags);
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 	
 #ifdef DEBUG_TX_INFO
 	wv_packet_info((u8 *) buf, length, dev->name,
@@ -2832,9 +3008,9 @@
 	 * we can do it now.
 	 */
 	if (lp->reconfig_82586) {
-		wv_splhi(lp, &flags);
+		spin_lock_irqsave(&lp->spinlock, flags);
 		wv_82586_config(dev);
-		wv_splx(lp, &flags);
+		spin_unlock_irqrestore(&lp->spinlock, flags);
 		/* Check that we can continue */
 		if (lp->tx_n_in_use == (NTXBLOCKS - 1))
 			return 1;
@@ -3694,7 +3870,7 @@
 
 	/* Prevent reentrancy. We need to do that because we may have
 	 * multiple interrupt handler running concurrently.
-	 * It is safe because wv_splhi() disables interrupts before acquiring
+	 * It is safe because interrupts are disabled before acquiring
 	 * the spinlock. */
 	spin_lock(&lp->spinlock);
 
@@ -3822,7 +3998,7 @@
 		return;
 	}
 
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 
 	/* Try to see if some buffers are not free (in case we missed
 	 * an interrupt */
@@ -3862,7 +4038,7 @@
 	if (lp->tx_n_in_use < NTXBLOCKS - 1)
 		netif_wake_queue(dev);
 
-	wv_splx(lp, &flags);
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 	
 #ifdef DEBUG_INTERRUPT_TRACE
 	printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
@@ -3909,7 +4085,7 @@
 		return -EAGAIN;
 	}
 
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 	
 	if (wv_hw_reset(dev) != -1) {
 		netif_start_queue(dev);
@@ -3920,10 +4096,10 @@
 		       "%s: wavelan_open(): impossible to start the card\n",
 		       dev->name);
 #endif
-		wv_splx(lp, &flags);
+		spin_unlock_irqrestore(&lp->spinlock, flags);
 		return -EAGAIN;
 	}
-	wv_splx(lp, &flags);
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 	
 #ifdef DEBUG_CALLBACK_TRACE
 	printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
@@ -3951,9 +4127,9 @@
 	/*
 	 * Flush the Tx and disable Rx.
 	 */
-	wv_splhi(lp, &flags);
+	spin_lock_irqsave(&lp->spinlock, flags);
 	wv_82586_stop(dev);
-	wv_splx(lp, &flags);
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
 	free_irq(dev->irq, dev);
 
@@ -4069,8 +4245,8 @@
 #endif				/* SET_MAC_ADDRESS */
 
 #ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
-	dev->do_ioctl = wavelan_ioctl;
 	dev->get_wireless_stats = wavelan_get_wireless_stats;
+	dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
 #endif
 
 	dev->mtu = WAVELAN_MTU;
diff -Nru a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
--- a/drivers/net/wireless/wavelan.p.h	Tue Feb 26 11:58:00 2002
+++ b/drivers/net/wireless/wavelan.p.h	Tue Feb 26 11:58:00 2002
@@ -345,6 +345,12 @@
  *	- Fix spinlock stupid bugs that I left in. The driver is now SMP
  *		compliant and doesn't lockup at startup.
  *
+ * Changes made for release in 2.5.2 :
+ * ---------------------------------
+ *	- Use new driver API for Wireless Extensions :
+ *		o got rid of wavelan_ioctl()
+ *		o use a bunch of iw_handler instead
+ *
  * Wishes & dreams:
  * ----------------
  *	- roaming (see Pcmcia driver)
@@ -379,6 +385,7 @@
 #include	<linux/init.h>
 
 #include <linux/wireless.h>		/* Wireless extensions */
+#include <net/iw_handler.h>		/* Wireless handlers */
 
 /* WaveLAN declarations */
 #include	"i82586.h"
@@ -436,7 +443,7 @@
 /************************ CONSTANTS & MACROS ************************/
 
 #ifdef DEBUG_VERSION_SHOW
-static const char	*version	= "wavelan.c : v23 (SMP + wireless extensions) 05/10/00\n";
+static const char	*version	= "wavelan.c : v24 (SMP + wireless extensions) 11/12/01\n";
 #endif
 
 /* Watchdog temporisation */
@@ -449,11 +456,9 @@
 
 #define SIOCSIPQTHR	SIOCIWFIRSTPRIV		/* Set quality threshold */
 #define SIOCGIPQTHR	SIOCIWFIRSTPRIV + 1	/* Get quality threshold */
-#define SIOCSIPLTHR	SIOCIWFIRSTPRIV + 2	/* Set level threshold */
-#define SIOCGIPLTHR	SIOCIWFIRSTPRIV + 3	/* Get level threshold */
 
-#define SIOCSIPHISTO	SIOCIWFIRSTPRIV + 6	/* Set histogram ranges */
-#define SIOCGIPHISTO	SIOCIWFIRSTPRIV + 7	/* Get histogram values */
+#define SIOCSIPHISTO	SIOCIWFIRSTPRIV + 2	/* Set histogram ranges */
+#define SIOCGIPHISTO	SIOCIWFIRSTPRIV + 3	/* Get histogram values */
 
 /****************************** TYPES ******************************/
 
@@ -516,12 +521,6 @@
 /**************************** PROTOTYPES ****************************/
 
 /* ----------------------- MISC. SUBROUTINES ------------------------ */
-static inline void
-	wv_splhi(net_local *,		/* Disable interrupts, lock driver */
-		 unsigned long *);	/* flags */
-static inline void
-	wv_splx(net_local *,		/* Enable interrupts, unlock driver */
-		unsigned long *);	/* flags */
 static u_char
 	wv_irq_to_psa(int);
 static int
diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
--- a/drivers/net/wireless/wavelan_cs.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/wireless/wavelan_cs.c	Tue Feb 26 11:57:59 2002
@@ -66,34 +66,6 @@
 
 /*------------------------------------------------------------------*/
 /*
- * Wrapper for disabling interrupts.
- * (note : inline, so optimised away)
- */
-static inline void
-wv_splhi(net_local *		lp,
-	 unsigned long *	pflags)
-{
-  spin_lock_irqsave(&lp->spinlock, *pflags);
-  /* Note : above does the cli(); itself */
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wrapper for re-enabling interrupts.
- */
-static inline void
-wv_splx(net_local *		lp,
-	unsigned long *		pflags)
-{
-  spin_unlock_irqrestore(&lp->spinlock, *pflags);
-
-  /* Note : enabling interrupts on the hardware is done in wv_ru_start()
-   * via : outb(OP1_INT_ENABLE, LCCR(base));
-   */
-}
-
-/*------------------------------------------------------------------*/
-/*
  * Wrapper for reporting error to cardservices
  */
 static void cs_error(client_handle_t handle, int func, int ret)
@@ -591,7 +563,7 @@
 #endif
   
   /* Disable interrupts & save flags */
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
   
   m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00;
   mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1);
@@ -602,7 +574,7 @@
     lp->cell_search=0;
 
   /* ReEnable interrupts & restore flags */
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 }
 
 /* Find a record in the WavePoint table matching a given NWID */
@@ -771,7 +743,7 @@
 #endif
  	
   /* Disable interrupts & save flags */
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF;
   m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8;
@@ -779,7 +751,7 @@
   mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2);
   
   /* ReEnable interrupts & restore flags */
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
   wv_nwid_filter(!NWID_PROMISC,lp);
   lp->curr_point=wavepoint;
@@ -1049,9 +1021,9 @@
   /* Check if we can do it now ! */
   if((link->open) && (netif_running(dev)) && !(netif_queue_stopped(dev)))
     {
-      wv_splhi(lp, &flags);	/* Disable interrupts */
+      spin_lock_irqsave(&lp->spinlock, flags);	/* Disable interrupts */
       wv_82593_config(dev);
-      wv_splx(lp, &flags);	/* Re-enable interrupts */
+      spin_unlock_irqrestore(&lp->spinlock, flags);	/* Re-enable interrupts */
     }
   else
     {
@@ -1179,7 +1151,7 @@
       return;
     }
 
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* Read the mmc */
   mmc_out(base, mmwoff(0, mmw_freeze), 1);
@@ -1191,7 +1163,7 @@
   lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
 #endif	/* WIRELESS_EXT */
 
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
   printk(KERN_DEBUG "##### wavelan modem status registers: #####\n");
 #ifdef DEBUG_SHOW_UNUSED
@@ -1884,557 +1856,1234 @@
 
 /*------------------------------------------------------------------*/
 /*
- * Perform ioctl : config & info stuff
- * This is here that are treated the wireless extensions (iwconfig)
+ * Wireless Handler : get protocol name
  */
-static int
-wavelan_ioctl(struct net_device *	dev,	/* Device on wich the ioctl apply */
-	      struct ifreq *	rq,	/* Data passed */
-	      int		cmd)	/* Ioctl number */
+static int wavelan_get_name(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
 {
-  ioaddr_t		base = dev->base_addr;
-  net_local *		lp = (net_local *)dev->priv;	/* lp is not unused */
-  struct iwreq *	wrq = (struct iwreq *) rq;
-  psa_t			psa;
-  mm_t			m;
-  unsigned long		flags;
-  int			ret = 0;
-
-#ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
-#endif
-
-  /* Disable interrupts & save flags */
-  wv_splhi(lp, &flags);
-
-  /* Look what is the request */
-  switch(cmd)
-    {
-      /* --------------- WIRELESS EXTENSIONS --------------- */
+	strcpy(wrqu->name, "WaveLAN");
+	return 0;
+}
 
-    case SIOCGIWNAME:
-      strcpy(wrq->u.name, "Wavelan");
-      break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set NWID
+ */
+static int wavelan_set_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	mm_t m;
+	unsigned long flags;
+	int ret = 0;
 
-    case SIOCSIWNWID:
-      /* Set NWID in wavelan */
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Set NWID in WaveLAN. */
 #if WIRELESS_EXT > 8
-      if(!wrq->u.nwid.disabled)
-	{
-	  /* Set NWID in psa */
-	  psa.psa_nwid[0] = (wrq->u.nwid.value & 0xFF00) >> 8;
-	  psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
+	if (!wrqu->nwid.disabled) {
+		/* Set NWID in psa */
+		psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;
+		psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;
 #else	/* WIRELESS_EXT > 8 */
-      if(wrq->u.nwid.on)
-	{
-	  /* Set NWID in psa */
-	  psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
-	  psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
+	if(wrq->u.nwid.on) {
+		/* Set NWID in psa */
+		psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
+		psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
 #endif	/* WIRELESS_EXT > 8 */
-	  psa.psa_nwid_select = 0x01;
-	  psa_write(dev, (char *)psa.psa_nwid - (char *)&psa,
-		    (unsigned char *)psa.psa_nwid, 3);
-
-	  /* Set NWID in mmc */
-	  m.w.mmw_netw_id_l = psa.psa_nwid[1];
-	  m.w.mmw_netw_id_h = psa.psa_nwid[0];
-	  mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m,
-		    (unsigned char *)&m.w.mmw_netw_id_l, 2);
-	  mmc_out(base, mmwoff(0, mmw_loopt_sel), 0x00);
-	}
-      else
-	{
-	  /* Disable nwid in the psa */
-	  psa.psa_nwid_select = 0x00;
-	  psa_write(dev, (char *)&psa.psa_nwid_select - (char *)&psa,
-		    (unsigned char *)&psa.psa_nwid_select, 1);
-
-	  /* Disable nwid in the mmc (no filtering) */
-	  mmc_out(base, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
-	}
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev);
-      break;
+		psa.psa_nwid_select = 0x01;
+		psa_write(dev,
+			  (char *) psa.psa_nwid - (char *) &psa,
+			  (unsigned char *) psa.psa_nwid, 3);
+
+		/* Set NWID in mmc. */
+		m.w.mmw_netw_id_l = psa.psa_nwid[1];
+		m.w.mmw_netw_id_h = psa.psa_nwid[0];
+		mmc_write(base,
+			  (char *) &m.w.mmw_netw_id_l -
+			  (char *) &m,
+			  (unsigned char *) &m.w.mmw_netw_id_l, 2);
+		mmc_out(base, mmwoff(0, mmw_loopt_sel), 0x00);
+	} else {
+		/* Disable NWID in the psa. */
+		psa.psa_nwid_select = 0x00;
+		psa_write(dev,
+			  (char *) &psa.psa_nwid_select -
+			  (char *) &psa,
+			  (unsigned char *) &psa.psa_nwid_select,
+			  1);
+
+		/* Disable NWID in the mmc (no filtering). */
+		mmc_out(base, mmwoff(0, mmw_loopt_sel),
+			MMW_LOOPT_SEL_DIS_NWID);
+	}
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev);
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
 
-    case SIOCGIWNWID:
-      /* Read the NWID */
-      psa_read(dev, (char *)psa.psa_nwid - (char *)&psa,
-	       (unsigned char *)psa.psa_nwid, 3);
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get NWID 
+ */
+static int wavelan_get_nwid(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Read the NWID. */
+	psa_read(dev,
+		 (char *) psa.psa_nwid - (char *) &psa,
+		 (unsigned char *) psa.psa_nwid, 3);
 #if WIRELESS_EXT > 8
-      wrq->u.nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
-      wrq->u.nwid.disabled = !(psa.psa_nwid_select);
-      wrq->u.nwid.fixed = 1;	/* Superfluous */
+	wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+	wrqu->nwid.disabled = !(psa.psa_nwid_select);
+	wrqu->nwid.fixed = 1;	/* Superfluous */
 #else	/* WIRELESS_EXT > 8 */
-      wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
-      wrq->u.nwid.on = psa.psa_nwid_select;
+	wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+	wrq->u.nwid.on = psa.psa_nwid_select;
 #endif	/* WIRELESS_EXT > 8 */
-      break;
 
-    case SIOCSIWFREQ:
-      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
-      if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
-	   (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-	ret = wv_set_frequency(base, &(wrq->u.freq));
-      else
-	ret = -EOPNOTSUPP;
-      break;
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-    case SIOCGIWFREQ:
-      /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
-       * (does it work for everybody ? - especially old cards...) */
-      if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
-	   (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-	{
-	  unsigned short	freq;
+	return ret;
+}
 
-	  /* Ask the EEprom to read the frequency from the first area */
-	  fee_read(base, 0x00 /* 1st area - frequency... */,
-		   &freq, 1);
-	  wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
-	  wrq->u.freq.e = 1;
-	}
-      else
-	{
-	  psa_read(dev, (char *)&psa.psa_subband - (char *)&psa,
-		   (unsigned char *)&psa.psa_subband, 1);
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int wavelan_set_freq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	int ret;
 
-	  if(psa.psa_subband <= 4)
-	    {
-	      wrq->u.freq.m = fixed_bands[psa.psa_subband];
-	      wrq->u.freq.e = (psa.psa_subband != 0);
-	    }
-	  else
-	    ret = -EOPNOTSUPP;
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+	if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+		ret = wv_set_frequency(base, &(wrqu->freq));
+	else
+		ret = -EOPNOTSUPP;
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int wavelan_get_freq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+	 * Does it work for everybody, especially old cards? */
+	if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+		unsigned short freq;
+
+		/* Ask the EEPROM to read the frequency from the first area. */
+		fee_read(base, 0x00, &freq, 1);
+		wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+		wrqu->freq.e = 1;
+	} else {
+		psa_read(dev,
+			 (char *) &psa.psa_subband - (char *) &psa,
+			 (unsigned char *) &psa.psa_subband, 1);
+
+		if (psa.psa_subband <= 4) {
+			wrqu->freq.m = fixed_bands[psa.psa_subband];
+			wrqu->freq.e = (psa.psa_subband != 0);
+		} else
+			ret = -EOPNOTSUPP;
 	}
-      break;
 
-    case SIOCSIWSENS:
-      /* Set the level threshold */
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set level threshold
+ */
+static int wavelan_set_sens(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Set the level threshold. */
 #if WIRELESS_EXT > 7
-      /* We should complain loudly if wrq->u.sens.fixed = 0, because we
-       * can't set auto mode... */
-      psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
+	/* We should complain loudly if wrqu->sens.fixed = 0, because we
+	 * can't set auto mode... */
+	psa.psa_thr_pre_set = wrqu->sens.value & 0x3F;
 #else	/* WIRELESS_EXT > 7 */
-      psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
+	psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
 #endif	/* WIRELESS_EXT > 7 */
-      psa_write(dev, (char *)&psa.psa_thr_pre_set - (char *)&psa,
-	       (unsigned char *)&psa.psa_thr_pre_set, 1);
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev);
-      mmc_out(base, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
-      break;
+	psa_write(dev,
+		  (char *) &psa.psa_thr_pre_set - (char *) &psa,
+		  (unsigned char *) &psa.psa_thr_pre_set, 1);
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev);
+	mmc_out(base, mmwoff(0, mmw_thr_pre_set),
+		psa.psa_thr_pre_set);
 
-    case SIOCGIWSENS:
-      /* Read the level threshold */
-      psa_read(dev, (char *)&psa.psa_thr_pre_set - (char *)&psa,
-	       (unsigned char *)&psa.psa_thr_pre_set, 1);
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get level threshold
+ */
+static int wavelan_get_sens(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Read the level threshold. */
+	psa_read(dev,
+		 (char *) &psa.psa_thr_pre_set - (char *) &psa,
+		 (unsigned char *) &psa.psa_thr_pre_set, 1);
 #if WIRELESS_EXT > 7
-      wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
-      wrq->u.sens.fixed = 1;
+	wrqu->sens.value = psa.psa_thr_pre_set & 0x3F;
+	wrqu->sens.fixed = 1;
 #else	/* WIRELESS_EXT > 7 */
-      wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
+	wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
 #endif	/* WIRELESS_EXT > 7 */
-      break;
 
-#if WIRELESS_EXT > 8
-    case SIOCSIWENCODE:
-      /* Set encryption key */
-      if(!mmc_encr(base))
-	{
-	  ret = -EOPNOTSUPP;
-	  break;
-	}
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-      /* Basic checking... */
-      if(wrq->u.encoding.pointer != (caddr_t) 0)
-	{
-	  /* Check the size of the key */
-	  if(wrq->u.encoding.length != 8)
-	    {
-	      ret = -EINVAL;
-	      break;
-	    }
+	return ret;
+}
 
-	  /* Copy the key in the driver */
-	  if(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer,
-			    wrq->u.encoding.length))
-	    {
-	      ret = -EFAULT;
-	      break;
-	    }
+#if WIRELESS_EXT > 8
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set encryption key
+ */
+static int wavelan_set_encode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	psa_t psa;
+	int ret = 0;
 
-	  psa.psa_encryption_select = 1;
-	  psa_write(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
-		    (unsigned char *) &psa.psa_encryption_select, 8+1);
-
-	  mmc_out(base, mmwoff(0, mmw_encr_enable),
-		  MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
-	  mmc_write(base, mmwoff(0, mmw_encr_key),
-		    (unsigned char *) &psa.psa_encryption_key, 8);
-	}
-
-      if(wrq->u.encoding.flags & IW_ENCODE_DISABLED)
-	{	/* disable encryption */
-	  psa.psa_encryption_select = 0;
-	  psa_write(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
-		    (unsigned char *) &psa.psa_encryption_select, 1);
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
 
-	  mmc_out(base, mmwoff(0, mmw_encr_enable), 0);
+	/* Check if capable of encryption */
+	if (!mmc_encr(base)) {
+		ret = -EOPNOTSUPP;
 	}
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev);
-      break;
 
-    case SIOCGIWENCODE:
-      /* Read the encryption key */
-      if(!mmc_encr(base))
-	{
-	  ret = -EOPNOTSUPP;
-	  break;
+	/* Check the size of the key */
+	if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) {
+		ret = -EINVAL;
 	}
 
-      /* only super-user can see encryption key */
-      if(!capable(CAP_NET_ADMIN))
-	{
-	  ret = -EPERM;
-	  break;
+	if(!ret) {
+		/* Basic checking... */
+		if (wrqu->encoding.length == 8) {
+			/* Copy the key in the driver */
+			memcpy(psa.psa_encryption_key, extra,
+			       wrqu->encoding.length);
+			psa.psa_encryption_select = 1;
+
+			psa_write(dev,
+				  (char *) &psa.psa_encryption_select -
+				  (char *) &psa,
+				  (unsigned char *) &psa.
+				  psa_encryption_select, 8 + 1);
+
+			mmc_out(base, mmwoff(0, mmw_encr_enable),
+				MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+			mmc_write(base, mmwoff(0, mmw_encr_key),
+				  (unsigned char *) &psa.
+				  psa_encryption_key, 8);
+		}
+
+		/* disable encryption */
+		if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
+			psa.psa_encryption_select = 0;
+			psa_write(dev,
+				  (char *) &psa.psa_encryption_select -
+				  (char *) &psa,
+				  (unsigned char *) &psa.
+				  psa_encryption_select, 1);
+
+			mmc_out(base, mmwoff(0, mmw_encr_enable), 0);
+		}
+		/* update the Wavelan checksum */
+		update_psa_checksum(dev);
 	}
 
-      /* Basic checking... */
-      if(wrq->u.encoding.pointer != (caddr_t) 0)
-	{
-	  psa_read(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
-		   (unsigned char *) &psa.psa_encryption_select, 1+8);
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-	  /* encryption is enabled ? */
-	  if(psa.psa_encryption_select)
-	    wrq->u.encoding.flags = IW_ENCODE_ENABLED;
-	  else
-	    wrq->u.encoding.flags = IW_ENCODE_DISABLED;
-	  wrq->u.encoding.flags |= mmc_encr(base);
+	return ret;
+}
 
-	  /* Copy the key to the user buffer */
-	  wrq->u.encoding.length = 8;
-	  if(copy_to_user(wrq->u.encoding.pointer, psa.psa_encryption_key, 8))
-	    ret = -EFAULT;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get encryption key
+ */
+static int wavelan_get_encode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu,
+			      char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Check if encryption is available */
+	if (!mmc_encr(base)) {
+		ret = -EOPNOTSUPP;
+	} else {
+		/* Read the encryption key */
+		psa_read(dev,
+			 (char *) &psa.psa_encryption_select -
+			 (char *) &psa,
+			 (unsigned char *) &psa.
+			 psa_encryption_select, 1 + 8);
+
+		/* encryption is enabled ? */
+		if (psa.psa_encryption_select)
+			wrqu->encoding.flags = IW_ENCODE_ENABLED;
+		else
+			wrqu->encoding.flags = IW_ENCODE_DISABLED;
+		wrqu->encoding.flags |= mmc_encr(base);
+
+		/* Copy the key to the user buffer */
+		wrqu->encoding.length = 8;
+		memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length);
 	}
-      break;
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
 #endif	/* WIRELESS_EXT > 8 */
 
 #ifdef WAVELAN_ROAMING_EXT
 #if WIRELESS_EXT > 5
-    case SIOCSIWESSID:
-      /* Check if disable */
-      if(wrq->u.data.flags == 0)
-	lp->filter_domains = 0;
-      else
-	/* Basic checking... */
-	if(wrq->u.data.pointer != (caddr_t) 0)
-	  {
-	    char	essid[IW_ESSID_MAX_SIZE + 1];
-	    char *	endp;
-
-	    /* Check the size of the string */
-	    if(wrq->u.data.length > IW_ESSID_MAX_SIZE + 1)
-	      {
-		ret = -E2BIG;
-		break;
-	      }
-
-	    /* Copy the string in the driver */
-	    if(copy_from_user(essid, wrq->u.data.pointer, wrq->u.data.length))
-	      {
-		ret = -EFAULT;
-		break;
-	      }
-	    essid[IW_ESSID_MAX_SIZE] = '\0';
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set ESSID (domain)
+ */
+static int wavelan_set_essid(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Check if disable */
+	if(wrqu->data.flags == 0)
+		lp->filter_domains = 0;
+	else {
+		char	essid[IW_ESSID_MAX_SIZE + 1];
+		char *	endp;
+
+		/* Terminate the string */
+		memcpy(essid, extra, wrqu->data.length);
+		essid[IW_ESSID_MAX_SIZE] = '\0';
 
 #ifdef DEBUG_IOCTL_INFO
-	    printk(KERN_DEBUG "SetEssid : ``%s''\n", essid);
+		printk(KERN_DEBUG "SetEssid : ``%s''\n", essid);
 #endif	/* DEBUG_IOCTL_INFO */
 
-	    /* Convert to a number (note : Wavelan specific) */
-	    lp->domain_id = simple_strtoul(essid, &endp, 16);
-	    /* Has it worked  ? */
-	    if(endp > essid)
-	      lp->filter_domains = 1;
-	    else
-	      {
-		lp->filter_domains = 0;
-		ret = -EINVAL;
-	      }
-	  }
-      break;
+		/* Convert to a number (note : Wavelan specific) */
+		lp->domain_id = simple_strtoul(essid, &endp, 16);
+		/* Has it worked  ? */
+		if(endp > essid)
+			lp->filter_domains = 1;
+		else {
+			lp->filter_domains = 0;
+			ret = -EINVAL;
+		}
+	}
 
-    case SIOCGIWESSID:
-      /* Basic checking... */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-	{
-	  char		essid[IW_ESSID_MAX_SIZE + 1];
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
 
-	  /* Is the domain ID active ? */
-	  wrq->u.data.flags = lp->filter_domains;
+	return ret;
+}
 
-	  /* Copy Domain ID into a string (Wavelan specific) */
-	  /* Sound crazy, be we can't have a snprintf in the kernel !!! */
-	  sprintf(essid, "%lX", lp->domain_id);
-	  essid[IW_ESSID_MAX_SIZE] = '\0';
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get ESSID (domain)
+ */
+static int wavelan_get_essid(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
 
-	  /* Set the length */
-	  wrq->u.data.length = strlen(essid) + 1;
+	/* Is the domain ID active ? */
+	wrqu->data.flags = lp->filter_domains;
 
-	  /* Copy structure to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, essid, wrq->u.data.length))
-	    ret = -EFAULT;
-	}
-      break;
+	/* Copy Domain ID into a string (Wavelan specific) */
+	/* Sound crazy, be we can't have a snprintf in the kernel !!! */
+	sprintf(extra, "%lX", lp->domain_id);
+	extra[IW_ESSID_MAX_SIZE] = '\0';
 
-    case SIOCSIWAP:
+	/* Set the length */
+	wrqu->data.length = strlen(extra) + 1;
+
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set AP address
+ */
+static int wavelan_set_wap(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
 #ifdef DEBUG_IOCTL_INFO
-      printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
-	     wrq->u.ap_addr.sa_data[0],
-	     wrq->u.ap_addr.sa_data[1],
-	     wrq->u.ap_addr.sa_data[2],
-	     wrq->u.ap_addr.sa_data[3],
-	     wrq->u.ap_addr.sa_data[4],
-	     wrq->u.ap_addr.sa_data[5]);
+	printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
+	       wrqu->ap_addr.sa_data[0],
+	       wrqu->ap_addr.sa_data[1],
+	       wrqu->ap_addr.sa_data[2],
+	       wrqu->ap_addr.sa_data[3],
+	       wrqu->ap_addr.sa_data[4],
+	       wrqu->ap_addr.sa_data[5]);
 #endif	/* DEBUG_IOCTL_INFO */
 
-      ret = -EOPNOTSUPP;	/* Not supported yet */
-      break;
+	return -EOPNOTSUPP;
+}
 
-    case SIOCGIWAP:
-      /* Should get the real McCoy instead of own Ethernet address */
-      memcpy(wrq->u.ap_addr.sa_data, dev->dev_addr, WAVELAN_ADDR_SIZE);
-      wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get AP address
+ */
+static int wavelan_get_wap(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	/* Should get the real McCoy instead of own Ethernet address */
+	memcpy(wrqu->ap_addr.sa_data, dev->dev_addr, WAVELAN_ADDR_SIZE);
+	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
 
-      ret = -EOPNOTSUPP;	/* Not supported yet */
-      break;
+	return -EOPNOTSUPP;
+}
 #endif	/* WIRELESS_EXT > 5 */
 #endif	/* WAVELAN_ROAMING_EXT */
 
 #if WIRELESS_EXT > 8
 #ifdef WAVELAN_ROAMING
-    case SIOCSIWMODE:
-      switch(wrq->u.mode)
-	{
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set mode
+ */
+static int wavelan_set_mode(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+	int ret = 0;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+
+	/* Check mode */
+	switch(wrqu->mode) {
 	case IW_MODE_ADHOC:
-	  if(do_roaming)
-	    {
-	      wv_roam_cleanup(dev);
-	      do_roaming = 0;
-	    }
-	  break;
+		if(do_roaming) {
+			wv_roam_cleanup(dev);
+			do_roaming = 0;
+		}
+		break;
 	case IW_MODE_INFRA:
-	  if(!do_roaming)
-	    {
-	      wv_roam_init(dev);
-	      do_roaming = 1;
-	    }
-	  break;
+		if(!do_roaming) {
+			wv_roam_init(dev);
+			do_roaming = 1;
+		}
+		break;
 	default:
-	  ret = -EINVAL;
+		ret = -EINVAL;
 	}
-      break;
 
-    case SIOCGIWMODE:
-      if(do_roaming)
-	wrq->u.mode = IW_MODE_INFRA;
-      else
-	wrq->u.mode = IW_MODE_ADHOC;
-      break;
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get mode
+ */
+static int wavelan_get_mode(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	if(do_roaming)
+		wrqu->mode = IW_MODE_INFRA;
+	else
+		wrqu->mode = IW_MODE_ADHOC;
+
+	return 0;
+}
 #endif	/* WAVELAN_ROAMING */
 #endif /* WIRELESS_EXT > 8 */
 
-    case SIOCGIWRANGE:
-      /* Basic checking... */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-	{
-	  struct iw_range	range;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int wavelan_get_range(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct iw_range *range = (struct iw_range *) extra;
+	unsigned long flags;
+	int ret = 0;
 
-	   /* Set the length (very important for backward compatibility) */
-	   wrq->u.data.length = sizeof(struct iw_range);
+	/* Set the length (very important for backward compatibility) */
+	wrqu->data.length = sizeof(struct iw_range);
 
-	   /* Set all the info we don't care or don't know about to zero */
-	   memset(&range, 0, sizeof(range));
+	/* Set all the info we don't care or don't know about to zero */
+	memset(range, 0, sizeof(struct iw_range));
 
 #if WIRELESS_EXT > 10
-	   /* Set the Wireless Extension versions */
-	   range.we_version_compiled = WIRELESS_EXT;
-	   range.we_version_source = 9;	/* Nothing for us in v10 and v11 */
+	/* Set the Wireless Extension versions */
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 9;
 #endif /* WIRELESS_EXT > 10 */
 
-	  /* Set information in the range struct */
-	  range.throughput = 1.4 * 1000 * 1000;	/* don't argue on this ! */
-	  range.min_nwid = 0x0000;
-	  range.max_nwid = 0xFFFF;
-
-	  /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
-	  if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
-	       (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
-	    {
-	      range.num_channels = 10;
-	      range.num_frequency = wv_frequency_list(base, range.freq,
-						      IW_MAX_FREQUENCIES);
-	    }
-	  else
-	    range.num_channels = range.num_frequency = 0;
-
-	  range.sensitivity = 0x3F;
-	  range.max_qual.qual = MMR_SGNL_QUAL;
-	  range.max_qual.level = MMR_SIGNAL_LVL;
-	  range.max_qual.noise = MMR_SILENCE_LVL;
+	/* Set information in the range struct.  */
+	range->throughput = 1.4 * 1000 * 1000;	/* don't argue on this ! */
+	range->min_nwid = 0x0000;
+	range->max_nwid = 0xFFFF;
+
+	range->sensitivity = 0x3F;
+	range->max_qual.qual = MMR_SGNL_QUAL;
+	range->max_qual.level = MMR_SIGNAL_LVL;
+	range->max_qual.noise = MMR_SILENCE_LVL;
 #if WIRELESS_EXT > 11
-	  range.avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
-	  /* Need to get better values for those two */
-	  range.avg_qual.level = 30;
-	  range.avg_qual.noise = 8;
+	range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
+	/* Need to get better values for those two */
+	range->avg_qual.level = 30;
+	range->avg_qual.noise = 8;
 #endif /* WIRELESS_EXT > 11 */
 
 #if WIRELESS_EXT > 7
-	  range.num_bitrates = 1;
-	  range.bitrate[0] = 2000000;	/* 2 Mb/s */
+	range->num_bitrates = 1;
+	range->bitrate[0] = 2000000;	/* 2 Mb/s */
 #endif /* WIRELESS_EXT > 7 */
 
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+	if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+	      (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+		range->num_channels = 10;
+		range->num_frequency = wv_frequency_list(base, range->freq,
+							IW_MAX_FREQUENCIES);
+	} else
+		range->num_channels = range->num_frequency = 0;
+
 #if WIRELESS_EXT > 8
-	  /* Encryption supported ? */
-	  if(mmc_encr(base))
-	    {
-	      range.encoding_size[0] = 8;	/* DES = 64 bits key */
-	      range.num_encoding_sizes = 1;
-	      range.max_encoding_tokens = 1;	/* Only one key possible */
-	    }
-	  else
-	    {
-	      range.num_encoding_sizes = 0;
-	      range.max_encoding_tokens = 0;
-	    }
+	/* Encryption supported ? */
+	if (mmc_encr(base)) {
+		range->encoding_size[0] = 8;	/* DES = 64 bits key */
+		range->num_encoding_sizes = 1;
+		range->max_encoding_tokens = 1;	/* Only one key possible */
+	} else {
+		range->num_encoding_sizes = 0;
+		range->max_encoding_tokens = 0;
+	}
 #endif /* WIRELESS_EXT > 8 */
 
-	  /* Copy structure to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, &range,
-			  sizeof(struct iw_range)))
-	    ret = -EFAULT;
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return ret;
+}
+
+#ifdef WIRELESS_SPY
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set spy list
+ */
+static int wavelan_set_spy(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct sockaddr *address = (struct sockaddr *) extra;
+	int i;
+	int ret = 0;
+
+	/* Disable spy while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this */
+	lp->spy_number = 0;
+
+	/* Are there are addresses to copy? */
+	if (wrqu->data.length > 0) {
+		/* Copy addresses to the lp structure. */
+		for (i = 0; i < wrqu->data.length; i++) {
+			memcpy(lp->spy_address[i], address[i].sa_data,
+			       WAVELAN_ADDR_SIZE);
+		}
+
+		/* Reset structure. */
+		memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+
+#ifdef DEBUG_IOCTL_INFO
+		printk(KERN_DEBUG
+		       "SetSpy:  set of new addresses is: \n");
+		for (i = 0; i < wrqu->data.length; i++)
+			printk(KERN_DEBUG
+			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
+			       lp->spy_address[i][0],
+			       lp->spy_address[i][1],
+			       lp->spy_address[i][2],
+			       lp->spy_address[i][3],
+			       lp->spy_address[i][4],
+			       lp->spy_address[i][5]);
+#endif			/* DEBUG_IOCTL_INFO */
+	}
+
+	/* Now we can set the number of addresses */
+	lp->spy_number = wrqu->data.length;
+
+	return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get spy list
+ */
+static int wavelan_get_spy(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	struct sockaddr *address = (struct sockaddr *) extra;
+	int i;
+
+	/* Set the number of addresses */
+	wrqu->data.length = lp->spy_number;
+
+	/* Copy addresses from the lp structure. */
+	for (i = 0; i < lp->spy_number; i++) {
+		memcpy(address[i].sa_data,
+		       lp->spy_address[i],
+		       WAVELAN_ADDR_SIZE);
+		address[i].sa_family = AF_UNIX;
+	}
+	/* Copy stats to the user buffer (just after). */
+	if(lp->spy_number > 0)
+		memcpy(extra  + (sizeof(struct sockaddr) * lp->spy_number),
+		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
+
+	/* Reset updated flags. */
+	for (i = 0; i < lp->spy_number; i++)
+		lp->spy_stat[i].updated = 0x0;
+
+	return(0);
+}
+#endif			/* WIRELESS_SPY */
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set quality threshold
+ */
+static int wavelan_set_qthr(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	ioaddr_t base = dev->base_addr;
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	psa.psa_quality_thr = *(extra) & 0x0F;
+	psa_write(dev,
+		  (char *) &psa.psa_quality_thr - (char *) &psa,
+		  (unsigned char *) &psa.psa_quality_thr, 1);
+	/* update the Wavelan checksum */
+	update_psa_checksum(dev);
+	mmc_out(base, mmwoff(0, mmw_quality_thr),
+		psa.psa_quality_thr);
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_qthr(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	psa_t psa;
+	unsigned long flags;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	psa_read(dev,
+		 (char *) &psa.psa_quality_thr - (char *) &psa,
+		 (unsigned char *) &psa.psa_quality_thr, 1);
+	*(extra) = psa.psa_quality_thr & 0x0F;
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return 0;
+}
+
+#ifdef WAVELAN_ROAMING
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set roaming
+ */
+static int wavelan_set_roam(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	unsigned long flags;
+
+	/* Disable interrupts and save flags. */
+	spin_lock_irqsave(&lp->spinlock, flags);
+	
+	/* Note : should check if user == root */
+	if(do_roaming && (*extra)==0)
+		wv_roam_cleanup(dev);
+	else if(do_roaming==0 && (*extra)!=0)
+		wv_roam_init(dev);
+
+	do_roaming = (*extra);
+
+	/* Enable interrupts and restore flags. */
+	spin_unlock_irqrestore(&lp->spinlock, flags);
+
+	return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_roam(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu,
+			    char *extra)
+{
+	*(extra) = do_roaming;
+
+	return 0;
+}
+#endif	/* WAVELAN_ROAMING */
+
+#ifdef HISTOGRAM
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set histogram
+ */
+static int wavelan_set_histo(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+
+	/* Check the number of intervals. */
+	if (wrqu->data.length > 16) {
+		return(-E2BIG);
 	}
+
+	/* Disable histo while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this */
+	lp->his_number = 0;
+
+	/* Are there ranges to copy? */
+	if (wrqu->data.length > 0) {
+		/* Copy interval ranges to the driver */
+		memcpy(lp->his_range, extra, wrqu->data.length);
+
+		{
+		  int i;
+		  printk(KERN_DEBUG "Histo :");
+		  for(i = 0; i < wrqu->data.length; i++)
+		    printk(" %d", lp->his_range[i]);
+		  printk("\n");
+		}
+
+		/* Reset result structure. */
+		memset(lp->his_sum, 0x00, sizeof(long) * 16);
+	}
+
+	/* Now we can set the number of ranges */
+	lp->his_number = wrqu->data.length;
+
+	return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get histogram
+ */
+static int wavelan_get_histo(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+
+	/* Set the number of intervals. */
+	wrqu->data.length = lp->his_number;
+
+	/* Give back the distribution statistics */
+	if(lp->his_number > 0)
+		memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number);
+
+	return(0);
+}
+#endif			/* HISTOGRAM */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const struct iw_priv_args wavelan_private_args[] = {
+/*{ cmd,         set_args,                            get_args, name } */
+  { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
+  { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
+  { SIOCSIPROAM, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setroam" },
+  { SIOCGIPROAM, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getroam" },
+  { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,                    0, "sethisto" },
+  { SIOCGIPHISTO, 0,                     IW_PRIV_TYPE_INT | 16, "gethisto" },
+};
+
+#if WIRELESS_EXT > 12
+
+static const iw_handler		wavelan_handler[] =
+{
+	NULL,				/* SIOCSIWNAME */
+	wavelan_get_name,		/* SIOCGIWNAME */
+	wavelan_set_nwid,		/* SIOCSIWNWID */
+	wavelan_get_nwid,		/* SIOCGIWNWID */
+	wavelan_set_freq,		/* SIOCSIWFREQ */
+	wavelan_get_freq,		/* SIOCGIWFREQ */
+#ifdef WAVELAN_ROAMING
+	wavelan_set_mode,		/* SIOCSIWMODE */
+	wavelan_get_mode,		/* SIOCGIWMODE */
+#else	/* WAVELAN_ROAMING */
+	NULL,				/* SIOCSIWMODE */
+	NULL,				/* SIOCGIWMODE */
+#endif	/* WAVELAN_ROAMING */
+	wavelan_set_sens,		/* SIOCSIWSENS */
+	wavelan_get_sens,		/* SIOCGIWSENS */
+	NULL,				/* SIOCSIWRANGE */
+	wavelan_get_range,		/* SIOCGIWRANGE */
+	NULL,				/* SIOCSIWPRIV */
+	NULL,				/* SIOCGIWPRIV */
+	NULL,				/* SIOCSIWSTATS */
+	NULL,				/* SIOCGIWSTATS */
+#ifdef WIRELESS_SPY
+	wavelan_set_spy,		/* SIOCSIWSPY */
+	wavelan_get_spy,		/* SIOCGIWSPY */
+#else	/* WIRELESS_SPY */
+	NULL,				/* SIOCSIWSPY */
+	NULL,				/* SIOCGIWSPY */
+#endif	/* WIRELESS_SPY */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+#ifdef WAVELAN_ROAMING_EXT
+	wavelan_set_wap,		/* SIOCSIWAP */
+	wavelan_get_wap,		/* SIOCGIWAP */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCGIWAPLIST */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	wavelan_set_essid,		/* SIOCSIWESSID */
+	wavelan_get_essid,		/* SIOCGIWESSID */
+#else	/* WAVELAN_ROAMING_EXT */
+	NULL,				/* SIOCSIWAP */
+	NULL,				/* SIOCGIWAP */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCGIWAPLIST */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWESSID */
+	NULL,				/* SIOCGIWESSID */
+#endif	/* WAVELAN_ROAMING_EXT */
+#if WIRELESS_EXT > 8
+	NULL,				/* SIOCSIWNICKN */
+	NULL,				/* SIOCGIWNICKN */
+	NULL,				/* -- hole -- */
+	NULL,				/* -- hole -- */
+	NULL,				/* SIOCSIWRATE */
+	NULL,				/* SIOCGIWRATE */
+	NULL,				/* SIOCSIWRTS */
+	NULL,				/* SIOCGIWRTS */
+	NULL,				/* SIOCSIWFRAG */
+	NULL,				/* SIOCGIWFRAG */
+	NULL,				/* SIOCSIWTXPOW */
+	NULL,				/* SIOCGIWTXPOW */
+	NULL,				/* SIOCSIWRETRY */
+	NULL,				/* SIOCGIWRETRY */
+	wavelan_set_encode,		/* SIOCSIWENCODE */
+	wavelan_get_encode,		/* SIOCGIWENCODE */
+#endif	/* WIRELESS_EXT > 8 */
+};
+
+static const iw_handler		wavelan_private_handler[] =
+{
+	wavelan_set_qthr,		/* SIOCIWFIRSTPRIV */
+	wavelan_get_qthr,		/* SIOCIWFIRSTPRIV + 1 */
+#ifdef WAVELAN_ROAMING
+	wavelan_set_roam,		/* SIOCIWFIRSTPRIV + 2 */
+	wavelan_get_roam,		/* SIOCIWFIRSTPRIV + 3 */
+#else	/* WAVELAN_ROAMING */
+	NULL,				/* SIOCIWFIRSTPRIV + 2 */
+	NULL,				/* SIOCIWFIRSTPRIV + 3 */
+#endif	/* WAVELAN_ROAMING */
+#ifdef HISTOGRAM
+	wavelan_set_histo,		/* SIOCIWFIRSTPRIV + 4 */
+	wavelan_get_histo,		/* SIOCIWFIRSTPRIV + 5 */
+#endif	/* HISTOGRAM */
+};
+
+static const struct iw_handler_def	wavelan_handler_def =
+{
+	num_standard:	sizeof(wavelan_handler)/sizeof(iw_handler),
+	num_private:	sizeof(wavelan_private_handler)/sizeof(iw_handler),
+	num_private_args: sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
+	standard:	(iw_handler *) wavelan_handler,
+	private:	(iw_handler *) wavelan_private_handler,
+	private_args:	(struct iw_priv_args *) wavelan_private_args,
+};
+
+#else /* WIRELESS_EXT > 12 */
+/*------------------------------------------------------------------*/
+/*
+ * Perform ioctl : config & info stuff
+ * This is here that are treated the wireless extensions (iwconfig)
+ */
+static int
+wavelan_ioctl(struct net_device *	dev,	/* Device on wich the ioctl apply */
+	      struct ifreq *	rq,	/* Data passed */
+	      int		cmd)	/* Ioctl number */
+{
+  struct iwreq *	wrq = (struct iwreq *) rq;
+  int			ret = 0;
+
+#ifdef DEBUG_IOCTL_TRACE
+  printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
+#endif
+
+  /* Look what is the request */
+  switch(cmd)
+    {
+      /* --------------- WIRELESS EXTENSIONS --------------- */
+
+    case SIOCGIWNAME:
+      wavelan_get_name(dev, NULL, &(wrq->u), NULL);
       break;
 
-    case SIOCGIWPRIV:
-      /* Basic checking... */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-	{
-	  struct iw_priv_args	priv[] =
-	  {	/* cmd,		set_args,	get_args,	name */
-	    { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
-	    { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
-	    { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,	0, "sethisto" },
-	    { SIOCGIPHISTO, 0,	    IW_PRIV_TYPE_INT | 16, "gethisto" },
-	    { SIOCSIPROAM, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1 , 0, "setroam" },
-	    { SIOCGIPROAM, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getroam" },
-	  };
+    case SIOCSIWNWID:
+      ret = wavelan_set_nwid(dev, NULL, &(wrq->u), NULL);
+      break;
 
-	  /* Set the number of ioctl available */
-	  wrq->u.data.length = 6;
+    case SIOCGIWNWID:
+      ret = wavelan_get_nwid(dev, NULL, &(wrq->u), NULL);
+      break;
 
-	  /* Copy structure to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
-		       sizeof(priv)))
+    case SIOCSIWFREQ:
+      ret = wavelan_set_freq(dev, NULL, &(wrq->u), NULL);
+      break;
+
+    case SIOCGIWFREQ:
+      ret = wavelan_get_freq(dev, NULL, &(wrq->u), NULL);
+      break;
+
+    case SIOCSIWSENS:
+      ret = wavelan_set_sens(dev, NULL, &(wrq->u), NULL);
+      break;
+
+    case SIOCGIWSENS:
+      ret = wavelan_get_sens(dev, NULL, &(wrq->u), NULL);
+      break;
+
+#if WIRELESS_EXT > 8
+    case SIOCSIWENCODE:
+      {
+	char keybuf[8];
+	if (wrq->u.encoding.pointer) {
+	  /* We actually have a key to set */
+	  if (wrq->u.encoding.length != 8) {
+	    ret = -EINVAL;
+	    break;
+	  }
+	  if (copy_from_user(keybuf,
+			     wrq->u.encoding.pointer,
+			     wrq->u.encoding.length)) {
 	    ret = -EFAULT;
+	    break;
+	  }
+	} else if (wrq->u.encoding.length != 0) {
+	  ret = -EINVAL;
+	  break;
 	}
+	ret = wavelan_set_encode(dev, NULL, &(wrq->u), keybuf);
+      }
       break;
 
-#ifdef WIRELESS_SPY
-    case SIOCSIWSPY:
-      /* Set the spy list */
+    case SIOCGIWENCODE:
+      if (! capable(CAP_NET_ADMIN)) {
+	ret = -EPERM;
+	break;
+      }
+      {
+	char keybuf[8];
+	ret = wavelan_get_encode(dev, NULL,
+				 &(wrq->u),
+				 keybuf);
+	if (wrq->u.encoding.pointer) {
+	  if (copy_to_user(wrq->u.encoding.pointer,
+			   keybuf,
+			   wrq->u.encoding.length))
+	    ret = -EFAULT;
+	}
+      }
+      break;
+#endif	/* WIRELESS_EXT > 8 */
 
-      /* Check the number of addresses */
-      if(wrq->u.data.length > IW_MAX_SPY)
-	{
+#ifdef WAVELAN_ROAMING_EXT
+#if WIRELESS_EXT > 5
+    case SIOCSIWESSID:
+      {
+	char essidbuf[IW_ESSID_MAX_SIZE+1];
+	if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
 	  ret = -E2BIG;
 	  break;
 	}
-      lp->spy_number = wrq->u.data.length;
-
-      /* If there is some addresses to copy */
-      if(lp->spy_number > 0)
-	{
-	  struct sockaddr	address[IW_MAX_SPY];
-	  int			i;
-
-	  /* Copy addresses to the driver */
-	  if(copy_from_user(address, wrq->u.data.pointer,
-			    sizeof(struct sockaddr) * lp->spy_number))
-	    {
-	      ret = -EFAULT;
-	      break;
-	    }
+	if (copy_from_user(essidbuf, wrq->u.essid.pointer,
+			   wrq->u.essid.length)) {
+	  ret = -EFAULT;
+	  break;
+	}
+	ret = wavelan_set_essid(dev, NULL,
+				&(wrq->u),
+				essidbuf);
+      }
+      break;
 
-	  /* Copy addresses to the lp structure */
-	  for(i = 0; i < lp->spy_number; i++)
-	    {
-	      memcpy(lp->spy_address[i], address[i].sa_data,
-		     WAVELAN_ADDR_SIZE);
-	    }
+    case SIOCGIWESSID:
+      {
+	char essidbuf[IW_ESSID_MAX_SIZE+1];
+	ret = wavelan_get_essid(dev, NULL,
+				&(wrq->u),
+				essidbuf);
+	if (wrq->u.essid.pointer)
+	  if ( copy_to_user(wrq->u.essid.pointer,
+			    essidbuf,
+			    wrq->u.essid.length) )
+	    ret = -EFAULT;
+      }
+      break;
 
-	  /* Reset structure... */
-	  memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+    case SIOCSIWAP:
+      ret = wavelan_set_wap(dev, NULL, &(wrq->u), NULL);
+      break;
 
-#ifdef DEBUG_IOCTL_INFO
-	  printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
-	  for(i = 0; i < wrq->u.data.length; i++)
-	    printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
-		   lp->spy_address[i][0],
-		   lp->spy_address[i][1],
-		   lp->spy_address[i][2],
-		   lp->spy_address[i][3],
-		   lp->spy_address[i][4],
-		   lp->spy_address[i][5]);
-#endif	/* DEBUG_IOCTL_INFO */
-	}
+    case SIOCGIWAP:
+      ret = wavelan_get_wap(dev, NULL, &(wrq->u), NULL);
+      break;
+#endif	/* WIRELESS_EXT > 5 */
+#endif	/* WAVELAN_ROAMING_EXT */
 
+#if WIRELESS_EXT > 8
+#ifdef WAVELAN_ROAMING
+    case SIOCSIWMODE:
+      ret = wavelan_set_mode(dev, NULL, &(wrq->u), NULL);
       break;
 
-    case SIOCGIWSPY:
-      /* Get the spy list and spy stats */
+    case SIOCGIWMODE:
+      ret = wavelan_get_mode(dev, NULL, &(wrq->u), NULL);
+      break;
+#endif	/* WAVELAN_ROAMING */
+#endif /* WIRELESS_EXT > 8 */
 
-      /* Set the number of addresses */
-      wrq->u.data.length = lp->spy_number;
+    case SIOCGIWRANGE:
+      {
+	struct iw_range range;
+	ret = wavelan_get_range(dev, NULL,
+				&(wrq->u),
+				(char *) &range);
+	if (copy_to_user(wrq->u.data.pointer, &range,
+			 sizeof(struct iw_range)))
+	  ret = -EFAULT;
+      }
+      break;
 
-      /* If the user want to have the addresses back... */
-      if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
+    case SIOCGIWPRIV:
+      /* Basic checking... */
+      if(wrq->u.data.pointer != (caddr_t) 0)
 	{
-	  struct sockaddr	address[IW_MAX_SPY];
-	  int			i;
-
-	  /* Copy addresses from the lp structure */
-	  for(i = 0; i < lp->spy_number; i++)
-	    {
-	      memcpy(address[i].sa_data, lp->spy_address[i],
-		     WAVELAN_ADDR_SIZE);
-	      address[i].sa_family = ARPHRD_ETHER;
-	    }
-
-	  /* Copy addresses to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, address,
-		       sizeof(struct sockaddr) * lp->spy_number))
-	    {
-	      ret = -EFAULT;
-	      break;
-	    }
+	  /* Set the number of ioctl available */
+	  wrq->u.data.length = sizeof(wavelan_private_args) / sizeof(wavelan_private_args[0]);
 
-	  /* Copy stats to the user buffer (just after) */
-	  if(copy_to_user(wrq->u.data.pointer +
-		       (sizeof(struct sockaddr) * lp->spy_number),
-		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number))
-	    {
-	      ret = -EFAULT;
-	      break;
-	    }
+	  /* Copy structure to the user buffer */
+	  if(copy_to_user(wrq->u.data.pointer, (u_char *) wavelan_private_args,
+		       sizeof(wavelan_private_args)))
+	    ret = -EFAULT;
+	}
+      break;
 
-	  /* Reset updated flags */
-	  for(i = 0; i < lp->spy_number; i++)
-	    lp->spy_stat[i].updated = 0x0;
-	}	/* if(pointer != NULL) */
+#ifdef WIRELESS_SPY
+    case SIOCSIWSPY:
+      {
+	struct sockaddr address[IW_MAX_SPY];
+	/* Check the number of addresses */
+	if (wrq->u.data.length > IW_MAX_SPY) {
+	  ret = -E2BIG;
+	  break;
+	}
+	/* Get the data in the driver */
+	if (wrq->u.data.pointer) {
+	  if (copy_from_user((char *) address,
+			     wrq->u.data.pointer,
+			     sizeof(struct sockaddr) *
+			     wrq->u.data.length)) {
+	    ret = -EFAULT;
+	    break;
+	  }
+	} else if (wrq->u.data.length != 0) {
+	  ret = -EINVAL;
+	  break;
+	}
+	ret = wavelan_set_spy(dev, NULL, &(wrq->u),
+			      (char *) address);
+      }
+      break;
 
+    case SIOCGIWSPY:
+      {
+	char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
+				  sizeof(struct iw_quality))];
+	ret = wavelan_get_spy(dev, NULL, &(wrq->u),
+			      buffer);
+	if (wrq->u.data.pointer) {
+	  if (copy_to_user(wrq->u.data.pointer,
+			   buffer,
+			   (wrq->u.data.length *
+			    (sizeof(struct sockaddr) +
+			     sizeof(struct iw_quality)))
+			   ))
+	    ret = -EFAULT;
+	}
+      }
       break;
 #endif	/* WIRELESS_SPY */
 
@@ -2446,34 +3095,21 @@
 	  ret = -EPERM;
 	  break;
 	}
-      psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
-      psa_write(dev, (char *)&psa.psa_quality_thr - (char *)&psa,
-	       (unsigned char *)&psa.psa_quality_thr, 1);
-      /* update the Wavelan checksum */
-      update_psa_checksum(dev);
-      mmc_out(base, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
+      ret = wavelan_set_qthr(dev, NULL, &(wrq->u), NULL);
       break;
 
     case SIOCGIPQTHR:
-      psa_read(dev, (char *)&psa.psa_quality_thr - (char *)&psa,
-	       (unsigned char *)&psa.psa_quality_thr, 1);
-      *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
+      ret = wavelan_get_qthr(dev, NULL, &(wrq->u), NULL);
       break;
 
 #ifdef WAVELAN_ROAMING
     case SIOCSIPROAM:
       /* Note : should check if user == root */
-      if(do_roaming && (*wrq->u.name)==0)
-	wv_roam_cleanup(dev);
-      else if(do_roaming==0 && (*wrq->u.name)!=0)
-	wv_roam_init(dev);
-
-      do_roaming = (*wrq->u.name);
-	  
+      ret = wavelan_set_roam(dev, NULL, &(wrq->u), NULL);
       break;
 
     case SIOCGIPROAM:
-      *(wrq->u.name) = do_roaming;
+      ret = wavelan_get_roam(dev, NULL, &(wrq->u), NULL);
       break;
 #endif	/* WAVELAN_ROAMING */
 
@@ -2484,44 +3120,44 @@
 	{
 	  ret = -EPERM;
 	}
-
-      /* Check the number of intervals */
-      if(wrq->u.data.length > 16)
-	{
-	  ret = -E2BIG;
-	  break;
+      {
+	char buffer[16];
+	/* Check the number of intervals */
+	if(wrq->u.data.length > 16)
+	  {
+	    ret = -E2BIG;
+	    break;
 	}
-      lp->his_number = wrq->u.data.length;
-
-      /* If there is some addresses to copy */
-      if(lp->his_number > 0)
-	{
-	  /* Copy interval ranges to the driver */
-	  if(copy_from_user(lp->his_range, wrq->u.data.pointer,
-			 sizeof(char) * lp->his_number))
-	    {
-	      ret = -EFAULT;
-	      break;
-	    }
-
-	  /* Reset structure... */
-	  memset(lp->his_sum, 0x00, sizeof(long) * 16);
+	/* Get the data in the driver */
+	if (wrq->u.data.pointer) {
+	  if (copy_from_user(buffer,
+			     wrq->u.data.pointer,
+			     sizeof(struct sockaddr) *
+			     wrq->u.data.length)) {
+	    ret = -EFAULT;
+	    break;
+	  }
+	} else if (wrq->u.data.length != 0) {
+	  ret = -EINVAL;
+	  break;
 	}
+	ret = wavelan_set_histo(dev, NULL, &(wrq->u),
+				buffer);
+      }
       break;
 
     case SIOCGIPHISTO:
-      /* Set the number of intervals */
-      wrq->u.data.length = lp->his_number;
-
-      /* Give back the distribution statistics */
-      if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
-	{
-	  /* Copy data to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, lp->his_sum,
-		       sizeof(long) * lp->his_number))
+      {
+	long buffer[16];
+	ret = wavelan_get_histo(dev, NULL, &(wrq->u),
+				(char *) buffer);
+	if (wrq->u.data.pointer) {
+	  if (copy_to_user(wrq->u.data.pointer,
+			   buffer,
+			   (wrq->u.data.length * sizeof(long))))
 	    ret = -EFAULT;
-
-	}	/* if(pointer != NULL) */
+	}
+      }
       break;
 #endif	/* HISTOGRAM */
 
@@ -2531,14 +3167,12 @@
       ret = -EOPNOTSUPP;
     }
 
-  /* ReEnable interrupts & restore flags */
-  wv_splx(lp, &flags);
-
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
 #endif
   return ret;
 }
+#endif /* WIRELESS_EXT > 12 */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2559,7 +3193,7 @@
 #endif
 
   /* Disable interrupts & save flags */
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   wstats = &lp->wstats;
 
@@ -2585,7 +3219,7 @@
   wstats->discard.misc = 0L;
 
   /* ReEnable interrupts & restore flags */
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
@@ -2921,7 +3555,7 @@
   printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
 #endif
 
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* Check if we need some padding */
   if(clen < ETH_ZLEN)
@@ -2951,7 +3585,7 @@
   /* Keep stats up to date */
   lp->stats.tx_bytes += length;
 
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
 #ifdef DEBUG_TX_INFO
   wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
@@ -2991,9 +3625,9 @@
    * we can do it now */
   if(lp->reconfig_82593)
     {
-      wv_splhi(lp, &flags);	/* Disable interrupts */
+      spin_lock_irqsave(&lp->spinlock, flags);	/* Disable interrupts */
       wv_82593_config(dev);
-      wv_splx(lp, &flags);	/* Re-enable interrupts */
+      spin_unlock_irqrestore(&lp->spinlock, flags);	/* Re-enable interrupts */
       /* Note : the configure procedure was totally synchronous,
        * so the Tx buffer is now free */
     }
@@ -3230,7 +3864,7 @@
   printk(KERN_DEBUG "%s: ->wv_ru_stop()\n", dev->name);
 #endif
 
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* First, send the LAN controller a stop receive command */
   wv_82593_cmd(dev, "wv_graceful_shutdown(): stop-rcv",
@@ -3255,7 +3889,7 @@
     }
   while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0));
 
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
   /* If there was a problem */
   if(spin <= 0)
@@ -3299,7 +3933,7 @@
   if(!wv_ru_stop(dev))
     return FALSE;
 
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* Now we know that no command is being executed. */
 
@@ -3354,7 +3988,7 @@
   }
 #endif
 
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
@@ -3630,7 +4264,7 @@
     return FALSE;
 
   /* Disable interrupts */
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* Disguised goto ;-) */
   do
@@ -3695,7 +4329,7 @@
   while(0);
 
   /* Re-enable interrupts */
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: <-wv_hw_config()\n", dev->name);
@@ -4021,7 +4655,7 @@
 
   /* Prevent reentrancy. We need to do that because we may have
    * multiple interrupt handler running concurently.
-   * It is safe because wv_splhi() disable interrupts before aquiring
+   * It is safe because interrupts are disabled before aquiring
    * the spinlock. */
   spin_lock(&lp->spinlock);
 
@@ -4254,7 +4888,7 @@
 	 dev->name);
 #endif
 
-  wv_splhi(lp, &flags);
+  spin_lock_irqsave(&lp->spinlock, flags);
 
   /* Ask to abort the current command */
   outb(OP0_ABORT, LCCR(base));
@@ -4265,7 +4899,7 @@
     aborted = TRUE;
 
   /* Release spinlock here so that wv_hw_reset() can grab it */
-  wv_splx(lp, &flags);
+  spin_unlock_irqrestore(&lp->spinlock, flags);
 
   /* Check if we were successful in aborting it */
   if(!aborted)
@@ -4530,7 +5164,11 @@
   dev->watchdog_timeo	= WATCHDOG_JIFFIES;
 
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+#if WIRELESS_EXT > 12
+  dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
+#else /* WIRELESS_EXT > 12 */
   dev->do_ioctl = wavelan_ioctl;	/* wireless extensions */
+#endif /* WIRELESS_EXT > 12 */
   dev->get_wireless_stats = wavelan_get_wireless_stats;
 #endif
 
diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
--- a/drivers/net/wireless/wavelan_cs.p.h	Tue Feb 26 11:57:58 2002
+++ b/drivers/net/wireless/wavelan_cs.p.h	Tue Feb 26 11:57:58 2002
@@ -394,6 +394,12 @@
  *		o control first busy loop in wv_82593_cmd()
  *		o Extend spinlock protection in wv_hw_config()
  *
+ * Changes made for release in 3.1.33 :
+ * ----------------------------------
+ *	- Optional use new driver API for Wireless Extensions :
+ *		o got rid of wavelan_ioctl()
+ *		o use a bunch of iw_handler instead
+ *
  * Wishes & dreams:
  * ----------------
  *	- Cleanup and integrate the roaming code
@@ -430,6 +436,9 @@
 
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Wireless extensions */
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif	/* WIRELESS_EXT > 12 */
 #endif
 
 /* Pcmcia headers that we need */
@@ -498,7 +507,7 @@
 /************************ CONSTANTS & MACROS ************************/
 
 #ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/12/00\n";
+static const char *version = "wavelan_cs.c : v24 (SMP + wireless extensions) 11/1/02\n";
 #endif
 
 /* Watchdog temporisation */
@@ -523,8 +532,8 @@
 #define SIOCSIPROAM     SIOCIWFIRSTPRIV + 2	/* Set roaming state */
 #define SIOCGIPROAM     SIOCIWFIRSTPRIV + 3	/* Get roaming state */
 
-#define SIOCSIPHISTO	SIOCIWFIRSTPRIV + 6	/* Set histogram ranges */
-#define SIOCGIPHISTO	SIOCIWFIRSTPRIV + 7	/* Get histogram values */
+#define SIOCSIPHISTO	SIOCIWFIRSTPRIV + 4	/* Set histogram ranges */
+#define SIOCGIPHISTO	SIOCIWFIRSTPRIV + 5	/* Get histogram values */
 
 /*************************** WaveLAN Roaming  **************************/
 #ifdef WAVELAN_ROAMING		/* Conditional compile, see above in options */
@@ -589,6 +598,16 @@
 typedef struct net_local	net_local;
 typedef struct timer_list	timer_list;
 
+#if WIRELESS_EXT <= 12
+/* Wireless extensions backward compatibility */
+/* Part of iw_handler prototype we need */
+struct iw_request_info
+{
+	__u16		cmd;		/* Wireless Extension command */
+	__u16		flags;		/* More to come ;-) */
+};
+#endif	/* WIRELESS_EXT <= 12 */
+
 /* Basic types */
 typedef u_char		mac_addr[WAVELAN_ADDR_SIZE];	/* Hardware address */
 
@@ -661,12 +680,6 @@
 #endif	/* WAVELAN_ROAMING */
 
 /* ----------------------- MISC SUBROUTINES ------------------------ */
-static inline void
-	wv_splhi(net_local *,		/* Disable interrupts */
-		 unsigned long *);	/* flags */
-static inline void
-	wv_splx(net_local *,		/* ReEnable interrupts */
-		unsigned long *);	/* flags */
 static void
 	cs_error(client_handle_t,	/* Report error to cardmgr */
 		 int,
diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
--- a/drivers/net/yellowfin.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/net/yellowfin.c	Tue Feb 26 11:57:59 2002
@@ -1487,7 +1487,7 @@
 	name:		DRV_NAME,
 	id_table:	yellowfin_pci_tbl,
 	probe:		yellowfin_init_one,
-	remove:		yellowfin_remove_one,
+	remove:		__devexit_p(yellowfin_remove_one),
 };
 
 
diff -Nru a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
--- a/drivers/parport/parport_serial.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/parport/parport_serial.c	Tue Feb 26 11:58:00 2002
@@ -331,7 +331,7 @@
 	name:		"parport_serial",
 	id_table:	parport_serial_pci_tbl,
 	probe:		parport_serial_pci_probe,
-	remove:		parport_serial_pci_remove,
+	remove:		__devexit_p(parport_serial_pci_remove),
 };
 
 
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	Tue Feb 26 11:57:56 2002
+++ b/drivers/pci/pci.ids	Tue Feb 26 11:57:56 2002
@@ -3952,6 +3952,7 @@
 	9511  16PCI954 Function 1
 		15ed 2000  Macrolink MCCR Serial p4-7 of 8
 		15ed 2001  Macrolink MCCR Serial p4-15 of 16
+	9521  Oxford Semi OX16PCI952 PCI/dual 16950 UART
 1416  Multiwave Innovation pte Ltd
 1417  Convergenet Technologies Inc
 1418  Kyushu electronics systems Inc
diff -Nru a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
--- a/drivers/pcmcia/pci_socket.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/pcmcia/pci_socket.c	Tue Feb 26 11:57:59 2002
@@ -249,7 +249,7 @@
 	name:		"cardbus",
 	id_table:	cardbus_table,
 	probe:		cardbus_probe,
-	remove:		cardbus_remove,
+	remove:		__devexit_p(cardbus_remove),
 	suspend:	cardbus_suspend,
 	resume:		cardbus_resume,
 };
diff -Nru a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c
--- a/drivers/pnp/isapnp.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/pnp/isapnp.c	Tue Feb 26 11:57:56 2002
@@ -21,7 +21,7 @@
  *  2000-01-01	Added quirks handling for buggy hardware
  *		Peter Denison <peterd@pnd-pc.demon.co.uk>
  *  2000-06-14	Added isapnp_probe_devs() and isapnp_activate_dev()
- *		Christoph Hellwig <hch@caldera.de>
+ *		Christoph Hellwig <hch@infradead.org>
  *  2001-06-03  Added release_region calls to correspond with
  *		request_region calls when a failure occurs.  Also
  *		added KERN_* constants to printk() calls.
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	Tue Feb 26 11:57:58 2002
+++ b/drivers/scsi/Makefile	Tue Feb 26 11:57:58 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for linux/drivers/scsi
 #
-# 30 May 2000, Christoph Hellwig <chhellwig@gmx.net>
+# 30 May 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 # 20 Sep 2000, Torben Mathiasen <tmm@image.dk>
diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
--- a/drivers/scsi/NCR5380.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/scsi/NCR5380.c	Tue Feb 26 11:57:58 2002
@@ -83,8 +83,6 @@
  *     basically, transfer size needs to be reduced by one 
  *     and the last byte read as is done with PSEUDO_DMA.
  * 
- * 3.  Test USLEEP code 
- *
  * 4.  Test SCSI-II tagged queueing (I have no devices which support 
  *      tagged queueing)
  *
@@ -110,6 +108,12 @@
 #define READ_OVERRUNS
 #endif
 
+#ifdef BOARD_REQUIRES_NO_DELAY
+#define io_recovery_delay(x)
+#else
+#define io_recovery_delay(x)	udelay(x)
+#endif
+
 /*
  * Design
  * Issues :
@@ -192,9 +196,8 @@
  * phase goes through the various phases as instructed by the target.
  * if the target goes into MSG IN and sends a DISCONNECT message,
  * the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work.  If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work.  If the target is 
+ * idle for too long, the system will try to sleep.
  *
  * If a command has disconnected, eventually an interrupt will trigger,
  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
@@ -244,21 +247,14 @@
  *      rely on phase mismatch and EOP interrupts to determine end 
  *      of phase.
  *
- * SCSI2 - if defined, SCSI-2 tagged queuing is used where possible
- *
  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
  *          only really want to use this if you're having a problem with
  *          dropped characters during high speed communications, and even
  *          then, you're going to be better off twiddling with transfersize
  *          in the high level code.
  *
- * USLEEP - if defined, on devices that aren't disconnecting from the 
- *      bus, we will go to sleep so that the CPU can get real work done 
- *      when we run a command that won't complete immediately.
- *
- * Defaults for these will be provided if USLEEP is defined, although
- * the user may want to adjust these to allocate CPU resources to 
- * the SCSI driver or "real" code.
+ * Defaults for these will be provided although the user may want to adjust 
+ * these to allocate CPU resources to the SCSI driver or "real" code.
  * 
  * USLEEP_SLEEP - amount of time, in jiffies, to sleep
  *
@@ -322,18 +318,13 @@
 static void do_reset(struct Scsi_Host *host);
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *the_template = NULL;
-
-#ifdef USLEEP
-struct timer_list usleep_timer;
-#endif
+static struct timer_list usleep_timer;
 
 /*
- * Function : void initialize_SCp(Scsi_Cmnd *cmd)
+ *	initialize_SCp		-	init the scsi pointer field
+ *	@cmd: command block to set up
  *
- * Purpose : initialize the saved data pointers for cmd to point to the 
- *      start of the buffer.
- *
- * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+ *	Set up the internal fields in the SCSI command.
  */
 
 static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
@@ -362,88 +353,49 @@
 static struct {
 	unsigned char mask;
 	const char *name;
-} signals[] = { {
-
-		SR_DBP, "PARITY"
-}, {
-	SR_RST, "RST"
-}, {
-	SR_BSY, "BSY"
-},
-{
-	SR_REQ, "REQ"
-}, {
-	SR_MSG, "MSG"
-}, {
-	SR_CD, "CD"
-}, {
-	SR_IO, "IO"
-},
-{
-	SR_SEL, "SEL"
-}, {
-	0, NULL
-}
-},
-
-basrs[] = { {
-		BASR_ATN, "ATN"
-}, {
-	BASR_ACK, "ACK"
-}, {
-	0, NULL
-}
-},
-
-icrs[] = { {
-		ICR_ASSERT_RST, "ASSERT RST"
-}, {
-	ICR_ASSERT_ACK, "ASSERT ACK"
-},
-{
-	ICR_ASSERT_BSY, "ASSERT BSY"
-}, {
-	ICR_ASSERT_SEL, "ASSERT SEL"
-},
-{
-	ICR_ASSERT_ATN, "ASSERT ATN"
-}, {
-	ICR_ASSERT_DATA, "ASSERT DATA"
-},
-{
-	0, NULL
-}
-},
-
-mrs[] = { {
-		MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"
-}, {
-	MR_TARGET, "MODE TARGET"
-},
-{
-	MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"
-}, {
-	MR_ENABLE_PAR_INTR,
-	    "MODE PARITY INTR"
-}, {
-	MR_MONITOR_BSY, "MODE MONITOR BSY"
-},
-{
-	MR_DMA_MODE, "MODE DMA"
-}, {
-	MR_ARBITRATE, "MODE ARBITRATION"
-},
-{
-	0, NULL
-}
+} signals[] = { 
+	{SR_DBP, "PARITY"}, 
+	{SR_RST, "RST"}, 
+	{SR_BSY, "BSY"}, 
+	{SR_REQ, "REQ"}, 
+	{SR_MSG, "MSG"}, 
+	{SR_CD, "CD"}, 
+	{SR_IO, "IO"}, 
+	{SR_SEL, "SEL"}, 
+	{0, NULL}
+}, 
+basrs[] = {
+	{BASR_ATN, "ATN"}, 
+	{BASR_ACK, "ACK"}, 
+	{0, NULL}
+}, 
+icrs[] = { 
+	{ICR_ASSERT_RST, "ASSERT RST"}, 
+	{ICR_ASSERT_ACK, "ASSERT ACK"}, 
+	{ICR_ASSERT_BSY, "ASSERT BSY"}, 
+	{ICR_ASSERT_SEL, "ASSERT SEL"}, 
+	{ICR_ASSERT_ATN, "ASSERT ATN"}, 
+	{ICR_ASSERT_DATA, "ASSERT DATA"}, 
+	{0, NULL}
+}, 
+mrs[] = { 
+	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, 
+	{MR_TARGET, "MODE TARGET"}, 
+	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, 
+	{MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, 
+	{MR_MONITOR_BSY, "MODE MONITOR BSY"}, 
+	{MR_DMA_MODE, "MODE DMA"}, 
+	{MR_ARBITRATE, "MODE ARBITRATION"}, 
+	{0, NULL}
 };
 
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
+/**
+ *	NCR5380_print	-	print scsi bus signals
+ *	@instance:	adapter state to dump
  *
- * Purpose : print the SCSI bus signals for debugging purposes
+ *	Print the SCSI bus signals for debugging purposes
  *
- * Input : instance - which NCR5380
+ *	Locks: none
  */
 
 static void NCR5380_print(struct Scsi_Host *instance)
@@ -452,6 +404,7 @@
 	unsigned long flags;
 	unsigned char status, data, basr, mr, icr, i;
 	NCR5380_setup(instance);
+	/* FIXME - this needs proper locking */
 	save_flags(flags);
 	cli();
 	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
@@ -483,32 +436,22 @@
 	unsigned char value;
 	const char *name;
 } phases[] = {
-
-	{
-		PHASE_DATAOUT, "DATAOUT"
-	}, {
-		PHASE_DATAIN, "DATAIN"
-	}, {
-		PHASE_CMDOUT, "CMDOUT"
-	},
-	{
-		PHASE_STATIN, "STATIN"
-	}, {
-		PHASE_MSGOUT, "MSGOUT"
-	}, {
-		PHASE_MSGIN, "MSGIN"
-	},
-	{
-		PHASE_UNKNOWN, "UNKNOWN"
-	}
+	{PHASE_DATAOUT, "DATAOUT"}, 
+	{PHASE_DATAIN, "DATAIN"}, 
+	{PHASE_CMDOUT, "CMDOUT"}, 
+	{PHASE_STATIN, "STATIN"}, 
+	{PHASE_MSGOUT, "MSGOUT"}, 
+	{PHASE_MSGIN, "MSGIN"}, 
+	{PHASE_UNKNOWN, "UNKNOWN"}
 };
 
 /* 
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+ *	NCR5380_print_phase	-	show SCSI phase
+ *	@instance: adapter to dump
  *
- * Purpose : print the current SCSI phase for debugging purposes
+ * 	Print the current SCSI phase for debugging purposes
  *
- * Input : instance - which NCR5380
+ *	Locks: none
  */
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -520,11 +463,9 @@
 
 	status = NCR5380_read(STATUS_REG);
 	if (!(status & SR_REQ))
-		printk("scsi%d : REQ not asserted, phase unknown.\n",
-		       instance->host_no);
+		printk("scsi%d : REQ not asserted, phase unknown.\n", instance->host_no);
 	else {
-		for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
-		     (phases[i].value != (status & PHASE_MASK)); ++i);
+		for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
 		printk("scsi%d : phase %s\n", instance->host_no, phases[i].name);
 	}
 }
@@ -549,7 +490,7 @@
  * conditions are possible.
  */
 
-static volatile int main_running = 0;
+static unsigned long main_running = 0;
 
 /* 
  * Function : run_main(void)
@@ -563,14 +504,10 @@
 
 static __inline__ void run_main(void)
 {
-	if (!main_running) {
-		main_running = 1;
+	if (!test_and_set_bit(0, &main_running))
 		NCR5380_main();
-	}
 }
 
-#ifdef USLEEP
-
 /*
  * These need tweaking, and would probably work best as per-device 
  * flags initialized differently for disk, tape, cd, etc devices.
@@ -621,63 +558,67 @@
 static int should_disconnect(unsigned char cmd)
 {
 	switch (cmd) {
-		case READ_6:
-		    case WRITE_6:
-		    case SEEK_6:
-		    case READ_10:
-		    case WRITE_10:
-		    case SEEK_10:
-		    return DISCONNECT_TIME_TO_DATA;
-		case FORMAT_UNIT:
-		    case SEARCH_HIGH:
-		    case SEARCH_LOW:
-		    case SEARCH_EQUAL:
-		    return DISCONNECT_LONG;
-		default:
-		    return DISCONNECT_NONE;
+	case READ_6:
+	case WRITE_6:
+	case SEEK_6:
+	case READ_10:
+	case WRITE_10:
+	case SEEK_10:
+		return DISCONNECT_TIME_TO_DATA;
+	case FORMAT_UNIT:
+	case SEARCH_HIGH:
+	case SEARCH_LOW:
+	case SEARCH_EQUAL:
+		return DISCONNECT_LONG;
+	default:
+		return DISCONNECT_NONE;
 	}
 }
 
 /*
  * Assumes instance->time_expires has been set in higher level code.
+ *
+ * Locks: Caller must hold io_request_lock
  */
 
 static int NCR5380_set_timer(struct Scsi_Host *instance)
 {
-	unsigned long flags;
 	struct Scsi_Host *tmp, **prev;
 
-	save_flags(flags);
-	cli();
 	if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
-		restore_flags(flags);
 		return -1;
 	}
-	for (prev = &expires_first, tmp = expires_first; tmp;
-		prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), 
-		tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
-		if (((struct NCR5380_hostdata *)instance->hostdata)->time_expires < 
-			((struct NCR5380_hostdata *)tmp->hostdata)->time_expires) 
+	for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
+		if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
 			break;
 
 	((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
 	*prev = instance;
-   
+
 	mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
-	restore_flags(flags);
 	return 0;
 }
 
-/* Doing something about unwanted reentrancy here might be useful */
-void NCR5380_timer_fn(unsigned long surplus_to_requirements)
+/**
+ *	NCR5380_timer_fn	-	handle polled timeouts
+ *	@unused: unused
+ *
+ *	Walk the list of controllers, find which controllers have exceeded
+ *	their expiry timeout and then schedule the processing co-routine to
+ *	do the real work.
+ *
+ *	Doing something about unwanted reentrancy here might be useful 
+ *
+ *	Locks: disables irqs, takes and frees io_request_lock
+ */
+ 
+static void NCR5380_timer_fn(unsigned long unused)
 {
-	unsigned long flags;
 	struct Scsi_Host *instance;
-	save_flags(flags);
-	cli();
-	for (; expires_first &&
-		time_before_eq(((struct NCR5380_hostdata *)expires_first->hostdata)->time_expires, jiffies); )
-	{
+
+	spin_lock_irq(&io_request_lock);
+	
+	for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) {
 		instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer;
 		((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL;
 		((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires = 0;
@@ -685,90 +626,91 @@
 	}
 
 	del_timer(&usleep_timer);
-	if (expires_first) 
-	{
-		usleep_timer.expires = ((struct NCR5380_hostdata *)expires_first->hostdata)->time_expires;
+	if (expires_first) {
+		usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
 		add_timer(&usleep_timer);
 	}
-	restore_flags(flags);
-
-	spin_lock_irqsave(instance->host_lock, flags);
 	run_main();
-	spin_unlock_irqrestore(instance->host_lock, flags);
+	spin_unlock_irq(&io_request_lock);
 }
-#endif				/* def USLEEP */
 
+/**
+ *	NCR5380_all_init	-	global setup
+ *
+ *	Set up the global values and timers needed by the NCR5380 driver
+ */
+ 
 static inline void NCR5380_all_init(void)
 {
 	static int done = 0;
 	if (!done) {
-#if (NDEBUG & NDEBUG_INIT)
-		printk("scsi : NCR5380_all_init()\n");
-#endif
+		dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
 		done = 1;
-#ifdef USLEEP
 		init_timer(&usleep_timer);
 		usleep_timer.function = NCR5380_timer_fn;
-#endif
 	}
 }
 
-#ifdef AUTOPROBE_IRQ
-/*
- * Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible)
- * 
- * Purpose : autoprobe for the IRQ line used by the NCR5380.  
- *
- * Inputs : instance - pointer to this instance of the NCR5380 driver,
- *          possible - bitmask of permissible interrupts.
- *
- * Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired.
- * 
- * XXX no effort is made to deal with spurious interrupts. 
- */
-
 
 static int probe_irq __initdata = 0;
 
+/**
+ *	probe_intr	-	helper for IRQ autoprobe
+ *	@irq: interrupt number
+ *	@dev_id: unused
+ *	@regs: unused
+ *
+ *	Set a flag to indicate the IRQ in question was received. This is
+ *	used by the IRQ probe code.
+ */
+ 
 static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	probe_irq = irq;
 }
 
+/**
+ *	NCR5380_probe_irq	-	find the IRQ of an NCR5380
+ *	@instance: NCR5380 controller
+ *	@possible: bitmask of ISA IRQ lines
+ *
+ *	Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
+ *	and then looking to see what interrupt actually turned up.
+ *
+ *	Locks: none, irqs must be enabled on entry
+ */
+
 static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
 {
 	NCR5380_local_declare();
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	unsigned long timeout;
 	int trying_irqs, i, mask;
 	NCR5380_setup(instance);
 
 	for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
-		if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", instance)
-					  == 0))
+		if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL) == 0))
 			trying_irqs |= mask;
 
 	timeout = jiffies + (250 * HZ / 1000);
 	probe_irq = IRQ_NONE;
 
-/*
- * A interrupt is triggered whenever BSY = false, SEL = true
- * and a bit set in the SELECT_ENABLE_REG is asserted on the 
- * SCSI bus.
- *
- * Note that the bus is only driven when the phase control signals
- * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
- * to zero.
- */
+	/*
+	 * A interrupt is triggered whenever BSY = false, SEL = true
+	 * and a bit set in the SELECT_ENABLE_REG is asserted on the 
+	 * SCSI bus.
+	 *
+	 * Note that the bus is only driven when the phase control signals
+	 * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
+	 * to zero.
+	 */
 
 	NCR5380_write(TARGET_COMMAND_REG, 0);
 	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA |
-		      ICR_ASSERT_SEL);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
 
-	while (probe_irq == IRQ_NONE && time_before(jiffies,timeout))
+	while (probe_irq == IRQ_NONE && time_before(jiffies, timeout))
 		barrier();
 
 	NCR5380_write(SELECT_ENABLE_REG, 0);
@@ -780,15 +722,16 @@
 
 	return probe_irq;
 }
-#endif				/* AUTOPROBE_IRQ */
 
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
- *
- * Purpose : called by probe code indicating the NCR5380 driver
- *           options that were selected.
+/**
+ *	NCR58380_print_options	-	show options
+ *	@instance: unused for now
+ *
+ *	Called by probe code indicating the NCR5380 driver options that 
+ *	were selected. At some point this will switch to runtime options
+ *	read from the adapter in question
  *
- * Inputs : instance, pointer to this instance.  Unused.
+ *	Locks: none
  */
 
 static void __init NCR5380_print_options(struct Scsi_Host *instance)
@@ -815,29 +758,25 @@
 #ifdef PSEUDO_DMA
 	       " PSEUDO DMA"
 #endif
-#ifdef SCSI2
-	       " SCSI-2"
-#endif
 #ifdef UNSAFE
 	       " UNSAFE "
 #endif
 	    );
-#ifdef USLEEP
 	printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
-#endif
 	printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
 	if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
 		printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
 	}
 }
 
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
+/**
+ *	NCR5380_print_status 	-	dump controller info
+ *	@instance: controller to dump
  *
- * Purpose : print commands in the various queues, called from
- *      NCR5380_abort and NCR5380_debug to aid debugging.
+ *	Print commands in the various queues, called from NCR5380_abort 
+ *	and NCR5380_debug to aid debugging.
  *
- * Inputs : instance, pointer to this instance.  
+ *	Locks: called functions disable irqs, missing queue lock in proc call
  */
 
 static void NCR5380_print_status(struct Scsi_Host *instance)
@@ -846,16 +785,12 @@
 	char *start;
 	int len;
 
-	printk("NCR5380 : coroutine is%s running.\n",
-	       main_running ? "" : "n't");
+	printk("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
 
-#ifdef NDEBUG
-	NCR5380_print(instance);
-	NCR5380_print_phase(instance);
-#endif
+	NCR5380_dprint(NDEBUG_ANY, instance);
+	NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
-	len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr),
-				instance->host_no, 0);
+	len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), instance->host_no, 0);
 	pr_bfr[len] = 0;
 	printk("\n%s\n", pr_bfr);
 }
@@ -886,18 +821,14 @@
 #ifndef NCR5380_proc_info
 static
 #endif
-int NCR5380_proc_info(
-			     char *buffer, char **start, off_t offset,
-			     int length, int hostno, int inout)
+int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
 {
-	unsigned long flags;
 	char *pos = buffer;
 	struct Scsi_Host *instance;
 	struct NCR5380_hostdata *hostdata;
 	Scsi_Cmnd *ptr;
 
-	for (instance = first_instance; instance &&
-	     instance->host_no != hostno; instance = instance->next);
+	for (instance = first_instance; instance && instance->host_no != hostno; instance = instance->next);
 	if (!instance)
 		return (-ESRCH);
 	hostdata = (struct NCR5380_hostdata *) instance->hostdata;
@@ -935,32 +866,27 @@
 		SPRINTF("IRQ: %d.\n", instance->irq);
 
 #ifdef DTC_PUBLIC_RELEASE
-	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",
-		dtc_wmaxi, dtc_maxi);
+	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", dtc_wmaxi, dtc_maxi);
 #endif
 #ifdef PAS16_PUBLIC_RELEASE
-	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",
-		pas_wmaxi, pas_maxi);
+	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irq(&io_request_lock);
 	SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
 	else
-		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
-				       pos, buffer, length);
+		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, pos, buffer, length);
 	SPRINTF("scsi%d: issue_queue\n", instance->host_no);
-	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;
-	     ptr = (Scsi_Cmnd *) ptr->host_scribble)
+	for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
 
 	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
-	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-	     ptr = (Scsi_Cmnd *) ptr->host_scribble)
+	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
 
-	restore_flags(flags);
+	spin_unlock_irq(&io_request_lock);
+	
 	*start = buffer;
 	if (pos - buffer < offset)
 		return 0;
@@ -972,16 +898,14 @@
 static
 char *lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, char *pos, char *buffer, int length)
 {
-	SPRINTF("scsi%d : destination target %d, lun %d\n",
-		cmd->host->host_no, cmd->target, cmd->lun);
+	SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->host->host_no, cmd->target, cmd->lun);
 	SPRINTF("        command = ");
 	pos = lprint_command(cmd->cmnd, pos, buffer, length);
 	return (pos);
 }
 
 static
-char *lprint_command(unsigned char *command,
-		     char *pos, char *buffer, int length)
+char *lprint_command(unsigned char *command, char *pos, char *buffer, int length)
 {
 	int i, s;
 	pos = lprint_opcode(command[0], pos, buffer, length);
@@ -999,17 +923,18 @@
 }
 
 
-/* 
- * Function : void NCR5380_init (struct Scsi_Host *instance, flags)
+/**
+ *	NCR5380_init	-	initialise an NCR5380
+ *	@instance: adapter to configure
+ *	@flags: control flags
  *
- * Purpose : initializes *instance and corresponding 5380 chip,
+ *	Initializes *instance and corresponding 5380 chip,
  *      with flags OR'd into the initial flags value.
  *
- * Inputs : instance - instantiation of the 5380 driver.  
- *
- * Notes : I assume that the host, hostno, and id bits have been
+ *	Notes : I assume that the host, hostno, and id bits have been
  *      set correctly.  I don't care about the irq and other fields. 
- * 
+ *
+ *	Locks: interrupts must be enabled when we are called 
  */
 
 static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -1017,9 +942,10 @@
 	NCR5380_local_declare();
 	int i, pass;
 	unsigned long timeout;
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
+	if(in_interrupt())
+		printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
 	/* 
 	 * On NCR53C400 boards, NCR5380 registers are mapped 8 past 
 	 * the base address.
@@ -1031,7 +957,6 @@
 #endif
 
 	NCR5380_setup(instance);
-
 	NCR5380_all_init();
 
 	hostdata->aborted = 0;
@@ -1070,17 +995,13 @@
 		the_template = instance->hostt;
 		first_instance = instance;
 	}
-#ifdef USLEEP
 	hostdata->time_expires = 0;
 	hostdata->next_timer = NULL;
-#endif
 
 #ifndef AUTOSENSE
 	if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
-		)
-		    printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n"
-			   "         without AUTOSENSE option, contingent allegiance conditions may\n"
-		"         be incorrectly cleared.\n", instance->host_no);
+		    printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" "         without AUTOSENSE option, contingent allegiance conditions may\n"
+		    	   "         be incorrectly cleared.\n", instance->host_no);
 #endif				/* def AUTOSENSE */
 
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
@@ -1106,50 +1027,40 @@
 	 * failing, do a hard reset of the SCSI bus 
 	 */
 
-	for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) &&
-	     pass <= 6; ++pass) {
+	for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
 		switch (pass) {
 		case 1:
 		case 3:
 		case 5:
-			printk("scsi%d: SCSI bus busy, waiting up to five seconds\n",
-			       instance->host_no);
+			printk("scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no);
 			timeout = jiffies + 5 * HZ;
-			while (time_before(jiffies,timeout) && (NCR5380_read(STATUS_REG) & SR_BSY));
+			while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY));
 			break;
 		case 2:
-			printk("scsi%d: bus busy, attempting abort\n",
-			       instance->host_no);
+			printk("scsi%d: bus busy, attempting abort\n", instance->host_no);
 			do_abort(instance);
 			break;
 		case 4:
-			printk("scsi%d: bus busy, attempting reset\n",
-			       instance->host_no);
+			printk("scsi%d: bus busy, attempting reset\n", instance->host_no);
 			do_reset(instance);
 			break;
 		case 6:
-			printk("scsi%d: bus locked solid or invalid override\n",
-			       instance->host_no);
+			printk("scsi%d: bus locked solid or invalid override\n", instance->host_no);
 		}
 	}
 }
 
-/* 
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
- *      void (*done)(Scsi_Cmnd *)) 
- *
- * Purpose :  enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *      a pointer to the command descriptor.
- * 
- * Returns : 0
+/**
+ *	NCR5380_queue_command 		-	queue a command
+ *	@cmd: SCSI command
+ *	@done: completion handler
  *
- * Side effects : 
  *      cmd is added to the per instance issue_queue, with minor 
  *      twiddling done to the host specific fields of cmd.  If the 
  *      main coroutine is not running, it is restarted.
  *
+ *	Locks: io_request lock held by caller. Called functions drop and
+ *	retake this lock. Called functions take dma lock.
  */
 
 /* Only make static if a wrapper function is used */
@@ -1158,16 +1069,14 @@
 #endif
 int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
 	struct Scsi_Host *instance = cmd->host;
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
 	switch (cmd->cmnd[0]) {
-		case WRITE_6:
-		    case WRITE_10:
-		    printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
-			   instance->host_no);
+	case WRITE_6:
+	case WRITE_10:
+		printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no);
 		cmd->result = (DID_ERROR << 16);
 		done(cmd);
 		return 0;
@@ -1175,31 +1084,22 @@
 #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
 
 #ifdef NCR5380_STATS
-#if 0
-	if (!hostdata->connected && !hostdata->issue_queue &&
-	    !hostdata->disconnected_queue) {
-		hostdata->timebase = jiffies;
-	}
-#endif
-#ifdef NCR5380_STAT_LIMIT
-	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
-#endif
-		switch (cmd->cmnd[0]) {
-			case WRITE:
-			    case WRITE_6:
-			    case WRITE_10:
-			    hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);
+	switch (cmd->cmnd[0]) {
+		case WRITE:
+		case WRITE_6:
+		case WRITE_10:
+			hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);
 			hostdata->bytes_write[cmd->target] += cmd->request_bufflen;
 			hostdata->pendingw++;
 			break;
-			case READ:
-			    case READ_6:
-			    case READ_10:
-			    hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);
+		case READ:
+		case READ_6:
+		case READ_10:
+			hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);
 			hostdata->bytes_read[cmd->target] += cmd->request_bufflen;
 			hostdata->pendingr++;
 			break;
-		}
+	}
 #endif
 
 	/* 
@@ -1209,10 +1109,8 @@
 
 	cmd->host_scribble = NULL;
 	cmd->scsi_done = done;
-
 	cmd->result = 0;
 
-
 	/* 
 	 * Insert the cmd into the issue queue. Note that REQUEST SENSE 
 	 * commands are added to the head of the queue since any command will
@@ -1225,31 +1123,28 @@
 		cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
 		hostdata->issue_queue = cmd;
 	} else {
-		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble;
-		     tmp = (Scsi_Cmnd *) tmp->host_scribble);
+		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
 		LIST(cmd, tmp);
 		tmp->host_scribble = (unsigned char *) cmd;
 	}
-#if (NDEBUG & NDEBUG_QUEUES)
-	printk("scsi%d : command added to %s of queue\n", instance->host_no,
-	       (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-#endif
+	dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
 
-/* Run the coroutine if it isn't already running. */
+	/* Run the coroutine if it isn't already running. */
 	run_main();
 	return 0;
 }
 
-/*
- * Function : NCR5380_main (void) 
+/**
+ *	NCR5380_main	-	NCR state machines
  *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
+ *	NCR5380_main is a coroutine that runs as long as more work can 
  *      be done on the NCR5380 host adapters in a system.  Both 
  *      NCR5380_queue_command() and NCR5380_intr() will try to start it 
  *      in case it is not running.
  * 
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
- *  reenable them.  This prevents reentrancy and kernel stack overflow.
+ *	Locks; The caller must hold the io_request_lock. The lock will still be
+ *	held on return but may be dropped while running. Called functions take
+ *	the DMA lock.
  */
 
 static void NCR5380_main(void) {
@@ -1257,7 +1152,6 @@
 	struct Scsi_Host *instance;
 	struct NCR5380_hostdata *hostdata;
 	int done;
-	unsigned long flags;
 
 	/*
 	 * We run (with interrupts disabled) until we're sure that none of 
@@ -1271,43 +1165,22 @@
 	 * this should prevent any race conditions.
 	 */
 
-	spin_unlock_irq(instance->host_lock);
-	
-	save_flags(flags);
-	
 	do {
-		cli();		/* Freeze request queues */
+		/* Lock held here */
 		done = 1;
-		for (instance = first_instance; instance &&
-		     instance->hostt == the_template; instance = instance->next) {
-			 hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-			 cli();
-#ifdef USLEEP
+		for (instance = first_instance; instance && instance->hostt == the_template; instance = instance->next) {
+			hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+			/* Lock held here */
 			if (!hostdata->connected && !hostdata->selecting) {
-#else
-			if (!hostdata->connected) {
-#endif			
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : not connected\n", instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no));
 				/*
 				 * Search through the issue_queue for a command destined
 				 * for a target that's not busy.
 				 */
-#if (NDEBUG & NDEBUG_LISTS)
-				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble);
-				/*printk("%p  ", tmp); */
-				if ((tmp == prev) && tmp)
-					printk(" LOOP\n");	/* else printk("\n"); */
-#endif
-				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
-				     prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *)
-				     tmp->host_scribble) {
-
-#if (NDEBUG & NDEBUG_LISTS)
+				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) 
+				{
 					if (prev != tmp)
-						printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);
-#endif
+						dprintk(NDEBUG_LISTS, ("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun));
 					/*  When we find one, remove it from the issue queue. */
 					if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
 						if (prev) {
@@ -1319,8 +1192,6 @@
 						}
 						tmp->host_scribble = NULL;
 
-						/* reenable interrupts after finding one */
-						restore_flags(flags);
 
 						/* 
 						 * Attempt to establish an I_T_L nexus here. 
@@ -1328,10 +1199,7 @@
 						 * On failure, we must add the command back to the
 						 *   issue queue so we can keep trying. 
 						 */
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-						printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n",
-						       instance->host_no, tmp->target, tmp->lun);
-#endif
+						dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
 
 						/*
 						 * A successful selection is defined as one that 
@@ -1343,105 +1211,81 @@
 						 * and see if we can do an information transfer,
 						 * with failures we will restart.
 						 */
-#ifdef USLEEP
-						hostdata->selecting = 0; /* RvC: have to preset this
-							to indicate a new command is being performed */
-#endif
+						hostdata->selecting = 0;	
+						/* RvC: have to preset this to indicate a new command is being performed */
 
 						if (!NCR5380_select(instance, tmp,
-						/* 
-						 * REQUEST SENSE commands are issued without tagged
-						 * queueing, even on SCSI-II devices because the 
-						 * contingent allegiance condition exists for the 
-						 * entire unit.
-						 */
-								    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
-							     TAG_NEXT)) {
+								    /* 
+								     * REQUEST SENSE commands are issued without tagged
+								     * queueing, even on SCSI-II devices because the 
+								     * contingent allegiance condition exists for the 
+								     * entire unit.
+								     */
+								    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
 							break;
 						} else {
-							cli();
 							LIST(tmp, hostdata->issue_queue);
-							tmp->host_scribble = (unsigned char *)
-							    hostdata->issue_queue;
+							tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 							hostdata->issue_queue = tmp;
 							done = 0;
-							restore_flags(flags);
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-							printk("scsi%d : main(): select() failed, returned to issue_queue\n",
-							       instance->host_no);
-#endif
+							dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));
 						}
+						/* lock held here still */
 					}	/* if target/lun is not busy */
 				}	/* for */
+				/* exited locked */
 			}	/* if (!hostdata->connected) */
-#ifdef USLEEP
-			if (hostdata->selecting) 
-			{
-				tmp = (Scsi_Cmnd *)hostdata->selecting;
-				if (!NCR5380_select(instance, tmp, 
-					(tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) 
-				{
+			if (hostdata->selecting) {
+				tmp = (Scsi_Cmnd *) hostdata->selecting;
+				/* Selection will drop and retake the lock */
+				if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
 					/* Ok ?? */
-				}
-				else
-				{
+				} else {
 					/* RvC: device failed, so we wait a long time
-					this is needed for Mustek scanners, that
-					do not respond to commands immediately
-					after a scan */
-					printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n",
-						instance->host_no, tmp->target);
-					cli();
+					   this is needed for Mustek scanners, that
+					   do not respond to commands immediately
+					   after a scan */
+					printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
+					//spin_lock_irq(&io_request_lock);
 					LIST(tmp, hostdata->issue_queue);
 					tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 					hostdata->issue_queue = tmp;
-					restore_flags(flags);
+					//spin_unlock_irq(&io_request_lock);
 
 					hostdata->time_expires = jiffies + USLEEP_WAITLONG;
-					NCR5380_set_timer (instance);
+					NCR5380_set_timer(instance);
 				}
-			} /* if hostdata->selecting */
-#endif
+			}	/* if hostdata->selecting */
 			if (hostdata->connected
 #ifdef REAL_DMA
 			    && !hostdata->dmalen
 #endif
-#ifdef USLEEP
 			    && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))
-#endif
 			    ) {
-				restore_flags(flags);
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : main() : performing information transfer\n",
-				       instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));
 				NCR5380_information_transfer(instance);
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : main() : done set false\n", instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));
 				done = 0;
 			} else
 				break;
 		}		/* for instance */
 	} while (!done);
-	spin_lock_irq(instance->host_lock);
-  /* 	cli();*/
-	main_running = 0;
+	/* Exit lock held */
+	clear_bit(0, &main_running);
 }
 
 #ifndef DONT_USE_INTR
 #include <linux/blk.h>
 #include <linux/spinlock.h>
 
-/*
- * Function : void NCR5380_intr (int irq)
- * 
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+/**
+ * 	NCR5380_intr	-	generic NCR5380 irq handler
+ *
+ *	Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
  *      from the disconnected queue, and restarting NCR5380_main() 
  *      as required.
  *
- * Inputs : int irq, irq that caused this interrupt.
- *
+ *	Locks: caller must hold the io_request lock.
  */
 
 static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
@@ -1449,17 +1293,12 @@
 	struct Scsi_Host *instance;
 	int done;
 	unsigned char basr;
-	unsigned long flags;
 
-	 save_flags(flags);
-	 cli();
-#if (NDEBUG & NDEBUG_INTR)
-	 printk("scsi : NCR5380 irq %d triggered\n", irq);
-#endif
+	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
+
 	do {
 		done = 1;
-		for (instance = first_instance; instance && (instance->hostt ==
-				the_template); instance = instance->next)
+		for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
 			if (instance->irq == irq) {
 
 				/* Look for pending interrupts */
@@ -1467,34 +1306,19 @@
 				basr = NCR5380_read(BUS_AND_STATUS_REG);
 				/* XXX dispatch to appropriate routine if found and done=0 */
 				if (basr & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_INTR)
-					NCR5380_print(instance);
-#endif
-					if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
-					    (SR_SEL | SR_IO)) {
+					NCR5380_dprint(NDEBUG_INTR, instance);
+					if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 						done = 0;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : SEL interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
 						NCR5380_reselect(instance);
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else if (basr & BASR_PARITY_ERROR) {
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : PARITY interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : RESET interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else {
-/*  
- * XXX the rest of the interrupt conditions should *only* occur during a 
- * DMA transfer, which I haven't gotten around to fixing yet.
- */
-
 #if defined(REAL_DMA)
 						/*
 						 * We should only get PHASE MISMATCH and EOP interrupts
@@ -1502,14 +1326,11 @@
 						 * the current setting of the MODE register.
 						 */
 
-						if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr &
-						BASR_END_DMA_TRANSFER) ||
-											  !(basr & BASR_PHASE_MATCH))) {
+						if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {
 							int transfered;
 
 							if (!hostdata->connected)
-								panic("scsi%d : received end of DMA interrupt with no connected cmd\n",
-								      instance->hostno);
+								panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);
 
 							transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));
 							hostdata->connected->SCp.this_residual -= transferred;
@@ -1521,16 +1342,14 @@
 							{
 								unsigned long timeout = jiffies + NCR_TIMEOUT;
 
-								spin_unlock_irq(instance->host_lock);
-								while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK
-								       && time_before(jiffies, timeout));
-								spin_lock_irq(instance->host_lock);
-								
-								if (time_after_eq(jiffies, timeout) )
-									printk("scsi%d: timeout at NCR5380.c:%d\n",
-									       host->host_no, __LINE__);
+								spin_unlock_irq(&io_request_lock);
+								while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout));
+								spin_lock_irq(&io_request_lock);
+
+								if (time_after_eq(jiffies, timeout))
+									printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
 							}
-#else				/* NCR_TIMEOUT */
+#else /* NCR_TIMEOUT */
 							while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
 #endif
 
@@ -1538,9 +1357,7 @@
 							NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 						}
 #else
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-#endif
+						dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 #endif
 					}
@@ -1551,42 +1368,57 @@
 	} while (!done);
 }
 
+/**
+ *	do_NCR5380_intr
+ *	@irq: interrupt number
+ *	@dev_id: device info
+ *	@regs: registers (unused)
+ *
+ *	Takes the io_request_lock and invokes the generic NCR5380 interrupt
+ *	handler code
+ *
+ *	Locks: takes and releases the io_request lock
+ */
 
 static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
 	unsigned long flags;
-	 
-	 struct Scsi_Host *dev = dev_id;
-	
-	 spin_lock_irqsave(dev->host_lock, flags);
+
+	 spin_lock_irqsave(&io_request_lock, flags);
 	 NCR5380_intr(irq, dev_id, regs);
-	 spin_unlock_irqrestore(dev->host_lock, flags);
+	 spin_unlock_irqrestore(&io_request_lock, flags);
 }
-
 #endif
 
+
+/**
+ *	collect_stats		-	collect stats on a scsi command
+ *	@hostdata: adapter 
+ *	@cmd: command being issued
+ *
+ *	Update the statistical data by parsing the command in question
+ */
+ 
+static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) 
+{
 #ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
-#ifdef NCR5380_STAT_LIMIT
-	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
-#endif
-		switch (cmd->cmnd[0]) {
-			case WRITE:
-			    case WRITE_6:
-			    case WRITE_10:
-			    hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
-			/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen; */
-			hostdata->pendingw--;
-			break;
-			case READ:
-			case READ_6:
-			case READ_10:
-			hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
-			/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen; */
-			hostdata->pendingr--;
-			break;
-		}
-}
+	switch (cmd->cmnd[0]) {
+	case WRITE:
+	case WRITE_6:
+	case WRITE_10:
+		hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
+		hostdata->pendingw--;
+		break;
+	case READ:
+	case READ_6:
+	case READ_10:
+		hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
+		hostdata->pendingr--;
+		break;
+	}
 #endif
+}
+
+
 /* 
  * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
  *      int tag);
@@ -1616,69 +1448,58 @@
  *
  *      If failed (no target) : cmd->scsi_done() will be called, and the 
  *              cmd->result host byte set to DID_BAD_TARGET.
+ *
+ *	Locks: caller holds io_request_lock
  */
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) {
+ 
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) 
+{
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	unsigned char tmp[3], phase;
 	unsigned char *data;
 	int len;
 	unsigned long timeout;
-	unsigned long flags;
-#ifdef USLEEP
 	unsigned char value;
-#endif
-
 	NCR5380_setup(instance);
 
-#ifdef USLEEP
-
-	if (hostdata->selecting) 
-	{
+	if (hostdata->selecting) {
 		goto part2;	/* RvC: sorry prof. Dijkstra, but it keeps the
 				   rest of the code nearly the same */
 	}
-#endif
 
-	 hostdata->restart_select = 0;
-#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION)
-	 NCR5380_print(instance);
-	 printk("scsi%d : starting arbitration, id = %d\n", instance->host_no,
-		instance->this_id);
-#endif
-	 save_flags(flags);
-	 cli();
+	hostdata->restart_select = 0;
+
+	NCR5380_dprint(NDEBUG_ARBITRATION, instance);
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id));
 
 	/* 
 	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
 	 * data bus during SELECTION.
 	 */
 
-	 NCR5380_write(TARGET_COMMAND_REG, 0);
-
+	NCR5380_write(TARGET_COMMAND_REG, 0);
 
 	/* 
 	 * Start arbitration.
 	 */
 
-	 NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
-	 NCR5380_write(MODE_REG, MR_ARBITRATE);
-
-	 restore_flags(flags);
+	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
+	NCR5380_write(MODE_REG, MR_ARBITRATE);
 
 	/* Wait for arbitration logic to complete */
 #if NCR_TIMEOUT
 	{
 		unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;
 
-		spin_unlock_irq(instance->host_lock);
+		spin_unlock_irq(&io_request_lock);
 
 		while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-		       && time_before(jiffies,timeout));
+		       && time_before(jiffies, timeout));
+
+		spin_lock_irq(&io_request_lock);
 
-		spin_lock_irq(instance->host_lock);
-		       
-		if (time_after_eq(jiffies,timeout)) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk("scsi: arbitration timeout at %d\n", __LINE__);
 			NCR5380_write(MODE_REG, MR_BASE);
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -1689,11 +1510,7 @@
 	while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));
 #endif
 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-	 printk("scsi%d : arbitration complete\n", instance->host_no);
-/* Avoid GCC 2.4.5 asm needs to many reloads error */
-	 __asm__("nop");
-#endif
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));
 
 	/* 
 	 * The arbitration delay is 2.2us, but this is a minimum and there is 
@@ -1702,34 +1519,25 @@
 	 *
 	 */
 
-	 udelay(3);
+	udelay(3);
 
 	/* Check for lost arbitration */
-	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-	     (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
-	  (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
+	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
 		NCR5380_write(MODE_REG, MR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
-		printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n",
-		       instance->host_no);
-#endif
+		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));
 		return -1;
 	}
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);
 
 	if (!(hostdata->flags & FLAG_DTC3181E) &&
-		/* RvC: DTC3181E has some trouble with this
-		 *	so we simply removed it. Seems to work with
-		 *	only Mustek scanner attached
-		 */
-		(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) 
-	{
+	    /* RvC: DTC3181E has some trouble with this
+	     *      so we simply removed it. Seems to work with
+	     *      only Mustek scanner attached
+	     */
+	    (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
 		NCR5380_write(MODE_REG, MR_BASE);
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
-		printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n",
-		       instance->host_no);
-#endif
+		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));
 		return -1;
 	}
 	/* 
@@ -1739,10 +1547,7 @@
 
 	udelay(2);
 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-	printk("scsi%d : won arbitration\n", instance->host_no);
-#endif
-
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : won arbitration\n", instance->host_no));
 
 	/* 
 	 * Now that we have won arbitration, start Selection process, asserting 
@@ -1757,8 +1562,7 @@
 	 * phase immediately after selection.
 	 */
 
-	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
-		     ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
 	NCR5380_write(MODE_REG, MR_BASE);
 
 	/* 
@@ -1774,8 +1578,7 @@
 	udelay(1);		/* wingel -- wait two bus deskew delay >2*45ns */
 
 	/* Reset BSY */
-	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
-				       ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));
 
 	/* 
 	 * Something weird happens when we cease to drive BSY - looks
@@ -1796,9 +1599,7 @@
 
 	udelay(1);
 
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->target));
 
 	/* 
 	 * The SCSI specification calls for a 250 ms timeout for the actual 
@@ -1813,40 +1614,30 @@
 	 * and it's detecting as true.  Sigh.
 	 */
 
-#ifdef USLEEP
-	hostdata->select_time = 0; /* we count the clock ticks at which we polled */
+	hostdata->select_time = 0;	/* we count the clock ticks at which we polled */
 	hostdata->selecting = cmd;
 
 part2:
-    	/* RvC: here we enter after a sleeping period, or immediately after
-		execution of part 1
-		we poll only once ech clock tick */
+	/* RvC: here we enter after a sleeping period, or immediately after
+	   execution of part 1
+	   we poll only once ech clock tick */
 	value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);
 
-	if (!value && (hostdata->select_time < 25)) 
-	{
+	if (!value && (hostdata->select_time < 25)) {
 		/* RvC: we still must wait for a device response */
-		hostdata->select_time++; /* after 25 ticks the device has failed */
+		hostdata->select_time++;	/* after 25 ticks the device has failed */
 		hostdata->time_expires = jiffies + 1;
 		NCR5380_set_timer(instance);
 		return 0;	/* RvC: we return here with hostdata->selecting set,
 				   to go to sleep */
 	}
 
-	hostdata->selecting = 0; /* clear this pointer, because we passed the
-				waiting period */
-#else
-	spin_unlock_irq(instance->host_lock);
-	while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
-					(SR_BSY | SR_IO)));
-	spin_lock_irq(instance->host_lock);
-#endif
-	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
-	    (SR_SEL | SR_IO)) {
+	hostdata->selecting = 0;	/* clear this pointer, because we passed the
+					   waiting period */
+	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		NCR5380_reselect(instance);
-		printk("scsi%d : reselection after won arbitration?\n",
-		       instance->host_no);
+		printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		return -1;
 	}
@@ -1866,22 +1657,15 @@
 			printk("scsi%d : weirdness\n", instance->host_no);
 			if (hostdata->restart_select)
 				printk("\trestart select\n");
-#if (NDEBUG & NDEBUG_SELECTION)
-			NCR5380_print(instance);
-#endif
+			NCR5380_dprint(NDEBUG_SELECTION, instance);
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 			return -1;
 		}
 		cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
 		collect_stats(hostdata, cmd);
-#endif
 		cmd->scsi_done(cmd);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-#if (NDEBUG & NDEBUG_SELECTION)
-		printk("scsi%d : target did not respond within 250ms\n",
-		       instance->host_no);
-#endif
+		dprintk(NDEBUG_SELECTION, ("scsi%d : target did not respond within 250ms\n", instance->host_no));
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		return 0;
 	}
@@ -1907,10 +1691,10 @@
 	{
 		unsigned long timeout = jiffies + NCR_TIMEOUT;
 
-		spin_unlock_irq(instance->host_lock);
+		spin_unlock_irq(&io_request_lock);
 		while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout));
-		spin_lock_irq(instance->host_lock);
-		
+		spin_lock_irq(&io_request_lock);
+
 		if (time_after_eq(jiffies, timeout)) {
 			printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -1921,47 +1705,20 @@
 	while (!(NCR5380_read(STATUS_REG) & SR_REQ));
 #endif				/* def NCR_TIMEOUT */
 
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n",
-	       instance->host_no, cmd->target);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
 	tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
-#ifdef SCSI2
-	if (cmd->device->tagged_queue && (tag != TAG_NONE)) {
-		tmp[1] = SIMPLE_QUEUE_TAG;
-		if (tag == TAG_NEXT) {
-			/* 0 is TAG_NONE, used to imply no tag for this command */
-			if (cmd->device->current_tag == 0)
-				cmd->device->current_tag = 1;
-
-			cmd->tag = cmd->device->current_tag;
-			cmd->device->current_tag++;
-		} else
-			cmd->tag = (unsigned char) tag;
-
-		tmp[2] = cmd->tag;
-		hostdata->last_message = SIMPLE_QUEUE_TAG;
-		len = 3;
-	} else
-#endif				/* def SCSI2 */
-	{
-		len = 1;
-		cmd->tag = 0;
-	}
+
+	len = 1;
+	cmd->tag = 0;
 
 	/* Send message(s) */
 	data = tmp;
 	phase = PHASE_MSGOUT;
 	NCR5380_transfer_pio(instance, &phase, &len, &data);
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : nexus established.\n", instance->host_no);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : nexus established.\n", instance->host_no));
 	/* XXX need to handle errors here */
 	hostdata->connected = cmd;
-#ifdef SCSI2
-	if (!cmd->device->tagged_queue)
-#endif
-		hostdata->busy[cmd->target] |= (1 << cmd->lun);
+	hostdata->busy[cmd->target] |= (1 << cmd->lun);
 
 	initialize_SCp(cmd);
 
@@ -1994,27 +1751,22 @@
  * counts, we will always do a pseudo DMA or DMA transfer.
  */
 
-static int NCR5380_transfer_pio(struct Scsi_Host *instance,
-		unsigned char *phase, int *count, unsigned char **data) {
+static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
 	NCR5380_local_declare();
-	register unsigned char p = *phase, tmp;
-	register int c = *count;
-	register unsigned char *d = *data;
-#ifdef USLEEP
+	unsigned char p = *phase, tmp;
+	int c = *count;
+	unsigned char *d = *data;
 	/*
-	 *	RvC: some administrative data to process polling time
+	 *      RvC: some administrative data to process polling time
 	 */
 	int break_allowed = 0;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-#endif
 	NCR5380_setup(instance);
 
-#if (NDEBUG & NDEBUG_PIO)
 	if (!(p & SR_IO))
-		 printk("scsi%d : pio write %d bytes\n", instance->host_no, c);
+		dprintk(NDEBUG_PIO, ("scsi%d : pio write %d bytes\n", instance->host_no, c));
 	else
-		 printk("scsi%d : pio read %d bytes\n", instance->host_no, c);
-#endif
+		dprintk(NDEBUG_PIO, ("scsi%d : pio read %d bytes\n", instance->host_no, c));
 
 	/* 
 	 * The NCR5380 chip will only drive the SCSI bus when the 
@@ -2024,56 +1776,42 @@
 
 	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
-#ifdef USLEEP
 	/* RvC: don't know if this is necessary, but other SCSI I/O is short
-	 *	so breaks are not necessary there
+	 *      so breaks are not necessary there
 	 */
-	if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) 
-	{
+	if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) {
 		break_allowed = 1;
 	}
-#endif
-
-
 	do {
 		/* 
 		 * Wait for assertion of REQ, after which the phase bits will be 
 		 * valid 
 		 */
 
-#ifdef USLEEP
 		/* RvC: we simply poll once, after that we stop temporarily
-		 *	and let the device buffer fill up
-		 *	if breaking is not allowed, we keep polling as long as needed
+		 *      and let the device buffer fill up
+		 *      if breaking is not allowed, we keep polling as long as needed
 		 */
 
-		while ( !((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) &&
-			!break_allowed );
-		if (!(tmp & SR_REQ)) 
-		{
+		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
+		if (!(tmp & SR_REQ)) {
 			/* timeout condition */
 			hostdata->time_expires = jiffies + USLEEP_SLEEP;
-			NCR5380_set_timer (instance);
+			NCR5380_set_timer(instance);
 			break;
 		}
-#else
-		while ( !((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) ); 
-#endif
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-		printk("scsi%d : REQ detected\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : REQ detected\n", instance->host_no));
 
 		/* Check for phase mismatch */
 		if ((tmp & PHASE_MASK) != p) {
-#if (NDEBUG & NDEBUG_PIO)
-			printk("scsi%d : phase mismatch\n", instance->host_no);
-			NCR5380_print_phase(instance);
-#endif
+			dprintk(NDEBUG_HANDSHAKE, ("scsi%d : phase mismatch\n", instance->host_no));
+			NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);
 			break;
 		}
-		/* Do actual transfer from SCSI bus to / from memory */ if (!(p & SR_IO))
-			 NCR5380_write(OUTPUT_DATA_REG, *d);
+		/* Do actual transfer from SCSI bus to / from memory */
+		if (!(p & SR_IO))
+			NCR5380_write(OUTPUT_DATA_REG, *d);
 		else
 			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
 
@@ -2088,34 +1826,22 @@
 
 		if (!(p & SR_IO)) {
 			if (!((p & SR_MSG) && c > 1)) {
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-					      ICR_ASSERT_DATA);
-#if (NDEBUG & NDEBUG_PIO)
-				NCR5380_print(instance);
-#endif
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-				       ICR_ASSERT_DATA | ICR_ASSERT_ACK);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+				NCR5380_dprint(NDEBUG_PIO, instance);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
 			} else {
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-				       ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-#if (NDEBUG & NDEBUG_PIO)
-				NCR5380_print(instance);
-#endif
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-					      ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
+				NCR5380_dprint(NDEBUG_PIO, instance);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
 			}
 		} else {
-#if (NDEBUG & NDEBUG_PIO)
-			NCR5380_print(instance);
-#endif
+			NCR5380_dprint(NDEBUG_PIO, instance);
 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
 		}
 
 		while (NCR5380_read(STATUS_REG) & SR_REQ);
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-		printk("scsi%d : req false, handshake complete\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));
 
 /*
  * We have several special cases to consider during REQ/ACK handshaking : 
@@ -2136,9 +1862,7 @@
 		}
 	} while (--c);
 
-#if (NDEBUG & NDEBUG_PIO)
-	printk("scsi%d : residual %d\n", instance->host_no, c);
-#endif
+	dprintk(NDEBUG_PIO, ("scsi%d : residual %d\n", instance->host_no, c));
 
 	*count = c;
 	*data = d;
@@ -2154,36 +1878,46 @@
 		return -1;
 }
 
+/**
+ *	do_reset	-	issue a reset command
+ *	@host: adapter to reset
+ *
+ *	Issue a reset sequence to the NCR5380 and try and get the bus
+ *	back into sane shape.
+ *
+ *	Locks: caller holds io_request lock
+ */
+ 
 static void do_reset(struct Scsi_Host *host) {
-	unsigned long flags;
-	 NCR5380_local_declare();
-	 NCR5380_setup(host);
+	NCR5380_local_declare();
+	NCR5380_setup(host);
+
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+	udelay(25);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+}
+
+/*
+ * Function : do_abort (Scsi_Host *host)
+ * 
+ * Purpose : abort the currently established nexus.  Should only be 
+ *      called from a routine which can drop into a 
+ * 
+ * Returns : 0 on success, -1 on failure.
+ *
+ * Locks: io_request lock held by caller
+ */
 
-	 save_flags(flags);
-	 cli();
-	 NCR5380_write(TARGET_COMMAND_REG,
-		 PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
-	 udelay(25);
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	 restore_flags(flags);
-}				/*
-
-				 * Function : do_abort (Scsi_Host *host)
-				 * 
-				 * Purpose : abort the currently established nexus.  Should only be 
-				 *      called from a routine which can drop into a 
-				 * 
-				 * Returns : 0 on success, -1 on failure.
-				 */ static int do_abort(struct Scsi_Host *host) {
+static int do_abort(struct Scsi_Host *host) {
 	NCR5380_local_declare();
 	unsigned char tmp, *msgptr, phase;
 	int len;
-	 NCR5380_setup(host);
+	NCR5380_setup(host);
 
 
 	/* Request message out phase */
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 
 	/* 
 	 * Wait for the target to indicate a valid phase by asserting 
@@ -2197,11 +1931,10 @@
 
 	while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
 
-	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
 
 	if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
-			      ICR_ASSERT_ACK);
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
 		while (NCR5380_read(STATUS_REG) & SR_REQ);
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 	}
@@ -2237,54 +1970,46 @@
  *
  *      Also, *phase, *count, *data are modified in place.
  *
+ *	Locks: io_request lock held by caller
  */
 
 
-static int NCR5380_transfer_dma(struct Scsi_Host *instance,
-		unsigned char *phase, int *count, unsigned char **data) {
+static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
 	NCR5380_local_declare();
 	register int c = *count;
 	register unsigned char p = *phase;
 	register unsigned char *d = *data;
 	unsigned char tmp;
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-	unsigned long flags;
-#endif
 	int foo;
 #if defined(REAL_DMA_POLL)
 	int cnt, toPIO;
 	unsigned char saved_data = 0, overrun = 0, residue;
 #endif
 
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
 	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
 		*phase = tmp;
 		return -1;
 	}
 #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
-#ifdef READ_OVERRUNS 
-	if (p & SR_IO) { c -= 2; }
-#endif
-#if (NDEBUG & NDEBUG_DMA)
-printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n",
-       instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" :
-       "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
+#ifdef READ_OVERRUNS
+	if (p & SR_IO) {
+		c -= 2;
+	}
 #endif
-hostdata->dma_len = (p & SR_IO) ?
-NCR5380_dma_read_setup(instance, d, c) :
-NCR5380_dma_write_setup(instance, d, c);
+	dprintk(NDEBUG_DMA, ("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d));
+	hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
 #endif
 
-NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
 #ifdef REAL_DMA
-NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
+	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
 #elif defined(REAL_DMA_POLL)
-NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
+	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
 #else
 	/*
 	 * Note : on my sample board, watch-dog timeouts occurred when interrupts
@@ -2292,58 +2017,38 @@
 	 * before the setting of DMA mode to after transfer of the last byte.
 	 */
 
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-save_flags(flags);
-cli();
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+	spin_unlock_irq(&io_request_lock);
 #endif
 	/* KLL May need eop and parity in 53c400 */
-if (hostdata->flags & FLAG_NCR53C400)
-	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK
-		  | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE
-		      | MR_MONITOR_BSY);
-else
-	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
+	if (hostdata->flags & FLAG_NCR53C400)
+		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY);
+	else
+		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
 #endif				/* def REAL_DMA */
 
-#if (NDEBUG & NDEBUG_DMA) & 0
-printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
-#endif
+	dprintk(NDEBUG_DMA, ("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)));
 
-/* 
- * FOO stuff. For some UNAPPARENT reason, I'm getting 
- * watchdog timers fired on bootup for NO APPARENT REASON, meaning it's
- * probably a timing problem.
- *
- * Since this is the only place I have back-to-back writes, perhaps this 
- * is the problem?
- */
+	/* 
+	 *	On the PAS16 at least I/O recovery delays are not needed here.
+	 *	Everyone else seems to want them.
+	 */
 
-if (p & SR_IO)
-{
-#ifndef FOO
-udelay(1);
-#endif
-NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
-} else {
-#ifndef FOO
-	udelay(1);
-#endif
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-#ifndef FOO
-	udelay(1);
-#endif
-	NCR5380_write(START_DMA_SEND_REG, 0);
-#ifndef FOO
-	udelay(1);
-#endif
-}
+	if (p & SR_IO) {
+		io_recovery_delay(1);
+		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+	} else {
+		io_recovery_delay(1);
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+		io_recovery_delay(1);
+		NCR5380_write(START_DMA_SEND_REG, 0);
+		io_recovery_delay(1);
+	}
 
 #if defined(REAL_DMA_POLL)
-do {
-	tmp = NCR5380_read(BUS_AND_STATUS_REG);
-} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR |
-
-					      BASR_END_DMA_TRANSFER)));
+	do {
+		tmp = NCR5380_read(BUS_AND_STATUS_REG);
+	} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER)));
 
 /*
    At this point, either we've completed DMA, or we have a phase mismatch,
@@ -2381,172 +2086,128 @@
    request.
  */
 
-if (p & SR_IO) {
+	if (p & SR_IO) {
 #ifdef READ_OVERRUNS
-	udelay(10);
-	if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
-	     (BASR_PHASE_MATCH | BASR_ACK))) {
-		saved_data = NCR5380_read(INPUT_DATA_REGISTER);
-		overrun = 1;
-	}
+		udelay(10);
+		if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == (BASR_PHASE_MATCH | BASR_ACK))) {
+			saved_data = NCR5380_read(INPUT_DATA_REGISTER);
+			overrun = 1;
+		}
 #endif
-} else {
-	int limit = 100;
-	while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) ||
-	       (NCR5380_read(STATUS_REG) & SR_REQ)) {
-		if (!(tmp & BASR_PHASE_MATCH))
-			break;
-		if (--limit < 0)
-			break;
+	} else {
+		int limit = 100;
+		while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) {
+			if (!(tmp & BASR_PHASE_MATCH))
+				break;
+			if (--limit < 0)
+				break;
+		}
 	}
-}
 
+	dprintk(NDEBUG_DMA, ("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG)));
 
-#if (NDEBUG & NDEBUG_DMA)
-printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n",
-       instance->host_no, tmp, NCR5380_read(STATUS_REG));
-#endif
+	NCR5380_write(MODE_REG, MR_BASE);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-NCR5380_write(MODE_REG, MR_BASE);
-NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-residue = NCR5380_dma_residual(instance);
-c -= residue;
-*count -= c;
-*data += c;
-*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
+	residue = NCR5380_dma_residual(instance);
+	c -= residue;
+	*count -= c;
+	*data += c;
+	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
 
 #ifdef READ_OVERRUNS
-if (*phase == p && (p & SR_IO) && residue == 0)
-{
-if (overrun) {
-#if (NDEBUG & NDEBUG_DMA)
-	printk("Got an input overrun, using saved byte\n");
-#endif
-	**data = saved_data;
-	*data += 1;
-	*count -= 1;
-	cnt = toPIO = 1;
-} else {
-	printk("No overrun??\n");
-	cnt = toPIO = 2;
-}
-#if (NDEBUG & NDEBUG_DMA)
-printk("Doing %d-byte PIO to 0x%X\n", cnt, *data);
-#endif
-NCR5380_transfer_pio(instance, phase, &cnt, data);
-*count -= toPIO - cnt;
-}
+	if (*phase == p && (p & SR_IO) && residue == 0) {
+		if (overrun) {
+			dprintk(NDEBUG_DMA, ("Got an input overrun, using saved byte\n"));
+			**data = saved_data;
+			*data += 1;
+			*count -= 1;
+			cnt = toPIO = 1;
+		} else {
+			printk("No overrun??\n");
+			cnt = toPIO = 2;
+		}
+		dprintk(NDEBUG_DMA, ("Doing %d-byte PIO to 0x%X\n", cnt, *data));
+		NCR5380_transfer_pio(instance, phase, &cnt, data);
+		*count -= toPIO - cnt;
+	}
 #endif
 
-#if (NDEBUG & NDEBUG_DMA)
-printk("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n",
-       *data, *count, *(*data + *count - 1), *(*data + *count));
-#endif
-return 0;
+	dprintk(NDEBUG_DMA, ("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)));
+	return 0;
 
 #elif defined(REAL_DMA)
-return 0;
+	return 0;
 #else				/* defined(REAL_DMA_POLL) */
-if (p & SR_IO) {
+	if (p & SR_IO) {
 #ifdef DMA_WORKS_RIGHT
-	foo = NCR5380_pread(instance, d, c);
+		foo = NCR5380_pread(instance, d, c);
 #else
-	int diff = 1;
-	if (hostdata->flags & FLAG_NCR53C400) {
-		diff = 0;
-	}
-	if (!(foo = NCR5380_pread(instance, d, c - diff))) {
-		/*
-		 * We can't disable DMA mode after successfully transferring 
-		 * what we plan to be the last byte, since that would open up
-		 * a race condition where if the target asserted REQ before 
-		 * we got the DMA mode reset, the NCR5380 would have latched
-		 * an additional byte into the INPUT DATA register and we'd
-		 * have dropped it.
-		 * 
-		 * The workaround was to transfer one fewer bytes than we 
-		 * intended to with the pseudo-DMA read function, wait for 
-		 * the chip to latch the last byte, read it, and then disable
-		 * pseudo-DMA mode.
-		 * 
-		 * After REQ is asserted, the NCR5380 asserts DRQ and ACK.
-		 * REQ is deasserted when ACK is asserted, and not reasserted
-		 * until ACK goes false.  Since the NCR5380 won't lower ACK
-		 * until DACK is asserted, which won't happen unless we twiddle
-		 * the DMA port or we take the NCR5380 out of DMA mode, we 
-		 * can guarantee that we won't handshake another extra 
-		 * byte.
-		 */
+		int diff = 1;
+		if (hostdata->flags & FLAG_NCR53C400) {
+			diff = 0;
+		}
+		if (!(foo = NCR5380_pread(instance, d, c - diff))) {
+			/*
+			 * We can't disable DMA mode after successfully transferring 
+			 * what we plan to be the last byte, since that would open up
+			 * a race condition where if the target asserted REQ before 
+			 * we got the DMA mode reset, the NCR5380 would have latched
+			 * an additional byte into the INPUT DATA register and we'd
+			 * have dropped it.
+			 * 
+			 * The workaround was to transfer one fewer bytes than we 
+			 * intended to with the pseudo-DMA read function, wait for 
+			 * the chip to latch the last byte, read it, and then disable
+			 * pseudo-DMA mode.
+			 * 
+			 * After REQ is asserted, the NCR5380 asserts DRQ and ACK.
+			 * REQ is deasserted when ACK is asserted, and not reasserted
+			 * until ACK goes false.  Since the NCR5380 won't lower ACK
+			 * until DACK is asserted, which won't happen unless we twiddle
+			 * the DMA port or we take the NCR5380 out of DMA mode, we 
+			 * can guarantee that we won't handshake another extra 
+			 * byte.
+			 */
 
-		if (!(hostdata->flags & FLAG_NCR53C400)) {
-			while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ));
-			/* Wait for clean handshake */
-			while (NCR5380_read(STATUS_REG) & SR_REQ);
-			d[c - 1] = NCR5380_read(INPUT_DATA_REG);
+			if (!(hostdata->flags & FLAG_NCR53C400)) {
+				while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ));
+				/* Wait for clean handshake */
+				while (NCR5380_read(STATUS_REG) & SR_REQ);
+				d[c - 1] = NCR5380_read(INPUT_DATA_REG);
+			}
 		}
-	}
 #endif
-} else {
+	} else {
 #ifdef DMA_WORKS_RIGHT
-	foo = NCR5380_pwrite(instance, d, c);
-#else
-	int timeout;
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-	printk("About to pwrite %d bytes\n", c);
-#endif
-	if (!(foo = NCR5380_pwrite(instance, d, c))) {
-		/*
-		 * Wait for the last byte to be sent.  If REQ is being asserted for 
-		 * the byte we're interested, we'll ACK it and it will go false.  
-		 */
-		if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) {
-			timeout = 20000;
-#if 1
-#if 1
-			while (!(NCR5380_read(BUS_AND_STATUS_REG) &
-			 BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) &
-				       BASR_PHASE_MATCH));
+		foo = NCR5380_pwrite(instance, d, c);
 #else
-			if (NCR5380_read(STATUS_REG) & SR_REQ) {
-				for (; timeout &&
-				     !(NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
-				     --timeout);
-				for (; timeout && (NCR5380_read(STATUS_REG) & SR_REQ);
-				     --timeout);
-			}
-#endif
-
-
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
-			if (!timeout)
-				printk("scsi%d : timed out on last byte\n",
-				       instance->host_no);
-#endif
-
-
-			if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {
-				hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;
-				if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {
-					hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
-					printk("scsi%d : last bit sent works\n",
-					       instance->host_no);
-#endif
+		int timeout;
+		dprintk(NDEBUG_C400_PWRITE, ("About to pwrite %d bytes\n", c));
+		if (!(foo = NCR5380_pwrite(instance, d, c))) {
+			/*
+			 * Wait for the last byte to be sent.  If REQ is being asserted for 
+			 * the byte we're interested, we'll ACK it and it will go false.  
+			 */
+			if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) {
+				timeout = 20000;
+				while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH));
+
+				if (!timeout)
+					dprintk(NDEBUG_LAST_BYTE_SENT, ("scsi%d : timed out on last byte\n", instance->host_no));
+
+				if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {
+					hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;
+					if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {
+						hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;
+						dprintk(NDEBUG_LAST_WRITE_SENT, ("scsi%d : last bit sent works\n", instance->host_no));
+					}
 				}
+			} else {
+				dprintk(NDEBUG_C400_PWRITE, ("Waiting for LASTBYTE\n"));
+				while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
+				dprintk(NDEBUG_C400_PWRITE, ("Got LASTBYTE\n"));
 			}
-		} else {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-			printk("Waiting for LASTBYTE\n");
-#endif
-			while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-			printk("Got LASTBYTE\n");
-#endif
-		}
-#else
-			udelay(5);
-#endif
 		}
 #endif
 	}
@@ -2554,13 +2215,9 @@
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
 	if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-		printk("53C400w: Checking for IRQ\n");
-#endif
+		dprintk(NDEBUG_C400_PWRITE, ("53C400w: Checking for IRQ\n"));
 		if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-			printk("53C400w:    got it, reading reset interrupt reg\n");
-#endif
+			dprintk(NDEBUG_C400_PWRITE, ("53C400w:    got it, reading reset interrupt reg\n"));
 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 		} else {
 			printk("53C400w:    IRQ NOT THERE!\n");
@@ -2569,11 +2226,8 @@
 	*data = d + c;
 	*count = 0;
 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
-#if 0
-	NCR5380_print_phase(instance);
-#endif
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-	restore_flags(flags);
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+	spin_lock_irq(&io_request_lock);
 #endif				/* defined(REAL_DMA_POLL) */
 	return foo;
 #endif				/* def REAL_DMA */
@@ -2595,12 +2249,13 @@
  *
  * XXX Note : we need to watch for bus free or a reset condition here 
  *      to recover from an unexpected bus free condition.
+ *
+ * Locks: io_request_lock held by caller
  */
 
 static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 	NCR5380_local_declare();
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 	unsigned char msgout = NOP;
 	int sink = 0;
 	int len;
@@ -2610,10 +2265,8 @@
 	unsigned char *data;
 	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
 	Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
-#ifdef USLEEP
 	/* RvC: we need to set the end of the polling time */
 	unsigned long poll_time = jiffies + USLEEP_POLL;
-#endif
 
 	NCR5380_setup(instance);
 
@@ -2624,27 +2277,22 @@
 			phase = (tmp & PHASE_MASK);
 			if (phase != old_phase) {
 				old_phase = phase;
-#if (NDEBUG & NDEBUG_INFORMATION)
-				NCR5380_print_phase(instance);
-#endif
+				NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
 			}
 			if (sink && (phase != PHASE_MSGOUT)) {
 				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
 
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
-					      ICR_ASSERT_ACK);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
 				while (NCR5380_read(STATUS_REG) & SR_REQ);
-				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-					      ICR_ASSERT_ATN);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 				sink = 0;
 				continue;
 			}
 			switch (phase) {
-				case PHASE_DATAIN:
-				    case PHASE_DATAOUT:
+			case PHASE_DATAIN:
+			case PHASE_DATAOUT:
 #if (NDEBUG & NDEBUG_NO_DATAOUT)
-				    printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n",
-					   instance->host_no);
+				printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", instance->host_no);
 				sink = 1;
 				do_abort(instance);
 				cmd->result = DID_ERROR << 16;
@@ -2661,11 +2309,7 @@
 					--cmd->SCp.buffers_residual;
 					cmd->SCp.this_residual = cmd->SCp.buffer->length;
 					cmd->SCp.ptr = cmd->SCp.buffer->address;
-#if (NDEBUG & NDEBUG_INFORMATION)
-					printk("scsi%d : %d bytes and %d buffers left\n",
-					       instance->host_no, cmd->SCp.this_residual,
-					       cmd->SCp.buffers_residual);
-#endif
+					dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
 				}
 				/*
 				 * The preferred transfer method is going to be 
@@ -2686,9 +2330,7 @@
 				 * We supplement these 2 if's with the flag.
 				 */
 #ifdef NCR5380_dma_xfer_len
-				if (!cmd->device->borken &&
-				!(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
-				    (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
+				if (!cmd->device->borken && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {
 #else
 				transfersize = cmd->transfersize;
 
@@ -2697,27 +2339,21 @@
 					transfersize = 512;
 #endif				/* LIMIT_TRANSFERSIZE */
 
-				if (!cmd->device->borken && transfersize &&
-				!(hostdata->flags & FLAG_NO_PSEUDO_DMA) &&
-				    cmd->SCp.this_residual && !(cmd->SCp.this_residual %
-							 transfersize)) {
+				if (!cmd->device->borken && transfersize && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && cmd->SCp.this_residual && !(cmd->SCp.this_residual % transfersize)) {
 					/* Limit transfers to 32K, for xx400 & xx406
 					 * pseudoDMA that transfers in 128 bytes blocks. */
 					if (transfersize > 32 * 1024)
 						transfersize = 32 * 1024;
 #endif
 					len = transfersize;
-					if (NCR5380_transfer_dma(instance, &phase,
-								 &len, (unsigned char **) &cmd->SCp.ptr)) {
+					if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) {
 						/*
 						 * If the watchdog timer fires, all future accesses to this
 						 * device will use the polled-IO.
 						 */
-						printk("scsi%d : switching target %d lun %d to slow handshake\n",
-						       instance->host_no, cmd->target, cmd->lun);
+						printk("scsi%d : switching target %d lun %d to slow handshake\n", instance->host_no, cmd->target, cmd->lun);
 						cmd->device->borken = 1;
-						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-							 ICR_ASSERT_ATN);
+						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 						sink = 1;
 						do_abort(instance);
 						cmd->result = DID_ERROR << 16;
@@ -2727,12 +2363,11 @@
 						cmd->SCp.this_residual -= transfersize - len;
 				} else
 #endif				/* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
-					NCR5380_transfer_pio(instance, &phase,
-							     (int *) &cmd->SCp.this_residual, (unsigned char **)
-							  &cmd->SCp.ptr);
+					NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **)
+							     &cmd->SCp.ptr);
 				break;
-				case PHASE_MSGIN:
-				    len = 1;
+			case PHASE_MSGIN:
+				len = 1;
 				data = &tmp;
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
 				cmd->SCp.Message = tmp;
@@ -2749,24 +2384,18 @@
 					 * next_link, done() is called as with unlinked commands.
 					 */
 #ifdef LINKED
-					case LINKED_CMD_COMPLETE:
-					    case LINKED_FLG_CMD_COMPLETE:
+				case LINKED_CMD_COMPLETE:
+				case LINKED_FLG_CMD_COMPLETE:
 					/* Accept message by clearing ACK */
-					    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_LINKED)
-					printk("scsi%d : target %d lun %d linked command complete.\n",
-					       instance->host_no, cmd->target, cmd->lun);
-#endif
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun));
 					/* 
 					 * Sanity check : A linked command should only terminate with
 					 * one of these messages if there are more linked commands
 					 * available.
 					 */
-
 					if (!cmd->next_link) {
-						printk("scsi%d : target %d lun %d linked command complete, no next_link\n"
-						       instance->host_no, cmd->target, cmd->lun);
+						printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->target, cmd->lun);
 						sink = 1;
 						do_abort(instance);
 						return;
@@ -2775,27 +2404,19 @@
 					/* The next command is still part of this process */
 					cmd->next_link->tag = cmd->tag;
 					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
-#if (NDEBUG & NDEBUG_LINKED)
-					printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n",
-					       instance->host_no, cmd->target, cmd->lun);
-#endif
-#ifdef NCR5380_STATS
+					dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun));
 					collect_stats(hostdata, cmd);
-#endif
 					cmd->scsi_done(cmd);
 					cmd = hostdata->connected;
 					break;
 #endif				/* def LINKED */
-					case ABORT:
-					    case COMMAND_COMPLETE:
+				case ABORT:
+				case COMMAND_COMPLETE:
 					/* Accept message by clearing ACK */
-					    sink = 1;
+					sink = 1;
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 					hostdata->connected = NULL;
-#if (NDEBUG & NDEBUG_QUEUES)
-					printk("scsi%d : command for target %d, lun %d completed\n",
-					       instance->host_no, cmd->target, cmd->lun);
-#endif
+					dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun));
 					hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 
 					/* 
@@ -2820,13 +2441,8 @@
 						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
 #ifdef AUTOSENSE
-					if ((cmd->cmnd[0] != REQUEST_SENSE) &&
-					    (cmd->SCp.Status == CHECK_CONDITION)) {
-						unsigned long flags;
-#if (NDEBUG & NDEBUG_AUTOSENSE)
-						printk("scsi%d : performing request sense\n",
-						       instance->host_no);
-#endif
+					if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) {
+						dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no));
 						cmd->cmnd[0] = REQUEST_SENSE;
 						cmd->cmnd[1] &= 0xe0;
 						cmd->cmnd[2] = 0;
@@ -2839,21 +2455,14 @@
 						cmd->SCp.ptr = (char *) cmd->sense_buffer;
 						cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
 
-						save_flags(flags);
-						cli();
 						LIST(cmd, hostdata->issue_queue);
 						cmd->host_scribble = (unsigned char *)
 						    hostdata->issue_queue;
 						hostdata->issue_queue = (Scsi_Cmnd *) cmd;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-						printk("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_QUEUES, ("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no));
 					} else {
 #endif				/* def AUTOSENSE */
-#ifdef NCR5380_STATS
 						collect_stats(hostdata, cmd);
-#endif
 						cmd->scsi_done(cmd);
 					}
 
@@ -2867,37 +2476,29 @@
 					while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
 						barrier();
 					return;
-					case MESSAGE_REJECT:
+				case MESSAGE_REJECT:
 					/* Accept message by clearing ACK */
-					    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 					switch (hostdata->last_message) {
-						case HEAD_OF_QUEUE_TAG:
-						    case ORDERED_QUEUE_TAG:
-						    case SIMPLE_QUEUE_TAG:
-						    cmd->device->tagged_queue = 0;
+					case HEAD_OF_QUEUE_TAG:
+					case ORDERED_QUEUE_TAG:
+					case SIMPLE_QUEUE_TAG:
+						cmd->device->tagged_queue = 0;
 						hostdata->busy[cmd->target] |= (1 << cmd->lun);
 						break;
-						default:
-						    break;
+					default:
+						break;
 					}
-					case DISCONNECT: {
-						unsigned long flags;
+				case DISCONNECT:{
 						/* Accept message by clearing ACK */
 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 						cmd->device->disconnect = 1;
-						save_flags(flags);
-						cli();
 						LIST(cmd, hostdata->disconnected_queue);
 						cmd->host_scribble = (unsigned char *)
 						    hostdata->disconnected_queue;
 						hostdata->connected = NULL;
 						hostdata->disconnected_queue = cmd;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-						printk("scsi%d : command for target %d lun %d was moved from connected to"
-						       "  the disconnected_queue\n", instance->host_no,
-						  cmd->target, cmd->lun);
-#endif
+						dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d lun %d was moved from connected to" "  the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun));
 						/* 
 						 * Restore phase bits to 0 so an interrupted selection, 
 						 * arbitration can resume.
@@ -2909,9 +2510,6 @@
 						/* Wait for bus free to avoid nasty timeouts */
 						while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
 							barrier();
-#if 0
-						NCR5380_print_status(instance);
-#endif
 						return;
 					}
 					/* 
@@ -2924,12 +2522,12 @@
 					 * disconnecting, and we have to break spec to remain 
 					 * compatible.
 					 */
-					case SAVE_POINTERS:
-					    case RESTORE_POINTERS:
+				case SAVE_POINTERS:
+				case RESTORE_POINTERS:
 					/* Accept message by clearing ACK */
-					    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 					break;
-					case EXTENDED_MESSAGE:
+				case EXTENDED_MESSAGE:
 /* 
  * Extended messages are sent in the following format :
  * Byte         
@@ -2942,28 +2540,19 @@
  * Start the extended message buffer with the EXTENDED_MESSAGE
  * byte, since print_msg() wants the whole thing.  
  */
-					    extended_msg[0] = EXTENDED_MESSAGE;
+					extended_msg[0] = EXTENDED_MESSAGE;
 					/* Accept first byte by clearing ACK */
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-					printk("scsi%d : receiving extended message\n",
-					       instance->host_no);
-#endif
+					dprintk(NDEBUG_EXTENDED, ("scsi%d : receiving extended message\n", instance->host_no));
 
 					len = 2;
 					data = extended_msg + 1;
 					phase = PHASE_MSGIN;
 					NCR5380_transfer_pio(instance, &phase, &len, &data);
 
-#if (NDEBUG & NDEBUG_EXTENDED)
-					printk("scsi%d : length=%d, code=0x%02x\n",
-					       instance->host_no, (int) extended_msg[1],
-					       (int) extended_msg[2]);
-#endif
+					dprintk(NDEBUG_EXTENDED, ("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]));
 
-					if (!len && extended_msg[1] <=
-					    (sizeof(extended_msg) - 1)) {
+					if (!len && extended_msg[1] <= (sizeof(extended_msg) - 1)) {
 						/* Accept third byte by clearing ACK */
 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 						len = extended_msg[1] - 1;
@@ -2971,26 +2560,20 @@
 						phase = PHASE_MSGIN;
 
 						NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-						printk("scsi%d : message received, residual %d\n",
-						 instance->host_no, len);
-#endif
+						dprintk(NDEBUG_EXTENDED, ("scsi%d : message received, residual %d\n", instance->host_no, len));
 
 						switch (extended_msg[2]) {
-							case EXTENDED_SDTR:
-							    case EXTENDED_WDTR:
-							    case EXTENDED_MODIFY_DATA_POINTER:
-							    case EXTENDED_EXTENDED_IDENTIFY:
-							    tmp = 0;
+						case EXTENDED_SDTR:
+						case EXTENDED_WDTR:
+						case EXTENDED_MODIFY_DATA_POINTER:
+						case EXTENDED_EXTENDED_IDENTIFY:
+							tmp = 0;
 						}
 					} else if (len) {
-						printk("scsi%d: error receiving extended message\n",
-						       instance->host_no);
+						printk("scsi%d: error receiving extended message\n", instance->host_no);
 						tmp = 0;
 					} else {
-						printk("scsi%d: extended message code %02x length %d is too long\n",
-						       instance->host_no, extended_msg[2], extended_msg[1]);
+						printk("scsi%d: extended message code %02x length %d is too long\n", instance->host_no, extended_msg[2], extended_msg[1]);
 						tmp = 0;
 					}
 					/* Fall through to reject message */
@@ -2999,26 +2582,23 @@
 					 * If we get something weird that we aren't expecting, 
 					 * reject it.
 					 */
-					default:
-					    if (!tmp) {
+				default:
+					if (!tmp) {
 						printk("scsi%d: rejecting message ", instance->host_no);
 						print_msg(extended_msg);
 						printk("\n");
 					} else if (tmp != EXTENDED_MESSAGE)
-						printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n",
-						       instance->host_no, tmp, cmd->target, cmd->lun);
+						printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n", instance->host_no, tmp, cmd->target, cmd->lun);
 					else
-						printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n",
-						       instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun);
+						printk("scsi%d: rejecting unknown extended message code %02x, length %d from target %d, lun %d\n", instance->host_no, extended_msg[1], extended_msg[0], cmd->target, cmd->lun);
 
 					msgout = MESSAGE_REJECT;
-					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-						      ICR_ASSERT_ATN);
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 					break;
 				}	/* switch (tmp) */
 				break;
-				case PHASE_MSGOUT:
-				    len = 1;
+			case PHASE_MSGOUT:
+				len = 1;
 				data = &msgout;
 				hostdata->last_message = msgout;
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
@@ -3026,69 +2606,50 @@
 					hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 					hostdata->connected = NULL;
 					cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
 					collect_stats(hostdata, cmd);
-#endif
 					cmd->scsi_done(cmd);
 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 					return;
 				}
 				msgout = NOP;
 				break;
-				case PHASE_CMDOUT:
-				    len = cmd->cmd_len;
+			case PHASE_CMDOUT:
+				len = cmd->cmd_len;
 				data = cmd->cmnd;
 				/* 
 				 * XXX for performance reasons, on machines with a 
 				 * PSEUDO-DMA architecture we should probably 
 				 * use the dma transfer function.  
 				 */
-				NCR5380_transfer_pio(instance, &phase, &len,
-						     &data);
-#ifdef USLEEP
-				if (!cmd->device->disconnect &&
-					should_disconnect(cmd->cmnd[0])) 
-				{
+				NCR5380_transfer_pio(instance, &phase, &len, &data);
+				if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
 					hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
-					printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no,
-					       hostdata->time_expires);
-#endif
+					dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
 					NCR5380_set_timer(instance);
 					return;
 				}
-#endif				/* def USLEEP */
 				break;
-				case PHASE_STATIN:
-				    len = 1;
+			case PHASE_STATIN:
+				len = 1;
 				data = &tmp;
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
 				cmd->SCp.Status = tmp;
 				break;
-				default:
-				    printk("scsi%d : unknown phase\n", instance->host_no);
-#ifdef NDEBUG
-				NCR5380_print(instance);
-#endif
+			default:
+				printk("scsi%d : unknown phase\n", instance->host_no);
+				NCR5380_dprint(NDEBUG_ALL, instance);
 			}	/* switch(phase) */
 		}		/* if (tmp * SR_REQ) */
-#ifdef USLEEP
-		else 
-		{
+		else {
 			/* RvC: go to sleep if polling time expired
 			 */
-			if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time))
-			{
+			if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
 				hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
-				printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no,
-				       hostdata->time_expires);
-#endif
+				dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
 				NCR5380_set_timer(instance);
 				return;
 			}
 		}
-#endif
 	}			/* while (1) */
 }
 
@@ -3101,9 +2662,9 @@
  *      
  * Inputs : instance - this instance of the NCR5380.
  *
+ * Locks: io_request_lock held by caller
  */
 
-
 static void NCR5380_reselect(struct Scsi_Host *instance) {
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
@@ -3111,28 +2672,22 @@
 	unsigned char target_mask;
 	unsigned char lun, phase;
 	int len;
-#ifdef SCSI2
-	unsigned char tag;
-#endif
 	unsigned char msg[3];
 	unsigned char *data;
 	Scsi_Cmnd *tmp = NULL, *prev;
 	int abort = 0;
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
 	/*
 	 * Disable arbitration, etc. since the host adapter obviously
 	 * lost, and tell an interrupted NCR5380_select() to restart.
 	 */
 
-	 NCR5380_write(MODE_REG, MR_BASE);
-	 hostdata->restart_select = 1;
-
-	 target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+	NCR5380_write(MODE_REG, MR_BASE);
+	hostdata->restart_select = 1;
 
-#if (NDEBUG & NDEBUG_RESELECTION)
-	 printk("scsi%d : reselect\n", instance->host_no);
-#endif
+	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+	dprintk(NDEBUG_SELECTION, ("scsi%d : reselect\n", instance->host_no));
 
 	/* 
 	 * At this point, we have detected that our SCSI ID is on the bus,
@@ -3143,10 +2698,10 @@
 	 * signal.
 	 */
 
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
 
 	while (NCR5380_read(STATUS_REG) & SR_SEL);
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
 	/*
 	 * Wait for target to go into MSGIN.
@@ -3154,15 +2709,13 @@
 
 	while (!(NCR5380_read(STATUS_REG) & SR_REQ));
 
-	 len = 1;
-	 data = msg;
-	 phase = PHASE_MSGIN;
-	 NCR5380_transfer_pio(instance, &phase, &len, &data);
-
+	len = 1;
+	data = msg;
+	phase = PHASE_MSGIN;
+	NCR5380_transfer_pio(instance, &phase, &len, &data);
 
 	if (!msg[0] & 0x80) {
-		printk("scsi%d : expecting IDENTIFY message, got ",
-		       instance->host_no);
+		printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no);
 		print_msg(msg);
 		abort = 1;
 	} else {
@@ -3176,22 +2729,14 @@
 		 * nexuses so we can chose to do additional data transfer.
 		 */
 
-#ifdef SCSI2
-#error "SCSI-II tagged queueing is not supported yet"
-#endif
-
 		/* 
 		 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
 		 * just reestablished, and remove it from the disconnected queue.
 		 */
 
 
-		for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
-		 tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
+		for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
 			if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun)
-#ifdef SCSI2
-			    && (tag == tmp->tag)
-#endif
 			    ) {
 				if (prev) {
 					REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
@@ -3204,13 +2749,7 @@
 				break;
 			}
 		if (!tmp) {
-#ifdef SCSI2
-			printk("scsi%d : warning : target bitmask %02x lun %d tag %d not in disconnect_queue.\n",
-			       instance->host_no, target_mask, lun, tag);
-#else
-			printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n",
-			       instance->host_no, target_mask, lun);
-#endif
+			printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun);
 			/* 
 			 * Since we have an established nexus that we can't do anything with,
 			 * we must abort it.  
@@ -3223,10 +2762,7 @@
 		do_abort(instance);
 	} else {
 		hostdata->connected = tmp;
-#if (NDEBUG & NDEBUG_RESELECTION)
-		printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n",
-		     instance->host_no, tmp->target, tmp->lun, tmp->tag);
-#endif
+		dprintk(NDEBUG_RESELECTION, ("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag));
 	}
 }
 
@@ -3245,8 +2781,7 @@
 #ifdef REAL_DMA
 static void NCR5380_dma_complete(NCR5380_instance * instance) {
 	NCR5380_local_declare();
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *
-					     instance->hostdata);
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * instance->hostdata);
 	int transferred;
 	NCR5380_setup(instance);
 
@@ -3289,10 +2824,12 @@
  *
  * Returns : 0 - success, -1 on failure.
  *
- * XXX - there is no way to abort the command that is currently 
- *       connected, you have to wait for it to complete.  If this is 
- *       a problem, we could implement longjmp() / setjmp(), setjmp()
- *       called where the loop started in NCR5380_main().
+ *	XXX - there is no way to abort the command that is currently 
+ *	connected, you have to wait for it to complete.  If this is 
+ *	a problem, we could implement longjmp() / setjmp(), setjmp()
+ *	called where the loop started in NCR5380_main().
+ *
+ *	Locks: io_request_lock held by caller
  */
 
 #ifndef NCR5380_abort
@@ -3300,10 +2837,8 @@
 #endif
 int NCR5380_abort(Scsi_Cmnd * cmd) {
 	NCR5380_local_declare();
-	unsigned long flags;
 	struct Scsi_Host *instance = cmd->host;
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp, **prev;
 
 	printk("scsi%d : aborting command\n", instance->host_no);
@@ -3316,15 +2851,10 @@
 
 	NCR5380_print_status(instance);
 
-	save_flags(flags);
-	cli();
 	NCR5380_setup(instance);
 
-#if (NDEBUG & NDEBUG_ABORT)
-	printk("scsi%d : abort called\n", instance->host_no);
-	printk("        basr 0x%X, sr 0x%X\n",
-	     NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG));
-#endif
+	dprintk(NDEBUG_ABORT, ("scsi%d : abort called\n", instance->host_no));
+	dprintk(NDEBUG_ABORT, ("        basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)));
 
 #if 0
 /*
@@ -3334,9 +2864,7 @@
  */
 
 	if (hostdata->connected == cmd) {
-#if (NDEBUG & NDEBUG_ABORT)
-		printk("scsi%d : aborting connected command\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ABORT, ("scsi%d : aborting connected command\n", instance->host_no));
 		hostdata->aborted = 1;
 /*
  * We should perform BSY checking, and make sure we haven't slipped
@@ -3363,24 +2891,15 @@
  * Case 2 : If the command hasn't been issued yet, we simply remove it 
  *          from the issue queue.
  */
-#if (NDEBUG & NDEBUG_ABORT)
 	/* KLL */
-	printk("scsi%d : abort going into loop.\n", instance->host_no);
-#endif
-	for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue),
-	     tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-	     tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp =
-	     (Scsi_Cmnd *) tmp->host_scribble)
+	dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
+	for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
 		if (cmd == tmp) {
 			REMOVE(5, *prev, tmp, tmp->host_scribble);
 			(*prev) = (Scsi_Cmnd *) tmp->host_scribble;
 			tmp->host_scribble = NULL;
 			tmp->result = DID_ABORT << 16;
-			restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : abort removed command from issue queue.\n",
-			       instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
 			tmp->done(tmp);
 			return SCSI_ABORT_SUCCESS;
 		}
@@ -3402,10 +2921,7 @@
  */
 
 	if (hostdata->connected) {
-		restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-		printk("scsi%d : abort failed, command connected.\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
 		return SCSI_ABORT_NOT_RUNNING;
 	}
 /*
@@ -3433,34 +2949,22 @@
  * it from the disconnected queue.
  */
 
-	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
-	     tmp = (Scsi_Cmnd *) tmp->host_scribble)
+	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
 		if (cmd == tmp) {
-			restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : aborting disconnected command.\n", instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
 
 			if (NCR5380_select(instance, cmd, (int) cmd->tag))
 				return SCSI_ABORT_BUSY;
-
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : nexus reestablished.\n", instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
 
 			do_abort(instance);
 
-			cli();
-			for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue),
-			tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
-			     tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp =
-			     (Scsi_Cmnd *) tmp->host_scribble)
+			for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
 				if (cmd == tmp) {
 					REMOVE(5, *prev, tmp, tmp->host_scribble);
 					*prev = (Scsi_Cmnd *) tmp->host_scribble;
 					tmp->host_scribble = NULL;
 					tmp->result = DID_ABORT << 16;
-					restore_flags(flags);
 					tmp->done(tmp);
 					return SCSI_ABORT_SUCCESS;
 				}
@@ -3474,10 +2978,7 @@
  * so we won't panic, but we will notify the user in case something really
  * broke.
  */
-
-	restore_flags(flags);
-	printk("scsi%d : warning : SCSI command probably completed successfully\n"
-	       "         before abortion\n", instance->host_no);
+	printk("scsi%d : warning : SCSI command probably completed successfully\n" "         before abortion\n", instance->host_no);
 	return SCSI_ABORT_NOT_RUNNING;
 }
 
@@ -3489,6 +2990,7 @@
  *
  * Returns : SCSI_RESET_WAKEUP
  *
+ * Locks: io_request_lock held by caller
  */
 
 #ifndef NCR5380_reset
diff -Nru a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
--- a/drivers/scsi/NCR5380.h	Tue Feb 26 11:57:59 2002
+++ b/drivers/scsi/NCR5380.h	Tue Feb 26 11:57:59 2002
@@ -55,6 +55,8 @@
 #define NDEBUG_C400_PWRITE	0x200000
 #define NDEBUG_LISTS		0x400000
 
+#define NDEBUG_ANY		0xFFFFFFFFUL
+
 /* 
  * The contents of the OUTPUT DATA register are asserted on the bus when
  * either arbitration is occurring or the phase-indicating signals (
@@ -62,8 +64,8 @@
  * bit in the INITIATOR COMMAND register is set.
  */
 
-#define OUTPUT_DATA_REG         0       /* wo DATA lines on SCSI bus */
-#define CURRENT_SCSI_DATA_REG   0       /* ro same */
+#define OUTPUT_DATA_REG         0	/* wo DATA lines on SCSI bus */
+#define CURRENT_SCSI_DATA_REG   0	/* ro same */
 
 #define INITIATOR_COMMAND_REG	1	/* rw */
 #define ICR_ASSERT_RST		0x80	/* rw Set to assert RST  */
@@ -91,10 +93,10 @@
  */
 #define MR_BLOCK_DMA_MODE	0x80	/* rw block mode DMA */
 #define MR_TARGET		0x40	/* rw target mode */
-#define MR_ENABLE_PAR_CHECK   0x20	/* rw enable parity checking */
+#define MR_ENABLE_PAR_CHECK	0x20	/* rw enable parity checking */
 #define MR_ENABLE_PAR_INTR	0x10	/* rw enable bad parity interrupt */
 #define MR_ENABLE_EOP_INTR	0x08	/* rw enable eop interrupt */
-#define MR_MONITOR_BSY	0x04	/* rw enable int on unexpected bsy fail */
+#define MR_MONITOR_BSY		0x04	/* rw enable int on unexpected bsy fail */
 #define MR_DMA_MODE		0x02	/* rw DMA / pseudo DMA mode */
 #define MR_ARBITRATE		0x01	/* rw start arbitration */
 
@@ -116,7 +118,7 @@
  * Note : a set bit indicates an active signal, driven by us or another 
  * device.
  */
-#define SR_RST			0x80	
+#define SR_RST			0x80
 #define SR_BSY			0x40
 #define SR_REQ			0x20
 #define SR_MSG			0x10
@@ -159,17 +161,17 @@
 /* Write any value to this register to start an ini mode DMA receive */
 #define START_DMA_INITIATOR_RECEIVE_REG 7	/* wo */
 
-#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8      /* rw */
+#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8	/* rw */
 
-#define CSR_RESET              0x80    /* wo  Resets 53c400 */
-#define CSR_53C80_REG          0x80    /* ro  5380 registers busy */
-#define CSR_TRANS_DIR          0x40    /* rw  Data transfer direction */
-#define CSR_SCSI_BUFF_INTR     0x20    /* rw  Enable int on transfer ready */
-#define CSR_53C80_INTR         0x10    /* rw  Enable 53c80 interrupts */
-#define CSR_SHARED_INTR        0x08    /* rw  Interrupt sharing */
-#define CSR_HOST_BUF_NOT_RDY   0x04    /* ro  Is Host buffer ready */
-#define CSR_SCSI_BUF_RDY       0x02    /* ro  SCSI buffer read */
-#define CSR_GATED_53C80_IRQ    0x01    /* ro  Last block xferred */
+#define CSR_RESET              0x80	/* wo  Resets 53c400 */
+#define CSR_53C80_REG          0x80	/* ro  5380 registers busy */
+#define CSR_TRANS_DIR          0x40	/* rw  Data transfer direction */
+#define CSR_SCSI_BUFF_INTR     0x20	/* rw  Enable int on transfer ready */
+#define CSR_53C80_INTR         0x10	/* rw  Enable 53c80 interrupts */
+#define CSR_SHARED_INTR        0x08	/* rw  Interrupt sharing */
+#define CSR_HOST_BUF_NOT_RDY   0x04	/* ro  Is Host buffer ready */
+#define CSR_SCSI_BUF_RDY       0x02	/* ro  SCSI buffer read */
+#define CSR_GATED_53C80_IRQ    0x01	/* ro  Last block xferred */
 
 #if 0
 #define CSR_BASE CSR_SCSI_BUFF_INTR | CSR_53C80_INTR
@@ -178,13 +180,13 @@
 #endif
 
 /* Number of 128-byte blocks to be transferred */
-#define C400_BLOCK_COUNTER_REG   NCR53C400_register_offset-7      /* rw */
+#define C400_BLOCK_COUNTER_REG   NCR53C400_register_offset-7	/* rw */
 
 /* Resume transfer after disconnect */
-#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6      /* wo */
+#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6	/* wo */
 
 /* Access to host buffer stack */
-#define C400_HOST_BUFFER         NCR53C400_register_offset-4      /* rw */
+#define C400_HOST_BUFFER         NCR53C400_register_offset-4	/* rw */
 
 
 /* Note : PHASE_* macros are based on the values of the STATUS register */
@@ -203,8 +205,8 @@
  * the target register so we can get phase mismatch interrupts on DMA 
  * transfers.
  */
- 
-#define PHASE_SR_TO_TCR(phase) ((phase) >> 2)	
+
+#define PHASE_SR_TO_TCR(phase) ((phase) >> 2)
 
 /*
  * The internal should_disconnect() function returns these based on the 
@@ -220,7 +222,7 @@
  * These are "special" values for the tag parameter passed to NCR5380_select.
  */
 
-#define TAG_NEXT	-1 	/* Use next free tag */
+#define TAG_NEXT	-1	/* Use next free tag */
 #define TAG_NONE	-2	/* 
 				 * Establish I_T_L nexus instead of I_T_L_Q
 				 * even on SCSI-II devices.
@@ -235,7 +237,7 @@
 #define DMA_NONE	255
 #define IRQ_AUTO	254
 #define DMA_AUTO	254
-#define PORT_AUTO	0xffff		/* autoprobe io port for 53c400a */
+#define PORT_AUTO	0xffff	/* autoprobe io port for 53c400a */
 
 #define FLAG_HAS_LAST_BYTE_SENT		1	/* NCR53c81 or better */
 #define FLAG_CHECK_LAST_BYTE_SENT	2	/* Only test once */
@@ -245,134 +247,188 @@
 
 #ifndef ASM
 struct NCR5380_hostdata {
-    NCR5380_implementation_fields;		/* implementation specific */
-    unsigned char id_mask, id_higher_mask;	/* 1 << id, all bits greater */
-    unsigned char targets_present;		/* targets we have connected
+	NCR5380_implementation_fields;		/* implementation specific */
+	unsigned char id_mask, id_higher_mask;	/* 1 << id, all bits greater */
+	unsigned char targets_present;		/* targets we have connected
 						   to, so we can call a select
 						   failure a retryable condition */
-    volatile unsigned char busy[8];		/* index = target, bit = lun */
+	volatile unsigned char busy[8];		/* index = target, bit = lun */
 #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
-    volatile int dma_len;			/* requested length of DMA */
+	volatile int dma_len;			/* requested length of DMA */
 #endif
-    volatile unsigned char last_message;	/* last message OUT */
-    volatile Scsi_Cmnd *connected;		/* currently connected command */
-    volatile Scsi_Cmnd *issue_queue;		/* waiting to be issued */
-    volatile Scsi_Cmnd *disconnected_queue;	/* waiting for reconnect */
-    volatile int restart_select;		/* we have disconnected,
+	volatile unsigned char last_message;	/* last message OUT */
+	volatile Scsi_Cmnd *connected;		/* currently connected command */
+	volatile Scsi_Cmnd *issue_queue;	/* waiting to be issued */
+	volatile Scsi_Cmnd *disconnected_queue;	/* waiting for reconnect */
+	volatile int restart_select;		/* we have disconnected,
 						   used to restart 
 						   NCR5380_select() */
-    volatile unsigned aborted:1;		/* flag, says aborted */
-    int flags;
-#ifdef USLEEP
-    unsigned long time_expires;			/* in jiffies, set prior to sleeping */
-    struct Scsi_Host *next_timer;
-    int select_time;				/* timer in select for target response */
-    volatile Scsi_Cmnd *selecting;
-#endif
+	volatile unsigned aborted:1;		/* flag, says aborted */
+	int flags;
+	unsigned long time_expires;		/* in jiffies, set prior to sleeping */
+	struct Scsi_Host *next_timer;
+	int select_time;			/* timer in select for target response */
+	volatile Scsi_Cmnd *selecting;
 #ifdef NCR5380_STATS
-    unsigned timebase;				/* Base for time calcs */
-    long time_read[8];				/* time to do reads */
-    long time_write[8];				/* time to do writes */
-    unsigned long bytes_read[8];		/* bytes read */
-    unsigned long bytes_write[8];		/* bytes written */
-    unsigned pendingr;
-    unsigned pendingw;
+	unsigned timebase;			/* Base for time calcs */
+	long time_read[8];			/* time to do reads */
+	long time_write[8];			/* time to do writes */
+	unsigned long bytes_read[8];		/* bytes read */
+	unsigned long bytes_write[8];		/* bytes written */
+	unsigned pendingr;
+	unsigned pendingw;
 #endif
 };
 
 #ifdef __KERNEL__
-static struct Scsi_Host *first_instance;		/* linked list of 5380's */
+static struct Scsi_Host *first_instance;	/* linked list of 5380's */
+
+#define dprintk(a,b)			do {} while(0)
+#define NCR5380_dprint(a,b)		do {} while(0)
+#define NCR5380_dprint_phase(a,b)	do {} while(0)
 
 #if defined(AUTOPROBE_IRQ)
-static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible);
+static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
-static void NCR5380_init (struct Scsi_Host *instance, int flags);
-static void NCR5380_information_transfer (struct Scsi_Host *instance);
+static void NCR5380_init(struct Scsi_Host *instance, int flags);
+static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
-static void NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs);
-static void do_NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs);
+static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
+static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
 #endif
-static void NCR5380_main (void);
-static void NCR5380_print_options (struct Scsi_Host *instance);
-static void NCR5380_print_phase (struct Scsi_Host *instance);
-static void NCR5380_print (struct Scsi_Host *instance);
+static void NCR5380_main(void);
+static void NCR5380_print_options(struct Scsi_Host *instance);
+static void NCR5380_print_phase(struct Scsi_Host *instance);
+static void NCR5380_print(struct Scsi_Host *instance);
 #ifndef NCR5380_abort
 static
 #endif
-int NCR5380_abort (Scsi_Cmnd *cmd);
+int NCR5380_abort(Scsi_Cmnd * cmd);
 #ifndef NCR5380_reset
 static
 #endif
-int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags);
+int NCR5380_reset(Scsi_Cmnd * cmd, unsigned int reset_flags);
 #ifndef NCR5380_queue_command
-static 
+static
 #endif
-int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *));
+int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
 
 
-static void NCR5380_reselect (struct Scsi_Host *instance);
-static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag);
+static void NCR5380_reselect(struct Scsi_Host *instance);
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
 #if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
-static int NCR5380_transfer_dma (struct Scsi_Host *instance,
-	unsigned char *phase, int *count, unsigned char **data);
+static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
 #endif
-static int NCR5380_transfer_pio (struct Scsi_Host *instance,
-	unsigned char *phase, int *count, unsigned char **data);
+static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
 
 #if (defined(REAL_DMA) || defined(REAL_DMA_POLL))
 
 #if defined(i386) || defined(__alpha__)
 
-static __inline__ int NCR5380_pc_dma_setup (struct Scsi_Host *instance,
-	unsigned char *ptr, unsigned int count, unsigned char mode) {
-    unsigned limit;
-    unsigned long bus_addr = virt_to_bus(ptr);
-
-    if (instance->dma_channel <=3) {
-	if (count > 65536)
-	    count = 65536;
-	limit = 65536 - (bus_addr & 0xFFFF);
-    } else {
-	if (count > 65536 * 2) 
-	    count = 65536 * 2;
-	limit = 65536* 2 - (bus_addr & 0x1FFFF);
-    }
-
-    if (count > limit) count = limit;
-
-    if ((count & 1) || (bus_addr & 1))
-	panic ("scsi%d : attempted unaligned DMA transfer\n", instance->host_no);
-    cli();
-    disable_dma(instance->dma_channel);
-    clear_dma_ff(instance->dma_channel);
-    set_dma_addr(instance->dma_channel, bus_addr);
-    set_dma_count(instance->dma_channel, count);
-    set_dma_mode(instance->dma_channel, mode);
-    enable_dma(instance->dma_channel);
-    sti();
-    return count;
+/**
+ *	NCR5380_pc_dma_setup		-	setup ISA DMA
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *	@mode: DMA controller mode to use
+ *
+ *	Program the DMA controller ready to perform an ISA DMA transfer
+ *	on this chip.
+ *
+ *	Locks: takes and releases the ISA DMA lock.
+ */
+ 
+static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode)
+{
+	unsigned limit;
+	unsigned long bus_addr = virt_to_bus(ptr);
+	unsigned long flags;
+
+	if (instance->dma_channel <= 3) {
+		if (count > 65536)
+			count = 65536;
+		limit = 65536 - (bus_addr & 0xFFFF);
+	} else {
+		if (count > 65536 * 2)
+			count = 65536 * 2;
+		limit = 65536 * 2 - (bus_addr & 0x1FFFF);
+	}
+
+	if (count > limit)
+		count = limit;
+
+	if ((count & 1) || (bus_addr & 1))
+		panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no);
+	
+	flags=claim_dma_lock();
+	disable_dma(instance->dma_channel);
+	clear_dma_ff(instance->dma_channel);
+	set_dma_addr(instance->dma_channel, bus_addr);
+	set_dma_count(instance->dma_channel, count);
+	set_dma_mode(instance->dma_channel, mode);
+	enable_dma(instance->dma_channel);
+	release_dma_lock(flags);
+	
+	return count;
 }
 
-static __inline__ int NCR5380_pc_dma_write_setup (struct Scsi_Host *instance,
-    unsigned char *src, unsigned int count) {
-    return NCR5380_pc_dma_setup (instance, src, count, DMA_MODE_WRITE);
+/**
+ *	NCR5380_pc_dma_write_setup		-	setup ISA DMA write
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *
+ *	Program the DMA controller ready to perform an ISA DMA write to the
+ *	SCSI controller.
+ *
+ *	Locks: called routines take and release the ISA DMA lock.
+ */
+
+static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
+{
+	return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE);
 }
 
-static __inline__ int NCR5380_pc_dma_read_setup (struct Scsi_Host *instance,
-    unsigned char *src, unsigned int count) {
-    return NCR5380_pc_dma_setup (instance, src, count, DMA_MODE_READ);
+/**
+ *	NCR5380_pc_dma_read_setup		-	setup ISA DMA read
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *
+ *	Program the DMA controller ready to perform an ISA DMA read from the
+ *	SCSI controller.
+ *
+ *	Locks: called routines take and release the ISA DMA lock.
+ */
+
+static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
+{
+	return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ);
 }
 
-static __inline__ int NCR5380_pc_dma_residual (struct Scsi_Host *instance) {
-    register int tmp;
-    cli();
-    clear_dma_ff(instance->dma_channel);
-    tmp = get_dma_residue(instance->dma_channel);
-    sti();
-    return tmp;
+/**
+ *	NCR5380_pc_dma_residual		-	return bytes left 
+ *	@instance: adapter
+ *
+ *	Reports the number of bytes left over after the DMA was terminated.
+ *
+ *	Locks: takes and releases the ISA DMA lock.
+ */
+
+static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance)
+{
+	unsigned long flags;
+	int tmp;
+
+	flags = claim_dma_lock();
+	clear_dma_ff(instance->dma_channel);
+	tmp = get_dma_residue(instance->dma_channel);
+	release_dma_lock(flags);
+	
+	return tmp;
 }
-#endif /* defined(i386) || defined(__alpha__) */
-#endif /* defined(REAL_DMA)  */
-#endif /* __KERNEL__ */
-#endif /* ndef ASM */
-#endif /* NCR5380_H */
+#endif				/* defined(i386) || defined(__alpha__) */
+#endif				/* defined(REAL_DMA)  */
+#endif				/* __KERNEL__ */
+#endif				/* ndef ASM */
+#endif				/* NCR5380_H */
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/scsi/eata.c	Tue Feb 26 11:57:58 2002
@@ -1,6 +1,13 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      20 Feb 2002 Rev. 7.22 for linux 2.5.5
+ *        + Remove any reference to virt_to_bus().
+ *        + Fix pio hang while detecting multiple HBAs.
+ *        + Fixed a board detection bug: in a system with
+ *          multiple ISA/EISA boards, all but the first one
+ *          were erroneously detected as PCI.
+ *
  *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
  *        + Use the dynamic DMA mapping API.
  *
@@ -29,7 +36,7 @@
  *          boot time.
  *        + Improved boot messages: all tagged capable device are
  *          indicated as "tagged" or "soft-tagged" :
- *          - "soft-tagged"  means that the driver is trying to do its 
+ *          - "soft-tagged"  means that the driver is trying to do its
  *            own tagging (i.e. the tc:y option is in effect);
  *          - "tagged" means that the device supports tagged commands,
  *            but the driver lets the HBA be responsible for tagging
@@ -40,7 +47,7 @@
  *        + When loaded as a module, accepts the new parameter boot_options
  *          which value is a string with the same format of the kernel boot
  *          command line options. A valid example is:
- *          modprobe eata boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\"
+ *          modprobe eata 'boot_options="0x7410,0x230,lc:y,tc:n,mq:4"'
  *
  *       9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17
  *        + 64bit cleanup for Linux/Alpha platform support
@@ -401,8 +408,6 @@
  *  the driver sets host->wish_block = TRUE for all ISA boards.
  */
 
-#error Please convert me to Documentation/DMA-mapping.txt
-
 #include <linux/version.h>
 
 #ifndef LinuxVersionCode
@@ -454,7 +459,7 @@
 #define ISA  0
 #define ESA 1
 
-#undef FORCE_CONFIG
+#undef  FORCE_CONFIG
 
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
@@ -645,11 +650,18 @@
    u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */
    u_int32_t sp_dma_addr;  /* Address where sp is DMA'ed when cp completes */
    u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */
+
    /* Additional fields begin here. */
    Scsi_Cmnd *SCpnt;
-   struct sg_list *sglist;
+
+   /* All the cp structure is zero filled by queuecommand except the
+      following CP_TAIL_SIZE bytes, initialized by detect */
+   dma_addr_t cp_dma_addr; /* dma handle for this cp structure */
+   struct sg_list *sglist; /* pointer to the allocated SG list */
    };
 
+#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t))
+
 struct hostdata {
    struct mscp cp[MAX_MAILBOXES];       /* Mailboxes for this board */
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
@@ -657,7 +669,6 @@
    unsigned int iocount;                /* Total i/o done for this board */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
-   char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
    int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */
    int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */
@@ -675,6 +686,7 @@
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "EATA";
 static char sha[MAX_BOARDS];
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
 
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
@@ -710,8 +722,6 @@
 #define H2DEV(x) cpu_to_be32(x)
 #define DEV2H(x) be32_to_cpu(x)
 
-#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
@@ -813,7 +823,7 @@
 
    if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE;
 
-   if ((addr = V2DEV(addr))) {
+   if ((addr = H2DEV(addr))) {
       outb((char) (addr >> 24), iobase + REG_LOW);
       outb((char) (addr >> 16), iobase + REG_LM);
       outb((char) (addr >> 8),  iobase + REG_MID);
@@ -919,7 +929,8 @@
    else
       protocol_rev = 'C';
 
-   if (!setup_done && j > 0 && j <= MAX_PCI) {
+   if (protocol_rev != 'A' && info.forcaddr) {
+      printk("%s: warning, port address has been forced.\n", name);
       bus_type = "PCI";
       is_pci = TRUE;
       subversion = ESA;
@@ -982,7 +993,7 @@
 
    if (is_pci) {
       pdev = get_pci_dev(port_base);
-      if (!pdev) 
+      if (!pdev)
          printk("%s: warning, failed to get pci_dev structure.\n", name);
       }
    else
@@ -1012,18 +1023,29 @@
 
 #if defined(FORCE_CONFIG)
    {
-   struct eata_config config;
+   struct eata_config *cf;
+   dma_addr_t cf_dma_addr;
+
+   cf = pci_alloc_consistent(pdev, sizeof(struct eata_config), &cf_dma_addr);
+
+   if (!cf) {
+      printk("%s: config, pci_alloc_consistent failed, detaching.\n", name);
+      release_region(port_base, REGION_SIZE);
+      return FALSE;
+      }
 
    /* Set board configuration */
-   memset((char *)&config, 0, sizeof(struct eata_config));
-   config.len = (ushort) cpu_to_be16((ushort)510);
-   config.ocena = TRUE;
+   memset((char *)cf, 0, sizeof(struct eata_config));
+   cf->len = (ushort) cpu_to_be16((ushort)510);
+   cf->ocena = TRUE;
 
-   if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
+   if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) {
       printk("%s: busy timeout sending configuration, detaching.\n", name);
+      pci_free_consistent(pdev, sizeof(struct eata_config), cf, cf_dma_addr);
       release_region(port_base, REGION_SIZE);
       return FALSE;
       }
+
    }
 #endif
 
@@ -1111,6 +1133,10 @@
    else                       sprintf(dma_name, "DMA %u", dma_channel);
 
    for (i = 0; i < sh[j]->can_queue; i++)
+      HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev,
+            &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
+
+   for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
             sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
@@ -1119,7 +1145,7 @@
          return FALSE;
          }
 
-   if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, 
+   if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev,
          sizeof(struct mssp), &HD(j)->sp_dma_addr))) {
       printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j));
       eata2x_release(sh[j]);
@@ -1279,6 +1305,9 @@
 
 int eata2x_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k;
+   unsigned long spin_flags;
+
+   spin_lock_irqsave(&driver_lock, spin_flags);
 
    tpnt->proc_name = "eata2x";
 
@@ -1304,6 +1333,7 @@
       }
 
    num_boards = j;
+   spin_unlock_irqrestore(&driver_lock, spin_flags);
    return j;
 }
 
@@ -1324,10 +1354,10 @@
 
    if (!SCpnt->use_sg) {
 
-      if (!SCpnt->request_bufflen)
-         cpp->data_address = V2DEV(SCpnt->request_buffer);
+      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
+      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
-      else if (SCpnt->request_buffer)
+      if (SCpnt->request_buffer)
          cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
                   SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
 
@@ -1344,7 +1374,8 @@
       }
 
    cpp->sg = TRUE;
-   cpp->data_address = V2DEV(cpp->sglist);
+   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
    cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
 }
 
@@ -1360,13 +1391,14 @@
       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg) 
+   if (SCpnt->use_sg)
       pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
 
-   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
-      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
-                       DEV2H(cpp->data_len), pci_dir);
+   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
+   if (DEV2H(cpp->data_address))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),
+                       DEV2H(cpp->data_len), pci_dir);
 }
 
 static void sync_dma(unsigned int i, unsigned int j) {
@@ -1381,14 +1413,15 @@
       pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg) 
-      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+   if (SCpnt->use_sg)
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer,
                          SCpnt->use_sg, pci_dir);
 
-   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
-      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
-                          DEV2H(cpp->data_len), pci_dir);
+   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
+   if (DEV2H(cpp->data_address))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address),
+                       DEV2H(cpp->data_len), pci_dir);
 }
 
 static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
@@ -1409,8 +1442,7 @@
    struct mscp *cpp;
    Scsi_Cmnd *SCpnt;
 
-   cpp = &HD(j)->cp[i];
-   SCpnt = cpp->SCpnt;
+   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;
 
    if (SCpnt->sc_data_direction == SCSI_DATA_READ) {
       cpp->din  = TRUE;
@@ -1428,7 +1460,7 @@
       return;
       }
 
-   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
       panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
@@ -1479,7 +1511,7 @@
    /* Set pointer to control packet structure */
    cpp = &HD(j)->cp[i];
 
-   memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
+   memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);
 
    /* Set pointer to status packet structure, Big Endian format */
    cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr);
@@ -1536,7 +1568,7 @@
       }
 
    /* Send control packet to the board */
-   if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
+   if (do_dma(sh[j]->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
       unmap_dma(i, j);
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
@@ -1935,7 +1967,7 @@
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
 
-      if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
+      if (do_dma(sh[j]->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
          printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
                 " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
                 SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
@@ -1985,7 +2017,7 @@
    reg = inb(sh[j]->io_port + REG_STATUS);
 
    /* Reject any sp with supspect data */
-   if (spp->eoc == FALSE)
+   if (spp->eoc == FALSE && HD(j)->iocount > 1)
       printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n",
              BN(j), irq, reg, HD(j)->iocount);
    if (spp->cpp_index < 0 || spp->cpp_index >= sh[j]->can_queue)
@@ -2191,10 +2223,14 @@
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (HD(j)->sp_cpu_addr) 
+   for (i = 0; i < sh[j]->can_queue; i++)
+      pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr,
+                     sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
+
+   if (HD(j)->sp_cpu_addr)
       pci_free_consistent(HD(j)->pdev, sizeof(struct mssp),
                           HD(j)->sp_cpu_addr, HD(j)->sp_dma_addr);
-                       
+
    free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h
--- a/drivers/scsi/eata.h	Tue Feb 26 11:57:57 2002
+++ b/drivers/scsi/eata.h	Tue Feb 26 11:57:57 2002
@@ -13,7 +13,7 @@
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_biosparam(Disk *, kdev_t, int *);
 
-#define EATA_VERSION "7.20.00"
+#define EATA_VERSION "7.22.00"
 
 #define EATA {                                                               \
                 name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c
--- a/drivers/scsi/imm.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/scsi/imm.c	Tue Feb 26 11:58:00 2002
@@ -1007,7 +1007,7 @@
 	    cmd->SCp.this_residual = cmd->request_bufflen;
 	    cmd->SCp.ptr = cmd->request_buffer;
 	}
-	cmd->SCp.buffers_residual = cmd->use_sg;
+	cmd->SCp.buffers_residual = cmd->use_sg - 1;
 	cmd->SCp.phase++;
 	if (cmd->SCp.this_residual & 0x01)
 	    cmd->SCp.this_residual++;
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/scsi/ips.c	Tue Feb 26 11:57:56 2002
@@ -81,7 +81,7 @@
 /*            2.3.18 and later                                               */
 /*          - Sync with other changes from the 2.3 kernels                   */
 /* 4.00.06  - Fix timeout with initial FFDC command                          */
-/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@caldera.de>    */
+/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@infradead.org> */
 /* 4.10.00  - Add support for ServeRAID 4M/4L                                */
 /* 4.10.13  - Fix for dynamic unload and proc file system                    */
 /* 4.20.03  - Rename version to coincide with new release schedules          */
diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
--- a/drivers/scsi/ppa.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/scsi/ppa.c	Tue Feb 26 11:57:56 2002
@@ -738,7 +738,7 @@
 	    if (cmd->SCp.buffers_residual--) {
 		cmd->SCp.buffer++;
 		cmd->SCp.this_residual = cmd->SCp.buffer->length;
-		cmd->SCp.ptr = cmd->SCp.buffer->address;
+		cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
 	    }
 	}
 	/* Now check to see if the drive is ready to comunicate */
@@ -923,14 +923,14 @@
 	    /* if many buffers are available, start filling the first */
 	    cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
 	    cmd->SCp.this_residual = cmd->SCp.buffer->length;
-	    cmd->SCp.ptr = cmd->SCp.buffer->address;
+	    cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
 	} else {
 	    /* else fill the only available buffer */
 	    cmd->SCp.buffer = NULL;
 	    cmd->SCp.this_residual = cmd->request_bufflen;
 	    cmd->SCp.ptr = cmd->request_buffer;
 	}
-	cmd->SCp.buffers_residual = cmd->use_sg;
+	cmd->SCp.buffers_residual = cmd->use_sg - 1;
 	cmd->SCp.phase++;
 
     case 5:			/* Phase 5 - Data transfer stage */
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/scsi/sr.c	Tue Feb 26 11:57:58 2002
@@ -524,7 +524,7 @@
 		scsi_CDs[i].needs_sector_size = 1;
 	} else {
 #if 0
-		if (cdrom_get_last_written(MKDEV(MAJOR_NR, i),
+		if (cdrom_get_last_written(mkdev(MAJOR_NR, i),
 					   &scsi_CDs[i].capacity))
 #endif
 			scsi_CDs[i].capacity = 1 + ((buffer[0] << 24) |
diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
--- a/drivers/scsi/u14-34f.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/scsi/u14-34f.c	Tue Feb 26 11:57:58 2002
@@ -1,6 +1,10 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      20 Feb 2002 Rev. 7.22 for linux 2.5.5
+ *        + Remove any reference to virt_to_bus().
+ *        + Fix pio hang while detecting multiple HBAs.
+ *
  *      01 Jan 2002 Rev. 7.20 for linux 2.5.1
  *        + Use the dynamic DMA mapping API.
  *
@@ -30,7 +34,7 @@
  *        + When loaded as a module, accepts the new parameter boot_options
  *          which value is a string with the same format of the kernel boot
  *          command line options. A valid example is:
- *          modprobe u14-34f boot_options=\"0x230,0x340,lc:y,mq:4\"
+ *          modprobe u14-34f 'boot_options="0x230,0x340,lc:y,mq:4"'
  *
  *      22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11
  *        + Removed pre-2.2 source code compatibility.
@@ -496,11 +500,19 @@
    unsigned char adapter_status;        /* non-zero indicates HA error */
    unsigned char target_status;         /* non-zero indicates target error */
    unsigned int sense_addr PACKED;
+
+   /* Additional fields begin here. */
    Scsi_Cmnd *SCpnt;
    unsigned int cpp_index;              /* cp index */
-   struct sg_list *sglist;
+
+   /* All the cp structure is zero filled by queuecommand except the
+      following CP_TAIL_SIZE bytes, initialized by detect */
+   dma_addr_t cp_dma_addr; /* dma handle for this cp structure */
+   struct sg_list *sglist; /* pointer to the allocated SG list */
    };
 
+#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t))
+
 struct hostdata {
    struct mscp cp[MAX_MAILBOXES];       /* Mailboxes for this board */
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
@@ -508,7 +520,6 @@
    unsigned int iocount;                /* Total i/o done for this board */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
-   char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
    int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */
    int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */
@@ -518,14 +529,13 @@
    struct pci_dev *pdev;                /* Always NULL */
    unsigned char heads;
    unsigned char sectors;
-
-   /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */
-   unsigned char slot;
+   char board_id[256];                  /* data from INQUIRY on this board */
    };
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "Ux4F";
 static char sha[MAX_BOARDS];
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
 
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
@@ -550,8 +560,6 @@
 #define H2DEV(x) cpu_to_le32(x)
 #define DEV2H(x) le32_to_cpu(x)
 
-#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-
 static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
@@ -644,13 +652,18 @@
 
 static int board_inquiry(unsigned int j) {
    struct mscp *cpp;
+   dma_addr_t id_dma_addr;
    unsigned int time, limit = 0;
 
+   id_dma_addr = pci_map_single(HD(j)->pdev, HD(j)->board_id,
+                    sizeof(HD(j)->board_id), PCI_DMA_BIDIRECTIONAL);
    cpp = &HD(j)->cp[0];
-   memset(cpp, 0, sizeof(struct mscp));
+   cpp->cp_dma_addr = pci_map_single(HD(j)->pdev, cpp, sizeof(struct mscp),
+                                     PCI_DMA_BIDIRECTIONAL);
+   memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);
    cpp->opcode = OP_HOST_ADAPTER;
    cpp->xdir = DTD_IN;
-   cpp->data_address = V2DEV(HD(j)->board_id);
+   cpp->data_address = H2DEV(id_dma_addr);
    cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
    cpp->cdb_len = 6;
    cpp->cdb[0] = HA_CMD_INQUIRY;
@@ -666,13 +679,15 @@
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
    /* Store pointer in OGM address bytes */
-   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+   outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
 
    /* Issue OGM interrupt */
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
 
+   spin_unlock_irq(&driver_lock);
    time = jiffies;
    while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);
+   spin_lock_irq(&driver_lock);
 
    if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {
       HD(j)->cp_stat[0] = FREE;
@@ -680,6 +695,10 @@
       return TRUE;
       }
 
+   pci_unmap_single(HD(j)->pdev, cpp->cp_dma_addr, sizeof(struct mscp),
+                    PCI_DMA_BIDIRECTIONAL);
+   pci_unmap_single(HD(j)->pdev, id_dma_addr, sizeof(HD(j)->board_id),
+                    PCI_DMA_BIDIRECTIONAL);
    return FALSE;
 }
 
@@ -817,6 +836,7 @@
    HD(j)->heads = mapping_table[config_2.mapping_mode].heads;
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
    HD(j)->subversion = subversion;
+   HD(j)->pdev = NULL;
    HD(j)->board_number = j;
 
    if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
@@ -864,6 +884,10 @@
    else                       sprintf(dma_name, "DMA %u", dma_channel);
 
    for (i = 0; i < sh[j]->can_queue; i++)
+      HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev,
+            &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
+
+   for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
             sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
@@ -950,6 +974,9 @@
 
 int u14_34f_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k;
+   unsigned long spin_flags;
+
+   spin_lock_irqsave(&driver_lock, spin_flags);
 
    tpnt->proc_name = "u14-34f";
 
@@ -973,6 +1000,7 @@
       }
 
    num_boards = j;
+   spin_unlock_irqrestore(&driver_lock, spin_flags);
    return j;
 }
 
@@ -994,10 +1022,10 @@
 
    if (!SCpnt->use_sg) {
 
-      if (!SCpnt->request_bufflen)
-         cpp->data_address = V2DEV(SCpnt->request_buffer);
+      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
+      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
-      else if (SCpnt->request_buffer)
+      if (SCpnt->request_buffer)
          cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
                   SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
 
@@ -1016,7 +1044,8 @@
 
    cpp->sg = TRUE;
    cpp->use_sg = SCpnt->use_sg;
-   cpp->data_address = V2DEV(cpp->sglist);
+   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
    cpp->data_len = H2DEV(data_len);
 }
 
@@ -1032,13 +1061,14 @@
       pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                        DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg) 
+   if (SCpnt->use_sg)
       pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
 
-   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
-      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address), 
-                       DEV2H(cpp->data_len), pci_dir);
+   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
+   if (DEV2H(cpp->data_address))
+      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),
+                       DEV2H(cpp->data_len), pci_dir);
 }
 
 static void sync_dma(unsigned int i, unsigned int j) {
@@ -1053,14 +1083,15 @@
       pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
                           DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
 
-   if (SCpnt->use_sg) 
-      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer, 
+   if (SCpnt->use_sg)
+      pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer,
                          SCpnt->use_sg, pci_dir);
 
-   else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
-      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address), 
-                          DEV2H(cpp->data_len), pci_dir);
+   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
 
+   if (DEV2H(cpp->data_address))
+      pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address),
+                       DEV2H(cpp->data_len), pci_dir);
 }
 
 static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
@@ -1096,7 +1127,7 @@
       return;
       }
 
-   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) 
+   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
       panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
 
    cpp->xdir = DTD_IN;
@@ -1149,7 +1180,7 @@
    /* Set pointer to control packet structure */
    cpp = &HD(j)->cp[i];
 
-   memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
+   memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);
    SCpnt->scsi_done = done;
    cpp->cpp_index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
@@ -1188,7 +1219,7 @@
       }
 
    /* Store pointer in OGM address bytes */
-   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+   outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
 
    /* Issue OGM interrupt */
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -1598,7 +1629,7 @@
          continue;
          }
 
-      outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+      outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
       outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
       HD(j)->cp_stat[k] = IN_USE;
       }
@@ -1636,11 +1667,11 @@
 
    /* Find the mailbox to be serviced on this board */
    for (i = 0; i < sh[j]->can_queue; i++)
-      if (V2DEV(&(HD(j)->cp[i])) == ret) break;
+      if (H2DEV(HD(j)->cp[i].cp_dma_addr) == ret) break;
 
    if (i >= sh[j]->can_queue)
       panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
-            (void *)ret, (void *)V2DEV(HD(j)->cp));
+            (void *)ret, (void *)H2DEV(HD(j)->cp[0].cp_dma_addr));
 
    cpp = &(HD(j)->cp[i]);
    spp = cpp;
@@ -1839,6 +1870,10 @@
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
+
+   for (i = 0; i < sh[j]->can_queue; i++)
+      pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr,
+                     sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
 
    free_irq(sh[j]->irq, &sha[j]);
 
diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h
--- a/drivers/scsi/u14-34f.h	Tue Feb 26 11:58:00 2002
+++ b/drivers/scsi/u14-34f.h	Tue Feb 26 11:58:00 2002
@@ -13,7 +13,7 @@
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "7.20.00"
+#define U14_34F_VERSION "7.22.00"
 
 #define ULTRASTOR_14_34F {                                                   \
                 name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
diff -Nru a/drivers/usb/hcd/Config.help b/drivers/usb/hcd/Config.help
--- a/drivers/usb/hcd/Config.help	Tue Feb 26 11:57:56 2002
+++ b/drivers/usb/hcd/Config.help	Tue Feb 26 11:57:56 2002
@@ -21,7 +21,6 @@
   The module will be called ehci-hcd.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-OHCI (most USB hosts except VIA, Intel PIIX) support
 CONFIG_USB_OHCI_HCD
   The Open Host Controller Interface (OHCI) is a standard for accessing
   USB 1.1 host controller hardware.  It does more in hardware than Intel's
diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
--- a/drivers/usb/hub.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/usb/hub.c	Tue Feb 26 11:57:59 2002
@@ -644,6 +644,49 @@
 			port + 1, hub->devpath, ret);
 }
 
+/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
+ *
+ * Between connect detection and reset signaling there must be a delay
+ * of 100ms at least for debounce and power-settling. The corresponding
+ * timer shall restart whenever the downstream port detects a disconnect.
+ * 
+ * Apparently there are some bluetooth and irda-dongles and a number
+ * of low-speed devices which require longer delays of about 200-400ms.
+ * Not covered by the spec - but easy to deal with.
+ *
+ * This implementation uses 400ms minimum debounce timeout and checks
+ * every 10ms for transient disconnects to restart the delay.
+ */
+
+#define HUB_DEBOUNCE_TIMEOUT	400
+#define HUB_DEBOUNCE_STEP	10
+
+/* return: -1 on error, 0 on success, 1 on disconnect.  */
+static int usb_hub_port_debounce(struct usb_device *hub, int port)
+{
+	int ret;
+	unsigned delay_time;
+	u16 portchange, portstatus;
+
+	for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
+
+		/* wait debounce step increment */
+		wait_ms(HUB_DEBOUNCE_STEP);
+
+		ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
+		if (ret < 0)
+			return -1;
+
+		if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
+			usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
+			delay_time = 0;
+		}
+		else
+			delay_time += HUB_DEBOUNCE_STEP;
+	}
+	return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
+}
+
 static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
 					u16 portstatus, u16 portchange)
 {
@@ -671,12 +714,16 @@
 		return;
 	}
 
+	if (usb_hub_port_debounce(hub, port)) {
+		err("connect-debounce failed, port %d disabled", port+1);
+		usb_hub_port_disable(hub, port);
+		return;
+	}
+
 	/* Some low speed devices have problems with the quick delay, so */
 	/*  be a bit pessimistic with those devices. RHbug #23670 */
-	if (portstatus & USB_PORT_STAT_LOW_SPEED) {
-		wait_ms(400);
+	if (portstatus & USB_PORT_STAT_LOW_SPEED)
 		delay = HUB_LONG_RESET_TIME;
-	}
 
 	down(&usb_address0_sem);
 
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/usb/ov511.c	Tue Feb 26 11:57:58 2002
@@ -58,7 +58,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.48a for Linux 2.4"
+#define DRIVER_VERSION "v1.49 for Linux 2.5"
 #define EMAIL "mmcclell@bigfoot.com"
 #define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
 	& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
@@ -309,7 +309,7 @@
 static inline int sensor_get_picture(struct usb_ov511 *, 
 				     struct video_picture *);
 static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
-static int ov511_control_ioctl(struct inode *, struct file *, unsigned int,
+static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
 			       unsigned long);
 
 /**********************************************************************
@@ -332,6 +332,7 @@
 	{ 100, "Lifeview RoboCam" },
 	{ 102, "AverMedia InterCam Elite" },
 	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */
+	{ 192, "Webeye 2000B" },
 	{  -1, NULL }
 };
 
@@ -373,17 +374,20 @@
 static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
 static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
 
+/**********************************************************************
+ * Memory management
+ **********************************************************************/
+
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long 
 kvirt_to_pa(unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
 	return ret;
 }
@@ -392,12 +396,9 @@
 rvmalloc(unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
-
-	/* Round it off to PAGE_SIZE */
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32(size);
 	if (!mem)
 		return NULL;
@@ -405,13 +406,9 @@
 	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 	adr = (unsigned long) mem;
 	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_reserve(virt_to_page(__va(page)));
+		mem_map_reserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 
 	return mem;
@@ -420,23 +417,16 @@
 static void 
 rvfree(void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (!mem)
 		return;
 
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
-
-	adr=(unsigned long) mem;
-	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_unreserve(virt_to_page(__va(page)));
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	vfree(mem);
 }
@@ -452,7 +442,7 @@
 extern struct proc_dir_entry *video_proc_entry;
 
 static struct file_operations ov511_control_fops = {
-	ioctl:		ov511_control_ioctl,
+	ioctl:		ov51x_control_ioctl,
 };
 
 #define YES_NO(x) ((x) ? "yes" : "no")
@@ -464,29 +454,29 @@
 {
 	char *out = page;
 	int i, j, len;
-	struct usb_ov511 *ov511 = data;
+	struct usb_ov511 *ov = data;
 	struct video_picture p;
 	unsigned char exp;
 
-	if (!ov511 || !ov511->dev)
+	if (!ov || !ov->dev)
 		return -ENODEV;
 
-	sensor_get_picture(ov511, &p);
-	sensor_get_exposure(ov511, &exp);
+	sensor_get_picture(ov, &p);
+	sensor_get_exposure(ov, &exp);
 
 	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
 	 *            or we need to get more sophisticated. */
 
 	out += sprintf(out, "driver_version  : %s\n", DRIVER_VERSION);
-	out += sprintf(out, "custom_id       : %d\n", ov511->customid);
-	out += sprintf(out, "model           : %s\n", ov511->desc ?
-		       clist[ov511->desc].description : "unknown");
-	out += sprintf(out, "streaming       : %s\n", YES_NO(ov511->streaming));
-	out += sprintf(out, "grabbing        : %s\n", YES_NO(ov511->grabbing));
-	out += sprintf(out, "compress        : %s\n", YES_NO(ov511->compress));
-	out += sprintf(out, "subcapture      : %s\n", YES_NO(ov511->sub_flag));
+	out += sprintf(out, "custom_id       : %d\n", ov->customid);
+	out += sprintf(out, "model           : %s\n", ov->desc ?
+		       clist[ov->desc].description : "unknown");
+	out += sprintf(out, "streaming       : %s\n", YES_NO(ov->streaming));
+	out += sprintf(out, "grabbing        : %s\n", YES_NO(ov->grabbing));
+	out += sprintf(out, "compress        : %s\n", YES_NO(ov->compress));
+	out += sprintf(out, "subcapture      : %s\n", YES_NO(ov->sub_flag));
 	out += sprintf(out, "sub_size        : %d %d %d %d\n",
-		       ov511->subx, ov511->suby, ov511->subw, ov511->subh);
+		       ov->subx, ov->suby, ov->subw, ov->subh);
 	out += sprintf(out, "data_format     : %s\n",
 		       force_rgb ? "RGB" : "BGR");
 	out += sprintf(out, "brightness      : %d\n", p.brightness >> 8);
@@ -498,12 +488,12 @@
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
 		out += sprintf(out, "frame           : %d\n", i);
 		out += sprintf(out, "  depth         : %d\n",
-			       ov511->frame[i].depth);
+			       ov->frame[i].depth);
 		out += sprintf(out, "  size          : %d %d\n",
-			       ov511->frame[i].width, ov511->frame[i].height);
+			       ov->frame[i].width, ov->frame[i].height);
 		out += sprintf(out, "  format        : ");
 		for (j = 0; plist[j].num >= 0; j++) {
-			if (plist[j].num == ov511->frame[i].format) {
+			if (plist[j].num == ov->frame[i].format) {
 				out += sprintf(out, "%s\n", plist[j].name);
 				break;
 			}
@@ -511,29 +501,28 @@
 		if (plist[j].num < 0)
 			out += sprintf(out, "unknown\n");
 		out += sprintf(out, "  data_buffer   : 0x%p\n",
-			       ov511->frame[i].data);
+			       ov->frame[i].data);
 	}
-	out += sprintf(out, "snap_enabled    : %s\n",
-		       YES_NO(ov511->snap_enabled));
+	out += sprintf(out, "snap_enabled    : %s\n", YES_NO(ov->snap_enabled));
 	out += sprintf(out, "bridge          : %s\n",
-		       ov511->bridge == BRG_OV511 ? "OV511" :
-			ov511->bridge == BRG_OV511PLUS ? "OV511+" :
-			ov511->bridge == BRG_OV518 ? "OV518" :
-			ov511->bridge == BRG_OV518PLUS ? "OV518+" :
+		       ov->bridge == BRG_OV511 ? "OV511" :
+			ov->bridge == BRG_OV511PLUS ? "OV511+" :
+			ov->bridge == BRG_OV518 ? "OV518" :
+			ov->bridge == BRG_OV518PLUS ? "OV518+" :
 			"unknown");
 	out += sprintf(out, "sensor          : %s\n",
-		       ov511->sensor == SEN_OV6620 ? "OV6620" :
-			ov511->sensor == SEN_OV6630 ? "OV6630" :
-			ov511->sensor == SEN_OV7610 ? "OV7610" :
-			ov511->sensor == SEN_OV7620 ? "OV7620" :
-			ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
-			ov511->sensor == SEN_OV8600 ? "OV8600" :
-			ov511->sensor == SEN_KS0127 ? "KS0127" :
-			ov511->sensor == SEN_KS0127B ? "KS0127B" :
-			ov511->sensor == SEN_SAA7111A ? "SAA7111A" :
+		       ov->sensor == SEN_OV6620 ? "OV6620" :
+			ov->sensor == SEN_OV6630 ? "OV6630" :
+			ov->sensor == SEN_OV7610 ? "OV7610" :
+			ov->sensor == SEN_OV7620 ? "OV7620" :
+			ov->sensor == SEN_OV7620AE ? "OV7620AE" :
+			ov->sensor == SEN_OV8600 ? "OV8600" :
+			ov->sensor == SEN_KS0127 ? "KS0127" :
+			ov->sensor == SEN_KS0127B ? "KS0127B" :
+			ov->sensor == SEN_SAA7111A ? "SAA7111A" :
 			"unknown");
-	out += sprintf(out, "packet_size     : %d\n", ov511->packet_size);
-	out += sprintf(out, "framebuffer     : 0x%p\n", ov511->fbuf);
+	out += sprintf(out, "packet_size     : %d\n", ov->packet_size);
+	out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);
 
 	len = out - page;
 	len -= off;
@@ -566,16 +555,16 @@
 {
 	char *out = page;
 	int len, status;
-	struct usb_ov511 *ov511 = data;
+	struct usb_ov511 *ov = data;
 
-	if (!ov511 || !ov511->dev)
+	if (!ov || !ov->dev)
 		return -ENODEV;
 
-	status = ov51x_check_snapshot(ov511);
+	status = ov51x_check_snapshot(ov);
 	out += sprintf(out, "%d", status);
 
 	if (status)
-		ov51x_clear_snapshot(ov511);
+		ov51x_clear_snapshot(ov);
 
 	len = out - page;
 	len -= off;
@@ -717,18 +706,22 @@
  *
  **********************************************************************/
 
+/* Write an OV51x register */
 static int 
-ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value)
+reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
 {
 	int rc;
 
 	PDEBUG(5, "0x%02X:0x%02X", reg, value);
 
-	rc = usb_control_msg(dev,
-			     usb_sndctrlpipe(dev, 0),
+	down(&ov->cbuf_lock);
+	ov->cbuf[0] = value;
+	rc = usb_control_msg(ov->dev,
+			     usb_sndctrlpipe(ov->dev, 0),
 			     2 /* REG_IO */,
 			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, &value, 1, HZ);	
+			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);	
+	up(&ov->cbuf_lock);
 
 	if (rc < 0)
 		err("reg write: error %d", rc);
@@ -736,45 +729,48 @@
 	return rc;
 }
 
+/* Read from an OV51x register */
 /* returns: negative is error, pos or zero is data */
 static int 
-ov511_reg_read(struct usb_device *dev, unsigned char reg)
+reg_r(struct usb_ov511 *ov, unsigned char reg)
 {
 	int rc;
-	unsigned char buffer[1];
 
-	rc = usb_control_msg(dev,
-			     usb_rcvctrlpipe(dev, 0),
+	down(&ov->cbuf_lock);
+	rc = usb_control_msg(ov->dev,
+			     usb_rcvctrlpipe(ov->dev, 0),
 			     2 /* REG_IO */,
 			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, buffer, 1, HZ);
+			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);
                                
-	PDEBUG(5, "0x%02X:0x%02X", reg, buffer[0]);
+	PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
 	
-	if (rc < 0) {
+	if (rc < 0)
 		err("reg read: error %d", rc);
-		return rc;
-	} else {
-		return buffer[0];	
-	}
+	else
+		rc = ov->cbuf[0];	
+
+	up(&ov->cbuf_lock);
+
+	return rc;
 }
 
 /*
- * Writes bits at positions specified by mask to a reg. Bits that are in
+ * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
  * the same position as 1's in "mask" are cleared and set to "value". Bits
  * that are in the same position as 0's in "mask" are preserved, regardless 
  * of their respective state in "value".
  */
 static int 
-ov511_reg_write_mask(struct usb_device *dev,
-		     unsigned char reg,
-		     unsigned char value,
-		     unsigned char mask)
+reg_w_mask(struct usb_ov511 *ov,
+	   unsigned char reg,
+	   unsigned char value,
+	   unsigned char mask)
 {
 	int ret;
 	unsigned char oldval, newval;
 
-	ret = ov511_reg_read(dev, reg);
+	ret = reg_r(ov, reg);
 	if (ret < 0)
 		return ret;
 
@@ -783,31 +779,30 @@
 	value &= mask;			/* Enforce mask on value */
 	newval = oldval | value;	/* Set the desired bits */
 
-	return (ov511_reg_write(dev, reg, newval));
+	return (reg_w(ov, reg, newval));
 }
 
-/* Writes multiple (n) values to a single register. Only valid with certain
- * registers (0x30 and 0xc4 - 0xce). Used for writing 16 and 24-bit values. */
+/* 
+ * Writes multiple (n) byte value to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce).
+ */
 static int 
-ov518_reg_write_multi(struct usb_device *dev,
-		      unsigned char reg,
-		      unsigned char *values,
-		      int n)
+ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
 {
 	int rc;
 
-	PDEBUG(5, "0x%02X:[multiple], n=%d", reg, n);  // FIXME
+	PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
 
-	if (values == NULL) {
-		err("reg write multiple: NULL buffer");
-		return -EINVAL;
-	}
+	down(&ov->cbuf_lock);
 
-	rc = usb_control_msg(dev,
-			     usb_sndctrlpipe(dev, 0),
+	*((u32 *)ov->cbuf) = __cpu_to_le32(val);
+
+	rc = usb_control_msg(ov->dev,
+			     usb_sndctrlpipe(ov->dev, 0),
 			     2 /* REG_IO */,
 			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, values, n, HZ);	
+			     0, (__u16)reg, ov->cbuf, n, HZ);
+	up(&ov->cbuf_lock);
 
 	if (rc < 0)
 		err("reg write multiple: error %d", rc);
@@ -816,12 +811,12 @@
 }
 
 static int 
-ov511_upload_quan_tables(struct usb_device *dev)
+ov511_upload_quan_tables(struct usb_ov511 *ov)
 {
 	unsigned char *pYTable = yQuanTable511;
 	unsigned char *pUVTable = uvQuanTable511;
 	unsigned char val0, val1;
-	int i, rc, reg = OV511_OMNICE_Y_LUT_BEGIN;
+	int i, rc, reg = R511_COMP_LUT_BEGIN;
 
 	PDEBUG(4, "Uploading quantization tables");
 
@@ -834,7 +829,7 @@
 			val0 &= 0x0f;
 			val1 &= 0x0f;
 			val0 |= val1 << 4;
-			rc = ov511_reg_write(dev, reg, val0);
+			rc = reg_w(ov, reg, val0);
 			if (rc < 0)
 				return rc;
 		}
@@ -846,8 +841,7 @@
 			val0 &= 0x0f;
 			val1 &= 0x0f;
 			val0 |= val1 << 4;
-			rc = ov511_reg_write(dev, reg + OV511_QUANTABLESIZE / 2,
-				val0);
+			rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0);
 			if (rc < 0)
 				return rc;
 		}
@@ -860,12 +854,12 @@
 
 /* OV518 quantization tables are 8x4 (instead of 8x8) */
 static int 
-ov518_upload_quan_tables(struct usb_device *dev)
+ov518_upload_quan_tables(struct usb_ov511 *ov)
 {
 	unsigned char *pYTable = yQuanTable518;
 	unsigned char *pUVTable = uvQuanTable518;
 	unsigned char val0, val1;
-	int i, rc, reg = OV511_OMNICE_Y_LUT_BEGIN;
+	int i, rc, reg = R511_COMP_LUT_BEGIN;
 
 	PDEBUG(4, "Uploading quantization tables");
 
@@ -878,7 +872,7 @@
 			val0 &= 0x0f;
 			val1 &= 0x0f;
 			val0 |= val1 << 4;
-			rc = ov511_reg_write(dev, reg, val0);
+			rc = reg_w(ov, reg, val0);
 			if (rc < 0)
 				return rc;
 		}
@@ -890,8 +884,7 @@
 			val0 &= 0x0f;
 			val1 &= 0x0f;
 			val0 |= val1 << 4;
-			rc = ov511_reg_write(dev, reg + OV518_QUANTABLESIZE / 2,
-				val0);
+			rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0);
 			if (rc < 0)
 				return rc;
 		}
@@ -902,13 +895,39 @@
 	return 0;
 }
 
+static int 
+ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type)
+{
+	int rc;
+		
+	/* Setting bit 0 not allowed on 518/518Plus */
+	if (ov->bclass == BCL_OV518)
+		reset_type &= 0xfe;
+
+	PDEBUG(4, "Reset: type=0x%X", reset_type);
+
+	rc = reg_w(ov, R51x_SYS_RESET, reset_type);
+	rc = reg_w(ov, R51x_SYS_RESET, 0);
+
+	if (rc < 0)
+		err("reset: command failed");
+
+	return rc;
+}
+
+/**********************************************************************
+ *
+ * I2C (sensor) I/O
+ *
+ **********************************************************************/
+
 /* NOTE: Do not call this function directly!
  * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from ov51x_i2c_write(). Note that this function
+ * This is normally only called from i2c_w(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
 static int 
-ov518_i2c_write_internal(struct usb_device *dev,
+ov518_i2c_write_internal(struct usb_ov511 *ov,
 			 unsigned char reg,
 			 unsigned char value)
 {
@@ -917,15 +936,15 @@
 	PDEBUG(5, "0x%02X:0x%02X", reg, value);
 
 	/* Select camera register */
-	rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
+	rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
 	if (rc < 0) goto error;
 
 	/* Write "value" to I2C data port of OV511 */
-	rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);
+	rc = reg_w(ov, R51x_I2C_DATA, value);
 	if (rc < 0) goto error;
 
 	/* Initiate 3-byte write cycle */
-	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x01);
+	rc = reg_w(ov, R518_I2C_CTL, 0x01);
 	if (rc < 0) goto error;
 
 	return 0;
@@ -937,7 +956,7 @@
 
 /* NOTE: Do not call this function directly! */
 static int 
-ov511_i2c_write_internal(struct usb_device *dev,
+ov511_i2c_write_internal(struct usb_ov511 *ov,
 			 unsigned char reg,
 			 unsigned char value)
 {
@@ -948,19 +967,18 @@
 	/* Three byte write cycle */
 	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Select camera register */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE,
-				     reg);
+		rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
 		if (rc < 0) goto error;
 
 		/* Write "value" to I2C data port of OV511 */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);	
+		rc = reg_w(ov, R51x_I2C_DATA, value);	
 		if (rc < 0) goto error;
 
 		/* Initiate 3-byte write cycle */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);
+		rc = reg_w(ov, R511_I2C_CTL, 0x01);
 		if (rc < 0) goto error;
 
-		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+		do rc = reg_r(ov, R511_I2C_CTL);
 		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
@@ -968,7 +986,7 @@
 			break;
 #if 0
 		/* I2C abort */	
-		ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+		reg_w(ov, R511_I2C_CTL, 0x10);
 #endif
 		if (--retries < 0) {
 			err("i2c write retries exhausted");
@@ -986,27 +1004,27 @@
 
 /* NOTE: Do not call this function directly!
  * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from ov51x_i2c_read(). Note that this function
+ * This is normally only called from i2c_r(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
 static int 
-ov518_i2c_read_internal(struct usb_device *dev, unsigned char reg)
+ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
 {
 	int rc, value;
 
 	/* Select camera register */
-	rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
+	rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
 	if (rc < 0) goto error;
 
 	/* Initiate 2-byte write cycle */
-	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x03);
+	rc = reg_w(ov, R518_I2C_CTL, 0x03);
 	if (rc < 0) goto error;
 
 	/* Initiate 2-byte read cycle */
-	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x05);
+	rc = reg_w(ov, R518_I2C_CTL, 0x05);
 	if (rc < 0) goto error;
 
-	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+	value = reg_r(ov, R51x_I2C_DATA);
 
 	PDEBUG(5, "0x%02X:0x%02X", reg, value);
 
@@ -1020,22 +1038,21 @@
 /* NOTE: Do not call this function directly!
  * returns: negative is error, pos or zero is data */
 static int 
-ov511_i2c_read_internal(struct usb_device *dev, unsigned char reg)
+ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
 {
 	int rc, value, retries;
 
 	/* Two byte write cycle */
 	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Select camera register */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE,
-				     reg);
+		rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
 		if (rc < 0) goto error;
 
 		/* Initiate 2-byte write cycle */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);
+		rc = reg_w(ov, R511_I2C_CTL, 0x03);
 		if (rc < 0) goto error;
 
-		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+		do rc = reg_r(ov, R511_I2C_CTL);
 		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
@@ -1043,7 +1060,7 @@
 			break;
 
 		/* I2C abort */	
-		ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+		reg_w(ov, R511_I2C_CTL, 0x10);
 
 		if (--retries < 0) {
 			err("i2c write retries exhausted");
@@ -1055,10 +1072,10 @@
 	/* Two byte read cycle */
 	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Initiate 2-byte read cycle */
-		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
+		rc = reg_w(ov, R511_I2C_CTL, 0x05);
 		if (rc < 0) goto error;
 
-		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
+		do rc = reg_r(ov, R511_I2C_CTL);
 		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
@@ -1066,7 +1083,7 @@
 			break;
 
 		/* I2C abort */	
-		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
+		rc = reg_w(ov, R511_I2C_CTL, 0x10);
 		if (rc < 0) goto error;
 
 		if (--retries < 0) {
@@ -1076,12 +1093,12 @@
 		}
 	}
 
-	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+	value = reg_r(ov, R51x_I2C_DATA);
 
 	PDEBUG(5, "0x%02X:0x%02X", reg, value);
 		
-	/* This is needed to make ov51x_i2c_write() work */
-	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
+	/* This is needed to make i2c_w() work */
+	rc = reg_w(ov, R511_I2C_CTL, 0x05);
 	if (rc < 0)
 		goto error;
 	
@@ -1094,48 +1111,42 @@
 
 /* returns: negative is error, pos or zero is data */
 static int 
-ov51x_i2c_read(struct usb_ov511 *ov511, unsigned char reg)
+i2c_r(struct usb_ov511 *ov, unsigned char reg)
 {
 	int rc;
-	struct usb_device *dev = ov511->dev;
 
-	down(&ov511->i2c_lock);
+	down(&ov->i2c_lock);
 
-	if (dev->descriptor.idProduct == PROD_OV518 ||
-	    dev->descriptor.idProduct == PROD_OV518PLUS)
-		rc = ov518_i2c_read_internal(dev, reg);
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_read_internal(ov, reg);
 	else
-		rc = ov511_i2c_read_internal(dev, reg);
+		rc = ov511_i2c_read_internal(ov, reg);
 
-	up(&ov511->i2c_lock);
+	up(&ov->i2c_lock);
 
 	return rc;
 }
 
 static int 
-ov51x_i2c_write(struct usb_ov511 *ov511,
-		unsigned char reg,
-		unsigned char value)
+i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
 {
 	int rc;
-	struct usb_device *dev = ov511->dev;
 
-	down(&ov511->i2c_lock);
+	down(&ov->i2c_lock);
 
-	if (dev->descriptor.idProduct == PROD_OV518 ||
-	    dev->descriptor.idProduct == PROD_OV518PLUS)
-		rc = ov518_i2c_write_internal(dev, reg, value);
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_write_internal(ov, reg, value);
 	else
-		rc = ov511_i2c_write_internal(dev, reg, value);
+		rc = ov511_i2c_write_internal(ov, reg, value);
 
-	up(&ov511->i2c_lock);
+	up(&ov->i2c_lock);
 
 	return rc;
 }
 
 /* Do not call this function directly! */
 static int 
-ov51x_i2c_write_mask_internal(struct usb_device *dev,
+ov51x_i2c_write_mask_internal(struct usb_ov511 *ov,
 			      unsigned char reg,
 			      unsigned char value,
 			      unsigned char mask)
@@ -1146,11 +1157,10 @@
 	if (mask == 0xff) {
 		newval = value;
 	} else {
-		if (dev->descriptor.idProduct == PROD_OV518 ||
-		    dev->descriptor.idProduct == PROD_OV518PLUS)
-			rc = ov518_i2c_read_internal(dev, reg);
+		if (ov->bclass == BCL_OV518)
+			rc = ov518_i2c_read_internal(ov, reg);
 		else
-			rc = ov511_i2c_read_internal(dev, reg);
+			rc = ov511_i2c_read_internal(ov, reg);
 		if (rc < 0)
 			return rc;
 
@@ -1160,11 +1170,10 @@
 		newval = oldval | value;	/* Set the desired bits */
 	}
 
-	if (dev->descriptor.idProduct == PROD_OV518 ||
-	    dev->descriptor.idProduct == PROD_OV518PLUS)
-		return (ov518_i2c_write_internal(dev, reg, newval));
+	if (ov->bclass == BCL_OV518)
+		return (ov518_i2c_write_internal(ov, reg, newval));
 	else
-		return (ov511_i2c_write_internal(dev, reg, newval));
+		return (ov511_i2c_write_internal(ov, reg, newval));
 }
 
 /* Writes bits at positions specified by mask to an I2C reg. Bits that are in
@@ -1173,126 +1182,138 @@
  * of their respective state in "value".
  */
 static int 
-ov51x_i2c_write_mask(struct usb_ov511 *ov511,
-		     unsigned char reg,
-		     unsigned char value,
-		     unsigned char mask)
+i2c_w_mask(struct usb_ov511 *ov,
+	   unsigned char reg,
+	   unsigned char value,
+	   unsigned char mask)
 {
 	int rc;
-	struct usb_device *dev = ov511->dev;
 
-	down(&ov511->i2c_lock);
-	rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);
-	up(&ov511->i2c_lock);
+	down(&ov->i2c_lock);
+	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
+	up(&ov->i2c_lock);
 
 	return rc;
 }
 
 /* Write to a specific I2C slave ID and register, using the specified mask */
 static int 
-ov51x_i2c_write_slave(struct usb_ov511 *ov511,
-		      unsigned char slave,
-		      unsigned char reg,
-		      unsigned char value,
-		      unsigned char mask)
+i2c_w_slave(struct usb_ov511 *ov,
+	    unsigned char slave,
+	    unsigned char reg,
+	    unsigned char value,
+	    unsigned char mask)
 {
 	int rc = 0;
-	struct usb_device *dev = ov511->dev;
 
-	down(&ov511->i2c_lock);
+	down(&ov->i2c_lock);
 
 	/* Set new slave IDs */
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);
+	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
 	/* Don't bail out yet if error; IDs must be restored */
 
 	/* Restore primary IDs */
-	slave = ov511->primary_i2c_slave;
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+	slave = ov->primary_i2c_slave;
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
 out:
-	up(&ov511->i2c_lock);
+	up(&ov->i2c_lock);
 	return rc;
 }
 
 /* Read from a specific I2C slave ID and register */
 static int 
-ov51x_i2c_read_slave(struct usb_ov511 *ov511,
-		     unsigned char slave,
-		     unsigned char reg)
+i2c_r_slave(struct usb_ov511 *ov,
+	    unsigned char slave,
+	    unsigned char reg)
 {
 	int rc;
-	struct usb_device *dev = ov511->dev;
 
-	down(&ov511->i2c_lock);
+	down(&ov->i2c_lock);
 
 	/* Set new slave IDs */
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (dev->descriptor.idProduct == PROD_OV518 ||
-	    dev->descriptor.idProduct == PROD_OV518PLUS)
-		rc = ov518_i2c_read_internal(dev, reg);
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_read_internal(ov, reg);
 	else
-		rc = ov511_i2c_read_internal(dev, reg);
+		rc = ov511_i2c_read_internal(ov, reg);
 	/* Don't bail out yet if error; IDs must be restored */
 
 	/* Restore primary IDs */
-	slave = ov511->primary_i2c_slave;
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {
+	slave = ov->primary_i2c_slave;
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
 		rc = -EIO;
 		goto out;
 	}
 
 out:
-	up(&ov511->i2c_lock);
+	up(&ov->i2c_lock);
 	return rc;
 }
 
+/* Sets I2C read and write slave IDs. Returns <0 for error */
+static int 
+ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid)
+{
+	down(&ov->i2c_lock);
+
+	if (reg_w(ov, R51x_I2C_W_SID, sid) < 0)
+		return -EIO;
+
+	if (reg_w(ov, R51x_I2C_R_SID, sid + 1) < 0)
+		return -EIO;
+
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
+		return -EIO;
+
+	up(&ov->i2c_lock);
+
+	return 0;
+}
+
 static int 
-ov511_write_regvals(struct usb_ov511 *ov511,
-		    struct ov511_regvals * pRegvals)
+write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
 {
 	int rc;
-	struct usb_device *dev = ov511->dev;
 
 	while (pRegvals->bus != OV511_DONE_BUS) {
 		if (pRegvals->bus == OV511_REG_BUS) {
-			if ((rc = ov511_reg_write(dev, pRegvals->reg,
-			                          pRegvals->val)) < 0)
+			if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)
 				goto error;
 		} else if (pRegvals->bus == OV511_I2C_BUS) {
-			if ((rc = ov51x_i2c_write(ov511, pRegvals->reg, 
-			                          pRegvals->val)) < 0)
+			if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)
 				goto error;
 		} else {
 			err("Bad regval array");
@@ -1310,57 +1331,60 @@
 
 #ifdef OV511_DEBUG 
 static void 
-ov511_dump_i2c_range(struct usb_ov511 *ov511, int reg1, int regn)
+dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
 {
 	int i;
 	int rc;
+
 	for (i = reg1; i <= regn; i++) {
-		rc = ov51x_i2c_read(ov511, i);
+		rc = i2c_r(ov, i);
 		info("OV7610[0x%X] = 0x%X", i, rc);
 	}
 }
 
 static void 
-ov51x_dump_i2c_regs(struct usb_ov511 *ov511)
+dump_i2c_regs(struct usb_ov511 *ov)
 {
 	info("I2C REGS");
-	ov511_dump_i2c_range(ov511, 0x00, 0x7C);
+	dump_i2c_range(ov, 0x00, 0x7C);
 }
 
 static void 
-ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
+dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
 {
 	int i;
 	int rc;
+
 	for (i = reg1; i <= regn; i++) {
-	  rc = ov511_reg_read(dev, i);
-	  info("OV511[0x%X] = 0x%X", i, rc);
+		rc = reg_r(ov, i);
+		info("OV511[0x%X] = 0x%X", i, rc);
 	}
 }
 
+/* FIXME: Should there be an OV518 version of this? */
 static void 
-ov511_dump_regs(struct usb_device *dev)
+ov511_dump_regs(struct usb_ov511 *ov)
 {
 	info("CAMERA INTERFACE REGS");
-	ov511_dump_reg_range(dev, 0x10, 0x1f);
+	dump_reg_range(ov, 0x10, 0x1f);
 	info("DRAM INTERFACE REGS");
-	ov511_dump_reg_range(dev, 0x20, 0x23);
+	dump_reg_range(ov, 0x20, 0x23);
 	info("ISO FIFO REGS");
-	ov511_dump_reg_range(dev, 0x30, 0x31);
+	dump_reg_range(ov, 0x30, 0x31);
 	info("PIO REGS");
-	ov511_dump_reg_range(dev, 0x38, 0x39);
-	ov511_dump_reg_range(dev, 0x3e, 0x3e);
+	dump_reg_range(ov, 0x38, 0x39);
+	dump_reg_range(ov, 0x3e, 0x3e);
 	info("I2C REGS");
-	ov511_dump_reg_range(dev, 0x40, 0x49);
+	dump_reg_range(ov, 0x40, 0x49);
 	info("SYSTEM CONTROL REGS");
-	ov511_dump_reg_range(dev, 0x50, 0x55);
-	ov511_dump_reg_range(dev, 0x5e, 0x5f);
+	dump_reg_range(ov, 0x50, 0x55);
+	dump_reg_range(ov, 0x5e, 0x5f);
 	info("OmniCE REGS");
-	ov511_dump_reg_range(dev, 0x70, 0x79);
+	dump_reg_range(ov, 0x70, 0x79);
 	/* NOTE: Quantization tables are not readable. You will get the value
 	 * in reg. 0x79 for every table register */
-	ov511_dump_reg_range(dev, 0x80, 0x9f);
-	ov511_dump_reg_range(dev, 0xa0, 0xbf);
+	dump_reg_range(ov, 0x80, 0x9f);
+	dump_reg_range(ov, 0xa0, 0xbf);
 
 }
 #endif
@@ -1373,7 +1397,7 @@
 
 /* For as-yet unimplemented I2C interface */
 static void 
-call_i2c_clients(struct usb_ov511 *ov511, unsigned int cmd,
+call_i2c_clients(struct usb_ov511 *ov, unsigned int cmd,
 		 void *arg)
 {
 	/* Do nothing */
@@ -1381,59 +1405,33 @@
 
 /*****************************************************************************/
 
-static int 
-ov511_reset(struct usb_ov511 *ov511, unsigned char reset_type)
-{
-	int rc;
-		
-	/* Setting bit 0 not allowed on 518/518Plus */
-	if (ov511->bridge == BRG_OV518 ||
-	    ov511->bridge == BRG_OV518PLUS)
-		reset_type &= 0xfe;
-
-	PDEBUG(4, "Reset: type=0x%X", reset_type);
-
-	rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, reset_type);
-	rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0);
-
-	if (rc < 0)
-		err("reset: command failed");
-
-	return rc;
-}
-
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
 static inline int 
-ov511_stop(struct usb_ov511 *ov511)
+ov51x_stop(struct usb_ov511 *ov)
 {
 	PDEBUG(4, "stopping");
-	ov511->stopped = 1;	
-	if (ov511->bridge == BRG_OV518 ||
-	    ov511->bridge == BRG_OV518PLUS)
-		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
-					0x3a));
+	ov->stopped = 1;	
+	if (ov->bclass == BCL_OV518)
+		return (reg_w(ov, R51x_SYS_RESET, 0x3a));
 	else
-		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
-					0x3d));
+		return (reg_w(ov, R51x_SYS_RESET, 0x3d));
 }
 
 /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
  * actually stopped (for performance). */
 static inline int 
-ov511_restart(struct usb_ov511 *ov511)
+ov51x_restart(struct usb_ov511 *ov)
 {
-	if (ov511->stopped) {
+	if (ov->stopped) {
 		PDEBUG(4, "restarting");
-		ov511->stopped = 0;	
+		ov->stopped = 0;	
 
 		/* Reinitialize the stream */
-		if (ov511->bridge == BRG_OV518 ||
-		    ov511->bridge == BRG_OV518PLUS)
-			ov511_reg_write(ov511->dev, 0x2f, 0x80);
+		if (ov->bclass == BCL_OV518)
+			reg_w(ov, 0x2f, 0x80);
 
-		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,
-					0x00));
+		return (reg_w(ov, R51x_SYS_RESET, 0x00));
 	}
 
 	return 0;
@@ -1441,14 +1439,13 @@
 
 /* Resets the hardware snapshot button */
 static void 
-ov51x_clear_snapshot(struct usb_ov511 *ov511)
+ov51x_clear_snapshot(struct usb_ov511 *ov)
 {
-	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
-		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
-		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
-		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
-	} else if (ov511->bridge == BRG_OV518 ||
-		   ov511->bridge == BRG_OV518PLUS) {
+	if (ov->bclass == BCL_OV511) {
+		reg_w(ov, R51x_SYS_SNAP, 0x01);
+		reg_w(ov, R51x_SYS_SNAP, 0x03);
+		reg_w(ov, R51x_SYS_SNAP, 0x01);
+	} else if (ov->bclass == BCL_OV518) {
 		warn("snapshot reset not supported yet on OV518(+)");
 	} else {
 		err("clear snap: invalid bridge type");
@@ -1459,19 +1456,18 @@
 /* Checks the status of the snapshot button. Returns 1 if it was pressed since
  * it was last cleared, and zero in all other cases (including errors) */
 static int 
-ov51x_check_snapshot(struct usb_ov511 *ov511)
+ov51x_check_snapshot(struct usb_ov511 *ov)
 {
 	int ret, status = 0;
 
-	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
-		ret = ov511_reg_read(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT);
+	if (ov->bclass == BCL_OV511) {
+		ret = reg_r(ov, R51x_SYS_SNAP);
 		if (ret < 0) {
 			err("Error checking snspshot status (%d)", ret);
 		} else if (ret & 0x08) {
 			status = 1;
 		}
-	} else if (ov511->bridge == BRG_OV518 ||
-		   ov511->bridge == BRG_OV518PLUS) {
+	} else if (ov->bclass == BCL_OV518) {
 		warn("snapshot check not supported yet on OV518(+)");
 	} else {
 		err("check snap: invalid bridge type");
@@ -1480,53 +1476,33 @@
 	return status;
 }
 
-/* Sets I2C read and write slave IDs. Returns <0 for error */
-static int 
-ov51x_set_slave_ids(struct usb_ov511 *ov511,
-		    unsigned char write_id,
-		    unsigned char read_id)
-{
-	struct usb_device *dev = ov511->dev;
-
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, write_id) < 0)
-		return -EIO;
-
-	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, read_id) < 0)
-		return -EIO;
-
-	if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
-		return -EIO;
-
-	return 0;
-}
-
 /* This does an initial reset of an OmniVision sensor and ensures that I2C
  * is synchronized. Returns <0 for failure.
  */
 static int 
-ov51x_init_ov_sensor(struct usb_ov511 *ov511)
+init_ov_sensor(struct usb_ov511 *ov)
 {
 	int i, success;
 
 	/* Reset the sensor */ 
-	if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -EIO;
+	if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
 
 	/* Wait for it to initialize */ 
 	schedule_timeout (1 + 150 * HZ / 1000);
 
 	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
-		if ((ov51x_i2c_read(ov511, OV7610_REG_ID_HIGH) == 0x7F) &&
-		    (ov51x_i2c_read(ov511, OV7610_REG_ID_LOW) == 0xA2)) {
+		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
+		    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
 			success = 1;
 			continue;
 		}
 
 		/* Reset the sensor */ 
-		if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -EIO;
+		if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
 		/* Wait for it to initialize */ 
 		schedule_timeout(1 + 150 * HZ / 1000);
 		/* Dummy read to sync I2C */
-		if (ov51x_i2c_read(ov511, 0x00) < 0) return -EIO;
+		if (i2c_r(ov, 0x00) < 0) return -EIO;
 	}
 
 	if (!success)
@@ -1538,16 +1514,16 @@
 }
 
 static int 
-ov511_set_packet_size(struct usb_ov511 *ov511, int size)
+ov51x_set_packet_size(struct usb_ov511 *ov, int size)
 {
 	int alt, mult;
 
-	if (ov511_stop(ov511) < 0)
+	if (ov51x_stop(ov) < 0)
 		return -EIO;
 
 	mult = size >> 5;
 
-	if (ov511->bridge == BRG_OV511) {
+	if (ov->bridge == BRG_OV511) {
 		if (size == 0) alt = OV511_ALT_SIZE_0;
 		else if (size == 257) alt = OV511_ALT_SIZE_257;
 		else if (size == 513) alt = OV511_ALT_SIZE_513;
@@ -1557,7 +1533,7 @@
 			err("Set packet size: invalid size (%d)", size);
 			return -EINVAL;
 		}
-	} else if (ov511->bridge == BRG_OV511PLUS) {
+	} else if (ov->bridge == BRG_OV511PLUS) {
 		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
 		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
 		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
@@ -1570,8 +1546,7 @@
 			err("Set packet size: invalid size (%d)", size);
 			return -EINVAL;
 		}
-	} else if (ov511->bridge == BRG_OV518 ||
-		   ov511->bridge == BRG_OV518PLUS) {
+	} else if (ov->bclass == BCL_OV518) {
 		if (size == 0) alt = OV518_ALT_SIZE_0;
 		else if (size == 128) alt = OV518_ALT_SIZE_128;
 		else if (size == 256) alt = OV518_ALT_SIZE_256;
@@ -1592,32 +1567,30 @@
 	PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
 
 	// FIXME: Don't know how to do this on OV518 yet
-	if (ov511->bridge != BRG_OV518 &&
-	    ov511->bridge != BRG_OV518PLUS) {
-		if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
+	if (ov->bclass == BCL_OV511) {
+		if (reg_w(ov, R51x_FIFO_PSIZE,
 				    mult) < 0) {
 			return -EIO;
 		}
 	}
 	
-	if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
+	if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
 		err("Set packet size: set interface error");
 		return -EBUSY;
 	}
 
 	/* Initialize the stream */
-	if (ov511->bridge == BRG_OV518 ||
-	    ov511->bridge == BRG_OV518PLUS)
-		if (ov511_reg_write(ov511->dev, 0x2f, 0x80) < 0)
+	if (ov->bclass == BCL_OV518)
+		if (reg_w(ov, 0x2f, 0x80) < 0)
 			return -EIO;
 
 	// FIXME - Should we only reset the FIFO?
-	if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
 		return -EIO;
 
-	ov511->packet_size = size;
+	ov->packet_size = size;
 
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return 0;
@@ -1625,51 +1598,49 @@
 
 /* Upload compression params and quantization tables. Returns 0 for success. */
 static int
-ov511_init_compression(struct usb_ov511 *ov511)
+ov511_init_compression(struct usb_ov511 *ov)
 {
-	struct usb_device *dev = ov511->dev;
 	int rc = 0;
 
-	if (!ov511->compress_inited) {
+	if (!ov->compress_inited) {
 
-		ov511_reg_write(dev, 0x70, phy);
-		ov511_reg_write(dev, 0x71, phuv);
-		ov511_reg_write(dev, 0x72, pvy);
-		ov511_reg_write(dev, 0x73, pvuv);
-		ov511_reg_write(dev, 0x74, qhy);
-		ov511_reg_write(dev, 0x75, qhuv);
-		ov511_reg_write(dev, 0x76, qvy);
-		ov511_reg_write(dev, 0x77, qvuv);
+		reg_w(ov, 0x70, phy);
+		reg_w(ov, 0x71, phuv);
+		reg_w(ov, 0x72, pvy);
+		reg_w(ov, 0x73, pvuv);
+		reg_w(ov, 0x74, qhy);
+		reg_w(ov, 0x75, qhuv);
+		reg_w(ov, 0x76, qvy);
+		reg_w(ov, 0x77, qvuv);
 
-		if (ov511_upload_quan_tables(dev) < 0) {
+		if (ov511_upload_quan_tables(ov) < 0) {
 			err("Error uploading quantization tables");
 			rc = -EIO;
 			goto out;
 		}
 	}
 
-	ov511->compress_inited = 1;
+	ov->compress_inited = 1;
 out:	
 	return rc;
 }
 
 /* Upload compression params and quantization tables. Returns 0 for success. */
 static int
-ov518_init_compression(struct usb_ov511 *ov511)
+ov518_init_compression(struct usb_ov511 *ov)
 {
-	struct usb_device *dev = ov511->dev;
 	int rc = 0;
 
-	if (!ov511->compress_inited) {
+	if (!ov->compress_inited) {
 
-		if (ov518_upload_quan_tables(dev) < 0) {
+		if (ov518_upload_quan_tables(ov) < 0) {
 			err("Error uploading quantization tables");
 			rc = -EIO;
 			goto out;
 		}
 	}
 
-	ov511->compress_inited = 1;
+	ov->compress_inited = 1;
 out:	
 	return rc;
 }
@@ -1678,22 +1649,22 @@
 
 /* Sets sensor's contrast setting to "val" */
 static int
-sensor_set_contrast(struct usb_ov511 *ov511, unsigned short val)
+sensor_set_contrast(struct usb_ov511 *ov, unsigned short val)
 {
 	int rc;
 
 	PDEBUG(3, "%d", val);
 
-	if (ov511->stop_during_set)
-		if (ov511_stop(ov511) < 0)
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
 			return -EIO;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV6620:
 	case SEN_OV6630:
 	{
-		rc = ov51x_i2c_write(ov511, OV7610_REG_CNT, val >> 8);
+		rc = i2c_w(ov, OV7610_REG_CNT, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
@@ -1706,14 +1677,14 @@
 		};
 
 		/* Use Y gamma control instead. Bit 0 enables it. */
-		rc = ov51x_i2c_write(ov511, 0x64, ctab[val>>12]);
+		rc = i2c_w(ov, 0x64, ctab[val>>12]);
 		if (rc < 0)
 			goto out;
 		break;
 	}
 	case SEN_SAA7111A:
 	{
-		rc = ov51x_i2c_write(ov511, 0x0b, val >> 9);
+		rc = i2c_w(ov, 0x0b, val >> 9);
 		if (rc < 0)
 			goto out;
 		break;
@@ -1727,9 +1698,9 @@
 	}
 
 	rc = 0;		/* Success */
-	ov511->contrast = val;
+	ov->contrast = val;
 out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -1737,15 +1708,15 @@
 
 /* Gets sensor's contrast setting */
 static int
-sensor_get_contrast(struct usb_ov511 *ov511, unsigned short *val)
+sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val)
 {
 	int rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_read(ov511, OV7610_REG_CNT);
+		rc = i2c_r(ov, OV7610_REG_CNT);
 		if (rc < 0)
 			return rc;
 		else
@@ -1753,14 +1724,14 @@
 		break;
 	case SEN_OV7620:
 		/* Use Y gamma reg instead. Bit 0 is the enable bit. */
-		rc = ov51x_i2c_read(ov511, 0x64);
+		rc = i2c_r(ov, 0x64);
 		if (rc < 0)
 			return rc;
 		else
 			*val = (rc & 0xfe) << 8;
 		break;
 	case SEN_SAA7111A:
-		*val = ov511->contrast;
+		*val = ov->contrast;
 		break;
 	default:
 		PDEBUG(3, "Unsupported with this sensor");
@@ -1768,7 +1739,7 @@
 	}
 
 	PDEBUG(3, "%d", *val);
-	ov511->contrast = *val;
+	ov->contrast = *val;
 
 	return 0;
 }
@@ -1777,35 +1748,35 @@
 
 /* Sets sensor's brightness setting to "val" */
 static int
-sensor_set_brightness(struct usb_ov511 *ov511, unsigned short val)
+sensor_set_brightness(struct usb_ov511 *ov, unsigned short val)
 {
 	int rc;
 
 	PDEBUG(4, "%d", val);
 
-	if (ov511->stop_during_set)
-		if (ov511_stop(ov511) < 0)
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
 			return -EIO;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620AE:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_write(ov511, OV7610_REG_BRT, val >> 8);
+		rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
 	case SEN_OV7620:
 		/* 7620 doesn't like manual changes when in auto mode */
-		if (!ov511->auto_brt) {
-			rc = ov51x_i2c_write(ov511, OV7610_REG_BRT, val >> 8);
+		if (!ov->auto_brt) {
+			rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
 			if (rc < 0)
 				goto out;
 		}
 		break;
 	case SEN_SAA7111A:
-		rc = ov51x_i2c_write(ov511, 0x0a, val >> 8);
+		rc = i2c_w(ov, 0x0a, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
@@ -1816,9 +1787,9 @@
 	}
 
 	rc = 0;		/* Success */
-	ov511->brightness = val;
+	ov->brightness = val;
 out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -1826,24 +1797,24 @@
 
 /* Gets sensor's brightness setting */
 static int
-sensor_get_brightness(struct usb_ov511 *ov511, unsigned short *val)
+sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val)
 {
 	int rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620AE:
 	case SEN_OV7620:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_read(ov511, OV7610_REG_BRT);
+		rc = i2c_r(ov, OV7610_REG_BRT);
 		if (rc < 0)
 			return rc;
 		else
 			*val = rc << 8;
 		break;
 	case SEN_SAA7111A:
-		*val = ov511->brightness;
+		*val = ov->brightness;
 		break;
 	default:
 		PDEBUG(3, "Unsupported with this sensor");
@@ -1851,7 +1822,7 @@
 	}
 
 	PDEBUG(3, "%d", *val);
-	ov511->brightness = *val;
+	ov->brightness = *val;
 
 	return 0;
 }
@@ -1860,36 +1831,36 @@
 
 /* Sets sensor's saturation (color intensity) setting to "val" */
 static int
-sensor_set_saturation(struct usb_ov511 *ov511, unsigned short val)
+sensor_set_saturation(struct usb_ov511 *ov, unsigned short val)
 {
 	int rc;
 
 	PDEBUG(3, "%d", val);
 
-	if (ov511->stop_during_set)
-		if (ov511_stop(ov511) < 0)
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
 			return -EIO;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620AE:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_write(ov511, OV7610_REG_SAT, val >> 8);
+		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
 	case SEN_OV7620:
 //		/* Use UV gamma control instead. Bits 0 & 7 are reserved. */
-//		rc = ov511_i2c_write(ov511->dev, 0x62, (val >> 9) & 0x7e);
+//		rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e);
 //		if (rc < 0)
 //			goto out;
-		rc = ov51x_i2c_write(ov511, OV7610_REG_SAT, val >> 8);
+		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
 	case SEN_SAA7111A:
-		rc = ov51x_i2c_write(ov511, 0x0c, val >> 9);
+		rc = i2c_w(ov, 0x0c, val >> 9);
 		if (rc < 0)
 			goto out;
 		break;
@@ -1900,9 +1871,9 @@
 	}
 
 	rc = 0;		/* Success */
-	ov511->colour = val;
+	ov->colour = val;
 out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -1910,16 +1881,16 @@
 
 /* Gets sensor's saturation (color intensity) setting */
 static int
-sensor_get_saturation(struct usb_ov511 *ov511, unsigned short *val)
+sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val)
 {
 	int rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620AE:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_read(ov511, OV7610_REG_SAT);
+		rc = i2c_r(ov, OV7610_REG_SAT);
 		if (rc < 0)
 			return rc;
 		else
@@ -1927,19 +1898,19 @@
 		break;
 	case SEN_OV7620:
 //		/* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
-//		rc = ov51x_i2c_read(ov511, 0x62);
+//		rc = i2c_r(ov, 0x62);
 //		if (rc < 0)
 //			return rc;
 //		else
 //			*val = (rc & 0x7e) << 9;
-		rc = ov51x_i2c_read(ov511, OV7610_REG_SAT);
+		rc = i2c_r(ov, OV7610_REG_SAT);
 		if (rc < 0)
 			return rc;
 		else
 			*val = rc << 8;
 		break;
 	case SEN_SAA7111A:
-		*val = ov511->colour;
+		*val = ov->colour;
 		break;
 	default:
 		PDEBUG(3, "Unsupported with this sensor");
@@ -1947,7 +1918,7 @@
 	}
 
 	PDEBUG(3, "%d", *val);
-	ov511->colour = *val;
+	ov->colour = *val;
 
 	return 0;
 }
@@ -1956,44 +1927,42 @@
 
 /* Sets sensor's hue (red/blue balance) setting to "val" */
 static int
-sensor_set_hue(struct usb_ov511 *ov511, unsigned short val)
+sensor_set_hue(struct usb_ov511 *ov, unsigned short val)
 {
 	int rc;
 
 	PDEBUG(3, "%d", val);
 
-	if (ov511->stop_during_set)
-		if (ov511_stop(ov511) < 0)
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
 			return -EIO;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_write(ov511, OV7610_REG_RED, 0xFF - (val >> 8));
+		rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8));
 		if (rc < 0)
 			goto out;
 
-		rc = ov51x_i2c_write(ov511, OV7610_REG_BLUE, val >> 8);
+		rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8);
 		if (rc < 0)
 			goto out;
 		break;
 	case SEN_OV7620:
 // Hue control is causing problems. I will enable it once it's fixed.
 #if 0
-		rc = ov51x_i2c_write(ov511, 0x7a,
-				     (unsigned char)(val >> 8) + 0xb);
+		rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb);
 		if (rc < 0)
 			goto out;
 
-		rc = ov51x_i2c_write(ov511, 0x79, 
-				     (unsigned char)(val >> 8) + 0xb);
+		rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb);
 		if (rc < 0)
 			goto out;
 #endif
 		break;
 	case SEN_SAA7111A:
-		rc = ov51x_i2c_write(ov511, 0x0d, (val + 32768) >> 8);
+		rc = i2c_w(ov, 0x0d, (val + 32768) >> 8);
 		if (rc < 0)
 			goto out;
 		break;
@@ -2004,9 +1973,9 @@
 	}
 
 	rc = 0;		/* Success */
-	ov511->hue = val;
+	ov->hue = val;
 out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -2014,29 +1983,29 @@
 
 /* Gets sensor's hue (red/blue balance) setting */
 static int
-sensor_get_hue(struct usb_ov511 *ov511, unsigned short *val)
+sensor_get_hue(struct usb_ov511 *ov, unsigned short *val)
 {
 	int rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = ov51x_i2c_read(ov511, OV7610_REG_BLUE);
+		rc = i2c_r(ov, OV7610_REG_BLUE);
 		if (rc < 0)
 			return rc;
 		else
 			*val = rc << 8;
 		break;
 	case SEN_OV7620:
-		rc = ov51x_i2c_read(ov511, 0x7a);
+		rc = i2c_r(ov, 0x7a);
 		if (rc < 0)
 			return rc;
 		else
 			*val = rc << 8;
 		break;
 	case SEN_SAA7111A:
-		*val = ov511->hue;
+		*val = ov->hue;
 		break;
 	default:
 		PDEBUG(3, "Unsupported with this sensor");
@@ -2044,7 +2013,7 @@
 	}
 
 	PDEBUG(3, "%d", *val);
-	ov511->hue = *val;
+	ov->hue = *val;
 
 	return 0;
 }
@@ -2052,30 +2021,30 @@
 /* -------------------------------------------------------------------------- */
 
 static inline int
-sensor_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
+sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
 
 	PDEBUG(4, "sensor_set_picture");
 
-	ov511->whiteness = p->whiteness;
+	ov->whiteness = p->whiteness;
 
 	/* Don't return error if a setting is unsupported, or rest of settings
          * will not be performed */
 
-	rc = sensor_set_contrast(ov511, p->contrast);
+	rc = sensor_set_contrast(ov, p->contrast);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_set_brightness(ov511, p->brightness);
+	rc = sensor_set_brightness(ov, p->brightness);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_set_saturation(ov511, p->colour);
+	rc = sensor_set_saturation(ov, p->colour);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_set_hue(ov511, p->hue);
+	rc = sensor_set_hue(ov, p->hue);
 	if (FATAL_ERROR(rc))
 		return rc;
 
@@ -2083,7 +2052,7 @@
 }
 
 static inline int
-sensor_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
+sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
 
@@ -2092,27 +2061,27 @@
 	/* Don't return error if a setting is unsupported, or rest of settings
          * will not be performed */
 
-	rc = sensor_get_contrast(ov511, &(p->contrast));
+	rc = sensor_get_contrast(ov, &(p->contrast));
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_get_brightness(ov511, &(p->brightness));
+	rc = sensor_get_brightness(ov, &(p->brightness));
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_get_saturation(ov511, &(p->colour));
+	rc = sensor_get_saturation(ov, &(p->colour));
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_get_hue(ov511, &(p->hue));
+	rc = sensor_get_hue(ov, &(p->hue));
 	if (FATAL_ERROR(rc))
 		return rc;
 
 	p->whiteness = 105 << 8;
 
 	/* Can we get these from frame[0]? -claudio? */
-	p->depth = ov511->frame[0].depth;
-	p->palette = ov511->frame[0].format;
+	p->depth = ov->frame[0].depth;
+	p->palette = ov->frame[0].format;
 
 	return 0;
 }
@@ -2121,24 +2090,24 @@
 /* Sets current exposure for sensor. This only has an effect if auto-exposure
  * is off */
 static inline int
-sensor_set_exposure(struct usb_ov511 *ov511, unsigned char val)
+sensor_set_exposure(struct usb_ov511 *ov, unsigned char val)
 {
 	int rc;
 
 	PDEBUG(3, "%d", val);
 
-	if (ov511->stop_during_set)
-		if (ov511_stop(ov511) < 0)
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
 			return -EIO;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV6620:
 	case SEN_OV6630:
 	case SEN_OV7610:
 	case SEN_OV7620:
 	case SEN_OV7620AE:
 	case SEN_OV8600:
-		rc = ov51x_i2c_write(ov511, 0x10, val);
+		rc = i2c_w(ov, 0x10, val);
 		if (rc < 0)
 			goto out;
 
@@ -2154,9 +2123,9 @@
 	}
 
 	rc = 0;		/* Success */
-	ov511->exposure = val;
+	ov->exposure = val;
 out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -2165,18 +2134,18 @@
 /* Gets current exposure level from sensor, regardless of whether it is under
  * manual control. */
 static int
-sensor_get_exposure(struct usb_ov511 *ov511, unsigned char *val)
+sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
 {
 	int rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV6620:
 	case SEN_OV6630:
 	case SEN_OV7620:
 	case SEN_OV7620AE:
 	case SEN_OV8600:
-		rc = ov51x_i2c_read(ov511, 0x10);
+		rc = i2c_r(ov, 0x10);
 		if (rc < 0)
 			return rc;
 		else
@@ -2194,24 +2163,22 @@
 	}
 
 	PDEBUG(3, "%d", *val);
-	ov511->exposure = *val;
+	ov->exposure = *val;
 
 	return 0;
 }
 
 /* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
 static inline void 
-ov51x_led_control(struct usb_ov511 *ov511, int enable)
+ov51x_led_control(struct usb_ov511 *ov, int enable)
 {
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
 
-	if (ov511->bridge == BRG_OV511PLUS)
-		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_LED_CTL, 
-			        enable ? 1 : 0);
-	else if (ov511->bridge == BRG_OV518 ||
-		 ov511->bridge == BRG_OV518PLUS)
-		ov511_reg_write_mask(ov511->dev, OV518_REG_GPIO_OUT, 
-				     enable ? 0x02 : 0x00, 0x02);
+	if (ov->bridge == BRG_OV511PLUS)
+		reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);
+	else if (ov->bclass == BCL_OV518)
+		reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);
+
 	return;
 }
 
@@ -2225,7 +2192,7 @@
  * Returns: 0 for success
  */
 static int
-sensor_set_light_freq(struct usb_ov511 *ov511, int freq)
+sensor_set_light_freq(struct usb_ov511 *ov, int freq)
 {
 	int sixty;
 
@@ -2240,24 +2207,24 @@
 		return -EINVAL;
 	}
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
-		ov51x_i2c_write_mask(ov511, 0x2a, sixty?0x00:0x80, 0x80);
-		ov51x_i2c_write(ov511, 0x2b, sixty?0x00:0xac);
-		ov51x_i2c_write_mask(ov511, 0x13, 0x10, 0x10);
-		ov51x_i2c_write_mask(ov511, 0x13, 0x00, 0x10);
+		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
+		i2c_w(ov, 0x2b, sixty?0x00:0xac);
+		i2c_w_mask(ov, 0x13, 0x10, 0x10);
+		i2c_w_mask(ov, 0x13, 0x00, 0x10);
 		break;
 	case SEN_OV7620:
 	case SEN_OV7620AE:
 	case SEN_OV8600:
-		ov51x_i2c_write_mask(ov511, 0x2a, sixty?0x00:0x80, 0x80);
-		ov51x_i2c_write(ov511, 0x2b, sixty?0x00:0xac);
-		ov51x_i2c_write_mask(ov511, 0x76, 0x01, 0x01);
+		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
+		i2c_w(ov, 0x2b, sixty?0x00:0xac);
+		i2c_w_mask(ov, 0x76, 0x01, 0x01);
 		break;		
 	case SEN_OV6620:
 	case SEN_OV6630:
-		ov51x_i2c_write(ov511, 0x2b, sixty?0xa8:0x28);
-		ov51x_i2c_write(ov511, 0x2a, sixty?0x84:0xa4);
+		i2c_w(ov, 0x2b, sixty?0xa8:0x28);
+		i2c_w(ov, 0x2a, sixty?0x84:0xa4);
 		break;
 	case SEN_KS0127:
 	case SEN_KS0127B:
@@ -2269,7 +2236,7 @@
 		return -EINVAL;
 	}
 
-	ov511->lightfreq = freq;
+	ov->lightfreq = freq;
 
 	return 0;
 }
@@ -2284,23 +2251,23 @@
  * Returns: 0 for success
  */
 static inline int
-sensor_set_banding_filter(struct usb_ov511 *ov511, int enable)
+sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
 {
 	int rc;
 
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
 
-	if (ov511->sensor == SEN_KS0127 || ov511->sensor == SEN_KS0127B
-		|| ov511->sensor == SEN_SAA7111A) {
+	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
+		|| ov->sensor == SEN_SAA7111A) {
 		PDEBUG(5, "Unsupported with this sensor");
 		return -EPERM;
 	}
 
-	rc = ov51x_i2c_write_mask(ov511, 0x2d, enable?0x04:0x00, 0x04);
+	rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);
 	if (rc < 0)
 		return rc;
 
-	ov511->bandfilt = enable;
+	ov->bandfilt = enable;
 
 	return 0;
 }
@@ -2312,23 +2279,23 @@
  * Returns: 0 for success
  */
 static inline int
-sensor_set_auto_brightness(struct usb_ov511 *ov511, int enable)
+sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
 {
 	int rc;
 
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
 
-	if (ov511->sensor == SEN_KS0127 || ov511->sensor == SEN_KS0127B
-		|| ov511->sensor == SEN_SAA7111A) {
+	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
+		|| ov->sensor == SEN_SAA7111A) {
 		PDEBUG(5, "Unsupported with this sensor");
 		return -EPERM;
 	}
 
-	rc = ov51x_i2c_write_mask(ov511, 0x2d, enable?0x10:0x00, 0x10);
+	rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);
 	if (rc < 0)
 		return rc;
 
-	ov511->auto_brt = enable;
+	ov->auto_brt = enable;
 
 	return 0;
 }
@@ -2340,22 +2307,22 @@
  * Returns: 0 for success
  */
 static inline int
-sensor_set_auto_exposure(struct usb_ov511 *ov511, int enable)
+sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
 {	
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
-		ov51x_i2c_write_mask(ov511, 0x29, enable?0x00:0x80, 0x80);
+		i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);
 		break;
 	case SEN_OV6620:
 	case SEN_OV7620:
 	case SEN_OV7620AE:
 	case SEN_OV8600:
-		ov51x_i2c_write_mask(ov511, 0x13, enable?0x01:0x00, 0x01);
+		i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);
 		break;		
 	case SEN_OV6630:
-		ov51x_i2c_write_mask(ov511, 0x28, enable?0x00:0x10, 0x10);
+		i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);
 		break;
 	case SEN_KS0127:
 	case SEN_KS0127B:
@@ -2367,7 +2334,7 @@
 		return -EINVAL;
 	}
 
-	ov511->auto_exp = enable;
+	ov->auto_exp = enable;
 
 	return 0;
 }
@@ -2380,27 +2347,27 @@
  * Returns: 0 for success
  */
 static int
-sensor_set_backlight(struct usb_ov511 *ov511, int enable)
+sensor_set_backlight(struct usb_ov511 *ov, int enable)
 {
 
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7620:
 	case SEN_OV8600:
-		ov51x_i2c_write_mask(ov511, 0x68, enable?0xe0:0xc0, 0xe0);
-		ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
-		ov51x_i2c_write_mask(ov511, 0x28, enable?0x02:0x00, 0x02);
+		i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
 		break;		
 	case SEN_OV6620:
-		ov51x_i2c_write_mask(ov511, 0x4e, enable?0xe0:0xc0, 0xe0);
-		ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
-		ov51x_i2c_write_mask(ov511, 0x0e, enable?0x80:0x00, 0x80);
+		i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);
 		break;
 	case SEN_OV6630:
-		ov51x_i2c_write_mask(ov511, 0x4e, enable?0x80:0x60, 0xe0);
-		ov51x_i2c_write_mask(ov511, 0x29, enable?0x08:0x00, 0x08);
-		ov51x_i2c_write_mask(ov511, 0x28, enable?0x02:0x00, 0x02);
+		i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
 		break;
 	case SEN_OV7610:
 	case SEN_OV7620AE:
@@ -2414,7 +2381,7 @@
 		return -EINVAL;
 	}
 
-	ov511->backlight = enable;
+	ov->backlight = enable;
 
 	return 0;
 }
@@ -2423,7 +2390,7 @@
  * planar or not), or zero for unsupported format.
  */
 static inline int 
-ov511_get_depth(int palette)
+get_depth(int palette)
 {
 	switch (palette) {
 	case VIDEO_PALETTE_GREY:    return 8;
@@ -2446,55 +2413,55 @@
 		return 0;
 	else
 		return ((frame->width * frame->height
-			 * ov511_get_depth(frame->format)) >> 3);
+			 * get_depth(frame->format)) >> 3);
 }
 
 static int
-mode_init_ov_sensor_regs(struct usb_ov511 *ov511, int width, int height,
+mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
 			 int mode, int sub_flag, int qvga)
 {
 	int clock;
 
 	/******** Mode (VGA/QVGA) and sensor specific regs ********/
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
-		ov51x_i2c_write(ov511, 0x14, qvga?0x24:0x04);
+		i2c_w(ov, 0x14, qvga?0x24:0x04);
 // FIXME: Does this improve the image quality or frame rate?
 #if 0
-		ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
-		ov51x_i2c_write(ov511, 0x24, 0x10);
-		ov51x_i2c_write(ov511, 0x25, qvga?0x40:0x8a);
-		ov51x_i2c_write(ov511, 0x2f, qvga?0x30:0xb0);
-		ov51x_i2c_write(ov511, 0x35, qvga?0x1c:0x9c);
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, 0x10);
+		i2c_w(ov, 0x25, qvga?0x40:0x8a);
+		i2c_w(ov, 0x2f, qvga?0x30:0xb0);
+		i2c_w(ov, 0x35, qvga?0x1c:0x9c);
 #endif
 		break;
 	case SEN_OV7620:
-//		ov51x_i2c_write(ov511, 0x2b, 0x00);
-		ov51x_i2c_write(ov511, 0x14, qvga?0xa4:0x84);
-		ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
-		ov51x_i2c_write(ov511, 0x24, qvga?0x20:0x3a);
-		ov51x_i2c_write(ov511, 0x25, qvga?0x30:0x60);
-		ov51x_i2c_write_mask(ov511, 0x2d, qvga?0x40:0x00, 0x40);
-		ov51x_i2c_write_mask(ov511, 0x67, qvga?0xf0:0x90, 0xf0);
-		ov51x_i2c_write_mask(ov511, 0x74, qvga?0x20:0x00, 0x20);
+//		i2c_w(ov, 0x2b, 0x00);
+		i2c_w(ov, 0x14, qvga?0xa4:0x84);
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, qvga?0x20:0x3a);
+		i2c_w(ov, 0x25, qvga?0x30:0x60);
+		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
+		i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0);
+		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
 		break;
 	case SEN_OV7620AE:
-//		ov51x_i2c_write(ov511, 0x2b, 0x00);
-		ov51x_i2c_write(ov511, 0x14, qvga?0xa4:0x84);
+//		i2c_w(ov, 0x2b, 0x00);
+		i2c_w(ov, 0x14, qvga?0xa4:0x84);
 // FIXME: Enable this once 7620AE uses 7620 initial settings
 #if 0
-		ov51x_i2c_write_mask(ov511, 0x28, qvga?0x00:0x20, 0x20);
-		ov51x_i2c_write(ov511, 0x24, qvga?0x20:0x3a);
-		ov51x_i2c_write(ov511, 0x25, qvga?0x30:0x60);
-		ov51x_i2c_write_mask(ov511, 0x2d, qvga?0x40:0x00, 0x40);
-		ov51x_i2c_write_mask(ov511, 0x67, qvga?0xb0:0x90, 0xf0);
-		ov51x_i2c_write_mask(ov511, 0x74, qvga?0x20:0x00, 0x20);
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, qvga?0x20:0x3a);
+		i2c_w(ov, 0x25, qvga?0x30:0x60);
+		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
+		i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0);
+		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
 #endif
 		break;
 	case SEN_OV6620:
 	case SEN_OV6630:
-		ov51x_i2c_write(ov511, 0x14, qvga?0x24:0x04);
+		i2c_w(ov, 0x14, qvga?0x24:0x04);
 		/* No special settings yet */
 		break;
 	default:
@@ -2505,19 +2472,17 @@
 	/******** Palette-specific regs ********/
 
 	if (mode == VIDEO_PALETTE_GREY) {
-		if (ov511->sensor == SEN_OV7610
-		    || ov511->sensor == SEN_OV7620AE) {
+		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
 			/* these aren't valid on the OV6620/OV7620/6630? */
-			ov51x_i2c_write_mask(ov511, 0x0e, 0x40, 0x40);
+			i2c_w_mask(ov, 0x0e, 0x40, 0x40);
 		}
-		ov51x_i2c_write_mask(ov511, 0x13, 0x20, 0x20);
+		i2c_w_mask(ov, 0x13, 0x20, 0x20);
 	} else {
-		if (ov511->sensor == SEN_OV7610
-		    || ov511->sensor == SEN_OV7620AE) {
+		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
 			/* not valid on the OV6620/OV7620/6630? */
-			ov51x_i2c_write_mask(ov511, 0x0e, 0x00, 0x40);
+			i2c_w_mask(ov, 0x0e, 0x00, 0x40);
 		}
-		ov51x_i2c_write_mask(ov511, 0x13, 0x00, 0x20);
+		i2c_w_mask(ov, 0x13, 0x00, 0x20);
 	}
 
 	/******** Clock programming ********/
@@ -2526,13 +2491,13 @@
 
 	/* The OV6620 needs special handling. This prevents the 
 	 * severe banding that normally occurs */
-	if (ov511->sensor == SEN_OV6620 || ov511->sensor == SEN_OV6630)
+	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
 	{
 		/* Clock down */
 
-		ov51x_i2c_write(ov511, 0x2a, 0x04);
+		i2c_w(ov, 0x2a, 0x04);
 
-		if (ov511->compress) {
+		if (ov->compress) {
 //			clock = 0;    /* This ensures the highest frame rate */
 			clock = 3;
 		} else if (clockdiv == -1) {   /* If user didn't override it */
@@ -2543,21 +2508,21 @@
 
 		PDEBUG(4, "Setting clock divisor to %d", clock);
 
-		ov51x_i2c_write(ov511, 0x11, clock);
+		i2c_w(ov, 0x11, clock);
 
-		ov51x_i2c_write(ov511, 0x2a, 0x84);
+		i2c_w(ov, 0x2a, 0x84);
 		/* This next setting is critical. It seems to improve
 		 * the gain or the contrast. The "reserved" bits seem
 		 * to have some effect in this case. */
-		ov51x_i2c_write(ov511, 0x2d, 0x85);
+		i2c_w(ov, 0x2d, 0x85);
 	}
 	else
 	{
-		if (ov511->compress) {
+		if (ov->compress) {
 			clock = 1;    /* This ensures the highest frame rate */
 		} else if (clockdiv == -1) {   /* If user didn't override it */
 			/* Calculate and set the clock divisor */
-			clock = ((sub_flag ? ov511->subw * ov511->subh
+			clock = ((sub_flag ? ov->subw * ov->subh
 				  : width * height)
 				 * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)
 				 / 66000;
@@ -2567,45 +2532,44 @@
 
 		PDEBUG(4, "Setting clock divisor to %d", clock);
 
-		ov51x_i2c_write(ov511, 0x11, clock);
+		i2c_w(ov, 0x11, clock);
 	}
 
 	/******** Special Features ********/
 
 	if (framedrop >= 0)
-		ov51x_i2c_write(ov511, 0x16, framedrop);
+		i2c_w(ov, 0x16, framedrop);
 
 	/* We only have code to convert GBR -> RGB24 */
 	if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
-		ov51x_i2c_write_mask(ov511, 0x12, 0x08, 0x08);
+		i2c_w_mask(ov, 0x12, 0x08, 0x08);
 	else
-		ov51x_i2c_write_mask(ov511, 0x12, 0x00, 0x08);
+		i2c_w_mask(ov, 0x12, 0x00, 0x08);
 
 	/* Test Pattern */
-	ov51x_i2c_write_mask(ov511, 0x12, (testpat?0x02:0x00), 0x02);
+	i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);
 
 	/* Auto white balance */
 //	if (awb)
-		ov51x_i2c_write_mask(ov511, 0x12, 0x04, 0x04);
+		i2c_w_mask(ov, 0x12, 0x04, 0x04);
 //	else
-//		ov51x_i2c_write_mask(ov511, 0x12, 0x00, 0x04);
+//		i2c_w_mask(ov, 0x12, 0x00, 0x04);
 
-	// This will go away as soon as ov511_mode_init_sensor_regs()
+	// This will go away as soon as ov51x_mode_init_sensor_regs()
 	// is fully tested.
 	/* 7620/6620/6630? don't have register 0x35, so play it safe */
-	if (ov511->sensor == SEN_OV7610 ||
-	    ov511->sensor == SEN_OV7620AE) {
+	if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
 		if (width == 640 && height == 480)
-			ov51x_i2c_write(ov511, 0x35, 0x9e);
+			i2c_w(ov, 0x35, 0x9e);
 		else
-			ov51x_i2c_write(ov511, 0x35, 0x1e);
+			i2c_w(ov, 0x35, 0x1e);
 	}
 
 	return 0;
 }
 
 static int
-set_ov_sensor_window(struct usb_ov511 *ov511, int width, int height, int mode,
+set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
 		     int sub_flag)
 {
 	int ret;
@@ -2614,7 +2578,7 @@
 
 	/* The different sensor ICs handle setting up of window differently.
 	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620AE:
 		hwsbase = 0x38;
@@ -2638,9 +2602,9 @@
 		return -EINVAL;
 	}
 
-	if (ov511->sensor == SEN_OV6620 || ov511->sensor == SEN_OV6630) {
+	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) {
 		if (width > 176 && height > 144) {  /* CIF */
-			ret = mode_init_ov_sensor_regs(ov511, width, height,
+			ret = mode_init_ov_sensor_regs(ov, width, height,
 				mode, sub_flag, 0);
 			if (ret < 0)
 				return ret;
@@ -2652,7 +2616,7 @@
 			err("Illegal dimensions");
 			return -EINVAL;
 		} else {			    /* QCIF */
-			ret = mode_init_ov_sensor_regs(ov511, width, height,
+			ret = mode_init_ov_sensor_regs(ov, width, height,
 				mode, sub_flag, 1);
 			if (ret < 0)
 				return ret;
@@ -2661,7 +2625,7 @@
 		}
 	} else {
 		if (width > 320 && height > 240) {  /* VGA */
-			ret = mode_init_ov_sensor_regs(ov511, width, height,
+			ret = mode_init_ov_sensor_regs(ov, width, height,
 				mode, sub_flag, 0);
 			if (ret < 0)
 				return ret;
@@ -2673,7 +2637,7 @@
 			err("Illegal dimensions");
 			return -EINVAL;
 		} else {			    /* QVGA */
-			ret = mode_init_ov_sensor_regs(ov511, width, height,
+			ret = mode_init_ov_sensor_regs(ov, width, height,
 				mode, sub_flag, 1);
 			if (ret < 0)
 				return ret;
@@ -2689,24 +2653,20 @@
 
 	/* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
 	if (sub_flag) {
-		ov51x_i2c_write(ov511, 0x17, hwsbase+(ov511->subx>>hwscale));
-		ov51x_i2c_write(ov511, 0x18,
-				hwebase+((ov511->subx+ov511->subw)>>hwscale));
-		ov51x_i2c_write(ov511, 0x19, vwsbase+(ov511->suby>>vwscale));
-		ov51x_i2c_write(ov511, 0x1a,
-				vwebase+((ov511->suby+ov511->subh)>>vwscale));
+		i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale));
+		i2c_w(ov, 0x18,	hwebase+((ov->subx+ov->subw)>>hwscale));
+		i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale));
+		i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale));
 	} else {
-		ov51x_i2c_write(ov511, 0x17, hwsbase + hoffset);
-		ov51x_i2c_write(ov511, 0x18,
-				hwebase + hoffset + (hwsize>>hwscale));
-		ov51x_i2c_write(ov511, 0x19, vwsbase + voffset);
-		ov51x_i2c_write(ov511, 0x1a,
-				vwebase + voffset + (vwsize>>vwscale));
+		i2c_w(ov, 0x17, hwsbase + hoffset);
+		i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale));
+		i2c_w(ov, 0x19, vwsbase + voffset);
+		i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale));
 	}
 
 #ifdef OV511_DEBUG
 	if (dump_sensor)
-		ov51x_dump_i2c_regs(ov511);
+		dump_i2c_regs(ov);
 #endif
 
 	return 0;
@@ -2717,18 +2677,14 @@
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
 static int
-ov511_mode_init_regs(struct usb_ov511 *ov511,
+ov511_mode_init_regs(struct usb_ov511 *ov,
 		     int width, int height, int mode, int sub_flag)
 {
 	int lncnt, pxcnt, rc = 0;
-	struct usb_device *dev = ov511->dev;
-
-	if (!ov511 || !dev)
-		return -EFAULT;
 
 	if (sub_flag) {
-		width = ov511->subw;
-		height = ov511->subh;
+		width = ov->subw;
+		height = ov->subh;
 	}
 
 	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
@@ -2736,7 +2692,7 @@
 
 	// FIXME: This should be moved to a 7111a-specific function once
 	// subcapture is dealt with properly
-	if (ov511->sensor == SEN_SAA7111A) {
+	if (ov->sensor == SEN_SAA7111A) {
 		if (width == 320 && height == 240) {
 			/* No need to do anything special */
 		} else if (width == 640 && height == 480) {
@@ -2755,26 +2711,22 @@
 		return -EINVAL;
 	}
 
-	if (width < ov511->minwidth || height < ov511->minheight) {
+	if (width < ov->minwidth || height < ov->minheight) {
 		err("Requested dimensions are too small");
 		return -EINVAL;
 	}
 
-	if (ov511_stop(ov511) < 0)
+	if (ov51x_stop(ov) < 0)
 		return -EIO;
 
 	if (mode == VIDEO_PALETTE_GREY) {
-		ov511_reg_write(dev, 0x16, 0x00);
-
-		/* For snapshot */
-		ov511_reg_write(dev, 0x1e, 0x00);
-		ov511_reg_write(dev, 0x1f, 0x01);
+		reg_w(ov, R511_CAM_UV_EN, 0x00);
+		reg_w(ov, R511_SNAP_UV_EN, 0x00);
+		reg_w(ov, R511_SNAP_OPTS, 0x01);
 	} else {
-		ov511_reg_write(dev, 0x16, 0x01);
-
-		/* For snapshot */
-		ov511_reg_write(dev, 0x1e, 0x01);
-		ov511_reg_write(dev, 0x1f, 0x03);
+		reg_w(ov, R511_CAM_UV_EN, 0x01);
+		reg_w(ov, R511_SNAP_UV_EN, 0x01);
+		reg_w(ov, R511_SNAP_OPTS, 0x03);
 	}
 
 	/* Here I'm assuming that snapshot size == image size.
@@ -2783,25 +2735,28 @@
 	pxcnt = (width >> 3) - 1;
 	lncnt = (height >> 3) - 1;
 
-	ov511_reg_write(dev, 0x12, pxcnt);
-	ov511_reg_write(dev, 0x13, lncnt);
-	ov511_reg_write(dev, 0x14, 0x00);
-	ov511_reg_write(dev, 0x15, 0x00);
-	ov511_reg_write(dev, 0x18, 0x03);	/* YUV420, low pass filer on */
+	reg_w(ov, R511_CAM_PXCNT, pxcnt);
+	reg_w(ov, R511_CAM_LNCNT, lncnt);
+	reg_w(ov, R511_CAM_PXDIV, 0x00);
+	reg_w(ov, R511_CAM_LNDIV, 0x00);
+
+	/* YUV420, low pass filer on */
+	reg_w(ov, R511_CAM_OPTS, 0x03);
 
 	/* Snapshot additions */
-	ov511_reg_write(dev, 0x1a, pxcnt);
-	ov511_reg_write(dev, 0x1b, lncnt);
-        ov511_reg_write(dev, 0x1c, 0x00);
-        ov511_reg_write(dev, 0x1d, 0x00);
-
-	if (ov511->compress) {
-		ov511_reg_write(dev, 0x78, 0x07); // Turn on Y & UV compression
-		ov511_reg_write(dev, 0x79, 0x03); // Enable LUTs
-		ov511_reset(ov511, OV511_RESET_OMNICE);
+	reg_w(ov, R511_SNAP_PXCNT, pxcnt);
+	reg_w(ov, R511_SNAP_LNCNT, lncnt);
+	reg_w(ov, R511_SNAP_PXDIV, 0x00);
+	reg_w(ov, R511_SNAP_LNDIV, 0x00);
+
+	if (ov->compress) {
+		/* Enable Y and UV quantization and compression */
+		reg_w(ov, R511_COMP_EN, 0x07);
+		reg_w(ov, R511_COMP_LUT_EN, 0x03);
+		ov51x_reset(ov, OV511_RESET_OMNICE);
 	}
 //out:
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	return rc;
@@ -2825,17 +2780,15 @@
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
 static int
-ov518_mode_init_regs(struct usb_ov511 *ov511,
+ov518_mode_init_regs(struct usb_ov511 *ov,
 		     int width, int height, int mode, int sub_flag)
 {
 	int i;
-	struct usb_device *dev = ov511->dev;
-	unsigned char b[3]; /* Multiple-value reg buffer */
 
 	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
 	       width, height, mode, sub_flag);
 
-	if (ov511_stop(ov511) < 0)
+	if (ov51x_stop(ov) < 0)
 		return -EIO;
 
 	for (i = 0; mlist518[i].width; i++) {
@@ -2853,113 +2806,94 @@
 //		pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
 //		lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
 //
-//		ov511_reg_write(dev, 0x12, pxcnt);
-//		ov511_reg_write(dev, 0x13, lncnt);
+//		reg_w(ov511, 0x12, pxcnt);
+//		reg_w(ov511, 0x13, lncnt);
 
 		/******** Set the mode ********/		
 
 		/* Mode independent regs */
-		ov511_reg_write(dev, 0x2b, 0x00);
-		ov511_reg_write(dev, 0x2d, 0x00);
-		ov511_reg_write(dev, 0x3b, 0x00);
-		ov511_reg_write(dev, 0x3d, 0x00);
+		reg_w(ov, 0x2b, 0x00);
+		reg_w(ov, 0x2d, 0x00);
+		reg_w(ov, 0x3b, 0x00);
+		reg_w(ov, 0x3d, 0x00);
 
 		/* Mode dependent regs. Regs 38 - 3e are always the same as
 		 * regs 28 - 2e */
-		ov511_reg_write_mask(dev, 0x28, mlist518[i].reg28
+		reg_w_mask(ov, 0x28, mlist518[i].reg28
 			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
-		ov511_reg_write(dev, 0x29, mlist518[i].reg29);
-		ov511_reg_write(dev, 0x2a, mlist518[i].reg2a);
-		ov511_reg_write(dev, 0x2c, mlist518[i].reg2c);
-		ov511_reg_write(dev, 0x2e, mlist518[i].reg2e);
-		ov511_reg_write_mask(dev, 0x38, mlist518[i].reg28 
+		reg_w(ov, 0x29, mlist518[i].reg29);
+		reg_w(ov, 0x2a, mlist518[i].reg2a);
+		reg_w(ov, 0x2c, mlist518[i].reg2c);
+		reg_w(ov, 0x2e, mlist518[i].reg2e);
+		reg_w_mask(ov, 0x38, mlist518[i].reg28 
 			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
-		ov511_reg_write(dev, 0x39, mlist518[i].reg29);
-		ov511_reg_write(dev, 0x3a, mlist518[i].reg2a);
-		ov511_reg_write(dev, 0x3c, mlist518[i].reg2c);
-		ov511_reg_write(dev, 0x3e, mlist518[i].reg2e);
-		ov511_reg_write(dev, 0x24, mlist518[i].reg24);
-		ov511_reg_write(dev, 0x25, mlist518[i].reg25);
+		reg_w(ov, 0x39, mlist518[i].reg29);
+		reg_w(ov, 0x3a, mlist518[i].reg2a);
+		reg_w(ov, 0x3c, mlist518[i].reg2c);
+		reg_w(ov, 0x3e, mlist518[i].reg2e);
+		reg_w(ov, 0x24, mlist518[i].reg24);
+		reg_w(ov, 0x25, mlist518[i].reg25);
 
 		/* Windows driver does this here; who knows why */
-		ov511_reg_write(dev, 0x2f, 0x80);
+		reg_w(ov, 0x2f, 0x80);
 
 		/******** Set the framerate (to 15 FPS) ********/		
 
 		/* Mode independent, but framerate dependent, regs */
 		/* These are for 15 FPS only */
-		ov511_reg_write(dev, 0x51, 0x08);
-		ov511_reg_write(dev, 0x22, 0x18);
-		ov511_reg_write(dev, 0x23, 0xff);
-		ov511_reg_write(dev, 0x71, 0x19);  /* Compression-related? */
+		reg_w(ov, 0x51, 0x08);
+		reg_w(ov, 0x22, 0x18);
+		reg_w(ov, 0x23, 0xff);
+		reg_w(ov, 0x71, 0x19);  /* Compression-related? */
 
 		// FIXME: Sensor-specific
 		/* Bit 5 is what matters here. Of course, it is "reserved" */
-		ov51x_i2c_write(ov511, 0x54, 0x23);
+		i2c_w(ov, 0x54, 0x23);
 
-		ov511_reg_write(dev, 0x2f, 0x80);
+		reg_w(ov, 0x2f, 0x80);
 
 		/* Mode dependent regs */
 		if ((width == 352 && height == 288) ||
 		    (width == 320 && height == 240)) {
-			b[0]=0x80; b[1]=0x02;
-			ov518_reg_write_multi(dev, 0x30, b, 2);
-			b[0]=0x90; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xc4, b, 2);
-			b[0]=0xf4; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xc6, b, 2);
-			b[0]=0xf4; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xc7, b, 2);
-			b[0]=0x8e; b[1]=0x00;
-			ov518_reg_write_multi(dev, 0xc8, b, 2);
-			b[0]=0x1a; b[1]=0x00; b[2]=0x02;
-			ov518_reg_write_multi(dev, 0xca, b, 3);
-			b[0]=0x14; b[1]=0x02;
-			ov518_reg_write_multi(dev, 0xcb, b, 2);
-			b[0]=0xd0; b[1]=0x07;
-			ov518_reg_write_multi(dev, 0xcc, b, 2);
-			b[0]=0x20; b[1]=0x00;
-			ov518_reg_write_multi(dev, 0xcd, b, 2);
-			b[0]=0x60; b[1]=0x02;
-			ov518_reg_write_multi(dev, 0xce, b, 2);
-
+			/*  640 (280h) byte iso packets */
+			ov518_reg_w32(ov, 0x30,    640, 2);	/* 280h   */
+			ov518_reg_w32(ov, 0xc4,    400, 2);	/* 190h   */
+			ov518_reg_w32(ov, 0xc6,    500, 2);	/* 1f4h   */
+			ov518_reg_w32(ov, 0xc7,    500, 2);	/* 1f4h   */
+			ov518_reg_w32(ov, 0xc8,    142, 2);	/* 8eh    */
+			ov518_reg_w32(ov, 0xca, 131098, 3);	/* 2001ah */
+			ov518_reg_w32(ov, 0xcb,    532, 2);	/* 214h   */
+			ov518_reg_w32(ov, 0xcc,   2000, 2);	/* 7d0h   */
+			ov518_reg_w32(ov, 0xcd,     32, 2);	/* 20h    */
+			ov518_reg_w32(ov, 0xce,    608, 2);	/* 260h   */
 		} else if ((width == 176 && height == 144) ||
 			   (width == 160 && height == 120)) {
-			b[0]=0x80; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0x30, b, 2);
-			b[0]=0xc8; b[1]=0x00;
-			ov518_reg_write_multi(dev, 0xc4, b, 2);
-			b[0]=0x40; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xc6, b, 2);
-			b[0]=0x40; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xc7, b, 2);
-			b[0]=0x60; b[1]=0x00;
-			ov518_reg_write_multi(dev, 0xc8, b, 2);
-			b[0]=0x0f; b[1]=0x33; b[2]=0x01;
-			ov518_reg_write_multi(dev, 0xca, b, 3);
-			b[0]=0x40; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xcb, b, 2);
-			b[0]=0xec; b[1]=0x04;
-			ov518_reg_write_multi(dev, 0xcc, b, 2);
-			b[0]=0x13; b[1]=0x00;
-			ov518_reg_write_multi(dev, 0xcd, b, 2);
-			b[0]=0x6d; b[1]=0x01;
-			ov518_reg_write_multi(dev, 0xce, b, 2);
+			/*  384 (180h) byte iso packets */
+			ov518_reg_w32(ov, 0x30,    384, 2);	/* 180h   */
+			ov518_reg_w32(ov, 0xc4,    200, 2);	/* c8h    */
+			ov518_reg_w32(ov, 0xc6,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xc7,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xc8,     96, 2);	/* 60h    */
+			ov518_reg_w32(ov, 0xca,  78607, 3);	/* 1330fh */
+			ov518_reg_w32(ov, 0xcb,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xcc,   1260, 2);	/* 4ech   */
+			ov518_reg_w32(ov, 0xcd,     19, 2);	/* 13h    */
+			ov518_reg_w32(ov, 0xce,    365, 2);	/* 16dh   */
 		} else {
 			/* Can't happen, since we already handled this case */
 			err("ov518_mode_init_regs(): **** logic error ****");
 		}
 
-		ov511_reg_write(dev, 0x2f, 0x80);
+		reg_w(ov, 0x2f, 0x80);
 
 		break;
 	}
 
-	if (ov511_restart(ov511) < 0)
+	if (ov51x_restart(ov) < 0)
 		return -EIO;
 
 	/* Reset it just for good measure */
-	if (ov511_reset(ov511, OV511_RESET_NOREGS) < 0)
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
 		return -EIO;
 
 	if (mlist518[i].width == 0) {
@@ -2972,29 +2906,31 @@
 
 /* This is a wrapper around the OV511, OV518, and sensor specific functions */
 static int
-mode_init_regs(struct usb_ov511 *ov511,
+mode_init_regs(struct usb_ov511 *ov,
 	       int width, int height, int mode, int sub_flag)
 {
 	int rc = 0;
 
-	if (ov511->bridge == BRG_OV518 ||
-	    ov511->bridge == BRG_OV518PLUS) {
-		rc = ov518_mode_init_regs(ov511, width, height, mode, sub_flag);
+	if (!ov || !ov->dev)
+		return -EFAULT;
+
+	if (ov->bclass == BCL_OV518) {
+		rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag);
 	} else {
-		rc = ov511_mode_init_regs(ov511, width, height, mode, sub_flag);
+		rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag);
 	}
 
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_OV7610:
 	case SEN_OV7620:
 	case SEN_OV7620AE:
 	case SEN_OV8600:
 	case SEN_OV6620:
 	case SEN_OV6630:
-		rc = set_ov_sensor_window(ov511, width, height, mode, sub_flag);
+		rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);
 		break;
 	case SEN_KS0127:
 	case SEN_KS0127B:
@@ -3002,10 +2938,10 @@
 		rc = -EINVAL;
 		break;
 	case SEN_SAA7111A:
-//		rc = mode_init_saa_sensor_regs(ov511, width, height, mode, 
+//		rc = mode_init_saa_sensor_regs(ov, width, height, mode, 
 //					       sub_flag);
 
-		PDEBUG(1, "SAA status = 0X%x", ov51x_i2c_read(ov511, 0x1f));
+		PDEBUG(1, "SAA status = 0X%x", i2c_r(ov, 0x1f));
 		break;
 	default:
 		err("Unknown sensor");
@@ -3016,25 +2952,25 @@
 		return rc;
 
 	/* Sensor-independent settings */
-	rc = sensor_set_auto_brightness(ov511, ov511->auto_brt);
+	rc = sensor_set_auto_brightness(ov, ov->auto_brt);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_set_auto_exposure(ov511, ov511->auto_exp);
+	rc = sensor_set_auto_exposure(ov, ov->auto_exp);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	rc = sensor_set_banding_filter(ov511, bandingfilter);
+	rc = sensor_set_banding_filter(ov, bandingfilter);
 	if (FATAL_ERROR(rc))
 		return rc;
 
-	if (ov511->lightfreq) {
-		rc = sensor_set_light_freq(ov511, lightfreq);
+	if (ov->lightfreq) {
+		rc = sensor_set_light_freq(ov, lightfreq);
 		if (FATAL_ERROR(rc))
 			return rc;
 	}
 
-	rc = sensor_set_backlight(ov511, ov511->backlight);
+	rc = sensor_set_backlight(ov, ov->backlight);
 	if (FATAL_ERROR(rc))
 		return rc;
 
@@ -3045,28 +2981,28 @@
  * useful for apps that use read() and do not set these.
  */
 static int 
-ov51x_set_default_params(struct usb_ov511 *ov511)
+ov51x_set_default_params(struct usb_ov511 *ov)
 {
 	int i;
 
-	PDEBUG(3, "%dx%d, RGB24", ov511->maxwidth, ov511->maxheight);
+	PDEBUG(3, "%dx%d, RGB24", ov->maxwidth, ov->maxheight);
 
 	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
 	 * (using read() instead). */
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov511->frame[i].width = ov511->maxwidth;
-		ov511->frame[i].height = ov511->maxheight;
-		ov511->frame[i].bytes_read = 0;
+		ov->frame[i].width = ov->maxwidth;
+		ov->frame[i].height = ov->maxheight;
+		ov->frame[i].bytes_read = 0;
 		if (force_palette)
-			ov511->frame[i].format = force_palette;
+			ov->frame[i].format = force_palette;
 		else
-			ov511->frame[i].format = VIDEO_PALETTE_RGB24;
-		ov511->frame[i].depth = ov511_get_depth(ov511->frame[i].format);
+			ov->frame[i].format = VIDEO_PALETTE_RGB24;
+		ov->frame[i].depth = get_depth(ov->frame[i].format);
 	}
 
 	/* Initialize to max width/height, RGB24 */
-	if (mode_init_regs(ov511, ov511->maxwidth, ov511->maxheight,
-			   ov511->frame[0].format, 0) < 0)
+	if (mode_init_regs(ov, ov->maxwidth, ov->maxheight,
+			   ov->frame[0].format, 0) < 0)
 		return -EINVAL;
 
 	return 0;
@@ -3080,18 +3016,17 @@
 
 /* Set analog input port of decoder */
 static int 
-decoder_set_input(struct usb_ov511 *ov511, int input)
+decoder_set_input(struct usb_ov511 *ov, int input)
 {
 	PDEBUG(4, "port %d", input);
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_SAA7111A:
 	{
 		/* Select mode */
-		ov51x_i2c_write_mask(ov511, 0x02, input, 0x07);
+		i2c_w_mask(ov, 0x02, input, 0x07);
 		/* Bypass chrominance trap for modes 4..7 */
-		ov51x_i2c_write_mask(ov511, 0x09,
-				     (input > 3) ? 0x80:0x00, 0x80);
+		i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80);
 		break;
 	}
 	default:
@@ -3103,9 +3038,9 @@
 
 /* Get ASCII name of video input */
 static int 
-decoder_get_input_name(struct usb_ov511 *ov511, int input, char *name)
+decoder_get_input_name(struct usb_ov511 *ov, int input, char *name)
 {
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_SAA7111A:
 	{
 		if (input < 0 || input > 7)
@@ -3126,11 +3061,11 @@
 
 /* Set norm (NTSC, PAL, SECAM, AUTO) */
 static int 
-decoder_set_norm(struct usb_ov511 *ov511, int norm)
+decoder_set_norm(struct usb_ov511 *ov, int norm)
 {
 	PDEBUG(4, "%d", norm);
 
-	switch (ov511->sensor) {
+	switch (ov->sensor) {
 	case SEN_SAA7111A:
 	{
 		int reg_8, reg_e;
@@ -3151,8 +3086,8 @@
 			return -EINVAL;
 		}
 
-		ov51x_i2c_write_mask(ov511, 0x08, reg_8, 0xc0);
-		ov51x_i2c_write_mask(ov511, 0x0e, reg_e, 0x70);
+		i2c_w_mask(ov, 0x08, reg_8, 0xc0);
+		i2c_w_mask(ov, 0x0e, reg_e, 0x70);
 		break;
 	}
 	default:
@@ -3199,8 +3134,8 @@
 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
 
 static inline void
-ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
-		     int rowPixels, unsigned char * rgb, int bits)
+move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
+	       int rowPixels, unsigned char * rgb, int bits)
 {
 	const int rvScale = 91881;
 	const int guScale = -22553;
@@ -3270,10 +3205,10 @@
  **********************************************************************/
 
 /* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the
- * array at pOut is specified by w.
+ * image at pOut is specified by w.
  */
 static inline void 
-ov511_make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
+make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
 {
 	unsigned char *pOut1 = pOut;
 	int x, y;
@@ -3311,7 +3246,7 @@
 	for (y = 0; y < frame->rawheight - 1; y += 8) {
 		pOut = pOutLine;
 		for (x = 0; x < frame->rawwidth - 1; x += 8) {
-			ov511_make_8x8(pIn, pOut, frame->rawwidth);
+			make_8x8(pIn, pOut, frame->rawwidth);
 			pIn += 64;
 			pOut += 8;
 		}
@@ -3370,8 +3305,8 @@
 	for (y = 0; y < frame->rawheight - 1; y += 16) {
 		pOut = pOutLine;
 		for (x = 0; x < frame->rawwidth - 1; x += 16) {
-			ov511_make_8x8(pIn, pOut, w);
-			ov511_make_8x8(pIn + 64, pOut + a/4, w);
+			make_8x8(pIn, pOut, w);
+			make_8x8(pIn + 64, pOut + a/4, w);
 			pIn += 384;
 			pOut += 8;
 		}
@@ -3385,7 +3320,7 @@
 	for (y = 0; y < frame->rawheight - 1; y += 8) {
 		pOut = pOutLine;
 		for (x = 0; x < frame->rawwidth - 1; x += 8) {
-			ov511_make_8x8(pIn, pOut, frame->rawwidth);
+			make_8x8(pIn, pOut, frame->rawwidth);
 			pIn += 64;
 			pOut += 8;
 			if ((++k) > 3) {
@@ -3442,17 +3377,17 @@
  *
  **********************************************************************/
 
-/* Chooses a decompression module, locks it, and sets ov511->decomp_ops
+/* Chooses a decompression module, locks it, and sets ov->decomp_ops
  * accordingly. Returns -ENXIO if decompressor is not available, otherwise
  * returns 0 if no other error.
  */
 static int 
-ov51x_request_decompressor(struct usb_ov511 *ov511)
+request_decompressor(struct usb_ov511 *ov)
 {
-	if (!ov511)
+	if (!ov)
 		return -ENODEV;
 
-	if (ov511->decomp_ops) {
+	if (ov->decomp_ops) {
 		err("ERROR: Decompressor already requested!");
 		return -EINVAL;
 	}
@@ -3460,24 +3395,23 @@
 	lock_kernel();
 
 	/* Try to get MMX, and fall back on no-MMX if necessary */
-	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {
+	if (ov->bclass == BCL_OV511) {
 		if (ov511_mmx_decomp_ops) {
 			PDEBUG(3, "Using OV511 MMX decompressor");
-			ov511->decomp_ops = ov511_mmx_decomp_ops;
+			ov->decomp_ops = ov511_mmx_decomp_ops;
 		} else if (ov511_decomp_ops) {
 			PDEBUG(3, "Using OV511 decompressor");
-			ov511->decomp_ops = ov511_decomp_ops;
+			ov->decomp_ops = ov511_decomp_ops;
 		} else {
 			err("No decompressor available");
 		}
-	} else if (ov511->bridge == BRG_OV518 ||
-		   ov511->bridge == BRG_OV518PLUS) {
+	} else if (ov->bclass == BCL_OV518) {
 		if (ov518_mmx_decomp_ops) {
 			PDEBUG(3, "Using OV518 MMX decompressor");
-			ov511->decomp_ops = ov518_mmx_decomp_ops;
+			ov->decomp_ops = ov518_mmx_decomp_ops;
 		} else if (ov518_decomp_ops) {
 			PDEBUG(3, "Using OV518 decompressor");
-			ov511->decomp_ops = ov518_decomp_ops;
+			ov->decomp_ops = ov518_decomp_ops;
 		} else {
 			err("No decompressor available");
 		}
@@ -3485,13 +3419,13 @@
 		err("Unknown bridge");
 	}
 
-	if (ov511->decomp_ops) {
-		if (!ov511->decomp_ops->decomp_lock) {
-			ov511->decomp_ops = NULL;
+	if (ov->decomp_ops) {
+		if (!ov->decomp_ops->decomp_lock) {
+			ov->decomp_ops = NULL;
 			unlock_kernel();
 			return -ENOSYS;
 		}
-		ov511->decomp_ops->decomp_lock();
+		ov->decomp_ops->decomp_lock();
 		unlock_kernel();
 		return 0;
 	} else {
@@ -3500,25 +3434,25 @@
 	}
 }
 
-/* Unlocks decompression module and nulls ov511->decomp_ops. Safe to call even
- * if ov511->decomp_ops is NULL.
+/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
+ * if ov->decomp_ops is NULL.
  */
 static void 
-ov51x_release_decompressor(struct usb_ov511 *ov511)
+release_decompressor(struct usb_ov511 *ov)
 {
 	int released = 0;	/* Did we actually do anything? */
 
-	if (!ov511)
+	if (!ov)
 		return;
 
 	lock_kernel();
 
-	if (ov511->decomp_ops && ov511->decomp_ops->decomp_unlock) {
-		ov511->decomp_ops->decomp_unlock();
+	if (ov->decomp_ops && ov->decomp_ops->decomp_unlock) {
+		ov->decomp_ops->decomp_unlock();
 		released = 1;
 	}
 
-	ov511->decomp_ops = NULL;
+	ov->decomp_ops = NULL;
 	
 	unlock_kernel();
 
@@ -3527,26 +3461,26 @@
 }
 
 static void 
-ov51x_decompress(struct usb_ov511 *ov511, struct ov511_frame *frame,
-		 unsigned char *pIn0, unsigned char *pOut0)
+decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
+	   unsigned char *pIn0, unsigned char *pOut0)
 {
-	if (!ov511->decomp_ops)
-		if (ov51x_request_decompressor(ov511))
+	if (!ov->decomp_ops)
+		if (request_decompressor(ov))
 			return;
 
 	PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
 
 	if (frame->format == VIDEO_PALETTE_GREY 
-	    && ov511->decomp_ops->decomp_400) {
-		int ret = ov511->decomp_ops->decomp_400(
+	    && ov->decomp_ops->decomp_400) {
+		int ret = ov->decomp_ops->decomp_400(
 			pIn0,
 			pOut0,
 			frame->rawwidth,
 			frame->rawheight,
 			frame->bytes_recvd);
 		PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
-	} else if (ov511->decomp_ops->decomp_420) {
-		int ret = ov511->decomp_ops->decomp_420(
+	} else if (ov->decomp_ops->decomp_420) {
+		int ret = ov->decomp_ops->decomp_420(
 			pIn0,
 			pOut0,
 			frame->rawwidth,
@@ -3586,8 +3520,8 @@
 			u = (*pU++) - 128;
 			v = (*pV++) - 128;
 
-			ov511_move_420_block(y00, y01, y10, y11, u, v,
-					     frame->width, pOut, bits);
+			move_420_block(y00, y01, y10, y11, u, v,
+				       frame->width, pOut, bits);
 	
 			pY += 2;
 			pOut += 2 * bytes;
@@ -3742,11 +3676,11 @@
  * 	4. Fix the RGB offset, if necessary
  */
 static void 
-ov511_postprocess(struct usb_ov511 *ov511, struct ov511_frame *frame)
+ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
 {
 	if (dumppix) {
 		memset(frame->data, 0, 
-			MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
+			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
 		PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
 		memmove(frame->data, frame->rawdata, frame->bytes_recvd);
 		return;
@@ -3755,9 +3689,9 @@
 	/* YUV400 must be handled separately */
 	if (frame->format == VIDEO_PALETTE_GREY) {
 		/* Deinterlace frame, if necessary */
-		if (ov511->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+		if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
 			if (frame->compressed)
-				ov51x_decompress(ov511, frame, frame->rawdata,
+				decompress(ov, frame, frame->rawdata,
 						 frame->tempdata);
 			else
 				yuv400raw_to_yuv400p(frame, frame->rawdata,
@@ -3767,7 +3701,7 @@
 			            frame->data);
 		} else {
 			if (frame->compressed)
-				ov51x_decompress(ov511, frame, frame->rawdata,
+				decompress(ov, frame, frame->rawdata,
 						 frame->data);
 			else
 				yuv400raw_to_yuv400p(frame, frame->rawdata,
@@ -3779,12 +3713,12 @@
 
 	/* Process frame->data to frame->rawdata */
 	if (frame->compressed)
-		ov51x_decompress(ov511, frame, frame->rawdata, frame->tempdata);
+		decompress(ov, frame, frame->rawdata, frame->tempdata);
 	else
 		yuv420raw_to_yuv420p(frame, frame->rawdata, frame->tempdata);
 
 	/* Deinterlace frame, if necessary */
-	if (ov511->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+	if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
 		memmove(frame->rawdata, frame->tempdata,
 			MAX_RAW_DATA_SIZE(frame->width, frame->height));
 		deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
@@ -3838,7 +3772,7 @@
  **********************************************************************/
 
 static int 
-ov511_move_data(struct usb_ov511 *ov511, struct urb *urb)
+ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
 {
 	unsigned char *cdata;
 	int data_size, num, offset, i, totlen = 0;
@@ -3848,7 +3782,7 @@
 
 	PDEBUG(5, "Moving %d packets", urb->number_of_packets);
 
-	data_size = ov511->packet_size - 1;
+	data_size = ov->packet_size - 1;
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		int n = urb->iso_frame_desc[i].actual_length;
@@ -3859,15 +3793,15 @@
 
 		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
-		aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;
+		aPackNum[i] = n ? cdata[ov->packet_size - 1] : -1;
 
-		if (!n || ov511->curframe == -1)
+		if (!n || ov->curframe == -1)
 			continue;
 
 		if (st)
 			PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
 
-		frame = &ov511->frame[ov511->curframe];
+		frame = &ov->frame[ov->curframe];
 
 		/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
 		 * byte non-zero. The EOF packet has image width/height in the
@@ -3885,7 +3819,7 @@
 
 		if (printph) {
 			info("packet header (%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
-				cdata[ov511->packet_size - 1],
+				cdata[ov->packet_size - 1],
 				cdata[0], cdata[1], cdata[2], cdata[3], cdata[4], cdata[5],
 				cdata[6], cdata[7], cdata[8], cdata[9], cdata[10], cdata[11]);
 		}
@@ -3899,7 +3833,7 @@
 		/* Frame end */
 		if (cdata[8] & 0x80) {
 			ts = (struct timeval *)(frame->data 
-			      + MAX_FRAME_SIZE(ov511->maxwidth, ov511->maxheight));
+			      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
 			do_gettimeofday(ts);
 
 			/* Get the actual frame size from the EOF header */
@@ -3907,21 +3841,21 @@
 			frame->rawheight = ((int)(cdata[10]) + 1) * 8;
 
 	 		PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d, recvd=%d",
-				ov511->curframe,
-				(int)(cdata[ov511->packet_size - 1]),
+				ov->curframe,
+				(int)(cdata[ov->packet_size - 1]),
 				frame->rawwidth,
 				frame->rawheight,
 				frame->bytes_recvd);
 
 			/* Validate the header data */
-			RESTRICT_TO_RANGE(frame->rawwidth, ov511->minwidth, ov511->maxwidth);
-			RESTRICT_TO_RANGE(frame->rawheight, ov511->minheight, ov511->maxheight);
+			RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
+			RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
 
 			/* Don't allow byte count to exceed buffer size */
 			RESTRICT_TO_RANGE(frame->bytes_recvd,
 					  8, 
-					  MAX_RAW_DATA_SIZE(ov511->maxwidth,
-					                    ov511->maxheight));
+					  MAX_RAW_DATA_SIZE(ov->maxwidth,
+					                    ov->maxheight));
 
 			if (frame->scanstate == STATE_LINES) {
 		    		int iFrameNext;
@@ -3935,20 +3869,20 @@
 
 				/* If next frame is ready or grabbing,
                                  * point to it */
-				iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
-				if (ov511->frame[iFrameNext].grabstate == FRAME_READY
-				    || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {
-					ov511->curframe = iFrameNext;
-					ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
+				iFrameNext = (ov->curframe + 1) % OV511_NUMFRAMES;
+				if (ov->frame[iFrameNext].grabstate == FRAME_READY
+				    || ov->frame[iFrameNext].grabstate == FRAME_GRABBING) {
+					ov->curframe = iFrameNext;
+					ov->frame[iFrameNext].scanstate = STATE_SCANNING;
 				} else {
 					if (frame->grabstate == FRAME_DONE) {
 						PDEBUG(4, "Frame done! congratulations");
 					} else {
 						PDEBUG(4, "Frame not ready? state = %d",
-							ov511->frame[iFrameNext].grabstate);
+							ov->frame[iFrameNext].grabstate);
 					}
 
-					ov511->curframe = -1;
+					ov->curframe = -1;
 				}
 			} else {
 				PDEBUG(5, "Frame done, but not scanning");
@@ -3958,7 +3892,7 @@
 			 */
 		} else {
 			/* Frame start */
-			PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
+			PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
 
 			/* Check to see if it's a snapshot frame */
 			/* FIXME?? Should the snapshot reset go here? Performance? */
@@ -4007,24 +3941,24 @@
 		/* Dump all data exactly as received */
 		if (dumppix == 2) {
 			frame->bytes_recvd += n - 1;
-			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
 				memmove(frame->rawdata + frame->bytes_recvd - (n - 1),
 					&cdata[0], n - 1);
 			else
 				PDEBUG(3, "Raw data buffer overrun!! (%d)",
 					frame->bytes_recvd
-					- MAX_RAW_DATA_SIZE(ov511->maxwidth,
-							    ov511->maxheight));
+					- MAX_RAW_DATA_SIZE(ov->maxwidth,
+							    ov->maxheight));
 		} else if (!frame->compressed && !remove_zeros) {
 			frame->bytes_recvd += num;
-			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
 				memmove(frame->rawdata + frame->bytes_recvd - num,
 					&cdata[offset], num);
 			else
 				PDEBUG(3, "Raw data buffer overrun!! (%d)",
 					frame->bytes_recvd
-					- MAX_RAW_DATA_SIZE(ov511->maxwidth,
-							    ov511->maxheight));
+					- MAX_RAW_DATA_SIZE(ov->maxwidth,
+							    ov->maxheight));
 		} else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
 			int b, in = 0, allzero, copied=0;
 			if (offset) {
@@ -4047,7 +3981,7 @@
 					/* Don't copy it */
 				} else {
 					if (frame->bytes_recvd + copied + 32
-					    <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight)) {
+					    <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight)) {
 						memmove(frame->rawdata + frame->bytes_recvd + copied,
 							&cdata[in], 32);
 						copied += 32;
@@ -4071,7 +4005,7 @@
 }
 
 static int 
-ov518_move_data(struct usb_ov511 *ov511, struct urb *urb)
+ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
 {
 	unsigned char *cdata;
 	int i, data_size, totlen = 0;
@@ -4081,7 +4015,7 @@
 	PDEBUG(5, "Moving %d packets", urb->number_of_packets);
 
 	/* OV518(+) has no packet numbering */
-	data_size = ov511->packet_size;
+	data_size = ov->packet_size;
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		int n = urb->iso_frame_desc[i].actual_length;
@@ -4097,7 +4031,7 @@
 			continue;
 		}
 
-		if (ov511->curframe == -1) {
+		if (ov->curframe == -1) {
 			PDEBUG(4, "No frame currently active");
 			continue;
 		}
@@ -4105,21 +4039,7 @@
 		if (st)
 			PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
 
-		frame = &ov511->frame[ov511->curframe];
-
-#if 0
-		{
-			int d;
-			/* Print all data */
-			for (d = 0; d <= data_size - 16; d += 16) {
-				info("%4x: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", d,
-					cdata[d], cdata[d+1], cdata[d+2], cdata[d+3],
-					cdata[d+4], cdata[d+5], cdata[d+6], cdata[d+7],
-					cdata[d+8], cdata[d+9], cdata[d+10], cdata[d+11],
-					cdata[d+12], cdata[d+13], cdata[d+14], cdata[d+15]);
-			}
-		}
-#endif
+		frame = &ov->frame[ov->curframe];
 
 		if (printph) {
 			info("packet header: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
@@ -4137,7 +4057,7 @@
 				goto eof;
 			} else { //scanstate == STATE_SCANNING
 				/* Frame start */
-				PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
+				PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
 				goto sof;
 			}
 		} else {
@@ -4146,11 +4066,11 @@
 	
 eof:
 		ts = (struct timeval *)(frame->data
-		      + MAX_FRAME_SIZE(ov511->maxwidth, ov511->maxheight));
+		      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
 		do_gettimeofday(ts);
 
  		PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
-			ov511->curframe,
+			ov->curframe,
 			(int)(cdata[9]), (int)(cdata[10]), frame->bytes_recvd);
 
 		// FIXME: Since we don't know the header formats yet,
@@ -4159,13 +4079,13 @@
 		frame->rawheight = frame->height;
 
 		/* Validate the header data */
-		RESTRICT_TO_RANGE(frame->rawwidth, ov511->minwidth, ov511->maxwidth);
-		RESTRICT_TO_RANGE(frame->rawheight, ov511->minheight, ov511->maxheight);
+		RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
+		RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
 
 		/* Don't allow byte count to exceed buffer size */
 		RESTRICT_TO_RANGE(frame->bytes_recvd,
 				  8, 
-				  MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
+				  MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight));
 
 		if (frame->scanstate == STATE_LINES) {
 	    		int iFrameNext;
@@ -4179,21 +4099,21 @@
 
 			/* If next frame is ready or grabbing,
 			 * point to it */
-			iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
-			if (ov511->frame[iFrameNext].grabstate == FRAME_READY
-			    || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {
-				ov511->curframe = iFrameNext;
-				ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
-				frame = &ov511->frame[iFrameNext];
+			iFrameNext = (ov->curframe + 1) % OV511_NUMFRAMES;
+			if (ov->frame[iFrameNext].grabstate == FRAME_READY
+			    || ov->frame[iFrameNext].grabstate == FRAME_GRABBING) {
+				ov->curframe = iFrameNext;
+				ov->frame[iFrameNext].scanstate = STATE_SCANNING;
+				frame = &ov->frame[iFrameNext];
 			} else {
 				if (frame->grabstate == FRAME_DONE) {
 					PDEBUG(4, "Frame done! congratulations");
 				} else {
 					PDEBUG(4, "Frame not ready? state = %d",
-						ov511->frame[iFrameNext].grabstate);
+						ov->frame[iFrameNext].grabstate);
 				}
 
-				ov511->curframe = -1;
+				ov->curframe = -1;
 				PDEBUG(4, "SOF dropped (no active frame)");
 				continue;  /* Nowhere to store this frame */
 			}
@@ -4226,31 +4146,26 @@
 		/* Dump all data exactly as received */
 		if (dumppix == 2) {
 			frame->bytes_recvd += n;
-			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight))
+			if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
 				memmove(frame->rawdata + frame->bytes_recvd - n,
 					&cdata[0], n);
 			else
 				PDEBUG(3, "Raw data buffer overrun!! (%d)",
 					frame->bytes_recvd
-					- MAX_RAW_DATA_SIZE(ov511->maxwidth,
-							    ov511->maxheight));
+					- MAX_RAW_DATA_SIZE(ov->maxwidth,
+							    ov->maxheight));
 		} else {
 			/* All incoming data are divided into 8-byte segments. If the
 			 * segment contains all zero bytes, it must be skipped. These
 			 * zero-segments allow the OV518 to mainain a constant data rate
 			 * regardless of the effectiveness of the compression. Segments
 			 * are aligned relative to the beginning of each isochronous
-			 * packet. The first segment is a header.
+			 * packet. The first segment is a header (the decompressor
+			 * skips it later).
 			 */
 
 			int b, in = 0, allzero, copied=0;
 
-// Decompressor expects the header
-#if 0
-			if (frame->bytes_recvd == 0)
-				in += 8;  /* Skip header */
-#endif
-
 			while (in < n) {
 				allzero = 1;
 				for (b = 0; b < 8; b++) {
@@ -4264,7 +4179,7 @@
 				/* Don't copy it */
 				} else {
 					if (frame->bytes_recvd + copied + 8
-					    <= MAX_RAW_DATA_SIZE(ov511->maxwidth, ov511->maxheight)) {
+					    <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight)) {
 						memmove(frame->rawdata + frame->bytes_recvd + copied,
 							&cdata[in], 8);
 						copied += 8;
@@ -4282,43 +4197,41 @@
 }
 
 static void 
-ov511_isoc_irq(struct urb *urb)
+ov51x_isoc_irq(struct urb *urb)
 {
 	int len;
-	struct usb_ov511 *ov511;
+	struct usb_ov511 *ov;
 
 	if (!urb->context) {
 		PDEBUG(4, "no context");
 		return;
 	}
 
-	ov511 = (struct usb_ov511 *) urb->context;
+	ov = (struct usb_ov511 *) urb->context;
 
-	if (!ov511->dev || !ov511->user) {
+	if (!ov || !ov->dev || !ov->user) {
 		PDEBUG(4, "no device, or not open");
 		return;
 	}
 
-	if (!ov511->streaming) {
+	if (!ov->streaming) {
 		PDEBUG(4, "hmmm... not streaming, but got interrupt");
 		return;
 	}
 
 	/* Copy the data received into our frame buffer */
-	if (ov511->curframe >= 0) {
-		if (ov511->bridge == BRG_OV511 || 
-		    ov511->bridge == BRG_OV511PLUS)
-			len = ov511_move_data(ov511, urb);
-		else if (ov511->bridge == BRG_OV518 ||
-			 ov511->bridge == BRG_OV518PLUS)
-			len = ov518_move_data(ov511, urb);
+	if (ov->curframe >= 0) {
+		if (ov->bclass == BCL_OV511)
+			len = ov511_move_data(ov, urb);
+		else if (ov->bclass == BCL_OV518)
+			len = ov518_move_data(ov, urb);
 		else
-			err("Unknown bridge device (%d)", ov511->bridge);
-	} else if (waitqueue_active(&ov511->wq)) {
-		wake_up_interruptible(&ov511->wq);
+			err("Unknown bridge device (%d)", ov->bridge);
+	} else if (waitqueue_active(&ov->wq)) {
+		wake_up_interruptible(&ov->wq);
 	}
 
-	urb->dev = ov511->dev;
+	urb->dev = ov->dev;
 
 	return;
 }
@@ -4330,16 +4243,16 @@
  ***************************************************************************/
 
 static int 
-ov511_init_isoc(struct usb_ov511 *ov511)
+ov51x_init_isoc(struct usb_ov511 *ov)
 {
 	struct urb *urb;
 	int fx, err, n, size;
 
 	PDEBUG(3, "*** Initializing capture ***");
 
-	ov511->curframe = -1;
+	ov->curframe = -1;
 
-	if (ov511->bridge == BRG_OV511) {
+	if (ov->bridge == BRG_OV511) {
 		if (cams == 1)				size = 993;
 		else if (cams == 2)			size = 513;
 		else if (cams == 3 || cams == 4)	size = 257;
@@ -4347,7 +4260,7 @@
 			err("\"cams\" parameter too high!");
 			return -1;
 		}
-	} else if (ov511->bridge == BRG_OV511PLUS) {
+	} else if (ov->bridge == BRG_OV511PLUS) {
 		if (cams == 1)				size = 961;
 		else if (cams == 2)			size = 513;
 		else if (cams == 3 || cams == 4)	size = 257;
@@ -4357,8 +4270,7 @@
 			err("\"cams\" parameter too high!");
 			return -1;
 		}
-	} else if (ov511->bridge == BRG_OV518 ||
-		   ov511->bridge == BRG_OV518PLUS) {
+	} else if (ov->bclass == BCL_OV518) {
 		if (cams == 1)				size = 896;
 		else if (cams == 2)			size = 512;
 		else if (cams == 3 || cams == 4)	size = 256;
@@ -4374,14 +4286,13 @@
 
 	if (packetsize == -1) {
 		// FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now
-		if (ov511->bridge == BRG_OV518 ||
-		    ov511->bridge == BRG_OV518PLUS)
-			ov511_set_packet_size(ov511, 640);
+		if (ov->bclass == BCL_OV518)
+			ov51x_set_packet_size(ov, 640);
 		else
-			ov511_set_packet_size(ov511, size);
+			ov51x_set_packet_size(ov, size);
 	} else {
 			info("Forcing packet size to %d", packetsize);
-			ov511_set_packet_size(ov511, packetsize);
+			ov51x_set_packet_size(ov, packetsize);
 	}
 
 	for (n = 0; n < OV511_NUMSBUF; n++) {
@@ -4391,32 +4302,30 @@
 			err("init isoc: usb_alloc_urb ret. NULL");
 			return -ENOMEM;
 		}
-		ov511->sbuf[n].urb = urb;
-		urb->dev = ov511->dev;
-		urb->context = ov511;
-		urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
+		ov->sbuf[n].urb = urb;
+		urb->dev = ov->dev;
+		urb->context = ov;
+		urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
 		urb->transfer_flags = USB_ISO_ASAP;
-		urb->transfer_buffer = ov511->sbuf[n].data;
-		urb->complete = ov511_isoc_irq;
+		urb->transfer_buffer = ov->sbuf[n].data;
+		urb->complete = ov51x_isoc_irq;
 		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length =
-		 ov511->packet_size * FRAMES_PER_DESC;
+		urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC;
 		for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-			urb->iso_frame_desc[fx].offset = 
-			 ov511->packet_size * fx;
-			urb->iso_frame_desc[fx].length = ov511->packet_size;
+			urb->iso_frame_desc[fx].offset = ov->packet_size * fx;
+			urb->iso_frame_desc[fx].length = ov->packet_size;
 		}
 	}
 
-	ov511->streaming = 1;
+	ov->streaming = 1;
 
-	ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb;
+	ov->sbuf[OV511_NUMSBUF - 1].urb->next = ov->sbuf[0].urb;
 	for (n = 0; n < OV511_NUMSBUF - 1; n++)
-		ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;
+		ov->sbuf[n].urb->next = ov->sbuf[n+1].urb;
 
 	for (n = 0; n < OV511_NUMSBUF; n++) {
-		ov511->sbuf[n].urb->dev = ov511->dev;
-		err = usb_submit_urb(ov511->sbuf[n].urb, GFP_KERNEL);
+		ov->sbuf[n].urb->dev = ov->dev;
+		err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL);
 		if (err)
 			err("init isoc: usb_submit_urb(%d) ret %d", n, err);
 	}
@@ -4425,51 +4334,51 @@
 }
 
 static void 
-ov511_stop_isoc(struct usb_ov511 *ov511)
+ov51x_stop_isoc(struct usb_ov511 *ov)
 {
 	int n;
 
-	if (!ov511->streaming || !ov511->dev)
+	if (!ov->streaming || !ov->dev)
 		return;
 
 	PDEBUG(3, "*** Stopping capture ***");
 
-	ov511_set_packet_size(ov511, 0);
+	ov51x_set_packet_size(ov, 0);
 
-	ov511->streaming = 0;
+	ov->streaming = 0;
 
 	/* Unschedule all of the iso td's */
 	for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
-		if (ov511->sbuf[n].urb) {
-			ov511->sbuf[n].urb->next = NULL;
-			usb_unlink_urb(ov511->sbuf[n].urb);
-			usb_free_urb(ov511->sbuf[n].urb);
-			ov511->sbuf[n].urb = NULL;
+		if (ov->sbuf[n].urb) {
+			ov->sbuf[n].urb->next = NULL;
+			usb_unlink_urb(ov->sbuf[n].urb);
+			usb_free_urb(ov->sbuf[n].urb);
+			ov->sbuf[n].urb = NULL;
 		}
 	}
 }
 
 static int 
-ov511_new_frame(struct usb_ov511 *ov511, int framenum)
+ov51x_new_frame(struct usb_ov511 *ov, int framenum)
 {
 	struct ov511_frame *frame;
 	int newnum;
 
-	PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
-		framenum);
-	if (!ov511->dev)
+	PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
+
+	if (!ov->dev)
 		return -1;
 
 	/* If we're not grabbing a frame right now and the other frame is */
 	/* ready to be grabbed into, then use it instead */
-	if (ov511->curframe == -1) {
+	if (ov->curframe == -1) {
 		newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
-		if (ov511->frame[newnum].grabstate == FRAME_READY)
+		if (ov->frame[newnum].grabstate == FRAME_READY)
 			framenum = newnum;
 	} else
 		return 0;
 
-	frame = &ov511->frame[framenum];
+	frame = &ov->frame[framenum];
 
 	PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, 
 	       frame->width, frame->height);
@@ -4478,16 +4387,16 @@
 	frame->scanstate = STATE_SCANNING;
 	frame->snapshot = 0;
 
-	ov511->curframe = framenum;
+	ov->curframe = framenum;
 
 	/* Make sure it's not too big */
-	if (frame->width > ov511->maxwidth)
-		frame->width = ov511->maxwidth;
+	if (frame->width > ov->maxwidth)
+		frame->width = ov->maxwidth;
 
 	frame->width &= ~7L;		/* Multiple of 8 */
 
-	if (frame->height > ov511->maxheight)
-		frame->height = ov511->maxheight;
+	if (frame->height > ov->maxheight)
+		frame->height = ov->maxheight;
 
 	frame->height &= ~3L;		/* Multiple of 4 */
 
@@ -4499,84 +4408,86 @@
  * Buffer management
  *
  ***************************************************************************/
+
 static int 
-ov511_alloc(struct usb_ov511 *ov511)
+ov51x_alloc(struct usb_ov511 *ov)
 {
 	int i;
-	int w = ov511->maxwidth;
-	int h = ov511->maxheight;
+	const int w = ov->maxwidth;
+	const int h = ov->maxheight;
+	const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h);
+	const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
 
 	PDEBUG(4, "entered");
-	down(&ov511->buf_lock);
+	down(&ov->buf_lock);
 
-	if (ov511->buf_state == BUF_PEND_DEALLOC) {
-		ov511->buf_state = BUF_ALLOCATED;
-		del_timer(&ov511->buf_timer);
+	if (ov->buf_state == BUF_PEND_DEALLOC) {
+		ov->buf_state = BUF_ALLOCATED;
+		del_timer(&ov->buf_timer);
 	}
 
-	if (ov511->buf_state == BUF_ALLOCATED)
+	if (ov->buf_state == BUF_ALLOCATED)
 		goto out;
 
-	ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
-	if (!ov511->fbuf)
+	ov->fbuf = rvmalloc(data_bufsize);
+	if (!ov->fbuf)
 		goto error;
 
-	ov511->rawfbuf = vmalloc(OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
-	if (!ov511->rawfbuf) {
-		rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
-		ov511->fbuf = NULL;
+	ov->rawfbuf = vmalloc(raw_bufsize);
+	if (!ov->rawfbuf) {
+		rvfree(ov->fbuf, data_bufsize);
+		ov->fbuf = NULL;
 		goto error;
 	}
-	memset(ov511->rawfbuf, 0, OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+	memset(ov->rawfbuf, 0, raw_bufsize);
 
-	ov511->tempfbuf = vmalloc(OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
-	if (!ov511->tempfbuf) {
-		vfree(ov511->rawfbuf);
-		ov511->rawfbuf = NULL;
-		rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
-		ov511->fbuf = NULL;
+	ov->tempfbuf = vmalloc(raw_bufsize);
+	if (!ov->tempfbuf) {
+		vfree(ov->rawfbuf);
+		ov->rawfbuf = NULL;
+		rvfree(ov->fbuf, data_bufsize);
+		ov->fbuf = NULL;
 		goto error;
 	}
-	memset(ov511->tempfbuf, 0, OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h));
+	memset(ov->tempfbuf, 0, raw_bufsize);
 
 	for (i = 0; i < OV511_NUMSBUF; i++) {
-		ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
+		ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
 			MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
-		if (!ov511->sbuf[i].data) {
+		if (!ov->sbuf[i].data) {
 			while (--i) {
-				kfree(ov511->sbuf[i].data);
-				ov511->sbuf[i].data = NULL;
+				kfree(ov->sbuf[i].data);
+				ov->sbuf[i].data = NULL;
 			}
-			vfree(ov511->tempfbuf);
-			ov511->tempfbuf = NULL;
-			vfree(ov511->rawfbuf);
-			ov511->rawfbuf = NULL;
-			rvfree(ov511->fbuf,
-			       OV511_NUMFRAMES * MAX_DATA_SIZE(w, h));
-			ov511->fbuf = NULL;
+			vfree(ov->tempfbuf);
+			ov->tempfbuf = NULL;
+			vfree(ov->rawfbuf);
+			ov->rawfbuf = NULL;
+			rvfree(ov->fbuf, data_bufsize);
+			ov->fbuf = NULL;
 
 			goto error;
 		}
-		PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
+		PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);
 	}
 
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE(w, h);
-		ov511->frame[i].rawdata = ov511->rawfbuf 
+		ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h);
+		ov->frame[i].rawdata = ov->rawfbuf 
 		 + i * MAX_RAW_DATA_SIZE(w, h);
-		ov511->frame[i].tempdata = ov511->tempfbuf 
+		ov->frame[i].tempdata = ov->tempfbuf 
 		 + i * MAX_RAW_DATA_SIZE(w, h);
-		PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data);
+		PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);
 	}
 
-	ov511->buf_state = BUF_ALLOCATED;
+	ov->buf_state = BUF_ALLOCATED;
 out:
-	up(&ov511->buf_lock);
+	up(&ov->buf_lock);
 	PDEBUG(4, "leaving");
 	return 0;
 error:
-	ov511->buf_state = BUF_NOT_ALLOCATED;
-	up(&ov511->buf_lock);
+	ov->buf_state = BUF_NOT_ALLOCATED;
+	up(&ov->buf_lock);
 	PDEBUG(4, "errored");
 	return -ENOMEM;
 }
@@ -4587,206 +4498,211 @@
  *   them if you explicitly free them somewhere else!
  */
 static void 
-ov511_do_dealloc(struct usb_ov511 *ov511)
+ov51x_do_dealloc(struct usb_ov511 *ov)
 {
 	int i;
 	PDEBUG(4, "entered");
 
-	if (ov511->fbuf) {
-		rvfree(ov511->fbuf, OV511_NUMFRAMES
-		       * MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight));
-		ov511->fbuf = NULL;
+	if (ov->fbuf) {
+		rvfree(ov->fbuf, OV511_NUMFRAMES
+		       * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
+		ov->fbuf = NULL;
 	}
 
-	if (ov511->rawfbuf) {
-		vfree(ov511->rawfbuf);
-		ov511->rawfbuf = NULL;
+	if (ov->rawfbuf) {
+		vfree(ov->rawfbuf);
+		ov->rawfbuf = NULL;
 	}
 
-	if (ov511->tempfbuf) {
-		vfree(ov511->tempfbuf);
-		ov511->tempfbuf = NULL;
+	if (ov->tempfbuf) {
+		vfree(ov->tempfbuf);
+		ov->tempfbuf = NULL;
 	}
 
 	for (i = 0; i < OV511_NUMSBUF; i++) {
-		if (ov511->sbuf[i].data) {
-			kfree(ov511->sbuf[i].data);
-			ov511->sbuf[i].data = NULL;
+		if (ov->sbuf[i].data) {
+			kfree(ov->sbuf[i].data);
+			ov->sbuf[i].data = NULL;
 		}
 	}
 
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov511->frame[i].data = NULL;
-		ov511->frame[i].rawdata = NULL;
-		ov511->frame[i].tempdata = NULL;
+		ov->frame[i].data = NULL;
+		ov->frame[i].rawdata = NULL;
+		ov->frame[i].tempdata = NULL;
 	}
 
 	PDEBUG(4, "buffer memory deallocated");
-	ov511->buf_state = BUF_NOT_ALLOCATED;
+	ov->buf_state = BUF_NOT_ALLOCATED;
 	PDEBUG(4, "leaving");
 }
 
 static void 
-ov511_buf_callback(unsigned long data)
+ov51x_buf_callback(unsigned long data)
 {
-	struct usb_ov511 *ov511 = (struct usb_ov511 *)data;
+	struct usb_ov511 *ov = (struct usb_ov511 *)data;
 	PDEBUG(4, "entered");
-	down(&ov511->buf_lock);
+	down(&ov->buf_lock);
 
-	if (ov511->buf_state == BUF_PEND_DEALLOC)
-		ov511_do_dealloc(ov511);
+	if (ov->buf_state == BUF_PEND_DEALLOC)
+		ov51x_do_dealloc(ov);
 
-	up(&ov511->buf_lock);
+	up(&ov->buf_lock);
 	PDEBUG(4, "leaving");
 }
 
 static void 
-ov511_dealloc(struct usb_ov511 *ov511, int now)
+ov51x_dealloc(struct usb_ov511 *ov, int now)
 {
-	struct timer_list *bt = &(ov511->buf_timer);
+	struct timer_list *bt = &(ov->buf_timer);
 	PDEBUG(4, "entered");
-	down(&ov511->buf_lock);
+	down(&ov->buf_lock);
 
 	PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later");
 
-	if (ov511->buf_state == BUF_PEND_DEALLOC) {
-		ov511->buf_state = BUF_ALLOCATED;
+	if (ov->buf_state == BUF_PEND_DEALLOC) {
+		ov->buf_state = BUF_ALLOCATED;
 		del_timer(bt);
 	}
 
 	if (now)
-		ov511_do_dealloc(ov511);
+		ov51x_do_dealloc(ov);
 	else {
-		ov511->buf_state = BUF_PEND_DEALLOC;
+		ov->buf_state = BUF_PEND_DEALLOC;
 		init_timer(bt);
-		bt->function = ov511_buf_callback;
-		bt->data = (unsigned long)ov511;
+		bt->function = ov51x_buf_callback;
+		bt->data = (unsigned long)ov;
 		bt->expires = jiffies + buf_timeout * HZ;
 		add_timer(bt);
 	}
-	up(&ov511->buf_lock);
+	up(&ov->buf_lock);
 	PDEBUG(4, "leaving");
 }
 
 /****************************************************************************
  *
- * V4L API
+ * V4L 1 API
  *
  ***************************************************************************/
 
 static int 
-ov511_open(struct video_device *vdev, int flags)
+ov51x_v4l1_open(struct video_device *vdev, int flags)
 {
-	struct usb_ov511 *ov511 = vdev->priv;
+	struct usb_ov511 *ov = vdev->priv;
 	int err, i;
 
 	PDEBUG(4, "opening");
 
-	down(&ov511->lock);
+	down(&ov->lock);
 
 	err = -EBUSY;
-	if (ov511->user) 
+	if (ov->user) 
 		goto out;
 
 	err = -ENOMEM;
-	if (ov511_alloc(ov511))
+	if (ov51x_alloc(ov))
 		goto out;
 
-	ov511->sub_flag = 0;
+	ov->sub_flag = 0;
 
 	/* In case app doesn't set them... */
-	if (ov51x_set_default_params(ov511) < 0)
+	if (ov51x_set_default_params(ov) < 0)
 		goto out;
 
 	/* Make sure frames are reset */
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov511->frame[i].grabstate = FRAME_UNUSED;
-		ov511->frame[i].bytes_read = 0;
+		ov->frame[i].grabstate = FRAME_UNUSED;
+		ov->frame[i].bytes_read = 0;
 	}
 
 	/* If compression is on, make sure now that a 
 	 * decompressor can be loaded */
-	if (ov511->compress && !ov511->decomp_ops) {
-		err = ov51x_request_decompressor(ov511);
-		if (err)
+	if (ov->compress && !ov->decomp_ops) {
+		err = request_decompressor(ov);
+		if (err && !dumppix)
 			goto out;
 	}
 
-	err = ov511_init_isoc(ov511);
+	err = ov51x_init_isoc(ov);
 	if (err) {
-		ov511_dealloc(ov511, 0);
+		ov51x_dealloc(ov, 0);
 		goto out;
 	}
 
-	ov511->user++;
+	ov->user++;
 	
-	if (ov511->led_policy == LED_AUTO)
-		ov51x_led_control(ov511, 1);
+	if (ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 1);
 
 out:
-	up(&ov511->lock);
-
+	up(&ov->lock);
 	return err;
 }
 
 static void 
-ov511_close(struct video_device *dev)
+ov51x_v4l1_close(struct video_device *vdev)
 {
-	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+	struct usb_ov511 *ov = vdev->priv;
 
 	PDEBUG(4, "ov511_close");
 	
-	down(&ov511->lock);
+	down(&ov->lock);
 
-	ov511->user--;
-	ov511_stop_isoc(ov511);
+	ov->user--;
+	ov51x_stop_isoc(ov);
 
-	ov51x_release_decompressor(ov511);
+	release_decompressor(ov);
 
-	if (ov511->led_policy == LED_AUTO)
-		ov51x_led_control(ov511, 0);
+	if (ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
 
-	if (ov511->dev)
-		ov511_dealloc(ov511, 0);
+	if (ov->dev)
+		ov51x_dealloc(ov, 0);
 
-	up(&ov511->lock);
+	up(&ov->lock);
 
 	/* Device unplugged while open. Only a minimum of unregistration is done
 	 * here; the disconnect callback already did the rest. */
-	if (!ov511->dev) {
-		ov511_dealloc(ov511, 1);
-		video_unregister_device(&ov511->vdev);
-		kfree(ov511);
-		ov511 = NULL;
+	if (!ov->dev) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+
+		ov51x_dealloc(ov, 1);
+		video_unregister_device(&ov->vdev);
+		kfree(ov);
+		ov = NULL;
 	}
 }
 
 static int 
-ov511_init_done(struct video_device *vdev)
+ov51x_v4l1_init_done(struct video_device *vdev)
 {
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	create_proc_ov511_cam((struct usb_ov511 *)vdev);
+	create_proc_ov511_cam(vdev->priv);
 #endif
 
 	return 0;
 }
 
 static long 
-ov511_write(struct video_device *vdev, const char *buf,
-	    unsigned long count, int noblock)
+ov51x_v4l1_write(struct video_device *vdev, const char *buf,
+		 unsigned long count, int noblock)
 {
 	return -EINVAL;
 }
 
 /* Do not call this function directly! */
 static int 
-ov511_ioctl_internal(struct video_device *vdev, unsigned int cmd, void *arg)
+ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
+			  void *arg)
 {
-	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
+	struct usb_ov511 *ov = vdev->priv;
 
 	PDEBUG(5, "IOCtl: 0x%X", cmd);
 
-	if (!ov511->dev)
+	if (!ov->dev)
 		return -EIO;	
 
 	switch (cmd) {
@@ -4798,20 +4714,20 @@
 
 		memset(&b, 0, sizeof(b));
 		sprintf(b.name, "%s USB Camera",
-			ov511->bridge == BRG_OV511 ? "OV511" :
-			ov511->bridge == BRG_OV511PLUS ? "OV511+" :
-			ov511->bridge == BRG_OV518 ? "OV518" :
-			ov511->bridge == BRG_OV518PLUS ? "OV518+" :
+			ov->bridge == BRG_OV511 ? "OV511" :
+			ov->bridge == BRG_OV511PLUS ? "OV511+" :
+			ov->bridge == BRG_OV518 ? "OV518" :
+			ov->bridge == BRG_OV518PLUS ? "OV518+" :
 			"unknown");
 		b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
-		if (ov511->has_tuner)
+		if (ov->has_tuner)
 			b.type |= VID_TYPE_TUNER;
-		b.channels = ov511->num_inputs;
-		b.audios = ov511->has_audio_proc ? 1:0;
-		b.maxwidth = ov511->maxwidth;
-		b.maxheight = ov511->maxheight;
-		b.minwidth = ov511->minwidth;
-		b.minheight = ov511->minheight;
+		b.channels = ov->num_inputs;
+		b.audios = ov->has_audio_proc ? 1:0;
+		b.maxwidth = ov->maxwidth;
+		b.maxheight = ov->maxheight;
+		b.minwidth = ov->minwidth;
+		b.minheight = ov->minheight;
 
 		if (copy_to_user(arg, &b, sizeof(b)))
 			return -EFAULT;
@@ -4827,18 +4743,18 @@
 		if (copy_from_user(&v, arg, sizeof(v)))
 			return -EFAULT;
 
-		if ((unsigned)(v.channel) >= ov511->num_inputs) {
+		if ((unsigned)(v.channel) >= ov->num_inputs) {
 			err("Invalid channel (%d)", v.channel);
 			return -EINVAL;
 		}
 
-		v.norm = ov511->norm;
-		v.type = (ov511->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
-		v.flags = (ov511->has_tuner) ? VIDEO_VC_TUNER : 0;
-		v.flags |= (ov511->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
-//		v.flags |= (ov511->has_decoder) ? VIDEO_VC_NORM : 0;
-		v.tuners = (ov511->has_tuner) ? 1:0;
-		decoder_get_input_name(ov511, v.channel, v.name);
+		v.norm = ov->norm;
+		v.type = (ov->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
+		v.flags = (ov->has_tuner) ? VIDEO_VC_TUNER : 0;
+		v.flags |= (ov->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
+//		v.flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
+		v.tuners = (ov->has_tuner) ? 1:0;
+		decoder_get_input_name(ov, v.channel, v.name);
 
 		if (copy_to_user(arg, &v, sizeof(v)))
 			return -EFAULT;
@@ -4856,7 +4772,7 @@
 			return -EFAULT;
 
 		/* Make sure it's not a camera */
-		if (!ov511->has_decoder) {
+		if (!ov->has_decoder) {
 			if (v.channel == 0)
 				return 0;
 			else
@@ -4871,16 +4787,16 @@
 			return -EINVAL;
 		}
 
-		if ((unsigned)(v.channel) >= ov511->num_inputs) {
+		if ((unsigned)(v.channel) >= ov->num_inputs) {
 			err("Invalid channel (%d)", v.channel);
 			return -EINVAL;
 		}
 
-		err = decoder_set_input(ov511, v.channel);
+		err = decoder_set_input(ov, v.channel);
 		if (err)
 			return err;
 
-		err = decoder_set_norm(ov511, v.norm);
+		err = decoder_set_norm(ov, v.norm);
 		if (err)
 			return err;
 
@@ -4894,7 +4810,7 @@
 
 		memset(&p, 0, sizeof(p));
 
-		if (sensor_get_picture(ov511, &p))
+		if (sensor_get_picture(ov, &p))
 			return -EIO;
 
 		if (copy_to_user(arg, &p, sizeof(p)))
@@ -4912,10 +4828,10 @@
 		if (copy_from_user(&p, arg, sizeof(p)))
 			return -EFAULT;
 
-		if (!ov511_get_depth(p.palette))
+		if (!get_depth(p.palette))
 			return -EINVAL;
 
-		if (sensor_set_picture(ov511, &p))
+		if (sensor_set_picture(ov, &p))
 			return -EIO;
 
 		if (force_palette && p.palette != force_palette) {
@@ -4924,23 +4840,22 @@
 		}
 
 		// FIXME: Format should be independent of frames
-		if (p.palette != ov511->frame[0].format) {
+		if (p.palette != ov->frame[0].format) {
 			PDEBUG(4, "Detected format change");
 
 			/* If we're collecting previous frame wait
 			   before changing modes */
-			interruptible_sleep_on(&ov511->wq);
+			interruptible_sleep_on(&ov->wq);
 			if (signal_pending(current)) return -EINTR;
 
-			mode_init_regs(ov511, ov511->frame[0].width,
-				ov511->frame[0].height,	p.palette,
-				ov511->sub_flag);
+			mode_init_regs(ov, ov->frame[0].width,
+				ov->frame[0].height, p.palette, ov->sub_flag);
 		}
 
 		PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
 		for (i = 0; i < OV511_NUMFRAMES; i++) {
-			ov511->frame[i].depth = p.depth;
-			ov511->frame[i].format = p.palette;
+			ov->frame[i].depth = p.depth;
+			ov->frame[i].format = p.palette;
 		}
 
 		return 0;
@@ -4953,7 +4868,7 @@
 
 		if (copy_from_user(&vf, arg, sizeof(vf)))
 			return -EFAULT;
-		ov511->sub_flag = vf;
+		ov->sub_flag = vf;
 		return 0;
 	}
 	case VIDIOCSCAPTURE:
@@ -4981,10 +4896,10 @@
 		if (vc.height == 0)
 			vc.height = 16;
 
-		ov511->subx = vc.x;
-		ov511->suby = vc.y;
-		ov511->subw = vc.width;
-		ov511->subh = vc.height;
+		ov->subx = vc.x;
+		ov->suby = vc.y;
+		ov->subw = vc.width;
+		ov->subh = vc.height;
 
 		return 0;
 	}
@@ -5004,25 +4919,25 @@
 			return -EINVAL;
 		if (vw.clipcount)
 			return -EINVAL;
-		if (vw.height != ov511->maxheight)
+		if (vw.height != ov->maxheight)
 			return -EINVAL;
-		if (vw.width != ov511->maxwidth)
+		if (vw.width != ov->maxwidth)
 			return -EINVAL;
 #endif
 
 		/* If we're collecting previous frame wait
 		   before changing modes */
-		interruptible_sleep_on(&ov511->wq);
+		interruptible_sleep_on(&ov->wq);
 		if (signal_pending(current)) return -EINTR;
 
-		result = mode_init_regs(ov511, vw.width, vw.height,
-			ov511->frame[0].format, ov511->sub_flag);
+		result = mode_init_regs(ov, vw.width, vw.height,
+			ov->frame[0].format, ov->sub_flag);
 		if (result < 0)
 			return result;
 
 		for (i = 0; i < OV511_NUMFRAMES; i++) {
-			ov511->frame[i].width = vw.width;
-			ov511->frame[i].height = vw.height;
+			ov->frame[i].width = vw.width;
+			ov->frame[i].height = vw.height;
 		}
 
 		return 0;
@@ -5034,8 +4949,8 @@
 		memset(&vw, 0, sizeof(vw));
 		vw.x = 0;		/* FIXME */
 		vw.y = 0;
-		vw.width = ov511->frame[0].width;
-		vw.height = ov511->frame[0].height;
+		vw.width = ov->frame[0].width;
+		vw.height = ov->frame[0].height;
 		vw.flags = 30;
 
 		PDEBUG(4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
@@ -5054,13 +4969,13 @@
 
 		memset(&vm, 0, sizeof(vm));
 		vm.size = OV511_NUMFRAMES
-			* MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight);
+			* MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
 		vm.frames = OV511_NUMFRAMES;
 
 		vm.offsets[0] = 0;
 		for (i = 1; i < OV511_NUMFRAMES; i++) {
 			vm.offsets[i] = vm.offsets[i-1]
-			   + MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight);
+			   + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
 		}
 
 		if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
@@ -5080,7 +4995,7 @@
 		PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
 			vm.frame, vm.width, vm.height, vm.format);
 
-		depth = ov511_get_depth(vm.format);
+		depth = get_depth(vm.format);
 		if (!depth) {
 			err("VIDIOCMCAPTURE: invalid format (%d)", vm.format);
 			return -EINVAL;
@@ -5091,13 +5006,13 @@
 			return -EINVAL;
 		}
 
-		if (vm.width > ov511->maxwidth 
-		    || vm.height > ov511->maxheight) {
+		if (vm.width > ov->maxwidth 
+		    || vm.height > ov->maxheight) {
 			err("VIDIOCMCAPTURE: requested dimensions too big");
 			return -EINVAL;
 		}
 
-		if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING) {
+		if (ov->frame[vm.frame].grabstate == FRAME_GRABBING) {
 			PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
 			return -EBUSY;
 		}
@@ -5107,38 +5022,38 @@
 			return -EINVAL;
 		}
 
-		if ((ov511->frame[vm.frame].width != vm.width) ||
-		    (ov511->frame[vm.frame].height != vm.height) ||
-		    (ov511->frame[vm.frame].format != vm.format) ||
-		    (ov511->frame[vm.frame].sub_flag != ov511->sub_flag) ||
-		    (ov511->frame[vm.frame].depth != depth)) {
+		if ((ov->frame[vm.frame].width != vm.width) ||
+		    (ov->frame[vm.frame].height != vm.height) ||
+		    (ov->frame[vm.frame].format != vm.format) ||
+		    (ov->frame[vm.frame].sub_flag != ov->sub_flag) ||
+		    (ov->frame[vm.frame].depth != depth)) {
 			PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
 
 			/* If we're collecting previous frame wait
 			   before changing modes */
-			interruptible_sleep_on(&ov511->wq);
+			interruptible_sleep_on(&ov->wq);
 			if (signal_pending(current)) return -EINTR;
-			ret = mode_init_regs(ov511, vm.width, vm.height,
-				vm.format, ov511->sub_flag);
+			ret = mode_init_regs(ov, vm.width, vm.height,
+				vm.format, ov->sub_flag);
 #if 0
 			if (ret < 0) {
 				PDEBUG(1, "Got error while initializing regs ");
 				return ret;
 			}
 #endif
-			ov511->frame[vm.frame].width = vm.width;
-			ov511->frame[vm.frame].height = vm.height;
-			ov511->frame[vm.frame].format = vm.format;
-			ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
-			ov511->frame[vm.frame].depth = depth;
+			ov->frame[vm.frame].width = vm.width;
+			ov->frame[vm.frame].height = vm.height;
+			ov->frame[vm.frame].format = vm.format;
+			ov->frame[vm.frame].sub_flag = ov->sub_flag;
+			ov->frame[vm.frame].depth = depth;
 		}
 
 		/* Mark it as ready */
-		ov511->frame[vm.frame].grabstate = FRAME_READY;
+		ov->frame[vm.frame].grabstate = FRAME_READY;
 
 		PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", vm.frame);
 
-		return ov511_new_frame(ov511, vm.frame);
+		return ov51x_new_frame(ov, vm.frame);
 	}
 	case VIDIOCSYNC:
 	{
@@ -5153,7 +5068,7 @@
 			return -EINVAL;
 		}
 
-		frame = &ov511->frame[fnum];
+		frame = &ov->frame[fnum];
 
 		PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum,
 		       frame->grabstate);
@@ -5165,7 +5080,7 @@
 		case FRAME_GRABBING:
 		case FRAME_ERROR:
 redo:
-			if (!ov511->dev)
+			if (!ov->dev)
 				return -EIO;
 
 			rc = wait_event_interruptible(frame->wq,
@@ -5178,15 +5093,15 @@
 			if (frame->grabstate == FRAME_ERROR) {
 				int ret;
 
-				if ((ret = ov511_new_frame(ov511, fnum)) < 0)
+				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
 					return ret;
 				goto redo;
 			}
 			/* Fall through */			
 		case FRAME_DONE:
-			if (ov511->snap_enabled && !frame->snapshot) {
+			if (ov->snap_enabled && !frame->snapshot) {
 				int ret;
-				if ((ret = ov511_new_frame(ov511, fnum)) < 0)
+				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
 					return ret;
 				goto redo;
 			}
@@ -5195,13 +5110,13 @@
 
 			/* Reset the hardware snapshot button */
 			/* FIXME - Is this the best place for this? */
-			if ((ov511->snap_enabled) && (frame->snapshot)) {
+			if ((ov->snap_enabled) && (frame->snapshot)) {
 				frame->snapshot = 0;
-				ov51x_clear_snapshot(ov511);
+				ov51x_clear_snapshot(ov);
 			}
 
 			/* Decompression, format conversion, etc... */
-			ov511_postprocess(ov511, frame);
+			ov51x_postprocess(ov, frame);
 
 			break;
 		} /* end switch */
@@ -5230,7 +5145,7 @@
 
 		memset(&vu, 0, sizeof(vu));
 
-		vu.video = ov511->vdev.minor;	/* Video minor */
+		vu.video = ov->vdev.minor;	/* Video minor */
 		vu.vbi = VIDEO_NO_UNIT;		/* VBI minor */
 		vu.radio = VIDEO_NO_UNIT;	/* Radio minor */
 		vu.audio = VIDEO_NO_UNIT;	/* Audio minor */
@@ -5250,7 +5165,7 @@
 		if (copy_from_user(&v, arg, sizeof(v)))
 			return -EFAULT;
 
-		if (!ov511->has_tuner || v.tuner)	// Only tuner 0
+		if (!ov->has_tuner || v.tuner)	// Only tuner 0
 			return -EINVAL;
 
 		strcpy(v.name, "Television");
@@ -5264,7 +5179,7 @@
 		v.mode = 0; 		/* FIXME:  Not sure what this is yet */
 		v.signal = 0xFFFF;	/* unknown */
 
-		call_i2c_clients(ov511, cmd, &v);
+		call_i2c_clients(ov, cmd, &v);
 
 		if (copy_to_user(arg, &v, sizeof(v)))
 			return -EFAULT;
@@ -5282,7 +5197,7 @@
 			return -EFAULT;
 
 		/* Only no or one tuner for now */
-		if (!ov511->has_tuner || v.tuner)
+		if (!ov->has_tuner || v.tuner)
 			return -EINVAL;
 
 		/* and it only has certain valid modes */
@@ -5291,21 +5206,21 @@
 		    v.mode != VIDEO_MODE_SECAM) return -EOPNOTSUPP;
 
 		/* Is this right/necessary? */
-		err = decoder_set_norm(ov511, v.mode);
+		err = decoder_set_norm(ov, v.mode);
 		if (err)
 			return err;
 
-		call_i2c_clients(ov511, cmd, &v);
+		call_i2c_clients(ov, cmd, &v);
 
 		return 0;
 	}
 	case VIDIOCGFREQ:
 	{
-		unsigned long v = ov511->freq;
+		unsigned long v = ov->freq;
 
 		PDEBUG(4, "VIDIOCGFREQ");
 
-		if (!ov511->has_tuner)
+		if (!ov->has_tuner)
 			return -EINVAL;
 #if 0
 		/* FIXME: this is necessary for testing */
@@ -5320,7 +5235,7 @@
 	{
 		unsigned long v;
 
-		if (!ov511->has_tuner)
+		if (!ov->has_tuner)
 			return -EINVAL;
 
 		if (copy_from_user(&v, arg, sizeof(v)))
@@ -5328,8 +5243,8 @@
 
 		PDEBUG(4, "VIDIOCSFREQ: %lx", v);
 
-		ov511->freq = v;
-		call_i2c_clients(ov511, cmd, &v);
+		ov->freq = v;
+		call_i2c_clients(ov, cmd, &v);
 
 		return 0;
 	}
@@ -5348,29 +5263,29 @@
 }
 
 static int 
-ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+ov51x_v4l1_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
 	int rc;
-	struct usb_ov511 *ov511 = vdev->priv;
+	struct usb_ov511 *ov = vdev->priv;
 
-	if (down_interruptible(&ov511->lock))
+	if (down_interruptible(&ov->lock))
 		return -EINTR;
 
-	rc = ov511_ioctl_internal(vdev, cmd, arg);
+	rc = ov51x_v4l1_ioctl_internal(vdev, cmd, arg);
 
-	up(&ov511->lock);
+	up(&ov->lock);
 	return rc;
 }
 
 static inline long 
-ov511_read(struct video_device *vdev, char *buf, unsigned long count,
-	   int noblock)
+ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count,
+		int noblock)
 {
-	struct usb_ov511 *ov511 = vdev->priv;
+	struct usb_ov511 *ov = vdev->priv;
 	int i, rc = 0, frmx = -1;
 	struct ov511_frame *frame;
 
-	if (down_interruptible(&ov511->lock))
+	if (down_interruptible(&ov->lock))
 		return -EINTR;
 
 	PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
@@ -5380,16 +5295,16 @@
 		goto error;
 	}
 
-	if (!ov511->dev) {
+	if (!ov->dev) {
 		rc = -EIO;
 		goto error;
 	}
 
 // FIXME: Only supports two frames
 	/* See if a frame is completed, then use it. */
-	if (ov511->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
+	if (ov->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
 		frmx = 0;
-	else if (ov511->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
+	else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
 		frmx = 1;
 
 	/* If nonblocking we return immediately */
@@ -5401,24 +5316,24 @@
 	/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
 	/* See if a frame is in process (grabbing), then use it. */
 	if (frmx == -1) {
-		if (ov511->frame[0].grabstate == FRAME_GRABBING)
+		if (ov->frame[0].grabstate == FRAME_GRABBING)
 			frmx = 0;
-		else if (ov511->frame[1].grabstate == FRAME_GRABBING)
+		else if (ov->frame[1].grabstate == FRAME_GRABBING)
 			frmx = 1;
 	}
 
 	/* If no frame is active, start one. */
 	if (frmx == -1) {
-		if ((rc = ov511_new_frame(ov511, frmx = 0))) {
-			err("read: ov511_new_frame error");
+		if ((rc = ov51x_new_frame(ov, frmx = 0))) {
+			err("read: ov51x_new_frame error");
 			goto error;
 		}
 	}
 
-	frame = &ov511->frame[frmx];
+	frame = &ov->frame[frmx];
 
 restart:
-	if (!ov511->dev) {
+	if (!ov->dev) {
 		rc = -EIO;
 		goto error;
 	}
@@ -5437,9 +5352,9 @@
 
 	if (frame->grabstate == FRAME_ERROR) {
 		frame->bytes_read = 0;
-		err("** ick! ** Errored frame %d", ov511->curframe);
-		if (ov511_new_frame(ov511, frmx)) {
-			err("read: ov511_new_frame error");
+		err("** ick! ** Errored frame %d", ov->curframe);
+		if (ov51x_new_frame(ov, frmx)) {
+			err("read: ov51x_new_frame error");
 			goto error;
 		}
 		goto restart;
@@ -5447,25 +5362,25 @@
 
 
 	/* Repeat until we get a snapshot frame */
-	if (ov511->snap_enabled)
+	if (ov->snap_enabled)
 		PDEBUG(4, "Waiting snapshot frame");
-	if (ov511->snap_enabled && !frame->snapshot) {
+	if (ov->snap_enabled && !frame->snapshot) {
 		frame->bytes_read = 0;
-		if ((rc = ov511_new_frame(ov511, frmx))) {
-			err("read: ov511_new_frame error");
+		if ((rc = ov51x_new_frame(ov, frmx))) {
+			err("read: ov51x_new_frame error");
 			goto error;
 		}
 		goto restart;
 	}
 
 	/* Clear the snapshot */
-	if (ov511->snap_enabled && frame->snapshot) {
+	if (ov->snap_enabled && frame->snapshot) {
 		frame->snapshot = 0;
-		ov51x_clear_snapshot(ov511);
+		ov51x_clear_snapshot(ov);
 	}
 
 	/* Decompression, format conversion, etc... */
-	ov511_postprocess(ov511, frame);
+	ov51x_postprocess(ov, frame);
 
 	PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx,
 		frame->bytes_read,
@@ -5497,48 +5412,49 @@
 
 // FIXME: Only supports two frames
 		/* Mark it as available to be used again. */
-		ov511->frame[frmx].grabstate = FRAME_UNUSED;
-		if ((rc = ov511_new_frame(ov511, !frmx))) {
-			err("ov511_new_frame returned error");
+		ov->frame[frmx].grabstate = FRAME_UNUSED;
+		if ((rc = ov51x_new_frame(ov, !frmx))) {
+			err("ov51x_new_frame returned error");
 			goto error;
 		}
 	}
 
 	PDEBUG(4, "read finished, returning %ld (sweet)", count);
 
-	up(&ov511->lock);
+	up(&ov->lock);
 	return count;
 
 error:
-	up(&ov511->lock);
+	up(&ov->lock);
 	return rc;
 }
 
 static int 
-ov511_mmap(struct vm_area_struct *vma, struct video_device *vdev, const char *adr, unsigned long size)
+ov51x_v4l1_mmap(struct vm_area_struct *vma, struct video_device *vdev,
+		const char *adr, unsigned long size)
 {
-	struct usb_ov511 *ov511 = vdev->priv;
+	struct usb_ov511 *ov = vdev->priv;
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
-	if (ov511->dev == NULL)
+	if (ov->dev == NULL)
 		return -EIO;
 
 	PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
 
 	if (size > (((OV511_NUMFRAMES
-	              * MAX_DATA_SIZE(ov511->maxwidth, ov511->maxheight)
+	              * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
 	              + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
 		return -EINVAL;
 
-	if (down_interruptible(&ov511->lock))
+	if (down_interruptible(&ov->lock))
 		return -EINTR;
 
-	pos = (unsigned long)ov511->fbuf;
+	pos = (unsigned long)ov->fbuf;
 	while (size > 0) {
 		page = kvirt_to_pa(pos);
 		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			up(&ov511->lock);
+			up(&ov->lock);
 			return -EAGAIN;
 		}
 		start += PAGE_SIZE;
@@ -5549,31 +5465,31 @@
 			size = 0;
 	}
 
-	up(&ov511->lock);
+	up(&ov->lock);
 	return 0;
 }
 
-static struct video_device ov511_template = {
+static struct video_device vdev_template = {
 	owner:		THIS_MODULE,
 	name:		"OV511 USB Camera",
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_OV511,
-	open:		ov511_open,
-	close:		ov511_close,
-	read:		ov511_read,
-	write:		ov511_write,
-	ioctl:		ov511_ioctl,
-	mmap:		ov511_mmap,
-	initialize:	ov511_init_done,
+	open:		ov51x_v4l1_open,
+	close:		ov51x_v4l1_close,
+	read:		ov51x_v4l1_read,
+	write:		ov51x_v4l1_write,
+	ioctl:		ov51x_v4l1_ioctl,
+	mmap:		ov51x_v4l1_mmap,
+	initialize:	ov51x_v4l1_init_done,
 };
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 static int 
-ov511_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		    unsigned long ularg)
 {
 	struct proc_dir_entry *pde;
-	struct usb_ov511 *ov511;
+	struct usb_ov511 *ov;
 	void *arg = (void *) ularg;
 	int rc;
 
@@ -5581,11 +5497,11 @@
 	if (!pde)
 		return -ENOENT;
 
-	ov511 = (struct usb_ov511 *) pde->data;
-	if (!ov511)
+	ov = (struct usb_ov511 *) pde->data;
+	if (!ov)
 		return -ENODEV;
 
-	if (!ov511->dev)
+	if (!ov->dev)
 		return -EIO;
 
 	/* Should we pass through standard V4L IOCTLs? */
@@ -5610,19 +5526,19 @@
 
 		switch (opt.optnum) {
 		case OV511_USOPT_BRIGHT:
-			rc = sensor_get_brightness(ov511, &(opt.val));
+			rc = sensor_get_brightness(ov, &(opt.val));
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_SAT:
-			rc = sensor_get_saturation(ov511, &(opt.val));
+			rc = sensor_get_saturation(ov, &(opt.val));
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_HUE:
-			rc = sensor_get_hue(ov511, &(opt.val));
+			rc = sensor_get_hue(ov, &(opt.val));
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_CONTRAST:
-			rc = sensor_get_contrast(ov511, &(opt.val));
+			rc = sensor_get_contrast(ov, &(opt.val));
 			if (rc)	return rc;
 			break;
 		default:
@@ -5644,19 +5560,19 @@
 
 		switch (opt.optnum) {
 		case OV511_USOPT_BRIGHT:
-			rc = sensor_set_brightness(ov511, opt.val);
+			rc = sensor_set_brightness(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_SAT:
-			rc = sensor_set_saturation(ov511, opt.val);
+			rc = sensor_set_saturation(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_HUE:
-			rc = sensor_set_hue(ov511, opt.val);
+			rc = sensor_set_hue(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		case OV511_USOPT_CONTRAST:
-			rc = sensor_set_contrast(ov511, opt.val);
+			rc = sensor_set_contrast(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		default:
@@ -5675,19 +5591,19 @@
 
 		switch (opt.optnum) {
 		case OV511_UIOPT_POWER_FREQ:
-			opt.val = ov511->lightfreq;
+			opt.val = ov->lightfreq;
 			break;
 		case OV511_UIOPT_BFILTER:
-			opt.val = ov511->bandfilt;
+			opt.val = ov->bandfilt;
 			break;
 		case OV511_UIOPT_LED:
-			opt.val = ov511->led_policy;
+			opt.val = ov->led_policy;
 			break;
 		case OV511_UIOPT_DEBUG:
 			opt.val = debug;
 			break;
 		case OV511_UIOPT_COMPRESS:
-			opt.val = ov511->compress;
+			opt.val = ov->compress;
 			break;
 		default:
 			err("Invalid get int option number");
@@ -5708,20 +5624,20 @@
 
 		switch (opt.optnum) {
 		case OV511_UIOPT_POWER_FREQ:
-			rc = sensor_set_light_freq(ov511, opt.val);
+			rc = sensor_set_light_freq(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		case OV511_UIOPT_BFILTER:
-			rc = sensor_set_banding_filter(ov511, opt.val);
+			rc = sensor_set_banding_filter(ov, opt.val);
 			if (rc)	return rc;
 			break;
 		case OV511_UIOPT_LED:
 			if (opt.val <= 2) {
-				ov511->led_policy = opt.val;
-				if (ov511->led_policy == LED_OFF)
-					ov51x_led_control(ov511, 0);
-				else if (ov511->led_policy == LED_ON)
-					ov51x_led_control(ov511, 1);
+				ov->led_policy = opt.val;
+				if (ov->led_policy == LED_OFF)
+					ov51x_led_control(ov, 0);
+				else if (ov->led_policy == LED_ON)
+					ov51x_led_control(ov, 1);
 			} else {
 				return -EINVAL;
 			}
@@ -5733,14 +5649,12 @@
 				return -EINVAL;
 			break;
 		case OV511_UIOPT_COMPRESS:
-			ov511->compress = opt.val;
-			if (ov511->compress) {
-				if (ov511->bridge == BRG_OV511 ||
-				    ov511->bridge == BRG_OV511PLUS)
-					ov511_init_compression(ov511);
-				else if (ov511->bridge == BRG_OV518 ||
-					 ov511->bridge == BRG_OV518PLUS)
-					ov518_init_compression(ov511);
+			ov->compress = opt.val;
+			if (ov->compress) {
+				if (ov->bclass == BCL_OV511)
+					ov511_init_compression(ov);
+				else if (ov->bclass == BCL_OV518)
+					ov518_init_compression(ov);
 			}
 			break;
 		default:
@@ -5757,7 +5671,7 @@
 		if (copy_from_user(&w, arg, sizeof(w)))
 			return -EFAULT;
 
-		return ov51x_i2c_write_slave(ov511, w.slave, w.reg, w.value,
+		return i2c_w_slave(ov, w.slave, w.reg, w.value,
 			w.mask);
 	}
 	case OV511IOC_RI2C:
@@ -5767,7 +5681,7 @@
 		if (copy_from_user(&r, arg, sizeof(r)))
 			return -EFAULT;
 
-		rc = ov51x_i2c_read_slave(ov511, r.slave, r.reg);
+		rc = i2c_r_slave(ov, r.slave, r.reg);
 		if (rc < 0)
 			return rc;
 
@@ -5796,7 +5710,7 @@
  * the same register settings as the OV7610, since they are very similar.
  */
 static int 
-ov7xx0_configure(struct usb_ov511 *ov511)
+ov7xx0_configure(struct usb_ov511 *ov)
 {
 	int i, success;
 	int rc;
@@ -5913,16 +5827,15 @@
 	PDEBUG(4, "starting configuration");
 
 	/* This looks redundant, but is necessary for WebCam 3 */
-	ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
-	if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
-				OV7xx0_I2C_READ_ID) < 0)
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
 		return -1;
 
-	if (ov51x_init_ov_sensor(ov511) >= 0) {
+	if (init_ov_sensor(ov) >= 0) {
 		PDEBUG(1, "OV7xx0 sensor initalized (method 1)");
 	} else {
 		/* Reset the 76xx */
-		if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) return -1;
+		if (i2c_w(ov, 0x12, 0x80) < 0) return -1;
 
 		/* Wait for it to initialize */
 		schedule_timeout(1 + 150 * HZ / 1000);
@@ -5930,10 +5843,8 @@
 		i = 0;
 		success = 0;
 		while (i <= i2c_detect_tries) {
-			if ((ov51x_i2c_read(ov511,
-					    OV7610_REG_ID_HIGH) == 0x7F) &&
-			    (ov51x_i2c_read(ov511,
-					    OV7610_REG_ID_LOW) == 0xA2)) {
+			if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
+			    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
 				success = 1;
 				break;
 			} else {
@@ -5957,17 +5868,17 @@
 	}
 
 	/* Detect sensor (sub)type */
-	rc = ov51x_i2c_read(ov511, OV7610_REG_COM_I);
+	rc = i2c_r(ov, OV7610_REG_COM_I);
 
 	if (rc < 0) {
 		err("Error detecting sensor type");
 		return -1;
 	} else if ((rc & 3) == 3) {
 		info("Sensor is an OV7610");
-		ov511->sensor = SEN_OV7610;
+		ov->sensor = SEN_OV7610;
 	} else if ((rc & 3) == 1) {
 		/* I don't know what's different about the 76BE yet */
-		if (ov51x_i2c_read(ov511, 0x15) & 1)
+		if (i2c_r(ov, 0x15) & 1)
 			info("Sensor is an OV7620AE");
 		else
 			info("Sensor is an OV76BE");
@@ -5975,48 +5886,48 @@
 		/* OV511+ will return all zero isoc data unless we
 		 * configure the sensor as a 7620. Someone needs to
 		 * find the exact reg. setting that causes this. */
-		if (ov511->bridge == BRG_OV511PLUS) {
+		if (ov->bridge == BRG_OV511PLUS) {
 			info("Enabling 511+/7620AE workaround");
-			ov511->sensor = SEN_OV7620;
+			ov->sensor = SEN_OV7620;
 		} else {
-			ov511->sensor = SEN_OV7620AE;
+			ov->sensor = SEN_OV7620AE;
 		}
 	} else if ((rc & 3) == 0) {
 		info("Sensor is an OV7620");
-		ov511->sensor = SEN_OV7620;
+		ov->sensor = SEN_OV7620;
 	} else {
 		err("Unknown image sensor version: %d", rc & 3);
 		return -1;
 	}
 
-	if (ov511->sensor == SEN_OV7620) {
+	if (ov->sensor == SEN_OV7620) {
 		PDEBUG(4, "Writing 7620 registers");
-		if (ov511_write_regvals(ov511, aRegvalsNorm7620))
+		if (write_regvals(ov, aRegvalsNorm7620))
 			return -1;
 	} else {
 		PDEBUG(4, "Writing 7610 registers");
-		if (ov511_write_regvals(ov511, aRegvalsNorm7610))
+		if (write_regvals(ov, aRegvalsNorm7610))
 			return -1;
 	}
 
 	/* Set sensor-specific vars */
-	ov511->maxwidth = 640;
-	ov511->maxheight = 480;
-	ov511->minwidth = 64;
-	ov511->minheight = 48;
+	ov->maxwidth = 640;
+	ov->maxheight = 480;
+	ov->minwidth = 64;
+	ov->minheight = 48;
 
 	// FIXME: These do not match the actual settings yet
-	ov511->brightness = 0x80 << 8;
-	ov511->contrast = 0x80 << 8;
-	ov511->colour = 0x80 << 8;
-	ov511->hue = 0x80 << 8;
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
 
 	return 0;
 }
 
 /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
 static int 
-ov6xx0_configure(struct usb_ov511 *ov511)
+ov6xx0_configure(struct usb_ov511 *ov)
 {
 	int rc;
 
@@ -6142,7 +6053,7 @@
 
 	PDEBUG(4, "starting sensor configuration");
 	
-	if (ov51x_init_ov_sensor(ov511) < 0) {
+	if (init_ov_sensor(ov) < 0) {
 		err("Failed to read sensor ID. You might not have an OV6xx0,");
 		err("or it may be not responding. Report this to " EMAIL);
 		return -1;
@@ -6151,50 +6062,44 @@
 	}
 
 	/* Detect sensor (sub)type */
-	rc = ov51x_i2c_read(ov511, OV7610_REG_COM_I);
+	rc = i2c_r(ov, OV7610_REG_COM_I);
 
 	if (rc < 0) {
 		err("Error detecting sensor type");
 		return -1;
 	} else if ((rc & 3) == 0) {
 		info("Sensor is an OV6630");
-		ov511->sensor = SEN_OV6630;
+		ov->sensor = SEN_OV6630;
 	} else if ((rc & 3) == 1) {
 		info("Sensor is an OV6620");
-		ov511->sensor = SEN_OV6620;
+		ov->sensor = SEN_OV6620;
 	} else if ((rc & 3) == 2) {
 		info("Sensor is an OV6630AE");
-		ov511->sensor = SEN_OV6630;
+		ov->sensor = SEN_OV6630;
 	} else if ((rc & 3) == 3) {
 		info("Sensor is an OV6630AF");
-		ov511->sensor = SEN_OV6630;
+		ov->sensor = SEN_OV6630;
 	} 
 
 	/* Set sensor-specific vars */
-	if (ov511->sensor == SEN_OV6620) {
-		ov511->maxwidth = 352;
-		ov511->maxheight = 288;
-	} else {
-		/* 352x288 not working with OV518 yet */
-		ov511->maxwidth = 320;
-		ov511->maxheight = 240;
-	}
-	ov511->minwidth = 64;
-	ov511->minheight = 48;
+	ov->maxwidth = 352;
+	ov->maxheight = 288;
+	ov->minwidth = 64;
+	ov->minheight = 48;
 
 	// FIXME: These do not match the actual settings yet
-	ov511->brightness = 0x80 << 8;
-	ov511->contrast = 0x80 << 8;
-	ov511->colour = 0x80 << 8;
-	ov511->hue = 0x80 << 8;
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
 
-	if (ov511->sensor == SEN_OV6620) {
+	if (ov->sensor == SEN_OV6620) {
 		PDEBUG(4, "Writing 6x20 registers");
-		if (ov511_write_regvals(ov511, aRegvalsNorm6x20))
+		if (write_regvals(ov, aRegvalsNorm6x20))
 			return -1;
 	} else {
 		PDEBUG(4, "Writing 6x30 registers");
-		if (ov511_write_regvals(ov511, aRegvalsNorm6x30))
+		if (write_regvals(ov, aRegvalsNorm6x30))
 			return -1;
 	}
 	
@@ -6203,13 +6108,13 @@
 
 /* This initializes the KS0127 and KS0127B video decoders. */
 static int 
-ks0127_configure(struct usb_ov511 *ov511)
+ks0127_configure(struct usb_ov511 *ov)
 {
 	int rc;
 
 // FIXME: I don't know how to sync or reset it yet
 #if 0
-	if (ov51x_init_ks_sensor(ov511) < 0) {
+	if (ov51x_init_ks_sensor(ov) < 0) {
 		err("Failed to initialize the KS0127");
 		return -1;
 	} else {
@@ -6218,21 +6123,21 @@
 #endif
 
 	/* Detect decoder subtype */
-	rc = ov51x_i2c_read(ov511, 0x00);
+	rc = i2c_r(ov, 0x00);
 	if (rc < 0) {
 		err("Error detecting sensor type");
 		return -1;
 	} else if (rc & 0x08) {
-		rc = ov51x_i2c_read(ov511, 0x3d);
+		rc = i2c_r(ov, 0x3d);
 		if (rc < 0) {
 			err("Error detecting sensor type");
 			return -1;
 		} else if ((rc & 0x0f) == 0) {
 			info("Sensor is a KS0127");
-			ov511->sensor = SEN_KS0127;
+			ov->sensor = SEN_KS0127;
 		} else if ((rc & 0x0f) == 9) {
 			info("Sensor is a KS0127B Rev. A");
-			ov511->sensor = SEN_KS0127B;
+			ov->sensor = SEN_KS0127B;
 		}
 	} else {
 		err("Error: Sensor is an unsupported KS0122");
@@ -6240,16 +6145,16 @@
 	}
 
 	/* Set sensor-specific vars */
-	ov511->maxwidth = 640;
-	ov511->maxheight = 480;
-	ov511->minwidth = 64;
-	ov511->minheight = 48;
+	ov->maxwidth = 640;
+	ov->maxheight = 480;
+	ov->minwidth = 64;
+	ov->minheight = 48;
 
 	// FIXME: These do not match the actual settings yet
-	ov511->brightness = 0x80 << 8;
-	ov511->contrast = 0x80 << 8;
-	ov511->colour = 0x80 << 8;
-	ov511->hue = 0x80 << 8;
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
 
 	/* This device is not supported yet. Bail out now... */
 	err("This sensor is not supported yet.");
@@ -6262,7 +6167,6 @@
 static int 
 saa7111a_configure(struct usb_ov511 *ov511)
 {
-	struct usb_device *dev = ov511->dev;
 	int rc;
 
 	/* Since there is no register reset command, all registers must be
@@ -6297,7 +6201,7 @@
 
 // FIXME: I don't know how to sync or reset it yet
 #if 0
-	if (ov51x_init_saa_sensor(ov511) < 0) {
+	if (ov51x_init_saa_sensor(ov) < 0) {
 		err("Failed to initialize the SAA7111A");
 		return -1;
 	} else {
@@ -6324,12 +6228,12 @@
 	ov511->hue = 32768;
 
 	PDEBUG(4, "Writing SAA7111A registers");
-	if (ov511_write_regvals(ov511, aRegvalsNormSAA7111A))
+	if (write_regvals(ov511, aRegvalsNormSAA7111A))
 		return -1;
 
 	/* Detect version of decoder. This must be done after writing the
          * initial regs or the decoder will lock up. */
-	rc = ov51x_i2c_read(ov511, 0x00);
+	rc = i2c_r(ov511, 0x00);
 
 	if (rc < 0) {
 		err("Error detecting sensor version");
@@ -6342,8 +6246,8 @@
 	// FIXME: Fix this for OV518(+)
 	/* Latch to negative edge of clock. Otherwise, we get incorrect
 	 * colors and jitter in the digital signal. */
-	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS)
-		ov511_reg_write(dev, 0x11, 0x00);
+	if (ov511->bclass == BCL_OV511)
+		reg_w(ov511, 0x11, 0x00);
 	else
 		warn("SAA7111A not yet supported with OV518/OV518+");
 
@@ -6352,144 +6256,138 @@
 
 /* This initializes the OV511/OV511+ and the sensor */
 static int 
-ov511_configure(struct usb_ov511 *ov511)
+ov511_configure(struct usb_ov511 *ov)
 {
-	struct usb_device *dev = ov511->dev;
 	int i;
 
 	static struct ov511_regvals aRegvalsInit511[] = {
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
-	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
-	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
+	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3f },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3d },
 		{ OV511_DONE_BUS, 0x0, 0x00},
 	};
 
 	static struct ov511_regvals aRegvalsNorm511[] = {
-		{ OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x03 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f },
-		{ OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x00 },
-		{ OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
+		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL, 	0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R511_FIFO_OPTS,	0x1f },
+		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
+		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
 		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
 	static struct ov511_regvals aRegvalsNorm511Plus[] = {
-		{ OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0xff },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x03 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x01 },
-		{ OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0xff },
-		{ OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x00 },
-		{ OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
+		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL,	0xff },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R511_FIFO_OPTS,	0xff },
+		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
+		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
 		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
 	PDEBUG(4, "");
 
-	ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
-	if (ov511->customid < 0) {
+	ov->customid = reg_r(ov, R511_SYS_CUST_ID);
+	if (ov->customid < 0) {
 		err("Unable to read camera bridge registers");
 		goto error;
 	}
 
-	ov511->desc = -1;
-	PDEBUG (1, "CustomID = %d", ov511->customid);
+	ov->desc = -1;
+	PDEBUG (1, "CustomID = %d", ov->customid);
 	for (i = 0; clist[i].id >= 0; i++) {
-		if (ov511->customid == clist[i].id) {
+		if (ov->customid == clist[i].id) {
 			info("model: %s", clist[i].description);
-			ov511->desc = i;
+			ov->desc = i;
 			break;
 		}
 	}
 
 	if (clist[i].id == -1) {
-		err("Camera type (%d) not recognized", ov511->customid);
+		err("Camera type (%d) not recognized", ov->customid);
 		err("Please notify " EMAIL " of the name,");
 		err("manufacturer, model, and this number of your camera.");
 		err("Also include the output of the detection process.");
 	} 
 
 	if (clist[i].id == 6) {	/* USB Life TV (NTSC) */
-		ov511->tuner_type = 8;		/* Temic 4036FY5 3X 1981 */
+		ov->tuner_type = 8;		/* Temic 4036FY5 3X 1981 */
 	}
 
-	if (ov511_write_regvals(ov511, aRegvalsInit511)) goto error;
+	if (write_regvals(ov, aRegvalsInit511)) goto error;
 
-	if (ov511->led_policy == LED_OFF || ov511->led_policy == LED_AUTO)
-		ov51x_led_control(ov511, 0);
+	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
 
 	/* The OV511+ has undocumented bits in the flow control register.
 	 * Setting it to 0xff fixes the corruption with moving objects. */
-	if (ov511->bridge == BRG_OV511) {
-		if (ov511_write_regvals(ov511, aRegvalsNorm511)) goto error;
-	} else if (ov511->bridge == BRG_OV511PLUS) {
-		if (ov511_write_regvals(ov511, aRegvalsNorm511Plus)) goto error;
+	if (ov->bridge == BRG_OV511) {
+		if (write_regvals(ov, aRegvalsNorm511)) goto error;
+	} else if (ov->bridge == BRG_OV511PLUS) {
+		if (write_regvals(ov, aRegvalsNorm511Plus)) goto error;
 	} else {
 		err("Invalid bridge");
 	}
 
-	if (ov511_init_compression(ov511)) goto error;
+	if (ov511_init_compression(ov)) goto error;
 
-	ov511_set_packet_size(ov511, 0);
+	ov51x_set_packet_size(ov, 0);
 
-	ov511->snap_enabled = snapshot;	
+	ov->snap_enabled = snapshot;	
 
 	/* Test for 7xx0 */
 	PDEBUG(3, "Testing for 0V7xx0");
-	ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
-	if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
-				OV7xx0_I2C_READ_ID) < 0)
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
 		goto error;
 
-	if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+	if (i2c_w(ov, 0x12, 0x80) < 0) {
 		/* Test for 6xx0 */
 		PDEBUG(3, "Testing for 0V6xx0");
-		ov511->primary_i2c_slave = OV6xx0_I2C_WRITE_ID;
-		if (ov51x_set_slave_ids(ov511, OV6xx0_I2C_WRITE_ID,
-					OV6xx0_I2C_READ_ID) < 0)
+		ov->primary_i2c_slave = OV6xx0_SID;
+		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
 			goto error;
 
-		if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+		if (i2c_w(ov, 0x12, 0x80) < 0) {
 			/* Test for 8xx0 */
 			PDEBUG(3, "Testing for 0V8xx0");
-			ov511->primary_i2c_slave = OV8xx0_I2C_WRITE_ID;
-			if (ov51x_set_slave_ids(ov511, OV8xx0_I2C_WRITE_ID,
-						OV8xx0_I2C_READ_ID))
+			ov->primary_i2c_slave = OV8xx0_SID;
+			if (ov51x_set_slave_ids(ov, OV8xx0_SID))
 				goto error;
 
-			if (ov51x_i2c_write(ov511, 0x12, 0x80) < 0) {
+			if (i2c_w(ov, 0x12, 0x80) < 0) {
 				/* Test for SAA7111A */
 				PDEBUG(3, "Testing for SAA7111A");
-				ov511->primary_i2c_slave = SAA7111A_I2C_WRITE_ID;
-				if (ov51x_set_slave_ids(ov511, SAA7111A_I2C_WRITE_ID,
-							SAA7111A_I2C_READ_ID))
+				ov->primary_i2c_slave = SAA7111A_SID;
+				if (ov51x_set_slave_ids(ov, SAA7111A_SID))
 					goto error;
 
-				if (ov51x_i2c_write(ov511, 0x0d, 0x00) < 0) {
+				if (i2c_w(ov, 0x0d, 0x00) < 0) {
 					/* Test for KS0127 */
 					PDEBUG(3, "Testing for KS0127");
-					ov511->primary_i2c_slave = KS0127_I2C_WRITE_ID;
-					if (ov51x_set_slave_ids(ov511, KS0127_I2C_WRITE_ID,
-								KS0127_I2C_READ_ID))
+					ov->primary_i2c_slave = KS0127_SID;
+					if (ov51x_set_slave_ids(ov, KS0127_SID))
 						goto error;
 
-					if (ov51x_i2c_write(ov511, 0x10, 0x00) < 0) {
+					if (i2c_w(ov, 0x10, 0x00) < 0) {
 						err("Can't determine sensor slave IDs");
 		 				goto error;
 					} else {
-						if(ks0127_configure(ov511) < 0) {
+						if (ks0127_configure(ov) < 0) {
 							err("Failed to configure KS0127");
 	 						goto error;
 						}
 					}
 				} else {
-					if(saa7111a_configure(ov511) < 0) {
+					if (saa7111a_configure(ov) < 0) {
 						err("Failed to configure SAA7111A");
 	 					goto error;
 					}
@@ -6499,13 +6397,13 @@
 				goto error;
 			}
 		} else {
-			if(ov6xx0_configure(ov511) < 0) {
+			if (ov6xx0_configure(ov) < 0) {
 				err("Failed to configure OV6xx0");
  				goto error;
 			}
 		}
 	} else {
-		if(ov7xx0_configure(ov511) < 0) {
+		if (ov7xx0_configure(ov) < 0) {
 			err("Failed to configure OV7xx0");
 	 		goto error;
 		}
@@ -6521,96 +6419,90 @@
 
 /* This initializes the OV518/OV518+ and the sensor */
 static int 
-ov518_configure(struct usb_ov511 *ov511)
+ov518_configure(struct usb_ov511 *ov)
 {
-	struct usb_device *dev = ov511->dev;
-
 	static struct ov511_regvals aRegvalsInit518[] = {
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x40 },
-	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
-	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3e },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x00 },
-		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0xe1 },
-		{ OV511_REG_BUS, 0x46, 0x00 }, 
-		{ OV511_REG_BUS, 0x5d, 0x03 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x40 },
+	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x3e },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x00 },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+		{ OV511_REG_BUS, 0x46,			0x00 }, 
+		{ OV511_REG_BUS, 0x5d,			0x03 },
 		{ OV511_DONE_BUS, 0x0, 0x00},
 	};
 
 	/* New values, based on Windows driver. Since what they do is not
 	 * known yet, this may be incorrect. */
 	static struct ov511_regvals aRegvalsNorm518[] = {
-		{ OV511_REG_BUS, 0x52, 0x02 }, /* Reset snapshot */
-		{ OV511_REG_BUS, 0x52, 0x01 }, /* Enable snapshot */
-		{ OV511_REG_BUS, 0x31, 0x0f },
-		{ OV511_REG_BUS, 0x5d, 0x03 },
-		{ OV511_REG_BUS, 0x24, 0x9f },
-		{ OV511_REG_BUS, 0x25, 0x90 },
-		{ OV511_REG_BUS, 0x20, 0x00 }, /* Was 0x08 */
-		{ OV511_REG_BUS, 0x51, 0x04 },
-		{ OV511_REG_BUS, 0x71, 0x19 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x02 }, /* Reset */
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 }, /* Enable */
+		{ OV511_REG_BUS, 0x31, 			0x0f },
+		{ OV511_REG_BUS, 0x5d,			0x03 },
+		{ OV511_REG_BUS, 0x24,			0x9f },
+		{ OV511_REG_BUS, 0x25,			0x90 },
+		{ OV511_REG_BUS, 0x20,			0x00 }, /* Was 0x08 */
+		{ OV511_REG_BUS, 0x51,			0x04 },
+		{ OV511_REG_BUS, 0x71,			0x19 },
 		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
 	PDEBUG(4, "");
 
 	/* First 5 bits of custom ID reg are a revision ID on OV518 */
-	info("Device revision %d",
-	     0x1F & ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID));
+	info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
 
-	if (ov511_write_regvals(ov511, aRegvalsInit518)) goto error;
+	if (write_regvals(ov, aRegvalsInit518)) goto error;
 
 	/* Set LED GPIO pin to output mode */
-	if (ov511_reg_write_mask(dev, 0x57,0x00, 0x02) < 0) goto error;
+	if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) goto error;
 
 	/* LED is off by default with OV518; have to explicitly turn it on */
-	if (ov511->led_policy == LED_OFF || ov511->led_policy == LED_AUTO)
-		ov51x_led_control(ov511, 0);
+	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
 	else
-		ov51x_led_control(ov511, 1);
+		ov51x_led_control(ov, 1);
 
 	/* Don't require compression if dumppix is enabled; otherwise it's
 	 * required. OV518 has no uncompressed mode, to save RAM. */
-	if (!dumppix && !ov511->compress) {
-		ov511->compress = 1;
+	if (!dumppix && !ov->compress) {
+		ov->compress = 1;
 		warn("Compression required with OV518...enabling");
 	}
 
-	if (ov511_write_regvals(ov511, aRegvalsNorm518)) goto error;
+	if (write_regvals(ov, aRegvalsNorm518)) goto error;
 
-	if (ov511_reg_write(dev, 0x2f,0x80) < 0) goto error;
+	if (reg_w(ov, 0x2f, 0x80) < 0) goto error;
 
-	if (ov518_init_compression(ov511)) goto error;
+	if (ov518_init_compression(ov)) goto error;
 
-	ov511_set_packet_size(ov511, 0);
+	ov51x_set_packet_size(ov, 0);
 
-	ov511->snap_enabled = snapshot;
+	ov->snap_enabled = snapshot;
 
 	/* Test for 76xx */
-	ov511->primary_i2c_slave = OV7xx0_I2C_WRITE_ID;
-	if (ov51x_set_slave_ids(ov511, OV7xx0_I2C_WRITE_ID,
-				OV7xx0_I2C_READ_ID) < 0)
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
 		goto error;
 
 	/* The OV518 must be more aggressive about sensor detection since
 	 * I2C write will never fail if the sensor is not present. We have
 	 * to try to initialize the sensor to detect its presence */
 
-	if (ov51x_init_ov_sensor(ov511) < 0) {
+	if (init_ov_sensor(ov) < 0) {
 		/* Test for 6xx0 */
-		ov511->primary_i2c_slave = OV6xx0_I2C_WRITE_ID;
-		if (ov51x_set_slave_ids(ov511, OV6xx0_I2C_WRITE_ID,
-					OV6xx0_I2C_READ_ID) < 0)
+		ov->primary_i2c_slave = OV6xx0_SID;
+		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
 			goto error;
 
-		if (ov51x_init_ov_sensor(ov511) < 0) {
+		if (init_ov_sensor(ov) < 0) {
 			/* Test for 8xx0 */
-			ov511->primary_i2c_slave = OV8xx0_I2C_WRITE_ID;
-			if (ov51x_set_slave_ids(ov511, OV8xx0_I2C_WRITE_ID,
-						OV8xx0_I2C_READ_ID) < 0)
+			ov->primary_i2c_slave = OV8xx0_SID;
+			if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0)
 				goto error;
 
-			if (ov51x_init_ov_sensor(ov511) < 0) {
+			if (init_ov_sensor(ov) < 0) {
 				err("Can't determine sensor slave IDs");
  				goto error;
 			} else {
@@ -6618,21 +6510,25 @@
 				goto error;
 			}
 		} else {
-			if (ov6xx0_configure(ov511) < 0) {
+			if (ov6xx0_configure(ov) < 0) {
 				err("Failed to configure OV6xx0");
  				goto error;
 			}
 		}
 	} else {
-		if (ov7xx0_configure(ov511) < 0) {
+		if (ov7xx0_configure(ov) < 0) {
 			err("Failed to configure OV7xx0");
 	 		goto error;
 		}
 	}
 
+	// FIXME: Sizes > 320x240 are not working yet
+	ov->maxwidth = 320;
+	ov->maxheight = 240;
+
 	// The OV518 cannot go as low as the sensor can
-	ov511->minwidth = 160;
-	ov511->minheight = 120;
+	ov->minwidth = 160;
+	ov->minheight = 120;
 
 	return 0;
 
@@ -6649,12 +6545,13 @@
  *
  ***************************************************************************/
 
+/* 2.2.x compatibility */
 static void *
 ov51x_probe(struct usb_device *dev, unsigned int ifnum,
 	    const struct usb_device_id *id)
 {
 	struct usb_interface_descriptor *interface;
-	struct usb_ov511 *ov511;
+	struct usb_ov511 *ov;
 	int i;
 	int registered = 0;
 
@@ -6672,57 +6569,54 @@
 	if (interface->bInterfaceSubClass != 0x00)
 		return NULL;
 
-	/* Since code below may sleep, we use this as a lock */
-	MOD_INC_USE_COUNT;
-
-	if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
-		err("couldn't kmalloc ov511 struct");
-		goto error_unlock;
-	}
-
-	memset(ov511, 0, sizeof(*ov511));
-
-	ov511->dev = dev;
-	ov511->iface = interface->bInterfaceNumber;
-	ov511->led_policy = led;
-	ov511->compress = compress;
-	ov511->lightfreq = lightfreq;
-	ov511->num_inputs = 1;	   /* Video decoder init functs. change this */
-	ov511->stop_during_set = !fastset;
-	ov511->tuner_type = tuner;
-	ov511->backlight = backlight;
-
-	ov511->auto_brt = autobright;
-	ov511->auto_gain = autogain;
-	ov511->auto_exp = autoexp;
+	if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
+		err("couldn't kmalloc ov struct");
+		goto error_out;
+	}
+
+	memset(ov, 0, sizeof(*ov));
+
+	ov->dev = dev;
+	ov->iface = interface->bInterfaceNumber;
+	ov->led_policy = led;
+	ov->compress = compress;
+	ov->lightfreq = lightfreq;
+	ov->num_inputs = 1;	   /* Video decoder init functs. change this */
+	ov->stop_during_set = !fastset;
+	ov->tuner_type = tuner;
+	ov->backlight = backlight;
+
+	ov->auto_brt = autobright;
+	ov->auto_gain = autogain;
+	ov->auto_exp = autoexp;
 
 	switch (dev->descriptor.idProduct) {
 	case PROD_OV511:
 		info("USB OV511 camera found");
-		ov511->bridge = BRG_OV511;
-		ov511->bclass = BCL_OV511;
+		ov->bridge = BRG_OV511;
+		ov->bclass = BCL_OV511;
 		break;
 	case PROD_OV511PLUS:
 		info("USB OV511+ camera found");
-		ov511->bridge = BRG_OV511PLUS;
-		ov511->bclass = BCL_OV511;
+		ov->bridge = BRG_OV511PLUS;
+		ov->bclass = BCL_OV511;
 		break;
 	case PROD_OV518:
 		info("USB OV518 camera found");
-		ov511->bridge = BRG_OV518;
-		ov511->bclass = BCL_OV518;
+		ov->bridge = BRG_OV518;
+		ov->bclass = BCL_OV518;
 		break;
 	case PROD_OV518PLUS:
 		info("USB OV518+ camera found");
-		ov511->bridge = BRG_OV518PLUS;
-		ov511->bclass = BCL_OV518;
+		ov->bridge = BRG_OV518PLUS;
+		ov->bclass = BCL_OV518;
 		break;
 	case PROD_ME2CAM:
 		if (dev->descriptor.idVendor != VEND_MATTEL)
 			goto error;
 		info("Intel Play Me2Cam (OV511+) found");
-		ov511->bridge = BRG_OV511PLUS;
-		ov511->bclass = BCL_OV511;
+		ov->bridge = BRG_OV511PLUS;
+		ov->bclass = BCL_OV511;
 		break;
 	default:
 		err("Unknown product ID 0x%x", dev->descriptor.idProduct);
@@ -6734,47 +6628,53 @@
 	if (force_rgb)
 		info("data format set to RGB");
 
-	init_waitqueue_head(&ov511->wq);
+	init_waitqueue_head(&ov->wq);
+
+	init_MUTEX(&ov->lock);	/* to 1 == available */
+	init_MUTEX(&ov->buf_lock);
+	init_MUTEX(&ov->param_lock);
+	init_MUTEX(&ov->i2c_lock);
+	init_MUTEX(&ov->cbuf_lock);
+
+	ov->buf_state = BUF_NOT_ALLOCATED;
+
+	/* Must be kmalloc()'ed, for DMA accessibility */
+	ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
+	if (!ov->cbuf)
+		goto error;
 
-	init_MUTEX(&ov511->lock);	/* to 1 == available */
-	init_MUTEX(&ov511->buf_lock);
-	init_MUTEX(&ov511->param_lock);
-	init_MUTEX(&ov511->i2c_lock);
-	ov511->buf_state = BUF_NOT_ALLOCATED;
-
-	if (ov511->bridge == BRG_OV518 ||
-	    ov511->bridge == BRG_OV518PLUS) {
-		if (ov518_configure(ov511) < 0)
+	if (ov->bclass == BCL_OV518) {
+		if (ov518_configure(ov) < 0)
 			goto error;
 	} else {
-		if (ov511_configure(ov511) < 0)
+		if (ov511_configure(ov) < 0)
 			goto error;
 	}
 
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov511->frame[i].framenum = i;
-		init_waitqueue_head(&ov511->frame[i].wq);
+		ov->frame[i].framenum = i;
+		init_waitqueue_head(&ov->frame[i].wq);
 	}
 
 	/* Unnecessary? (This is done on open(). Need to make sure variables
 	 * are properly initialized without this before removing it, though). */
-	if (ov51x_set_default_params(ov511) < 0)
+	if (ov51x_set_default_params(ov) < 0)
 		goto error;
 
 #ifdef OV511_DEBUG
 	if (dump_bridge)
-		ov511_dump_regs(dev);
+		ov511_dump_regs(ov);
 #endif
 
-	memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
-	ov511->vdev.priv = ov511;
+	memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template));
+	ov->vdev.priv = ov;
 
 	for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
 		/* Minor 0 cannot be specified; assume user wants autodetect */
 		if (unit_video[i] == 0)
 			break;
 
-		if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER,
+		if (video_register_device(&ov->vdev, VFL_TYPE_GRABBER,
 			unit_video[i]) >= 0) {
 			registered = 1;
 			break;
@@ -6783,35 +6683,40 @@
 
 	/* Use the next available one */
 	if (!registered &&
-	    video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, -1) < 0) {
+	    video_register_device(&ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
 		err("video_register_device failed");
 		goto error;
 	}
 
-	info("Device registered on minor %d", ov511->vdev.minor);
+	info("Device registered on minor %d", ov->vdev.minor);
 
-	MOD_DEC_USE_COUNT;
-     	return ov511;
+     	return ov;
 
 error:
 	err("Camera initialization failed");
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 	/* Safe to call even if entry doesn't exist */
-	destroy_proc_ov511_cam(ov511);
+	destroy_proc_ov511_cam(ov);
 #endif
 
+	if (ov->cbuf) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+	}
+
 	usb_driver_release_interface(&ov511_driver,
-		&dev->actconfig->interface[ov511->iface]);
+		&dev->actconfig->interface[ov->iface]);
 
 error_dealloc:
-	if (ov511) {
-		kfree(ov511);
-		ov511 = NULL;
+	if (ov) {
+		kfree(ov);
+		ov = NULL;
 	}
 
-error_unlock:
-	MOD_DEC_USE_COUNT;
+error_out:
 	return NULL;
 }
 
@@ -6819,62 +6724,64 @@
 static void
 ov51x_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
+	struct usb_ov511 *ov = (struct usb_ov511 *) ptr;
 	int n;
 
-	MOD_INC_USE_COUNT;
-
 	PDEBUG(3, "");
 
 	/* We don't want people trying to open up the device */
-	if (!ov511->user)
-		video_unregister_device(&ov511->vdev);
+	if (!ov->user)
+		video_unregister_device(&ov->vdev);
 	else
 		PDEBUG(3, "Device open...deferring video_unregister_device");
 
 	for (n = 0; n < OV511_NUMFRAMES; n++)
-		ov511->frame[n].grabstate = FRAME_ERROR;
+		ov->frame[n].grabstate = FRAME_ERROR;
 
-	ov511->curframe = -1;
+	ov->curframe = -1;
 
 	/* This will cause the process to request another frame */
 	for (n = 0; n < OV511_NUMFRAMES; n++)
-		if (waitqueue_active(&ov511->frame[n].wq))
-			wake_up_interruptible(&ov511->frame[n].wq);
-	if (waitqueue_active(&ov511->wq))
-		wake_up_interruptible(&ov511->wq);
+		if (waitqueue_active(&ov->frame[n].wq))
+			wake_up_interruptible(&ov->frame[n].wq);
+	if (waitqueue_active(&ov->wq))
+		wake_up_interruptible(&ov->wq);
 
-	ov511->streaming = 0;
+	ov->streaming = 0;
 
 	/* Unschedule all of the iso td's */
 	for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
-		if (ov511->sbuf[n].urb) {
-			ov511->sbuf[n].urb->next = NULL;
-			usb_unlink_urb(ov511->sbuf[n].urb);
-			usb_free_urb(ov511->sbuf[n].urb);
-			ov511->sbuf[n].urb = NULL;
+		if (ov->sbuf[n].urb) {
+			ov->sbuf[n].urb->next = NULL;
+			usb_unlink_urb(ov->sbuf[n].urb);
+			usb_free_urb(ov->sbuf[n].urb);
+			ov->sbuf[n].urb = NULL;
 		}
 	}
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-        destroy_proc_ov511_cam(ov511);
+        destroy_proc_ov511_cam(ov);
 #endif
 
 	usb_driver_release_interface(&ov511_driver,
-		&ov511->dev->actconfig->interface[ov511->iface]);
-	ov511->dev = NULL;
+		&ov->dev->actconfig->interface[ov->iface]);
+	ov->dev = NULL;
 
 	/* Free the memory */
-	if (ov511 && !ov511->user) {
-		ov511_dealloc(ov511, 1);
-		kfree(ov511);
-		ov511 = NULL;
+	if (ov && !ov->user) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+
+		ov51x_dealloc(ov, 1);
+		kfree(ov);
+		ov = NULL;
 	}
-
-	MOD_DEC_USE_COUNT;
 }
 
 static struct usb_driver ov511_driver = {
+	owner:		THIS_MODULE,
 	name:		"ov511",
 	id_table:       device_table,
 	probe:		ov51x_probe,
diff -Nru a/drivers/usb/ov511.h b/drivers/usb/ov511.h
--- a/drivers/usb/ov511.h	Tue Feb 26 11:57:59 2002
+++ b/drivers/usb/ov511.h	Tue Feb 26 11:57:59 2002
@@ -9,11 +9,11 @@
 #define OV511_DEBUG	/* Turn on debug messages */
 
 #ifdef OV511_DEBUG
-#  define PDEBUG(level, fmt, args...) \
-if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , \
-	## args)
+	#define PDEBUG(level, fmt, args...) \
+		if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt,\
+		__LINE__ , ## args)
 #else
-#  define PDEBUG(level, fmt, args...) do {} while(0)
+	#define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
 
 /* This macro restricts an int variable to an inclusive range */
@@ -36,98 +36,105 @@
 #define VEND_MATTEL	0x0813
 #define PROD_ME2CAM	0x0002
 
+/* --------------------------------- */
+/*     OV51x REGISTER MNEMONICS      */
+/* --------------------------------- */
+
 /* Camera interface register numbers */
-#define OV511_REG_CAMERA_DELAY_MODE		0x10
-#define OV511_REG_CAMERA_EDGE_MODE		0x11
-#define OV511_REG_CAMERA_CLAMPED_PIXEL_NUM	0x12
-#define OV511_REG_CAMERA_CLAMPED_LINE_NUM	0x13
-#define OV511_REG_CAMERA_PIXEL_DIVISOR		0x14
-#define OV511_REG_CAMERA_LINE_DIVISOR		0x15
-#define OV511_REG_CAMERA_DATA_INPUT_SELECT	0x16
-#define OV511_REG_CAMERA_RESERVED_LINE_MODE	0x17
-#define OV511_REG_CAMERA_BITMASK		0x18
+#define R511_CAM_DELAY		0x10
+#define R511_CAM_EDGE		0x11
+#define R511_CAM_PXCNT		0x12
+#define R511_CAM_LNCNT		0x13
+#define R511_CAM_PXDIV		0x14
+#define R511_CAM_LNDIV		0x15
+#define R511_CAM_UV_EN		0x16
+#define R511_CAM_LINE_MODE	0x17
+#define R511_CAM_OPTS		0x18
 
 /* Snapshot mode camera interface register numbers */
-#define OV511_REG_SNAP_CAPTURED_FRAME		0x19
-#define OV511_REG_SNAP_CLAMPED_PIXEL_NUM	0x1A
-#define OV511_REG_SNAP_CLAMPED_LINE_NUM		0x1B
-#define OV511_REG_SNAP_PIXEL_DIVISOR		0x1C
-#define OV511_REG_SNAP_LINE_DIVISOR		0x1D
-#define OV511_REG_SNAP_DATA_INPUT_SELECT	0x1E
-#define OV511_REG_SNAP_BITMASK			0x1F
+#define R511_SNAP_FRAME		0x19
+#define R511_SNAP_PXCNT		0x1A
+#define R511_SNAP_LNCNT		0x1B
+#define R511_SNAP_PXDIV		0x1C
+#define R511_SNAP_LNDIV		0x1D
+#define R511_SNAP_UV_EN		0x1E
+#define R511_SNAP_OPTS		0x1F
 
 /* DRAM register numbers */
-#define OV511_REG_DRAM_ENABLE_FLOW_CONTROL	0x20
-#define OV511_REG_DRAM_READ_CYCLE_PREDICT	0x21
-#define OV511_REG_DRAM_MANUAL_READ_CYCLE	0x22
-#define OV511_REG_DRAM_REFRESH_COUNTER		0x23
+#define R511_DRAM_FLOW_CTL	0x20
+#define R511_DRAM_ARCP		0x21
+#define R511_DRAM_MRC		0x22
+#define R511_DRAM_RFC		0x23
 
 /* ISO FIFO register numbers */
-#define OV511_REG_FIFO_PACKET_SIZE		0x30
-#define OV511_REG_FIFO_BITMASK			0x31
+#define R51x_FIFO_PSIZE		0x30	/* 2 bytes wide w/ OV518(+) */
+#define R511_FIFO_OPTS		0x31
 
-/* PIO register numbers */
-#define OV511_REG_PIO_BITMASK			0x38
-#define OV511_REG_PIO_DATA_PORT			0x39
-#define OV511_REG_PIO_BIST			0x3E
-
-/* I2C register numbers */
-#define OV511_REG_I2C_CONTROL			0x40
-#define OV518_REG_I2C_CONTROL			0x47	/* OV518(+) only */
-#define OV511_REG_I2C_SLAVE_ID_WRITE		0x41
-#define OV511_REG_I2C_SUB_ADDRESS_3_BYTE	0x42
-#define OV511_REG_I2C_SUB_ADDRESS_2_BYTE	0x43
-#define OV511_REG_I2C_SLAVE_ID_READ		0x44
-#define OV511_REG_I2C_DATA_PORT			0x45
-#define OV511_REG_I2C_CLOCK_PRESCALER		0x46
-#define OV511_REG_I2C_TIME_OUT_COUNTER		0x47
-
-/* I2C snapshot register numbers */
-#define OV511_REG_I2C_SNAP_SUB_ADDRESS		0x48
-#define OV511_REG_I2C_SNAP_DATA_PORT		0x49
-
-/* System control register numbers */
-#define OV511_REG_SYSTEM_RESET			0x50
-#define 	OV511_RESET_UDC			0x01
-#define 	OV511_RESET_I2C			0x02
-#define 	OV511_RESET_FIFO		0x04
-#define 	OV511_RESET_OMNICE		0x08
-#define 	OV511_RESET_DRAM_INTF		0x10
-#define 	OV511_RESET_CAMERA_INTF		0x20
-#define 	OV511_RESET_OV511		0x40
-#define 	OV511_RESET_NOREGS		0x3F /* All but OV511 & regs */
-#define 	OV511_RESET_ALL			0x7F
-#define OV511_REG_SYSTEM_CLOCK_DIVISOR		0x51
-#define OV511_REG_SYSTEM_SNAPSHOT		0x52
-#define OV511_REG_SYSTEM_INIT         		0x53
-#define OV511_REG_SYSTEM_PWR_CLK		0x54 /* OV511+/OV518(+) only */
-#define OV511_REG_SYSTEM_LED_CTL		0x55	/* OV511+ only */
-#define OV518_REG_GPIO_IN			0x55	/* OV518(+) only */
-#define OV518_REG_GPIO_OUT			0x56	/* OV518(+) only */
-#define OV518_REG_GPIO_CTL			0x57	/* OV518(+) only */
-#define OV518_REG_GPIO_PULSE_IN			0x58	/* OV518(+) only */
-#define OV518_REG_GPIO_PULSE_CLEAR		0x59	/* OV518(+) only */
-#define OV518_REG_GPIO_PULSE_POLARITY		0x5a	/* OV518(+) only */
-#define OV518_REG_GPIO_PULSE_EN			0x5b	/* OV518(+) only */
-#define OV518_REG_GPIO_RESET			0x5c	/* OV518(+) only */
-#define OV511_REG_SYSTEM_USER_DEFINED		0x5E
-#define OV511_REG_SYSTEM_CUSTOM_ID		0x5F
-
-/* OmniCE register numbers */
-#define OV511_OMNICE_PREDICTION_HORIZ_Y		0x70
-#define OV511_OMNICE_PREDICTION_HORIZ_UV	0x71
-#define OV511_OMNICE_PREDICTION_VERT_Y		0x72
-#define OV511_OMNICE_PREDICTION_VERT_UV		0x73
-#define OV511_OMNICE_QUANTIZATION_HORIZ_Y	0x74
-#define OV511_OMNICE_QUANTIZATION_HORIZ_UV	0x75
-#define OV511_OMNICE_QUANTIZATION_VERT_Y	0x76
-#define OV511_OMNICE_QUANTIZATION_VERT_UV	0x77
-#define OV511_OMNICE_ENABLE			0x78
-#define OV511_OMNICE_LUT_ENABLE			0x79		
-#define OV511_OMNICE_Y_LUT_BEGIN		0x80
-#define OV511_OMNICE_Y_LUT_END			0x9F
-#define OV511_OMNICE_UV_LUT_BEGIN		0xA0
-#define OV511_OMNICE_UV_LUT_END			0xBF
+/* Parallel IO register numbers */
+#define R511_PIO_OPTS		0x38
+#define R511_PIO_DATA		0x39
+#define R511_PIO_BIST		0x3E
+#define R518_GPIO_IN		0x55	/* OV518(+) only */
+#define R518_GPIO_OUT		0x56	/* OV518(+) only */
+#define R518_GPIO_CTL		0x57	/* OV518(+) only */
+#define R518_GPIO_PULSE_IN	0x58	/* OV518(+) only */
+#define R518_GPIO_PULSE_CLEAR	0x59	/* OV518(+) only */
+#define R518_GPIO_PULSE_POL	0x5a	/* OV518(+) only */
+#define R518_GPIO_PULSE_EN	0x5b	/* OV518(+) only */
+#define R518_GPIO_RESET		0x5c	/* OV518(+) only */
+
+/* I2C registers */
+#define R511_I2C_CTL		0x40
+#define R518_I2C_CTL		0x47	/* OV518(+) only */
+#define R51x_I2C_W_SID		0x41
+#define R51x_I2C_SADDR_3	0x42
+#define R51x_I2C_SADDR_2	0x43
+#define R51x_I2C_R_SID		0x44
+#define R51x_I2C_DATA		0x45
+#define R51x_I2C_CLOCK		0x46
+#define R51x_I2C_TIMEOUT	0x47
+
+/* I2C snapshot registers */
+#define R511_SI2C_SADDR_3	0x48
+#define R511_SI2C_DATA		0x49
+
+/* System control registers */
+#define R51x_SYS_RESET		0x50
+		/* Reset type definitions */
+#define 	OV511_RESET_UDC		0x01
+#define 	OV511_RESET_I2C		0x02
+#define 	OV511_RESET_FIFO	0x04
+#define 	OV511_RESET_OMNICE	0x08
+#define 	OV511_RESET_DRAM	0x10
+#define 	OV511_RESET_CAM_INT	0x20
+#define 	OV511_RESET_OV511	0x40
+#define 	OV511_RESET_NOREGS	0x3F /* All but OV511 & regs */
+#define 	OV511_RESET_ALL		0x7F
+
+#define R511_SYS_CLOCK_DIV	0x51
+#define R51x_SYS_SNAP		0x52
+#define R51x_SYS_INIT         	0x53
+#define R511_SYS_PWR_CLK	0x54 /* OV511+/OV518(+) only */
+#define R511_SYS_LED_CTL	0x55 /* OV511+ only */
+#define R511_SYS_USER		0x5E
+#define R511_SYS_CUST_ID	0x5F
+
+/* OmniCE (compression) registers */
+#define R511_COMP_PHY		0x70
+#define R511_COMP_PHUV		0x71
+#define R511_COMP_PVY		0x72
+#define R511_COMP_PVUV		0x73
+#define R511_COMP_QHY		0x74
+#define R511_COMP_QHUV		0x75
+#define R511_COMP_QVY		0x76
+#define R511_COMP_QVUV		0x77
+#define R511_COMP_EN		0x78
+#define R511_COMP_LUT_EN	0x79		
+#define R511_COMP_LUT_BEGIN	0x80
+
+/* --------------------------------- */
+/*         ALTERNATE NUMBERS         */
+/* --------------------------------- */
 
 /* Alternate numbers for various max packet sizes (OV511 only) */
 #define OV511_ALT_SIZE_992	0
@@ -159,6 +166,10 @@
 #define OV518_ALT_SIZE_768	6
 #define OV518_ALT_SIZE_896	7
 
+/* --------------------------------- */
+/*     OV7610 REGISTER MNEMONICS     */
+/* --------------------------------- */
+
 /* OV7610 registers */
 #define OV7610_REG_GAIN          0x00	/* gain setting (5:0) */
 #define OV7610_REG_BLUE          0x01	/* blue channel balance */
@@ -210,26 +221,27 @@
 					/* 36-37 reserved */
 #define OV7610_REG_COM_K         0x38	/* misc registers */
 
+/* --------------------------------- */
+/*           I2C ADDRESSES           */
+/* --------------------------------- */
+
+#define OV7xx0_SID   0x42
+#define OV6xx0_SID   0xC0
+#define OV8xx0_SID   0xA0
+#define KS0127_SID   0xD8
+#define SAA7111A_SID 0x48
+
+/* --------------------------------- */
+/*       MISCELLANEOUS DEFINES       */
+/* --------------------------------- */
+
+#define I2C_CLOCK_PRESCALER 	0x03
+
 #define FRAMES_PER_DESC		10	/* FIXME - What should this be? */
-#define FRAME_SIZE_PER_DESC	993	/* FIXME - Deprecated */
 #define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
 #define PIXELS_PER_SEG		256	/* Pixels per segment */
 
-#define OV511_ENDPOINT_ADDRESS 1	/* Isoc endpoint number */
-
-/* I2C addresses */
-#define OV7xx0_I2C_WRITE_ID   0x42
-#define OV7xx0_I2C_READ_ID    0x43
-#define OV6xx0_I2C_WRITE_ID   0xC0
-#define OV6xx0_I2C_READ_ID    0xC1
-#define OV8xx0_I2C_WRITE_ID   0xA0
-#define OV8xx0_I2C_READ_ID    0xA1
-#define KS0127_I2C_WRITE_ID   0xD8
-#define KS0127_I2C_READ_ID    0xD9
-#define SAA7111A_I2C_WRITE_ID 0x48
-#define SAA7111A_I2C_READ_ID  0x49
-
-#define OV511_I2C_CLOCK_PRESCALER 0x03
+#define OV511_ENDPOINT_ADDRESS	1	/* Isoc endpoint number */
 
 /* Bridge types */
 enum {
@@ -429,11 +441,14 @@
 
 #define OV511_NUMFRAMES	2
 #if OV511_NUMFRAMES > VIDEO_MAX_FRAME
-#error "OV511_NUMFRAMES is too high"
+	#error "OV511_NUMFRAMES is too high"
 #endif
 
 #define OV511_NUMSBUF		2
 
+/* Control transfers use up to 4 bytes */
+#define OV511_CBUF_SIZE		4
+
 struct usb_ov511 {
 	struct video_device vdev;
 
@@ -535,6 +550,10 @@
 	/* I2C interface to kernel */
 	struct semaphore i2c_lock;	  /* Protect I2C controller regs */
 	unsigned char primary_i2c_slave;  /* I2C write id of sensor */
+
+	/* Control transaction stuff */
+	unsigned char *cbuf;		/* Buffer for payload */
+	struct semaphore cbuf_lock;
 };
 
 struct cam_list {
diff -Nru a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
--- a/drivers/usb/pwc-if.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/usb/pwc-if.c	Tue Feb 26 11:58:00 2002
@@ -179,28 +179,24 @@
 /* Private functions */
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr) 
 {
-        unsigned long va, kva, ret;
+        unsigned long kva, ret;
 
-        va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
         return ret;
 }
 
-static void * rvmalloc(signed long size)
+static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr, page;
+	unsigned long adr;
 
-        /* Round it off to PAGE_SIZE */
-        size += (PAGE_SIZE - 1);
-        size &= ~(PAGE_SIZE - 1);	
-        
+	size=PAGE_ALIGN(size);
         mem=vmalloc_32(size);
 	if (mem) 
 	{
@@ -208,8 +204,7 @@
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -217,20 +212,16 @@
 	return mem;
 }
 
-static void rvfree(void * mem, signed long size)
+static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr, page;
-        
-        /* Round it off to PAGE_SIZE */
-        size += (PAGE_SIZE - 1);
-        size &= ~(PAGE_SIZE - 1);	
+        unsigned long adr;
+
 	if (mem) 
 	{
 	        adr=(unsigned long) mem;
-		while (size > 0) 
+		while ((long) size > 0) 
                 {
-	                page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
diff -Nru a/drivers/usb/se401.c b/drivers/usb/se401.c
--- a/drivers/usb/se401.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/usb/se401.c	Tue Feb 26 11:57:58 2002
@@ -84,15 +84,14 @@
  **********************************************************************/
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
 	return ret;
 }
@@ -100,12 +99,9 @@
 static void *rvmalloc(unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
-
-	/* Round it off to PAGE_SIZE */
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32(size);
 	if (!mem)
 		return NULL;
@@ -113,13 +109,9 @@
 	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 	adr = (unsigned long) mem;
 	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_reserve(virt_to_page(__va(page)));
+		mem_map_reserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 
 	return mem;
@@ -127,23 +119,16 @@
 
 static void rvfree(void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (!mem)
 		return;
 
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
-
-	adr=(unsigned long) mem;
-	while (size > 0) {
-		page = kvirt_to_pa(adr);
-		mem_map_unreserve(virt_to_page(__va(page)));
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	vfree(mem);
 }
diff -Nru a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
--- a/drivers/usb/storage/Makefile	Tue Feb 26 11:57:59 2002
+++ b/drivers/usb/storage/Makefile	Tue Feb 26 11:57:59 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the USB Mass Storage device drivers.
 #
-# 15 Aug 2000, Christoph Hellwig <hch@caldera.de>
+# 15 Aug 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/drivers/usb/stv680.c b/drivers/usb/stv680.c
--- a/drivers/usb/stv680.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/usb/stv680.c	Tue Feb 26 11:57:57 2002
@@ -127,54 +127,25 @@
  * And the STV0680 driver - Kevin
  ********************************************************************/
 
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long uvirt_to_kva (pgd_t * pgd, unsigned long adr)
-{
-	unsigned long ret = 0UL;
-	pmd_t *pmd;
-	pte_t *ptep, pte;
-
-	if (!pgd_none (*pgd)) {
-		pmd = pmd_offset (pgd, adr);
-		if (!pmd_none (*pmd)) {
-			preempt_disable();
-			ptep = pte_offset_map (pmd, adr);
-			pte = *ptep;
-			pte_unmap(pte);
-			preempt_enable();
-			if (pte_present (pte)) {
-				ret = (unsigned long) page_address (pte_page (pte));
-				ret |= (adr & (PAGE_SIZE - 1));
-			}
-		}
-	}
-	return ret;
-}
-
-/* Here we want the physical address of the memory. This is used when 
- * initializing the contents of the area and marking the pages as reserved.
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa (unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR (adr);
-	kva = uvirt_to_kva (pgd_offset_k (va), va);
-	ret = __pa (kva);
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
 	return ret;
 }
 
 static void *rvmalloc (unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
-
-	/* Round it off to PAGE_SIZE */
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32 (size);
 	if (!mem)
 		return NULL;
@@ -182,36 +153,25 @@
 	memset (mem, 0, size);	/* Clear the ram out, no junk to the user */
 	adr = (unsigned long) mem;
 	while (size > 0) {
-		page = kvirt_to_pa (adr);
-		mem_map_reserve (virt_to_page (__va (page)));
+		mem_map_reserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	return mem;
 }
 
 static void rvfree (void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (!mem)
 		return;
 
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
-
 	adr = (unsigned long) mem;
-	while (size > 0) {
-		page = kvirt_to_pa (adr);
-		mem_map_unreserve (virt_to_page (__va (page)));
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	vfree (mem);
 }
diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
--- a/drivers/usb/uhci.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/usb/uhci.c	Tue Feb 26 11:57:58 2002
@@ -4,7 +4,7 @@
  * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
  *
  * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2001 Johannes Erdfelt, johannes@erdfelt.com
+ * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
  * (C) Copyright 1999 Randy Dunlap
  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
@@ -240,10 +240,10 @@
 	unsigned long flags;
 
 	/* If it's not inserted, don't remove it */
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	if (td->frame == -1 && list_empty(&td->fl_list))
-		return;
+		goto out;
 
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
 		if (list_empty(&td->fl_list)) {
 			uhci->fl->frame[td->frame] = td->link;
@@ -268,6 +268,7 @@
 	list_del_init(&td->fl_list);
 	td->frame = -1;
 
+out:
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
@@ -358,6 +359,9 @@
 	pci_pool_free(uhci->qh_pool, qh, qh->dma_handle);
 }
 
+/*
+ * MUST be called with uhci->frame_list_lock acquired
+ */
 static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
 {
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
@@ -417,11 +421,10 @@
 		return;
 
 	/* Only go through the hoops if it's actually linked in */
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	if (!list_empty(&qh->list)) {
 		qh->urbp = NULL;
 
-		spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
 		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
 
 		if (pqh->urbp) {
@@ -444,9 +447,8 @@
 		qh->element = qh->link = UHCI_PTR_TERM;
 
 		list_del_init(&qh->list);
-
-		spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 	}
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 
 	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
 
@@ -658,6 +660,9 @@
 	return urbp;
 }
 
+/*
+ * MUST be called with urb->lock acquired
+ */
 static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
 {
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
@@ -667,6 +672,9 @@
 	list_add_tail(&td->list, &urbp->td_list);
 }
 
+/*
+ * MUST be called with urb->lock acquired
+ */
 static void uhci_remove_td_from_urb(struct uhci_td *td)
 {
 	if (list_empty(&td->list))
@@ -677,22 +685,22 @@
 	td->urb = NULL;
 }
 
+/*
+ * MUST be called with urb->lock acquired
+ */
 static void uhci_destroy_urb_priv(struct urb *urb)
 {
 	struct list_head *head, *tmp;
 	struct urb_priv *urbp;
 	struct uhci *uhci;
-	unsigned long flags;
-
-	spin_lock_irqsave(&urb->lock, flags);
 
 	urbp = (struct urb_priv *)urb->hcpriv;
 	if (!urbp)
-		goto out;
+		return;
 
 	if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) {
 		warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb);
-		goto out;
+		return;
 	}
 
 	if (!list_empty(&urb->urb_list))
@@ -715,20 +723,21 @@
 		uhci_free_td(uhci, td);
 	}
 
-	if (urbp->setup_packet_dma_handle)
+	if (urbp->setup_packet_dma_handle) {
 		pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
 			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+		urbp->setup_packet_dma_handle = 0;
+	}
 
-	if (urbp->transfer_buffer_dma_handle)
+	if (urbp->transfer_buffer_dma_handle) {
 		pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
 			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
 			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+		urbp->transfer_buffer_dma_handle = 0;
+	}
 
 	urb->hcpriv = NULL;
 	kmem_cache_free(uhci_up_cachep, urbp);
-
-out:
-	spin_unlock_irqrestore(&urb->lock, flags);
 }
 
 static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
@@ -872,7 +881,7 @@
 	 * It's IN if the pipe is an output pipe or we're not expecting
 	 * data back.
 	 */
-	destination &= ~TD_PID;
+	destination &= ~TD_TOKEN_PID_MASK;
 	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
 		destination |= USB_PID_IN;
 	else
@@ -1312,9 +1321,7 @@
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct list_head *tmp, *head;
 	int ret = 0;
-	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 	head = &uhci->urb_list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1337,8 +1344,6 @@
 	} else
 		ret = -1;	/* no previous urb found */
 
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
 	return ret;
 }
 
@@ -1446,34 +1451,30 @@
 	return ret;
 }
 
+/*
+ * MUST be called with uhci->urb_list_lock acquired
+ */
 static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb)
 {
 	struct list_head *tmp, *head;
-	unsigned long flags;
-	struct urb *u = NULL;
 
 	/* We don't match Isoc transfers since they are special */
 	if (usb_pipeisoc(urb->pipe))
 		return NULL;
 
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 	head = &uhci->urb_list;
 	tmp = head->next;
 	while (tmp != head) {
-		u = list_entry(tmp, struct urb, urb_list);
+		struct urb *u = list_entry(tmp, struct urb, urb_list);
 
 		tmp = tmp->next;
 
 		if (u->dev == urb->dev && u->pipe == urb->pipe &&
 		    u->status == -EINPROGRESS)
-			goto out;
+			return u;
 	}
-	u = NULL;
-
-out:
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
-	return u;
+	return NULL;
 }
 
 static int uhci_submit_urb(struct urb *urb, int mem_flags)
@@ -1492,19 +1493,25 @@
 		return -ENODEV;
 	}
 
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb(urb);
+
 	uhci = (struct uhci *)urb->dev->bus->hcpriv;
 
 	INIT_LIST_HEAD(&urb->urb_list);
 	usb_inc_dev_use(urb->dev);
 
-	spin_lock_irqsave(&urb->lock, flags);
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	spin_lock(&urb->lock);
 
 	if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
 	    urb->status == -ECONNABORTED) {
 		dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status);
 		/* Since we can have problems on the out path */
-		spin_unlock_irqrestore(&urb->lock, flags);
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 		usb_dec_dev_use(urb->dev);
+		usb_put_urb(urb);
 
 		return ret;
 	}
@@ -1572,18 +1579,21 @@
 out:
 	urb->status = ret;
 
-	spin_unlock_irqrestore(&urb->lock, flags);
-
 	if (ret == -EINPROGRESS) {
-		spin_lock_irqsave(&uhci->urb_list_lock, flags);
 		/* We use _tail to make find_urb_ep more efficient */
 		list_add_tail(&urb->urb_list, &uhci->urb_list);
+
+		spin_unlock(&urb->lock);
 		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
 		return 0;
 	}
 
 	uhci_unlink_generic(uhci, urb);
+
+	spin_unlock(&urb->lock);
+	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
 	uhci_call_completion(urb);
 
 	return ret;
@@ -1592,7 +1602,7 @@
 /*
  * Return the result of a transfer
  *
- * Must be called with urb_list_lock acquired
+ * MUST be called with urb_list_lock acquired
  */
 static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
 {
@@ -1631,10 +1641,10 @@
 
 	urbp->status = ret;
 
-	spin_unlock_irqrestore(&urb->lock, flags);
-
-	if (ret == -EINPROGRESS)
+	if (ret == -EINPROGRESS) {
+		spin_unlock_irqrestore(&urb->lock, flags);
 		return;
+	}
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
@@ -1664,15 +1674,22 @@
 			usb_pipetype(urb->pipe), urb);
 	}
 
+	/* Remove it from uhci->urb_list */
 	list_del_init(&urb->urb_list);
 
 	uhci_add_complete(urb);
+
+	spin_unlock_irqrestore(&urb->lock, flags);
 }
 
+/*
+ * MUST be called with urb->lock acquired
+ */
 static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
 {
 	struct list_head *head, *tmp;
 	struct urb_priv *urbp = urb->hcpriv;
+	int prevactive = 1;
 
 	/* We can get called when urbp allocation fails, so check */
 	if (!urbp)
@@ -1680,6 +1697,19 @@
 
 	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
 
+	/*
+	 * Now we need to find out what the last successful toggle was
+	 * so we can update the local data toggle for the next transfer
+	 *
+	 * There's 3 way's the last successful completed TD is found:
+	 *
+	 * 1) The TD is NOT active and the actual length < expected length
+	 * 2) The TD is NOT active and it's the last TD in the chain
+	 * 3) The TD is active and the previous TD is NOT active
+	 *
+	 * Control and Isochronous ignore the toggle, so this is safe
+	 * for all types
+	 */
 	head = &urbp->td_list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1687,15 +1717,18 @@
 
 		tmp = tmp->next;
 
-		/* Control and Isochronous ignore the toggle, so this */
-		/* is safe for all types */
-		if ((!(td->status & TD_CTRL_ACTIVE) &&
-		    (uhci_actual_length(td->status) < uhci_expected_length(td->info)) ||
-		    tmp == head)) {
+		if (!(td->status & TD_CTRL_ACTIVE) &&
+		    (uhci_actual_length(td->status) < uhci_expected_length(td->info) ||
+		    tmp == head))
 			usb_settoggle(urb->dev, uhci_endpoint(td->info),
 				uhci_packetout(td->info),
 				uhci_toggle(td->info) ^ 1);
-		}
+		else if ((td->status & TD_CTRL_ACTIVE) && !prevactive)
+			usb_settoggle(urb->dev, uhci_endpoint(td->info),
+				uhci_packetout(td->info),
+				uhci_toggle(td->info));
+
+		prevactive = td->status & TD_CTRL_ACTIVE;
 	}
 
 	uhci_delete_queued_urb(uhci, urb);
@@ -1718,6 +1751,9 @@
 
 	uhci = (struct uhci *)urb->dev->bus->hcpriv;
 
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	spin_lock(&urb->lock);
+
 	/* Release bandwidth for Interrupt or Isoc. transfers */
 	/* Spinlock needed ? */
 	if (urb->bandwidth) {
@@ -1733,35 +1769,41 @@
 		}
 	}
 
-	if (urb->status != -EINPROGRESS)
+	if (urb->status != -EINPROGRESS) {
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 		return 0;
+	}
 
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 	list_del_init(&urb->urb_list);
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
 	uhci_unlink_generic(uhci, urb);
 
 	/* Short circuit the virtual root hub */
 	if (urb->dev == uhci->rh.dev) {
 		rh_unlink_urb(urb);
+
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
 		uhci_call_completion(urb);
 	} else {
 		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-			/* urb_list is available now since we called */
-			/*  uhci_unlink_generic already */
-
 			urbp->status = urb->status = -ECONNABORTED;
 
-			spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
+			spin_lock(&uhci->urb_remove_list_lock);
 
-			/* Check to see if the remove list is empty */
+			/* If we're the first, set the next interrupt bit */
 			if (list_empty(&uhci->urb_remove_list))
 				uhci_set_next_interrupt(uhci);
 			
 			list_add(&urb->urb_list, &uhci->urb_remove_list);
 
-			spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
+			spin_unlock(&uhci->urb_remove_list_lock);
+
+			spin_unlock(&urb->lock);
+			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
 		} else {
 			urb->status = -ENOENT;
 
@@ -1774,6 +1816,9 @@
 			} else
 				schedule_timeout(1+1*HZ/1000); 
 
+			spin_unlock(&urb->lock);
+			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
 			uhci_call_completion(urb);
 		}
 	}
@@ -1907,12 +1952,14 @@
 /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
 static int rh_send_irq(struct urb *urb)
 {
-	int i, len = 1;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	unsigned int io_addr = uhci->io_addr;
+	unsigned long flags;
+	int i, len = 1;
 	__u16 data = 0;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
+	spin_lock_irqsave(&urb->lock, flags);
 	for (i = 0; i < uhci->rh.numports; i++) {
 		data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
 		len = (i + 1) / 8 + 1;
@@ -1922,6 +1969,8 @@
 	urb->actual_length = len;
 	urbp->status = 0;
 
+	spin_unlock_irqrestore(&urb->lock, flags);
+
 	if ((data > 0) && (uhci->rh.send != 0)) {
 		dbg("root-hub INT complete: port1: %x port2: %x data: %x",
 			inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data);
@@ -1948,7 +1997,6 @@
 
 	spin_lock_irqsave(&uhci->urb_list_lock, flags);
 	head = &uhci->urb_list;
-
 	tmp = head->next;
 	while (tmp != head) {
 		struct urb *u = list_entry(tmp, struct urb, urb_list);
@@ -1956,6 +2004,8 @@
 
 		tmp = tmp->next;
 
+		spin_lock(&urb->lock);
+
 		/* Check if the FSBR timed out */
 		if (urbp->fsbr && !urbp->fsbr_timeout && time_after_eq(jiffies, urbp->fsbrtime + IDLE_TIMEOUT))
 			uhci_fsbr_timeout(uhci, u);
@@ -1965,6 +2015,8 @@
 			list_del(&u->urb_list);
 			list_add_tail(&u->urb_list, &list);
 		}
+
+		spin_unlock(&urb->lock);
 	}
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
@@ -2198,6 +2250,9 @@
 	return stat;
 }
 
+/*
+ * MUST be called with urb->lock acquired
+ */
 static int rh_unlink_urb(struct urb *urb)
 {
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
@@ -2233,16 +2288,25 @@
 
 static void uhci_call_completion(struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *urbp;
 	struct usb_device *dev = urb->dev;
 	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
 	int is_ring = 0, killed, resubmit_interrupt, status;
 	struct urb *nurb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+	if (!urbp || !urb->dev) {
+		spin_unlock_irqrestore(&urb->lock, flags);
+		return;
+	}
 
 	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
 			urb->status == -ECONNRESET);
 	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
-			urb->interval && !killed);
+			urb->interval);
 
 	nurb = urb->next;
 	if (nurb && !killed) {
@@ -2267,14 +2331,6 @@
 		is_ring = (nurb == urb);
 	}
 
-	status = urbp->status;
-	if (!resubmit_interrupt)
-		/* We don't need urb_priv anymore */
-		uhci_destroy_urb_priv(urb);
-
-	if (!killed)
-		urb->status = status;
-
 	if (urbp->transfer_buffer_dma_handle)
 		pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
 			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
@@ -2284,11 +2340,28 @@
 		pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
 			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
 
+	status = urbp->status;
+	if (!resubmit_interrupt || killed)
+		/* We don't need urb_priv anymore */
+		uhci_destroy_urb_priv(urb);
+
+	if (!killed)
+		urb->status = status;
+
 	urb->dev = NULL;
-	if (urb->complete)
+	spin_unlock_irqrestore(&urb->lock, flags);
+
+	if (urb->complete) {
 		urb->complete(urb);
 
-	if (resubmit_interrupt) {
+		/* Recheck the status. The completion handler may have */
+		/*  unlinked the resubmitting interrupt URB */
+		killed = (urb->status == -ENOENT ||
+			  urb->status == -ECONNABORTED ||
+			  urb->status == -ECONNRESET);
+	}
+
+	if (resubmit_interrupt && !killed) {
 		urb->dev = dev;
 		uhci_reset_interrupt(urb);
 	} else {
@@ -2299,6 +2372,7 @@
 			/* We decrement the usage count after we're done */
 			/*  with everything */
 			usb_dec_dev_use(dev);
+			usb_put_urb(urb);
 		}
 	}
 }
@@ -2315,11 +2389,14 @@
 		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
 		struct urb *urb = urbp->urb;
 
-		tmp = tmp->next;
-
 		list_del_init(&urbp->complete_list);
+		spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
 
 		uhci_call_completion(urb);
+
+		spin_lock_irqsave(&uhci->complete_list_lock, flags);
+		head = &uhci->complete_list;
+		tmp = head->next;
 	}
 	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
 }
@@ -2341,7 +2418,8 @@
 		list_del_init(&urb->urb_list);
 
 		urbp->status = urb->status = -ECONNRESET;
-		uhci_call_completion(urb);
+
+		uhci_add_complete(urb);
 	}
 	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
 }
@@ -2996,7 +3074,7 @@
 	id_table:	uhci_pci_ids,
 
 	probe:		uhci_pci_probe,
-	remove:		uhci_pci_remove,
+	remove:		__devexit_p(uhci_pci_remove),
 
 #ifdef	CONFIG_PM
 	suspend:	uhci_pci_suspend,
@@ -3074,3 +3152,4 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/uhci.h b/drivers/usb/uhci.h
--- a/drivers/usb/uhci.h	Tue Feb 26 11:57:57 2002
+++ b/drivers/usb/uhci.h	Tue Feb 26 11:57:57 2002
@@ -121,15 +121,16 @@
  * for TD <info>: (a.k.a. Token)
  */
 #define TD_TOKEN_TOGGLE		19
-#define TD_PID			0xFF
+#define TD_TOKEN_PID_MASK	0xFF
+#define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
 
 #define uhci_maxlen(token)	((token) >> 21)
-#define uhci_expected_length(info) (((info >> 21) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
+#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */
 #define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
 #define uhci_endpoint(token)	(((token) >> 15) & 0xf)
 #define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
 #define uhci_devep(token)	(((token) >> 8) & 0x7ff)
-#define uhci_packetid(token)	((token) & 0xff)
+#define uhci_packetid(token)	((token) & TD_TOKEN_PID_MASK)
 #define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
 #define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
 
@@ -163,7 +164,7 @@
 	struct list_head list;		/* P: urb->lock */
 
 	int frame;
-	struct list_head fl_list;	/* P: frame_list_lock */
+	struct list_head fl_list;	/* P: uhci->frame_list_lock */
 } __attribute__((aligned(16)));
 
 /*
@@ -306,21 +307,25 @@
 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
 	spinlock_t frame_list_lock;
-	struct uhci_frame_list *fl;		/* Frame list */
+	struct uhci_frame_list *fl;		/* P: uhci->frame_list_lock */
 	int fsbr;				/* Full speed bandwidth reclamation */
 	int is_suspended;
 
+	/* Main list of URB's currently controlled by this HC */
+	spinlock_t urb_list_lock;
+	struct list_head urb_list;		/* P: uhci->urb_list_lock */
+
+	/* List of QH's that are done, but waiting to be unlinked (race) */
 	spinlock_t qh_remove_list_lock;
-	struct list_head qh_remove_list;
+	struct list_head qh_remove_list;	/* P: uhci->qh_remove_list_lock */
 
+	/* List of asynchronously unlinked URB's */
 	spinlock_t urb_remove_list_lock;
-	struct list_head urb_remove_list;
-
-	spinlock_t urb_list_lock;
-	struct list_head urb_list;
+	struct list_head urb_remove_list;	/* P: uhci->urb_remove_list_lock */
 
+	/* List of URB's awaiting completion callback */
 	spinlock_t complete_list_lock;
-	struct list_head complete_list;
+	struct list_head complete_list;		/* P: uhci->complete_list_lock */
 
 	struct virt_root_hub rh;	/* private data of the virtual root hub */
 };
@@ -333,7 +338,7 @@
 	dma_addr_t transfer_buffer_dma_handle;
 
 	struct uhci_qh *qh;		/* QH for this URB */
-	struct list_head td_list;
+	struct list_head td_list;	/* P: urb->lock */
 
 	int fsbr : 1;			/* URB turned on FSBR */
 	int fsbr_timeout : 1;		/* URB timed out on FSBR */
@@ -345,11 +350,36 @@
 	int status;			/* Final status */
 
 	unsigned long inserttime;	/* In jiffies */
-	unsigned long fsbrtime;	/* In jiffies */
+	unsigned long fsbrtime;		/* In jiffies */
 
-	struct list_head queue_list;
-	struct list_head complete_list;
+	struct list_head queue_list;	/* P: uhci->frame_list_lock */
+	struct list_head complete_list;	/* P: uhci->complete_list_lock */
 };
+
+/*
+ * Locking in uhci.c
+ *
+ * spinlocks are used extensively to protect the many lists and data
+ * structures we have. It's not that pretty, but it's necessary. We
+ * need to be done with all of the locks (except complete_list_lock) when
+ * we call urb->complete. I've tried to make it simple enough so I don't
+ * have to spend hours racking my brain trying to figure out if the
+ * locking is safe.
+ *
+ * Here's the safe locking order to prevent deadlocks:
+ *
+ * #1 uhci->urb_list_lock
+ * #2 urb->lock
+ * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, 
+ *   uhci->qh_remove_list_lock
+ * #4 uhci->complete_list_lock
+ *
+ * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
+ * at the lowest level FIRST and NEVER grab locks at the same level at the
+ * same time.
+ * 
+ * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock
+ */
 
 /* -------------------------------------------------------------------------
    Virtual Root HUB
diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
--- a/drivers/usb/usb-ohci.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/usb/usb-ohci.c	Tue Feb 26 11:57:58 2002
@@ -205,6 +205,7 @@
 		urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
 		usb_dec_dev_use (urb->dev);
 		urb->dev = NULL;
+		usb_put_urb (urb);
 	}
 }
 
@@ -553,6 +554,9 @@
 //	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) 
 //		return -EPIPE;
 	
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb (urb);
+
 	usb_inc_dev_use (urb->dev);
 	ohci = (ohci_t *) urb->dev->bus->hcpriv;
 	
@@ -568,12 +572,14 @@
 	 * such as powering down ports */
 	if (ohci->disabled) {
 		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
 		return -ESHUTDOWN;
 	}
 
 	/* every endpoint has a ed, locate and fill it */
 	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
 		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
 		return -ENOMEM;
 	}
 
@@ -595,6 +601,7 @@
 			size = urb->number_of_packets;
 			if (size <= 0) {
 				usb_dec_dev_use (urb->dev);	
+				usb_put_urb (urb);
 				return -EINVAL;
 			}
 			for (i = 0; i < urb->number_of_packets; i++) {
@@ -615,6 +622,7 @@
 	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), mem_flags);
 	if (!urb_priv) {
 		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
 		return -ENOMEM;
 	}
 	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));
@@ -632,6 +640,7 @@
 			urb_free_priv (ohci, urb_priv);
 			spin_unlock_irqrestore (&usb_ed_lock, flags);
 			usb_dec_dev_use (urb->dev);	
+			usb_put_urb (urb);
 			return -ENOMEM;
 		}
 	}	
@@ -640,6 +649,7 @@
 		urb_free_priv (ohci, urb_priv);
 		spin_unlock_irqrestore (&usb_ed_lock, flags);
 		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
 		return -EINVAL;
 	}
 	
@@ -662,6 +672,7 @@
 				urb_free_priv (ohci, urb_priv);
 				spin_unlock_irqrestore (&usb_ed_lock, flags);
 				usb_dec_dev_use (urb->dev);	
+				usb_put_urb (urb);
 				return bustime;
 			}
 			usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe));
@@ -2100,6 +2111,7 @@
 	urb->dev = NULL;
 	if (urb->complete)
 	    	urb->complete (urb);
+	usb_put_urb (urb);
 	return 0;
 }
 
@@ -2123,6 +2135,7 @@
 				urb->complete (urb);
 		} else
 			urb->status = -ENOENT;
+		usb_put_urb (urb);
 	}
 	return 0;
 }
@@ -2859,7 +2872,7 @@
 	id_table:	&ohci_pci_ids [0],
 
 	probe:		ohci_pci_probe,
-	remove:		ohci_pci_remove,
+	remove:		__devexit_p(ohci_pci_remove),
 
 #ifdef	CONFIG_PM
 	suspend:	ohci_pci_suspend,
diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
--- a/drivers/usb/usb-uhci.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/usb/usb-uhci.c	Tue Feb 26 11:57:59 2002
@@ -1217,6 +1217,7 @@
 			urb->complete ((struct urb *) urb);
 		}
 		usb_dec_dev_use (usb_dev);
+		usb_put_urb (urb);
 	}
 	else
 		spin_unlock_irqrestore (&s->urb_list_lock, flags);
@@ -1305,7 +1306,7 @@
 #else
 			kfree (urb_priv);
 #endif
-
+			usb_put_urb (urb);
 		}
 	}
 }
@@ -1650,6 +1651,9 @@
 		return -EINVAL;
 	}
 
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb (urb);
+
 	usb_inc_dev_use (urb->dev);
 
 	spin_lock_irqsave (&s->urb_list_lock, flags);
@@ -1665,6 +1669,7 @@
 		     (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) {
 			spin_unlock_irqrestore (&s->urb_list_lock, flags);
 			usb_dec_dev_use (urb->dev);
+			usb_put_urb (urb);
 			err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb);
 			return -ENXIO;	// urb already queued
 		}
@@ -1678,6 +1683,7 @@
 	if (!urb_priv) {
 		usb_dec_dev_use (urb->dev);
 		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+		usb_put_urb (urb);
 		return -ENOMEM;
 	}
 
@@ -1766,6 +1772,7 @@
 #else
 		kfree (urb_priv);
 #endif
+		usb_put_urb (urb);
 		return ret;
 	}
 
@@ -2730,6 +2737,7 @@
 			}
 			
 			usb_dec_dev_use (usb_dev);
+			usb_put_urb (urb);
 		}
 	}
 
diff -Nru a/drivers/usb/usbvideo.c b/drivers/usb/usbvideo.c
--- a/drivers/usb/usbvideo.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/usb/usbvideo.c	Tue Feb 26 11:57:59 2002
@@ -59,33 +59,26 @@
 /* Memory management functions */
 /*******************************/
 
-#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
-
 /*
  * Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 unsigned long usbvideo_kvirt_to_pa(unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR(adr);
-	kva = page_address(vmalloc_to_page(va));
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
-	MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
 	return ret;
 }
 
 void *usbvideo_rvmalloc(unsigned long size)
 {
 	void *mem;
-	unsigned long adr, page;
-
-	/* Round it off to PAGE_SIZE */
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
+	unsigned long adr;
 
+	size = PAGE_ALIGN(size);
 	mem = vmalloc_32(size);
 	if (!mem)
 		return NULL;
@@ -93,13 +86,9 @@
 	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
 	adr = (unsigned long) mem;
 	while (size > 0) {
-		page = usbvideo_kvirt_to_pa(adr);
-		mem_map_reserve(virt_to_page(__va(page)));
+		mem_map_reserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 
 	return mem;
@@ -107,23 +96,16 @@
 
 void usbvideo_rvfree(void *mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (!mem)
 		return;
 
-	size += (PAGE_SIZE - 1);
-	size &= ~(PAGE_SIZE - 1);
-
-	adr=(unsigned long) mem;
-	while (size > 0) {
-		page = usbvideo_kvirt_to_pa(adr);
-		mem_map_unreserve(virt_to_page(__va(page)));
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
 		adr += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
+		size -= PAGE_SIZE;
 	}
 	vfree(mem);
 }
diff -Nru a/drivers/usb/vicam.c b/drivers/usb/vicam.c
--- a/drivers/usb/vicam.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/usb/vicam.c	Tue Feb 26 11:57:58 2002
@@ -40,6 +40,8 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/module.h>
@@ -91,83 +93,25 @@
  *
  ******************************************************************************/
 
-/* [DaveM] I've recoded most of this so that:
- * 1) It's easier to tell what is happening
- * 2) It's more portable, especially for translating things
- *    out of vmalloc mapped areas in the kernel.
- * 3) Less unnecessary translations happen.
- *
- * The code used to assume that the kernel vmalloc mappings
- * existed in the page tables of every process, this is simply
- * not guarenteed.  We now use pgd_offset_k which is the
- * defined way to get at the kernel page tables.
- */
-
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
-{
-	unsigned long ret = 0UL;
-	pmd_t *pmd;
-	pte_t *ptep, pte;
-
-	if (!pgd_none(*pgd)) {
-		pmd = pmd_offset(pgd, adr);
-		if (!pmd_none(*pmd)) {
-			preempt_disable();
-			ptep = pte_offset_map(pmd, adr);
-			pte = *ptep;
-			pte_unmap(pte);
-			preempt_enable();
-			if(pte_present(pte)) {
-				ret  = (unsigned long) page_address(pte_page(pte));
-				ret |= (adr & (PAGE_SIZE - 1));
-
-			}
-		}
-	}
-	return ret;
-}
-
-static inline unsigned long uvirt_to_bus(unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
-	ret = virt_to_bus((void *)kva);
-	return ret;
-}
-
-static inline unsigned long kvirt_to_bus(unsigned long adr)
-{
-	unsigned long va, kva, ret;
-
-	va = VMALLOC_VMADDR(adr);
-	kva = uvirt_to_kva(pgd_offset_k(va), va);
-	ret = virt_to_bus((void *)kva);
-	return ret;
-}
-
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
+ * This is used when initializing the contents of the area.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr)
 {
-	unsigned long va, kva, ret;
+	unsigned long kva, ret;
 
-	va = VMALLOC_VMADDR(adr);
-	kva = uvirt_to_kva(pgd_offset_k(va), va);
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
 	ret = __pa(kva);
 	return ret;
 }
 
-static void * rvmalloc(signed long size)
+static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr, page;
+	unsigned long adr;
 
+	size=PAGE_ALIGN(size);
 	mem=vmalloc_32(size);
 	if (mem)
 	{
@@ -175,8 +119,7 @@
 		adr=(unsigned long) mem;
 		while (size > 0)
 		{
-			page = kvirt_to_pa(adr);
-			mem_map_reserve(virt_to_page(__va(page)));
+			mem_map_reserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -184,17 +127,16 @@
 	return mem;
 }
 
-static void rvfree(void * mem, signed long size)
+static void rvfree(void * mem, unsigned long size)
 {
-	unsigned long adr, page;
+	unsigned long adr;
 
 	if (mem)
 	{
 		adr=(unsigned long) mem;
-		while (size > 0)
+		while ((long) size > 0)
 		{
-			page = kvirt_to_pa(adr);
-			mem_map_unreserve(virt_to_page(__va(page)));
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
diff -Nru a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
--- a/drivers/video/cyber2000fb.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/video/cyber2000fb.c	Tue Feb 26 11:57:58 2002
@@ -1683,7 +1683,7 @@
 static struct pci_driver cyberpro_driver = {
 	name:		"CyberPro",
 	probe:		cyberpro_probe,
-	remove:		cyberpro_remove,
+	remove:		__devexit_p(cyberpro_remove),
 	suspend:	cyberpro_suspend,
 	resume:		cyberpro_resume,
 	id_table:	cyberpro_pci_table
diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
--- a/drivers/video/imsttfb.c	Tue Feb 26 11:57:59 2002
+++ b/drivers/video/imsttfb.c	Tue Feb 26 11:57:59 2002
@@ -1643,7 +1643,7 @@
 	name:		"imsttfb",
 	id_table:	imsttfb_pci_tbl,
 	probe:		imsttfb_probe,
-	remove:		imsttfb_remove,
+	remove:		__devexit_p(imsttfb_remove),
 };
 
 static struct fb_ops imsttfb_ops = {
diff -Nru a/drivers/video/neofb.c b/drivers/video/neofb.c
--- a/drivers/video/neofb.c	Tue Feb 26 11:57:56 2002
+++ b/drivers/video/neofb.c	Tue Feb 26 11:57:56 2002
@@ -2332,7 +2332,7 @@
   name:      "neofb",
   id_table:  neofb_devices,
   probe:     neofb_probe,
-  remove:    neofb_remove
+  remove:    __devexit_p(neofb_remove)
 };
 
 /* **************************** init-time only **************************** */
diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	Tue Feb 26 11:58:00 2002
+++ b/drivers/video/radeonfb.c	Tue Feb 26 11:58:00 2002
@@ -619,7 +619,7 @@
 	name:		"radeonfb",
 	id_table:	radeonfb_pci_table,
 	probe:		radeonfb_pci_register,
-	remove:		radeonfb_pci_unregister,
+	remove:		__devexit_p(radeonfb_pci_unregister),
 };
 
 
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	Tue Feb 26 11:57:57 2002
+++ b/drivers/video/riva/fbdev.c	Tue Feb 26 11:57:57 2002
@@ -1811,7 +1811,7 @@
 	info = &rinfo->info;
 
 	strcpy(info->modename, rinfo->drvr_name);
-	info->node = -1;
+	info->node = NODEV;
 	info->flags = FBINFO_FLAG_DEFAULT;
 	info->fbops = &riva_fb_ops;
 
@@ -2082,7 +2082,7 @@
 	name:		"rivafb",
 	id_table:	rivafb_pci_tbl,
 	probe:		rivafb_init_one,
-	remove:		rivafb_remove_one,
+	remove:		__devexit_p(rivafb_remove_one),
 };
 
 
diff -Nru a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
--- a/drivers/video/tdfxfb.c	Tue Feb 26 11:57:58 2002
+++ b/drivers/video/tdfxfb.c	Tue Feb 26 11:57:58 2002
@@ -495,7 +495,7 @@
 	name:		"tdfxfb",
 	id_table:	tdfxfb_id_table,
 	probe:		tdfxfb_probe,
-	remove:		tdfxfb_remove,
+	remove:		__devexit_p(tdfxfb_remove),
 };
 
 MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	Tue Feb 26 11:57:56 2002
+++ b/fs/Makefile	Tue Feb 26 11:57:56 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the Linux filesystems.
 #
-# 14 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 # 
 
diff -Nru a/fs/bad_inode.c b/fs/bad_inode.c
--- a/fs/bad_inode.c	Tue Feb 26 11:57:57 2002
+++ b/fs/bad_inode.c	Tue Feb 26 11:57:57 2002
@@ -17,9 +17,7 @@
  */
 static int bad_follow_link(struct dentry *dent, struct nameidata *nd)
 {
-	dput(nd->dentry);
-	nd->dentry = dget(dent);
-	return 0;
+	return vfs_follow_link(nd, ERR_PTR(-EIO));
 }
 
 static int return_EIO(void)
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Tue Feb 26 11:57:57 2002
+++ b/fs/dcache.c	Tue Feb 26 11:57:57 2002
@@ -30,6 +30,7 @@
 /* #define DCACHE_DEBUG 1 */
 
 spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+rwlock_t dparent_lock __cacheline_aligned_in_smp = RW_LOCK_UNLOCKED;
 
 /* Right now the dcache depends on the kernel lock */
 #define check_lock()	if (!kernel_locked()) BUG()
@@ -916,7 +917,9 @@
 
 	/* Switch the parents and the names.. */
 	switch_names(dentry, target);
+	write_lock(&dparent_lock);
 	do_switch(dentry->d_parent, target->d_parent);
+	write_unlock(&dparent_lock);
 	do_switch(dentry->d_name.len, target->d_name.len);
 	do_switch(dentry->d_name.hash, target->d_name.hash);
 
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	Tue Feb 26 11:57:59 2002
+++ b/fs/fat/inode.c	Tue Feb 26 11:57:59 2002
@@ -516,7 +516,9 @@
 	fh[1] = inode->i_generation;
 	fh[2] = MSDOS_I(inode)->i_location;
 	fh[3] = MSDOS_I(inode)->i_logstart;
+	read_lock(&dparent_lock);
 	fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
+	read_unlock(&dparent_lock);
 	return 3;
 }
 
@@ -625,6 +627,18 @@
 	}
 
 	b = (struct fat_boot_sector *) bh->b_data;
+	if (!b->reserved) {
+		if (!silent)
+			printk("FAT: bogus number of reserved sectors\n");
+		brelse(bh);
+		goto out_invalid;
+	}
+	if (!b->fats) {
+		if (!silent)
+			printk("FAT: bogus number of FAT structure\n");
+		brelse(bh);
+		goto out_invalid;
+	}
 	if (!b->secs_track) {
 		if (!silent)
 			printk("FAT: bogus sectors-per-track value\n");
diff -Nru a/fs/file.c b/fs/file.c
--- a/fs/file.c	Tue Feb 26 11:57:56 2002
+++ b/fs/file.c	Tue Feb 26 11:57:56 2002
@@ -1,5 +1,5 @@
 /*
- *  linux/fs/open.c
+ *  linux/fs/file.c
  *
  *  Copyright (C) 1998-1999, Stephen Tweedie and Bill Hawes
  *
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Tue Feb 26 11:57:59 2002
+++ b/fs/inode.c	Tue Feb 26 11:57:59 2002
@@ -144,6 +144,8 @@
 	INIT_LIST_HEAD(&inode->i_devices);
 	sema_init(&inode->i_sem, 1);
 	spin_lock_init(&inode->i_data.i_shared_lock);
+	INIT_LIST_HEAD(&inode->i_data.i_mmap);
+	INIT_LIST_HEAD(&inode->i_data.i_mmap_shared);
 }
 
 static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
diff -Nru a/fs/intermezzo/kml_reint.c b/fs/intermezzo/kml_reint.c
--- a/fs/intermezzo/kml_reint.c	Tue Feb 26 11:58:00 2002
+++ b/fs/intermezzo/kml_reint.c	Tue Feb 26 11:58:00 2002
@@ -280,7 +280,7 @@
         old_fs = get_fs();
         set_fs (get_ds());
         error = lento_mknod (mknod->path, mknod->mode, 
-                MKDEV(mknod->major, mknod->minor), &info);
+                mk_kdev(mknod->major, mknod->minor), &info);
         set_fs (old_fs);
         kmlreint_post_secure (rec);
         EXIT;
diff -Nru a/fs/intermezzo/psdev.c b/fs/intermezzo/psdev.c
--- a/fs/intermezzo/psdev.c	Tue Feb 26 11:57:58 2002
+++ b/fs/intermezzo/psdev.c	Tue Feb 26 11:57:58 2002
@@ -789,7 +789,7 @@
                 }
 
                 error = lento_mknod(input.name, input.mode,
-                                    MKDEV(input.major,input.minor),&input.info);
+                                    mk_kdev(input.major,input.minor),&input.info);
                 EXIT;
                 return error;
         }
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Tue Feb 26 11:57:59 2002
+++ b/fs/locks.c	Tue Feb 26 11:57:59 2002
@@ -1459,7 +1459,7 @@
 	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
 		struct address_space *mapping = inode->i_mapping;
 
-		if (mapping->i_mmap_shared != NULL) {
+		if (!list_empty(&mapping->i_mmap_shared)) {
 			error = -EAGAIN;
 			goto out_putf;
 		}
@@ -1615,7 +1615,7 @@
 	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
 		struct address_space *mapping = inode->i_mapping;
 
-		if (mapping->i_mmap_shared != NULL) {
+		if (!list_empty(&mapping->i_mmap_shared)) {
 			error = -EAGAIN;
 			goto out_putf;
 		}
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	Tue Feb 26 11:57:56 2002
+++ b/fs/ncpfs/dir.c	Tue Feb 26 11:57:56 2002
@@ -257,12 +257,18 @@
 __ncp_lookup_validate(struct dentry * dentry, int flags)
 {
 	struct ncp_server *server;
-	struct inode *dir = dentry->d_parent->d_inode;
+	struct dentry *parent;
+	struct inode *dir;
 	struct ncp_entry_info finfo;
 	int res, val = 0, len = dentry->d_name.len + 1;
 	__u8 __name[len];
 
-	if (!dentry->d_inode || !dir)
+	read_lock(&dparent_lock);
+	parent = dget(dentry->d_parent);
+	read_unlock(&dparent_lock);
+	dir = parent->d_inode;
+
+	if (!dentry->d_inode)
 		goto finished;
 
 	server = NCP_SERVER(dir);
@@ -313,6 +319,7 @@
 
 finished:
 	DDPRINTK("ncp_lookup_validate: result=%d\n", val);
+	dput(parent);
 	return val;
 }
 
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	Tue Feb 26 11:57:59 2002
+++ b/fs/nfs/dir.c	Tue Feb 26 11:57:59 2002
@@ -467,12 +467,16 @@
 {
 	struct inode *dir;
 	struct inode *inode;
+	struct dentry *parent;
 	int error;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
 
+	read_lock(&dparent_lock);
+	parent = dget(dentry->d_parent);
+	read_unlock(&dparent_lock);
 	lock_kernel();
-	dir = dentry->d_parent->d_inode;
+	dir = parent->d_inode;
 	inode = dentry->d_inode;
 
 	if (!inode) {
@@ -508,6 +512,7 @@
 	nfs_renew_times(dentry);
  out_valid:
 	unlock_kernel();
+	dput(parent);
 	return 1;
  out_bad:
 	NFS_CACHEINV(dir);
@@ -521,6 +526,7 @@
 	}
 	d_drop(dentry);
 	unlock_kernel();
+	dput(parent);
 	return 0;
 }
 
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Tue Feb 26 11:57:59 2002
+++ b/fs/nfsd/export.c	Tue Feb 26 11:57:59 2002
@@ -112,11 +112,15 @@
 	struct list_head *head = &clp->cl_export[EXPORT_HASH(sb->s_dev)];
 	struct list_head *p;
 
+	spin_lock(&dcache_lock);
 	list_for_each(p, head) {
 		svc_export *exp = list_entry(p, svc_export, ex_hash);
-		if (is_subdir(dentry, exp->ex_dentry))
+		if (is_subdir(dentry, exp->ex_dentry)) {
+			spin_unlock(&dcache_lock);
 			return exp;
+		}
 	}
+	spin_unlock(&dcache_lock);
 	return NULL;
 }
 
@@ -132,12 +136,16 @@
 	struct list_head *p;
 	struct dentry *ndentry;
 
+	spin_lock(&dcache_lock);
 	list_for_each(p, head) {
 		svc_export *exp = list_entry(p, svc_export, ex_hash);
 		ndentry = exp->ex_dentry;
-		if (ndentry && is_subdir(ndentry->d_parent, dentry))
+		if (ndentry && is_subdir(ndentry->d_parent, dentry)) {
+			spin_unlock(&dcache_lock);
 			return exp;
+		}
 	}
+	spin_unlock(&dcache_lock);
 	return NULL;
 }
 
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	Tue Feb 26 11:57:56 2002
+++ b/fs/nfsd/nfs3xdr.c	Tue Feb 26 11:57:56 2002
@@ -699,10 +699,12 @@
 
 		fh_init(&fh, NFS3_FHSIZE);
 		if (isdotent(name, namlen)) {
-			dchild = dparent;
-			if (namlen == 2)
-				dchild = dchild->d_parent;
-			dchild = dget(dchild);
+			if (namlen == 2) {
+				read_lock(&dparent_lock);
+				dchild = dget(dparent->d_parent);
+				read_unlock(&dparent_lock);
+			} else
+				dchild = dget(dparent);
 		} else
 			dchild = lookup_one_len(name, dparent,namlen);
 		if (IS_ERR(dchild))
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	Tue Feb 26 11:57:58 2002
+++ b/fs/nfsd/nfsfh.c	Tue Feb 26 11:57:58 2002
@@ -477,6 +477,11 @@
 			/* Something wrong.  We need to drop the whole dentry->result path
 			 * whatever it was
 			 */
+			/*
+			 *  FIXME: the loop below will do Bad Things(tm) if
+			 *  dentry (or one of its ancestors) become attached
+			 *  to the tree (e.g. due to VFAT-style alias handling)
+			 */
 			struct dentry *d;
 			for (d=result ; d ; d=(d->d_parent == d)?NULL:d->d_parent)
 				d_drop(d);
@@ -610,7 +615,7 @@
 				dentry = dget(exp->ex_dentry);
 				break;
 			default:
-				dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+				dentry = find_fh_dentry(exp->ex_dentry->d_sb,
 							datap, data_left, fh->fh_fileid_type,
 							!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
 			}
@@ -619,7 +624,7 @@
 			tfh[0] = fh->ofh_ino;
 			tfh[1] = fh->ofh_generation;
 			tfh[2] = fh->ofh_dirino;
-			dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+			dentry = find_fh_dentry(exp->ex_dentry->d_sb,
 						tfh, 3, fh->ofh_dirino?2:1,
 						!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
 		}
@@ -676,11 +681,15 @@
 		if (exp->ex_dentry != dentry) {
 			struct dentry *tdentry = dentry;
 
+			spin_lock(&dcache_lock);
 			do {
 				tdentry = tdentry->d_parent;
 				if (exp->ex_dentry == tdentry)
 					break;
 				/* executable only by root and we can't be root */
+				/*
+				 * FIXME: permissions check is not that simple
+				 */
 				if (current->fsuid
 				    && (exp->ex_flags & NFSEXP_ROOTSQUASH)
 				    && !(tdentry->d_inode->i_uid
@@ -700,8 +709,10 @@
 				printk("nfsd Security: %s/%s bad export.\n",
 				       dentry->d_parent->d_name.name,
 				       dentry->d_name.name);
+				spin_unlock(&dcache_lock);
 				goto out;
 			}
+			spin_unlock(&dcache_lock);
 		}
 	}
 
@@ -729,7 +740,7 @@
 inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
 		      __u32 *datap, int *maxsize)
 {
-	struct super_block *sb = dentry->d_inode->i_sb;
+	struct super_block *sb = dentry->d_sb;
 	
 	if (dentry == exp->ex_dentry) {
 		*maxsize = 0;
@@ -806,7 +817,7 @@
 
 	if (ref_fh &&
 	    ref_fh->fh_handle.fh_version == 0xca &&
-	    parent->d_inode->i_sb->s_op->dentry_to_fh == NULL) {
+	    dentry->d_sb->s_op->dentry_to_fh == NULL) {
 		/* old style filehandle please */
 		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
 		fhp->fh_handle.fh_size = NFS_FHSIZE;
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Tue Feb 26 11:57:59 2002
+++ b/fs/nfsd/vfs.c	Tue Feb 26 11:57:59 2002
@@ -114,29 +114,33 @@
 	if (isdotent(name, len)) {
 		if (len==1)
 			dentry = dget(dparent);
-		else if (dparent != exp->ex_dentry)
+		else if (dparent != exp->ex_dentry) {
+			read_lock(&dparent_lock);
 			dentry = dget(dparent->d_parent);
-		else  if (!EX_CROSSMNT(exp))
+			read_unlock(&dparent_lock);
+		} else  if (!EX_CROSSMNT(exp))
 			dentry = dget(dparent); /* .. == . just like at / */
 		else {
 			/* checking mountpoint crossing is very different when stepping up */
 			struct svc_export *exp2 = NULL;
-			struct dentry *dp;
+			struct dentry *dp, *old;
 			struct vfsmount *mnt = mntget(exp->ex_mnt);
 			dentry = dget(dparent);
 			while(follow_up(&mnt, &dentry))
 				;
-			dp = dget(dentry->d_parent);
-			dput(dentry);
-			dentry = dp;
+			old = dentry;
+			read_lock(&dparent_lock);
+			dp = dentry->d_parent;
 			for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent)
 				exp2 = exp_get_by_name(exp->ex_client, mnt, dp);
 			if (!exp2) {
-				dput(dentry);
 				dentry = dget(dparent);
 			} else {
+				dget(dentry->d_parent);
 				exp = exp2;
 			}
+			read_unlock(&dparent_lock);
+			dput(old);
 			mntput(mnt);
 		}
 	} else {
diff -Nru a/fs/pipe.c b/fs/pipe.c
--- a/fs/pipe.c	Tue Feb 26 11:57:56 2002
+++ b/fs/pipe.c	Tue Feb 26 11:57:56 2002
@@ -116,7 +116,7 @@
 		 * writers synchronously that there is more
 		 * room.
 		 */
-		wake_up_interruptible_sync(PIPE_WAIT(*inode));
+		wake_up_interruptible(PIPE_WAIT(*inode));
 		if (!PIPE_EMPTY(*inode))
 			BUG();
 		goto do_more_read;
@@ -214,7 +214,7 @@
 			 * is going to give up this CPU, so it doesnt have
 			 * to do idle reschedules.
 			 */
-			wake_up_interruptible_sync(PIPE_WAIT(*inode));
+			wake_up_interruptible(PIPE_WAIT(*inode));
 			PIPE_WAITING_WRITERS(*inode)++;
 			pipe_wait(inode);
 			PIPE_WAITING_WRITERS(*inode)--;
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Tue Feb 26 11:57:58 2002
+++ b/fs/reiserfs/inode.c	Tue Feb 26 11:57:58 2002
@@ -1325,15 +1325,17 @@
     if (maxlen < 5 || ! need_parent)
         return 3 ;
 
+    read_lock(&dparent_lock);
     inode = dentry->d_parent->d_inode ;
     data[3] = inode->i_ino ;
     data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;
     *lenp = 5 ;
-    if (maxlen < 6)
-	    return 5 ;
-    data[5] = inode->i_generation ;
-    *lenp = 6 ;
-    return 6 ;
+    if (maxlen >= 6) {
+	    data[5] = inode->i_generation ;
+	    *lenp = 6 ;
+    }
+    read_unlock(&dparent_lock);
+    return *lenp ;
 }
 
 
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Tue Feb 26 11:57:56 2002
+++ b/fs/reiserfs/namei.c	Tue Feb 26 11:57:56 2002
@@ -344,8 +344,6 @@
     struct reiserfs_dir_entry de;
     INITIALIZE_PATH (path_to_entry);
 
-    reiserfs_check_lock_depth("lookup") ;
-
     if (dentry->d_name.len > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize))
 	return ERR_PTR(-ENAMETOOLONG);
 
diff -Nru a/fs/smbfs/dir.c b/fs/smbfs/dir.c
--- a/fs/smbfs/dir.c	Tue Feb 26 11:57:59 2002
+++ b/fs/smbfs/dir.c	Tue Feb 26 11:57:59 2002
@@ -378,12 +378,14 @@
 void
 smb_renew_times(struct dentry * dentry)
 {
+	read_lock(&dparent_lock);
 	for (;;) {
 		dentry->d_time = jiffies;
 		if (IS_ROOT(dentry))
 			break;
 		dentry = dentry->d_parent;
 	}
+	read_unlock(&dparent_lock);
 }
 
 static struct dentry *
diff -Nru a/fs/smbfs/proc.c b/fs/smbfs/proc.c
--- a/fs/smbfs/proc.c	Tue Feb 26 11:57:57 2002
+++ b/fs/smbfs/proc.c	Tue Feb 26 11:57:57 2002
@@ -245,15 +245,20 @@
 	 * Build the path string walking the tree backward from end to ROOT
 	 * and store it in reversed order [see reverse_string()]
 	 */
+	read_lock(&dparent_lock);
 	while (!IS_ROOT(entry)) {
-		if (maxlen < 3)
+		if (maxlen < 3) {
+			read_unlock(&dparent_lock);
 			return -ENAMETOOLONG;
+		}
 
 		len = server->convert(path, maxlen-2, 
 				      entry->d_name.name, entry->d_name.len,
 				      server->local_nls, server->remote_nls);
-		if (len < 0)
+		if (len < 0) {
+			read_unlock(&dparent_lock);
 			return len;
+		}
 		reverse_string(path, len);
 		path += len;
 		*path++ = '\\';
@@ -263,6 +268,7 @@
 		if (IS_ROOT(entry))
 			break;
 	}
+	read_unlock(&dparent_lock);
 	reverse_string(buf, path-buf);
 
 	/* maxlen is at least 1 */
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Tue Feb 26 11:57:59 2002
+++ b/fs/super.c	Tue Feb 26 11:57:59 2002
@@ -355,6 +355,7 @@
 	}
 	up_write(&s->s_umount);
 	put_super(s);
+	yield();
 	return 0;
 }
  
@@ -381,33 +382,86 @@
  *	remove_super	-	makes superblock unreachable
  *	@s:	superblock in question
  *
- *	Removes superblock from the lists, unlocks it, drop the reference
- *	and releases the hosting device.  @s should have no active
- *	references by that time and after remove_super() it's essentially
- *	in rundown mode - all remaining references are temporary, no new
- *	reference of any sort are going to appear and all holders of
- *	temporary ones will eventually drop them.  At that point superblock
- *	itself will be destroyed; all its contents is already gone.
+ *	Removes superblock from the lists, unlocks it and drop the reference
+ *	@s should have no active references by that time and after
+ *	remove_super() it's essentially	in rundown mode - all remaining
+ *	references are temporary, no new reference of any sort are going
+ *	to appear and all holders of temporary ones will eventually drop them.
+ *	At that point superblock itself will be destroyed; all its contents
+ *	is already gone.
  */
 static void remove_super(struct super_block *s)
 {
-	kdev_t dev = s->s_dev;
-	struct block_device *bdev = s->s_bdev;
-	struct file_system_type *fs = s->s_type;
-
 	spin_lock(&sb_lock);
 	list_del(&s->s_list);
 	list_del(&s->s_instances);
 	spin_unlock(&sb_lock);
 	up_write(&s->s_umount);
 	put_super(s);
-	put_filesystem(fs);
+}
+
+static void generic_shutdown_super(struct super_block *sb)
+{
+	struct dentry *root = sb->s_root;
+	struct super_operations *sop = sb->s_op;
+
+	if (root) {
+		sb->s_root = NULL;
+		shrink_dcache_parent(root);
+		dput(root);
+		fsync_super(sb);
+		lock_super(sb);
+		lock_kernel();
+		sb->s_flags &= ~MS_ACTIVE;
+		/* bad name - it should be evict_inodes() */
+		invalidate_inodes(sb);
+		if (sop) {
+			if (sop->write_super && sb->s_dirt)
+				sop->write_super(sb);
+			if (sop->put_super)
+				sop->put_super(sb);
+		}
+
+		/* Forget any remaining inodes */
+		if (invalidate_inodes(sb)) {
+			printk("VFS: Busy inodes after unmount. "
+			   "Self-destruct in 5 seconds.  Have a nice day...\n");
+		}
+
+		unlock_kernel();
+		unlock_super(sb);
+	}
+	remove_super(sb);
+}
+
+static void shutdown_super(struct super_block *sb)
+{
+	struct file_system_type *fs = sb->s_type;
+	kdev_t dev = sb->s_dev;
+	struct block_device *bdev = sb->s_bdev;
+
+	/* Need to clean after the sucker */
+	if (fs->fs_flags & FS_LITTER && sb->s_root)
+		d_genocide(sb->s_root);
+	generic_shutdown_super(sb);
 	if (bdev)
 		blkdev_put(bdev, BDEV_FS);
 	else
 		put_anon_dev(dev);
 }
 
+void kill_super(struct super_block *sb)
+{
+	struct file_system_type *fs = sb->s_type;
+
+	if (!deactivate_super(sb))
+		return;
+
+	down_write(&sb->s_umount);
+	shutdown_super(sb);
+	put_filesystem(fs);
+}
+
 struct vfsmount *alloc_vfsmnt(char *name);
 void free_vfsmnt(struct vfsmount *mnt);
 
@@ -724,8 +778,8 @@
 	return s;
 
 failed:
-	deactivate_super(s);
-	remove_super(s);
+	up_write(&s->s_umount);
+	kill_super(s);
 	goto out;
 out1:
 	blkdev_put(bdev, BDEV_FS);
@@ -748,8 +802,8 @@
 
 	error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
-		deactivate_super(s);
-		remove_super(s);
+		up_write(&s->s_umount);
+		kill_super(s);
 		return ERR_PTR(error);
 	}
 	s->s_flags |= MS_ACTIVE;
@@ -774,8 +828,8 @@
 		s->s_flags = flags;
 		error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 		if (error) {
-			deactivate_super(s);
-			remove_super(s);
+			up_write(&s->s_umount);
+			kill_super(s);
 			return ERR_PTR(error);
 		}
 		s->s_flags |= MS_ACTIVE;
@@ -814,45 +868,6 @@
 out:
 	put_filesystem(type);
 	return (struct vfsmount *)sb;
-}
-
-void kill_super(struct super_block *sb)
-{
-	struct dentry *root = sb->s_root;
-	struct file_system_type *fs = sb->s_type;
-	struct super_operations *sop = sb->s_op;
-
-	if (!deactivate_super(sb))
-		return;
-
-	down_write(&sb->s_umount);
-	sb->s_root = NULL;
-	/* Need to clean after the sucker */
-	if (fs->fs_flags & FS_LITTER)
-		d_genocide(root);
-	shrink_dcache_parent(root);
-	dput(root);
-	fsync_super(sb);
-	lock_super(sb);
-	lock_kernel();
-	sb->s_flags &= ~MS_ACTIVE;
-	invalidate_inodes(sb);	/* bad name - it should be evict_inodes() */
-	if (sop) {
-		if (sop->write_super && sb->s_dirt)
-			sop->write_super(sb);
-		if (sop->put_super)
-			sop->put_super(sb);
-	}
-
-	/* Forget any remaining inodes */
-	if (invalidate_inodes(sb)) {
-		printk("VFS: Busy inodes after unmount. "
-			"Self-destruct in 5 seconds.  Have a nice day...\n");
-	}
-
-	unlock_kernel();
-	unlock_super(sb);
-	remove_super(sb);
 }
 
 struct vfsmount *kern_mount(struct file_system_type *type)
diff -Nru a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
--- a/fs/sysv/ChangeLog	Tue Feb 26 11:57:56 2002
+++ b/fs/sysv/ChangeLog	Tue Feb 26 11:57:56 2002
@@ -81,7 +81,7 @@
 	* super.c (sysv_read_super): Likewise.
 	  (v7_read_super): Likewise.
 
-Sat Dec 15 2001  Christoph Hellwig  <hch@caldera.de>
+Sat Dec 15 2001  Christoph Hellwig  <hch@infradead.org>
 
 	* inode.c (sysv_read_inode): Mark inode as bad in case of failure.
 	* super.c (complete_read_super): Check for bad root inode.
@@ -90,13 +90,13 @@
 
 	* file.c (sysv_sync_file): Call fsync_inode_data_buffers.
 
-Fri Oct 26 2001  Christoph Hellwig  <hch@caldera.de>
+Fri Oct 26 2001  Christoph Hellwig  <hch@infradead.org>
 
 	* dir.c, ialloc.c, namei.c, include/linux/sysv_fs_i.h:
 	Implement per-Inode lookup offset cache.
 	Modelled after Ted's ext2 patch.
 
-Fri Oct 26 2001  Christoph Hellwig  <hch@caldera.de>
+Fri Oct 26 2001  Christoph Hellwig  <hch@infradead.org>
 
 	* inode.c, super.c, include/linux/sysv_fs.h,
 	  include/linux/sysv_fs_sb.h:
diff -Nru a/fs/sysv/symlink.c b/fs/sysv/symlink.c
--- a/fs/sysv/symlink.c	Tue Feb 26 11:58:00 2002
+++ b/fs/sysv/symlink.c	Tue Feb 26 11:58:00 2002
@@ -2,7 +2,7 @@
  *  linux/fs/sysv/symlink.c
  *
  *  Handling of System V filesystem fast symlinks extensions.
- *  Aug 2001, Christoph Hellwig (hch@caldera.de)
+ *  Aug 2001, Christoph Hellwig (hch@infradead.org)
  */
 
 #include <linux/fs.h>
diff -Nru a/fs/udf/dir.c b/fs/udf/dir.c
--- a/fs/udf/dir.c	Tue Feb 26 11:57:58 2002
+++ b/fs/udf/dir.c	Tue Feb 26 11:57:58 2002
@@ -224,7 +224,7 @@
 
 		if ( cfi.fileCharacteristics & FILE_PARENT )
 		{
-			iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0);
+			iblock = parent_ino(filp->f_dentry);
 			flen = 2;
 			memcpy(fname, "..", flen);
 			dt_type = DT_DIR;
diff -Nru a/fs/ufs/swab.h b/fs/ufs/swab.h
--- a/fs/ufs/swab.h	Tue Feb 26 11:58:00 2002
+++ b/fs/ufs/swab.h	Tue Feb 26 11:58:00 2002
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997, 1998 Francois-Rene Rideau <fare@tunes.org>
  * Copyright (C) 1998 Jakub Jelinek <jj@ultra.linux.cz>
- * Copyright (C) 2001 Christoph Hellwig <hch@caldera.de>
+ * Copyright (C) 2001 Christoph Hellwig <hch@infradead.org>
  */
 
 #ifndef _UFS_SWAB_H
diff -Nru a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
--- a/include/asm-alpha/bitops.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-alpha/bitops.h	Tue Feb 26 11:57:59 2002
@@ -460,6 +460,27 @@
 
 #ifdef __KERNEL__
 
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is set.
+ */
+static inline unsigned long
+sched_find_first_bit(unsigned long b[3])
+{
+	unsigned long b0 = b[0], b1 = b[1], b2 = b[2];
+	unsigned long ofs;
+
+	ofs = (b1 ? 64 : 128);
+	b1 = (b1 ? b1 : b2);
+	ofs = (b0 ? 0 : ofs);
+	b0 = (b0 ? b0 : b1);
+
+	return __ffs(b0) + ofs;
+}
+
+
 #define ext2_set_bit                 __test_and_set_bit
 #define ext2_clear_bit               __test_and_clear_bit
 #define ext2_test_bit                test_bit
diff -Nru a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
--- a/include/asm-alpha/mmu_context.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-alpha/mmu_context.h	Tue Feb 26 11:57:59 2002
@@ -21,31 +21,6 @@
 #include <asm/io.h>
 #endif
 
-/* ??? This does not belong here.  */
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 168-bit bitmap where the first 128 bits are
- * unlikely to be set. It's guaranteed that at least one of the 168
- * bits is set.
- */
-#if MAX_RT_PRIO != 128 || MAX_PRIO > 192
-# error update this function.
-#endif
-
-static inline int
-sched_find_first_bit(unsigned long *b)
-{
-	unsigned long b0 = b[0], b1 = b[1], b2 = b[2];
-	unsigned long offset = 128;
-
-	if (unlikely(b0 | b1)) {
-		b2 = (b0 ? b0 : b1);
-		offset = (b0 ? 0 : 64);
-	}
-
-	return __ffs(b2) + offset;
-}
-
 
 extern inline unsigned long
 __reload_thread(struct pcb_struct *pcb)
diff -Nru a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
--- a/include/asm-alpha/spinlock.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-alpha/spinlock.h	Tue Feb 26 11:57:59 2002
@@ -121,8 +121,8 @@
 	"	bne	%1,6b\n"
 	"	br	1b\n"
 	".previous"
-	: "=m" (*(volatile int *)lock), "=&r" (regx)
-	: "0" (*(volatile int *)lock) : "memory");
+	: "=m" (*lock), "=&r" (regx)
+	: "0" (*lock) : "memory");
 }
 
 static inline void _raw_read_lock(rwlock_t * lock)
@@ -141,8 +141,8 @@
 	"	blbs	%1,6b\n"
 	"	br	1b\n"
 	".previous"
-	: "=m" (*(volatile int *)lock), "=&r" (regx)
-	: "m" (*(volatile int *)lock) : "memory");
+	: "=m" (*lock), "=&r" (regx)
+	: "m" (*lock) : "memory");
 }
 #endif /* CONFIG_DEBUG_RWLOCK */
 
@@ -164,8 +164,8 @@
 	".subsection 2\n"
 	"6:	br	1b\n"
 	".previous"
-	: "=m" (*(volatile int *)lock), "=&r" (regx)
-	: "m" (*(volatile int *)lock) : "memory");
+	: "=m" (*lock), "=&r" (regx)
+	: "m" (*lock) : "memory");
 }
 
 #endif /* _ALPHA_SPINLOCK_H */
diff -Nru a/include/asm-alpha/system.h b/include/asm-alpha/system.h
--- a/include/asm-alpha/system.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-alpha/system.h	Tue Feb 26 11:57:56 2002
@@ -131,15 +131,13 @@
 #define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
 
 #define prepare_to_switch()	do { } while(0)
-#define switch_to(prev,next,last)			\
-do {							\
-	unsigned long pcbb;				\
-	pcbb = virt_to_phys(&(next)->thread_info->pcb);	\
-	(last) = alpha_switch_to(pcbb, (prev));		\
-	check_mmu_context();				\
+#define switch_to(prev,next)						  \
+do {									  \
+	alpha_switch_to(virt_to_phys(&(next)->thread_info->pcb), (prev)); \
+	check_mmu_context();						  \
 } while (0)
 
-extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*);
+extern void alpha_switch_to(unsigned long, struct task_struct*);
 
 #define mb() \
 __asm__ __volatile__("mb": : :"memory")
@@ -368,7 +366,59 @@
  * it must clobber "memory" (also for interrupts in UP).
  */
 
-extern __inline__ unsigned long
+static inline unsigned long
+__xchg_u8(volatile char *m, unsigned long val)
+{
+	unsigned long ret, tmp, addr64;
+
+	__asm__ __volatile__(
+	"	andnot	%4,7,%3\n"
+	"	insbl	%1,%4,%1\n"
+	"1:	ldq_l	%2,0(%3)\n"
+	"	extbl	%2,%4,%0\n"
+	"	mskbl	%2,%4,%2\n"
+	"	or	%1,%2,%2\n"
+	"	stq_c	%2,0(%3)\n"
+	"	beq	%2,2f\n"
+#ifdef CONFIG_SMP
+	"	mb\n"
+#endif
+	".subsection 2\n"
+	"2:	br	1b\n"
+	".previous"
+	: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
+	: "r" ((long)m), "1" (val) : "memory");
+
+	return ret;
+}
+
+static inline unsigned long
+__xchg_u16(volatile short *m, unsigned long val)
+{
+	unsigned long ret, tmp, addr64;
+
+	__asm__ __volatile__(
+	"	andnot	%4,7,%3\n"
+	"	inswl	%1,%4,%1\n"
+	"1:	ldq_l	%2,0(%3)\n"
+	"	extwl	%2,%4,%0\n"
+	"	mskwl	%2,%4,%2\n"
+	"	or	%1,%2,%2\n"
+	"	stq_c	%2,0(%3)\n"
+	"	beq	%2,2f\n"
+#ifdef CONFIG_SMP
+	"	mb\n"
+#endif
+	".subsection 2\n"
+	"2:	br	1b\n"
+	".previous"
+	: "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
+	: "r" ((long)m), "1" (val) : "memory");
+
+	return ret;
+}
+
+static inline unsigned long
 __xchg_u32(volatile int *m, unsigned long val)
 {
 	unsigned long dummy;
@@ -390,7 +440,7 @@
 	return val;
 }
 
-extern __inline__ unsigned long
+static inline unsigned long
 __xchg_u64(volatile long *m, unsigned long val)
 {
 	unsigned long dummy;
@@ -416,10 +466,14 @@
    if something tries to do an invalid xchg().  */
 extern void __xchg_called_with_bad_pointer(void);
 
-static __inline__ unsigned long
+static inline unsigned long
 __xchg(volatile void *ptr, unsigned long x, int size)
 {
 	switch (size) {
+		case 1:
+			return __xchg_u8(ptr, x);
+		case 2:
+			return __xchg_u16(ptr, x);
 		case 4:
 			return __xchg_u32(ptr, x);
 		case 8:
@@ -451,7 +505,65 @@
 
 #define __HAVE_ARCH_CMPXCHG 1
 
-extern __inline__ unsigned long
+static inline unsigned long
+__cmpxchg_u8(volatile char *m, long old, long new)
+{
+	unsigned long prev, tmp, cmp, addr64;
+
+	__asm__ __volatile__(
+	"	andnot	%5,7,%4\n"
+	"	insbl	%1,%5,%1\n"
+	"1:	ldq_l	%2,0(%4)\n"
+	"	extbl	%2,%5,%0\n"
+	"	cmpeq	%0,%6,%3\n"
+	"	beq	%3,2f\n"
+	"	mskbl	%2,%5,%2\n"
+	"	or	%1,%2,%2\n"
+	"	stq_c	%2,0(%4)\n"
+	"	beq	%2,3f\n"
+#ifdef CONFIG_SMP
+	"	mb\n"
+#endif
+	"2:\n"
+	".subsection 2\n"
+	"3:	br	1b\n"
+	".previous"
+	: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
+	: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
+
+	return prev;
+}
+
+static inline unsigned long
+__cmpxchg_u16(volatile short *m, long old, long new)
+{
+	unsigned long prev, tmp, cmp, addr64;
+
+	__asm__ __volatile__(
+	"	andnot	%5,7,%4\n"
+	"	inswl	%1,%5,%1\n"
+	"1:	ldq_l	%2,0(%4)\n"
+	"	extwl	%2,%5,%0\n"
+	"	cmpeq	%0,%6,%3\n"
+	"	beq	%3,2f\n"
+	"	mskwl	%2,%5,%2\n"
+	"	or	%1,%2,%2\n"
+	"	stq_c	%2,0(%4)\n"
+	"	beq	%2,3f\n"
+#ifdef CONFIG_SMP
+	"	mb\n"
+#endif
+	"2:\n"
+	".subsection 2\n"
+	"3:	br	1b\n"
+	".previous"
+	: "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
+	: "r" ((long)m), "Ir" (old), "1" (new) : "memory");
+
+	return prev;
+}
+
+static inline unsigned long
 __cmpxchg_u32(volatile int *m, int old, int new)
 {
 	unsigned long prev, cmp;
@@ -476,7 +588,7 @@
 	return prev;
 }
 
-extern __inline__ unsigned long
+static inline unsigned long
 __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
 {
 	unsigned long prev, cmp;
@@ -505,10 +617,14 @@
    if something tries to do an invalid cmpxchg().  */
 extern void __cmpxchg_called_with_bad_pointer(void);
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 {
 	switch (size) {
+		case 1:
+			return __cmpxchg_u8(ptr, old, new);
+		case 2:
+			return __cmpxchg_u16(ptr, old, new);
 		case 4:
 			return __cmpxchg_u32(ptr, old, new);
 		case 8:
diff -Nru a/include/asm-arm/arch-adifcc/serial.h b/include/asm-arm/arch-adifcc/serial.h
--- a/include/asm-arm/arch-adifcc/serial.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/arch-adifcc/serial.h	Tue Feb 26 11:57:59 2002
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2001 MontaVista Software, Inc.
  */
-
+#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff -Nru a/include/asm-arm/arch-anakin/ide.h b/include/asm-arm/arch-anakin/ide.h
--- a/include/asm-arm/arch-anakin/ide.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/arch-anakin/ide.h	Tue Feb 26 11:57:56 2002
@@ -7,7 +7,6 @@
  *              (jonm@bluemug.com).
  */
  
-#include <linux/config.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
 
diff -Nru a/include/asm-arm/arch-anakin/uncompress.h b/include/asm-arm/arch-anakin/uncompress.h
--- a/include/asm-arm/arch-anakin/uncompress.h	Tue Feb 26 11:58:00 2002
+++ b/include/asm-arm/arch-anakin/uncompress.h	Tue Feb 26 11:58:00 2002
@@ -14,6 +14,7 @@
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H
 
+#include <linux/config.h>
 #include <asm/io.h>
 #include <asm/arch/serial_reg.h>
 
diff -Nru a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h
--- a/include/asm-arm/arch-clps711x/memory.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/arch-clps711x/memory.h	Tue Feb 26 11:57:56 2002
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARCH_MMU_H
 #define __ASM_ARCH_MMU_H
 
+#include <linux/config.h>
+
 /*
  * Task size: 3GB
  */
diff -Nru a/include/asm-arm/arch-ebsa285/keyboard.h b/include/asm-arm/arch-ebsa285/keyboard.h
--- a/include/asm-arm/arch-ebsa285/keyboard.h	Tue Feb 26 11:57:58 2002
+++ b/include/asm-arm/arch-ebsa285/keyboard.h	Tue Feb 26 11:57:58 2002
@@ -6,6 +6,7 @@
  * Copyright (C) 1998-2001 Russell King
  * (C) 1998 Phil Blundell
  */
+#include <linux/config.h>
 #include <linux/ioport.h>
 #include <asm/irq.h>
 #include <asm/system.h>
diff -Nru a/include/asm-arm/arch-epxa10db/time.h b/include/asm-arm/arch-epxa10db/time.h
--- a/include/asm-arm/arch-epxa10db/time.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/arch-epxa10db/time.h	Tue Feb 26 11:57:59 2002
@@ -17,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/arch/hardware.h>
diff -Nru a/include/asm-arm/arch-iop310/irqs.h b/include/asm-arm/arch-iop310/irqs.h
--- a/include/asm-arm/arch-iop310/irqs.h	Tue Feb 26 11:57:58 2002
+++ b/include/asm-arm/arch-iop310/irqs.h	Tue Feb 26 11:57:58 2002
@@ -11,7 +11,7 @@
  * 06/13/01: Added 80310 on-chip interrupt sources <dsaxena@mvista.com>
  *
  */
-
+#include <linux/config.h>
 
 /*
  * XS80200 specific IRQs
diff -Nru a/include/asm-arm/arch-iop310/memory.h b/include/asm-arm/arch-iop310/memory.h
--- a/include/asm-arm/arch-iop310/memory.h	Tue Feb 26 11:57:58 2002
+++ b/include/asm-arm/arch-iop310/memory.h	Tue Feb 26 11:57:58 2002
@@ -5,6 +5,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
+#include <linux/config.h>
 
 /*
  * Task size: 3GB
diff -Nru a/include/asm-arm/arch-iop310/serial.h b/include/asm-arm/arch-iop310/serial.h
--- a/include/asm-arm/arch-iop310/serial.h	Tue Feb 26 11:58:00 2002
+++ b/include/asm-arm/arch-iop310/serial.h	Tue Feb 26 11:58:00 2002
@@ -1,7 +1,7 @@
 /*
  * include/asm-arm/arch-iop310/serial.h
  */
-
+#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff -Nru a/include/asm-arm/arch-iop310/timex.h b/include/asm-arm/arch-iop310/timex.h
--- a/include/asm-arm/arch-iop310/timex.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/arch-iop310/timex.h	Tue Feb 26 11:57:56 2002
@@ -3,7 +3,7 @@
  *
  * IOP310 architecture timex specifications
  */
-
+#include <linux/config.h>
 
 
 #ifdef CONFIG_ARCH_IQ80310
diff -Nru a/include/asm-arm/arch-iop310/uncompress.h b/include/asm-arm/arch-iop310/uncompress.h
--- a/include/asm-arm/arch-iop310/uncompress.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/arch-iop310/uncompress.h	Tue Feb 26 11:57:59 2002
@@ -1,6 +1,7 @@
 /*
  *  linux/include/asm-arm/arch-iop80310/uncompress.h
  */
+#include <linux/config.h>
 
 #ifdef CONFIG_ARCH_IQ80310
 #define UART1_BASE    ((volatile unsigned char *)0xfe800000)
diff -Nru a/include/asm-arm/arch-sa1100/assabet.h b/include/asm-arm/arch-sa1100/assabet.h
--- a/include/asm-arm/arch-sa1100/assabet.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/arch-sa1100/assabet.h	Tue Feb 26 11:57:56 2002
@@ -12,6 +12,8 @@
 #ifndef __ASM_ARCH_ASSABET_H
 #define __ASM_ARCH_ASSABET_H
 
+#include <linux/config.h>
+
 /* System Configuration Register flags */
 
 #define ASSABET_SCR_SDRAM_LOW	(1<<2)	/* SDRAM size (low bit) */
diff -Nru a/include/asm-arm/arch-sa1100/cerf.h b/include/asm-arm/arch-sa1100/cerf.h
--- a/include/asm-arm/arch-sa1100/cerf.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/arch-sa1100/cerf.h	Tue Feb 26 11:57:59 2002
@@ -1,6 +1,8 @@
 #ifndef _INCLUDE_CERF_H_
 #define _INCLUDE_CERF_H_
 
+#include <linux/config.h>
+
 #ifdef CONFIG_SA1100_CERF_CPLD
 
 
diff -Nru a/include/asm-arm/arch-sa1100/pangolin.h b/include/asm-arm/arch-sa1100/pangolin.h
--- a/include/asm-arm/arch-sa1100/pangolin.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/arch-sa1100/pangolin.h	Tue Feb 26 11:57:59 2002
@@ -6,10 +6,11 @@
  * This file contains the hardware specific definitions for Pangolin
  *
  */
-
 #ifndef __ASM_ARCH_HARDWARE_H
 #error "include <asm/hardware.h> instead"
 #endif
+
+#include <linux/config.h>
 
 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
 
diff -Nru a/include/asm-arm/arch-shark/keyboard.h b/include/asm-arm/arch-shark/keyboard.h
--- a/include/asm-arm/arch-shark/keyboard.h	Tue Feb 26 11:57:57 2002
+++ b/include/asm-arm/arch-shark/keyboard.h	Tue Feb 26 11:57:57 2002
@@ -6,6 +6,7 @@
  * (C) 1998 Russell King
  * (C) 1998 Phil Blundell
  */
+#include <linux/config.h>
 #include <linux/ioport.h>
 #include <asm/irq.h>
 #include <asm/io.h>
diff -Nru a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
--- a/include/asm-arm/bitops.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/bitops.h	Tue Feb 26 11:57:56 2002
@@ -302,6 +302,23 @@
 }
 
 /*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+	int k;
+
+	k = 31;
+	if (word & 0x0000ffff) { k -= 16; word <<= 16; }
+	if (word & 0x00ff0000) { k -= 8;  word <<= 8;  }
+	if (word & 0x0f000000) { k -= 4;  word <<= 4;  }
+	if (word & 0x30000000) { k -= 2;  word <<= 2;  }
+	if (word & 0x40000000) { k -= 1; }
+        return k;
+}
+
+/*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
  * differs in spirit from the above ffz (man ffs).
diff -Nru a/include/asm-arm/current.h b/include/asm-arm/current.h
--- a/include/asm-arm/current.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/current.h	Tue Feb 26 11:57:56 2002
@@ -1,12 +1,13 @@
 #ifndef _ASMARM_CURRENT_H
 #define _ASMARM_CURRENT_H
 
+#include <asm/thread_info.h>
+
 static inline struct task_struct *get_current(void) __attribute__ (( __const__ ));
 
 static inline struct task_struct *get_current(void)
 {
-	register unsigned long sp asm ("sp");
-	return (struct task_struct *)(sp & ~0x1fff);
+	return current_thread_info()->task;
 }
 
 #define current (get_current())
diff -Nru a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/fpstate.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,29 @@
+/*
+ *  linux/include/asm-arm/fpstate.h
+ *
+ *  Copyright (C) 1995 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.
+ */
+
+#ifndef __ASM_ARM_FPSTATE_H
+#define __ASM_ARM_FPSTATE_H
+
+#define FP_SIZE 35
+
+struct fp_hard_struct {
+	unsigned int save[FP_SIZE];		/* as yet undefined */
+};
+
+struct fp_soft_struct {
+	unsigned int save[FP_SIZE];		/* undefined information */
+};
+
+union fp_state {
+	struct fp_hard_struct	hard;
+	struct fp_soft_struct	soft;
+};
+
+#endif
diff -Nru a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
--- a/include/asm-arm/hardirq.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/hardirq.h	Tue Feb 26 11:57:56 2002
@@ -34,6 +34,7 @@
 #define irq_exit(cpu,irq)	(local_irq_count(cpu)--)
 
 #define synchronize_irq()	do { } while (0)
+#define release_irqlock(cpu)	do { } while (0)
 
 #else
 #error SMP not supported
diff -Nru a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
--- a/include/asm-arm/mmu_context.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/mmu_context.h	Tue Feb 26 11:57:59 2002
@@ -42,14 +42,34 @@
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
 	  struct task_struct *tsk, unsigned int cpu)
 {
-	if (prev != next) {
+	if (prev != next)
 		cpu_switch_mm(next->pgd, tsk);
-		clear_bit(cpu, &prev->cpu_vm_mask);
-	}
-	set_bit(cpu, &next->cpu_vm_mask);
 }
 
 #define activate_mm(prev, next) \
 	switch_mm((prev),(next),NULL,smp_processor_id())
+
+/*
+ * Find first bit set in a 168-bit bitmap, where the first
+ * 128 bits are unlikely to be set.
+ */
+static inline int sched_find_first_bit(unsigned long *b)
+{
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
+#error update this function
+#endif
+
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 32;
+	if (unlikely(b[2]))
+		return __ffs(b[2]) + 64;
+	if (unlikely(b[3]))
+		return __ffs(b[3]) + 96;
+	if (b[4])
+		return __ffs(b[4]) + MAX_RT_PRIO;
+	return __ffs(b[5]) + 32 + MAX_RT_PRIO;
+}
 
 #endif
diff -Nru a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
--- a/include/asm-arm/pgalloc.h	Tue Feb 26 11:58:00 2002
+++ b/include/asm-arm/pgalloc.h	Tue Feb 26 11:58:00 2002
@@ -57,40 +57,48 @@
 {
 	unsigned long *ret;
 
+	preempt_disable();
 	if ((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)__pgd_next(ret);
 		ret[1] = ret[2];
 		clean_dcache_entry(ret + 1);
 		pgtable_cache_size--;
 	}
+	preempt_enable();
 	return (pgd_t *)ret;
 }
 
 static inline void free_pgd_fast(pgd_t *pgd)
 {
+	preempt_disable();
 	__pgd_next(pgd) = (unsigned long) pgd_quicklist;
 	pgd_quicklist = (unsigned long *) pgd;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
 	unsigned long *ret;
 
+	preempt_disable();
 	if((ret = pte_quicklist) != NULL) {
 		pte_quicklist = (unsigned long *)__pte_next(ret);
 		ret[0] = 0;
 		clean_dcache_entry(ret);
 		pgtable_cache_size--;
 	}
+	preempt_enable();
 	return (pte_t *)ret;
 }
 
 static inline void free_pte_fast(pte_t *pte)
 {
+	preempt_disable();
 	__pte_next(pte) = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pte;
 	pgtable_cache_size++;
+	preempt_enable();
 }
 
 #else	/* CONFIG_NO_PGT_CACHE */
diff -Nru a/include/asm-arm/proc-armo/processor.h b/include/asm-arm/proc-armo/processor.h
--- a/include/asm-arm/proc-armo/processor.h	Tue Feb 26 11:57:58 2002
+++ b/include/asm-arm/proc-armo/processor.h	Tue Feb 26 11:57:58 2002
@@ -23,7 +23,7 @@
 
 #define KERNEL_STACK_SIZE 4096
 
-struct context_save_struct {
+struct cpu_context_save {
 	unsigned long r4;
 	unsigned long r5;
 	unsigned long r6;
@@ -35,7 +35,7 @@
 	unsigned long pc;
 };
 
-#define INIT_CSS (struct context_save_struct){ 0, 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
+#define INIT_CSS (struct cpu_context_save){ 0, 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
 
 typedef struct {
 	void (*put_byte)(void);			/* Special calling convention */
@@ -73,15 +73,5 @@
 
 #define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
 #define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
-
-/* Allocation and freeing of basic task resources. */
-/*
- * NOTE! The task struct and the stack go together
- */
-extern unsigned long get_page_8k(int priority);
-extern void free_page_8k(unsigned long page);
-
-#define ll_alloc_task_struct()	((struct task_struct *)get_page_8k(GFP_KERNEL))
-#define ll_free_task_struct(p)  free_page_8k((unsigned long)(p))
 
 #endif
diff -Nru a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h
--- a/include/asm-arm/proc-armv/processor.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/proc-armv/processor.h	Tue Feb 26 11:57:59 2002
@@ -22,7 +22,7 @@
 
 #define KERNEL_STACK_SIZE	PAGE_SIZE
 
-struct context_save_struct {
+struct cpu_context_save {
 	unsigned long cpsr;
 	unsigned long r4;
 	unsigned long r5;
@@ -35,15 +35,12 @@
 	unsigned long pc;
 };
 
-#define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define INIT_CSS (struct cpu_context_save){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 
-#define EXTRA_THREAD_STRUCT						\
-	unsigned int	domain;
-
-#define EXTRA_THREAD_STRUCT_INIT					\
-	domain:	  domain_val(DOMAIN_USER, DOMAIN_CLIENT) |		\
-		  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |		\
-		  domain_val(DOMAIN_IO, DOMAIN_CLIENT)
+#define INIT_EXTRA_THREAD_INFO						\
+	cpu_domain:	  domain_val(DOMAIN_USER, DOMAIN_CLIENT) |	\
+			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
+			  domain_val(DOMAIN_IO, DOMAIN_CLIENT)
 
 #define start_thread(regs,pc,sp)					\
 ({									\
@@ -63,12 +60,5 @@
 
 #define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
 #define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-
-/* Allocation and freeing of basic task resources. */
-/*
- * NOTE! The task struct and the stack go together
- */
-#define ll_alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 
 #endif
diff -Nru a/include/asm-arm/proc-armv/uaccess.h b/include/asm-arm/proc-armv/uaccess.h
--- a/include/asm-arm/proc-armv/uaccess.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/proc-armv/uaccess.h	Tue Feb 26 11:57:56 2002
@@ -16,8 +16,7 @@
 
 static inline void set_fs (mm_segment_t fs)
 {
-	current->addr_limit = fs;
-
+	current_thread_info()->addr_limit = fs;
 	modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
 }
 
@@ -26,7 +25,7 @@
 	unsigned long flag, sum; \
 	__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
 		: "=&r" (flag), "=&r" (sum) \
-		: "r" (addr), "Ir" (size), "0" (current->addr_limit) \
+		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
 		: "cc"); \
 	flag; })
 
@@ -34,7 +33,7 @@
 	unsigned long flag; \
 	__asm__("cmp %2, %0; movlo %0, #0" \
 		: "=&r" (flag) \
-		: "0" (current->addr_limit), "r" (addr) \
+		: "0" (current_thread_info()->addr_limit), "r" (addr) \
 		: "cc"); \
 	(flag == 0); })
 
diff -Nru a/include/asm-arm/processor.h b/include/asm-arm/processor.h
--- a/include/asm-arm/processor.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/processor.h	Tue Feb 26 11:57:59 2002
@@ -17,23 +17,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#define FP_SIZE 35
-
-struct fp_hard_struct {
-	unsigned int save[FP_SIZE];		/* as yet undefined */
-};
-
-struct fp_soft_struct {
-	unsigned int save[FP_SIZE];		/* undefined information */
-};
-
-union fp_state {
-	struct fp_hard_struct	hard;
-	struct fp_soft_struct	soft;
-};
-
-typedef unsigned long mm_segment_t;		/* domain register	*/
-
 #ifdef __KERNEL__
 
 #define EISA_bus 0
@@ -54,37 +37,15 @@
 };
 
 struct thread_struct {
-	atomic_t			refcount;
 							/* fault info	  */
 	unsigned long			address;
 	unsigned long			trap_no;
 	unsigned long			error_code;
-							/* floating point */
-	union fp_state			fpstate;
 							/* debugging	  */
 	struct debug_info		debug;
-							/* context info	  */
-	struct context_save_struct	*save;
-	EXTRA_THREAD_STRUCT
 };
 
-#define INIT_THREAD  {					\
-	refcount:	ATOMIC_INIT(1),			\
-	EXTRA_THREAD_STRUCT_INIT			\
-}
-
-/*
- * Return saved PC of a blocked thread.
- */
-static inline unsigned long thread_saved_pc(struct thread_struct *t)
-{
-	return t->save ? pc_pointer(t->save->pc) : 0;
-}
-
-static inline unsigned long get_css_fp(struct thread_struct *t)
-{
-	return t->save ? t->save->fp : 0;
-}
+#define INIT_THREAD  {	}
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -98,21 +59,7 @@
 
 unsigned long get_wchan(struct task_struct *p);
 
-#define THREAD_SIZE	(8192)
-
-extern struct task_struct *alloc_task_struct(void);
-extern void __free_task_struct(struct task_struct *);
-#define get_task_struct(p)	atomic_inc(&(p)->thread.refcount)
-#define free_task_struct(p)					\
- do {								\
-	if (atomic_dec_and_test(&(p)->thread.refcount))		\
-		__free_task_struct((p));			\
- } while (0)
-
-#define init_task	(init_task_union.task)
-#define init_stack	(init_task_union.stack)
-
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()			do { } while (0)
 
 /*
  * Create a new kernel thread
diff -Nru a/include/asm-arm/smplock.h b/include/asm-arm/smplock.h
--- a/include/asm-arm/smplock.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/smplock.h	Tue Feb 26 11:57:56 2002
@@ -3,31 +3,34 @@
  *
  * Default SMP lock implementation
  */
+#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 
 extern spinlock_t kernel_flag;
 
+#ifdef CONFIG_PREEMPT
+#define kernel_locked()		preempt_get_count()
+#else
 #define kernel_locked()		spin_is_locked(&kernel_flag)
+#endif
 
 /*
  * Release global kernel lock and global interrupt lock
  */
-#define release_kernel_lock(task, cpu) \
-do { \
-	if (task->lock_depth >= 0) \
-		spin_unlock(&kernel_flag); \
-	release_irqlock(cpu); \
-	__sti(); \
+#define release_kernel_lock(task, cpu)		\
+do {						\
+	if (unlikely(task->lock_depth >= 0))	\
+		spin_unlock(&kernel_flag);	\
 } while (0)
 
 /*
  * Re-acquire the kernel lock
  */
-#define reacquire_kernel_lock(task) \
-do { \
-	if (task->lock_depth >= 0) \
-		spin_lock(&kernel_flag); \
+#define reacquire_kernel_lock(task)		\
+do {						\
+	if (unlikely(task->lock_depth >= 0))	\
+		spin_lock(&kernel_flag);	\
 } while (0)
 
 
@@ -40,8 +43,14 @@
  */
 static inline void lock_kernel(void)
 {
+#ifdef CONFIG_PREEMPT
+	if (current->lock_depth == -1)
+		spin_lock(&kernel_flag);
+	++current->lock_depth;
+#else
 	if (!++current->lock_depth)
 		spin_lock(&kernel_flag);
+#endif
 }
 
 static inline void unlock_kernel(void)
diff -Nru a/include/asm-arm/softirq.h b/include/asm-arm/softirq.h
--- a/include/asm-arm/softirq.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/softirq.h	Tue Feb 26 11:57:59 2002
@@ -5,20 +5,22 @@
 #include <asm/hardirq.h>
 
 #define __cpu_bh_enable(cpu) \
-		do { barrier(); local_bh_count(cpu)--; } while (0)
+		do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
 #define cpu_bh_disable(cpu) \
-		do { local_bh_count(cpu)++; barrier(); } while (0)
+		do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define __local_bh_enable()	__cpu_bh_enable(smp_processor_id())
 
 #define in_softirq()		(local_bh_count(smp_processor_id()) != 0)
 
-#define local_bh_enable()						\
+#define _local_bh_enable()						\
 do {									\
 	unsigned int *ptr = &local_bh_count(smp_processor_id());	\
 	if (!--*ptr && ptr[-2])						\
 		__asm__("bl%? __do_softirq": : : "lr");/* out of line */\
 } while (0)
+
+#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -Nru a/include/asm-arm/stat.h b/include/asm-arm/stat.h
--- a/include/asm-arm/stat.h	Tue Feb 26 11:57:57 2002
+++ b/include/asm-arm/stat.h	Tue Feb 26 11:57:57 2002
@@ -42,8 +42,14 @@
  * insane amounts of padding around dev_t's.
  */
 struct stat64 {
-	unsigned short	st_dev;
-	unsigned char	__pad0[10];
+#if defined(__ARMEB__)
+	unsigned char   __pad0b[6];
+	unsigned short  st_dev;
+#else
+	unsigned short  st_dev;
+	unsigned char   __pad0b[6];
+#endif
+	unsigned char   __pad0[4];
 
 #define STAT64_HAS_BROKEN_ST_INO	1
 	unsigned long	__st_ino;
@@ -53,14 +59,25 @@
 	unsigned long	st_uid;
 	unsigned long	st_gid;
 
-	unsigned short	st_rdev;
-	unsigned char	__pad3[10];
+#if defined(__ARMEB__)
+	unsigned char   __pad3b[6];
+	unsigned short  st_rdev;
+#else /* Must be little */
+	unsigned short  st_rdev;
+	unsigned char   __pad3b[6];
+#endif
+	unsigned char   __pad3[4];
 
 	long long	st_size;
 	unsigned long	st_blksize;
 
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
+#if defined(__ARMEB__)
+	unsigned long   __pad4;		/* Future possible st_blocks hi bits */
+	unsigned long   st_blocks;	/* Number 512-byte blocks allocated. */
+#else /* Must be little */
+	unsigned long   st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long   __pad4;		/* Future possible st_blocks hi bits */
+#endif
 
 	unsigned long	st_atime;
 	unsigned long	__pad5;
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Tue Feb 26 11:57:57 2002
+++ b/include/asm-arm/system.h	Tue Feb 26 11:57:57 2002
@@ -6,6 +6,8 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 
+struct thread_info;
+
 /* information about the system we're running on */
 extern unsigned int system_rev;
 extern unsigned int system_serial_low;
@@ -48,12 +50,13 @@
  * `prev' will never be the same as `next'.
  * The `mb' is to tell GCC not to cache `current' across this call.
  */
-extern struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next);
+struct thread_info;
+extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *);
 
-#define switch_to(prev,next,last)		\
-	do {			 		\
-		last = __switch_to(prev,next);	\
-		mb();				\
+#define switch_to(prev,next,last)					\
+	do {			 					\
+		last = __switch_to(prev->thread_info,next->thread_info); \
+		mb();							\
 	} while (0)
 
 /* For spinlocks etc */
diff -Nru a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/thread_info.h	Tue Feb 26 11:58:00 2002
@@ -0,0 +1,134 @@
+/*
+ *  linux/include/asm-arm/thread_info.h
+ *
+ *  Copyright (C) 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.
+ */
+#ifndef __ASM_ARM_THREAD_INFO_H
+#define __ASM_ARM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+struct exec_domain;
+
+#include <asm/fpstate.h>
+#include <asm/proc/processor.h>
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+typedef unsigned long mm_segment_t;		/* domain register	*/
+
+/*
+ * low level task data that entry.S needs immediate access to.
+ */
+struct thread_info {
+	__u32			flags;		/* low level flags */
+	__s32			preempt_count;	/* 0 => preemptable, <0 => bug */
+	mm_segment_t		addr_limit;	/* address limit */
+	__u32			cpu;		/* cpu */
+	struct cpu_context_save	*cpu_context;	/* cpu context */
+	__u32			cpu_domain;	/* cpu domain */
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	union fp_state		fpstate;
+};
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	task:		&tsk,			\
+	exec_domain:	&default_exec_domain,	\
+	flags:		0,			\
+	preempt_count:	0,			\
+	addr_limit:	KERNEL_DS,		\
+	INIT_EXTRA_THREAD_INFO,			\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/*
+ * how to get the thread information struct from C
+ */
+static inline struct thread_info *current_thread_info(void) __attribute__ (( __const__ ));
+
+static inline struct thread_info *current_thread_info(void)
+{
+	register unsigned long sp asm ("sp");
+	return (struct thread_info *)(sp & ~0x1fff);
+}
+
+#define THREAD_SIZE		(8192)
+
+extern struct thread_info *alloc_thread_info(void);
+extern void free_thread_info(struct thread_info *);
+
+#define get_thread_info(ti)	get_task_struct((ti)->task)
+#define put_thread_info(ti)	put_task_struct((ti)->task)
+
+static inline unsigned long __thread_saved_pc(struct thread_info *thread)
+{
+	struct cpu_context_save *context = thread->cpu_context;
+
+	return context ? pc_pointer(context->pc) : 0;
+}
+
+static inline unsigned long __thread_saved_fp(struct thread_info *thread)
+{
+	struct cpu_context_save *context = thread->cpu_context;
+
+	return context ? context->fp : 0;
+}
+
+#define thread_saved_pc(tsk)	__thread_saved_pc((tsk)->thread_info)
+#define thread_saved_fp(tsk)	__thread_saved_fp((tsk)->thread_info)
+
+#else /* !__ASSEMBLY__ */
+
+#define TI_FLAGS	0
+#define TI_PREEMPT	4
+#define TI_ADDR_LIMIT	8
+#define TI_CPU		12
+#define TI_CPU_SAVE	16
+#define TI_CPU_DOMAIN	20
+#define TI_TASK		24
+#define TI_EXEC_DOMAIN	28
+#define TI_FPSTATE	32
+
+#endif
+
+/*
+ * thread information flags:
+ *  TIF_SYSCALL_TRACE	- syscall trace active
+ *  TIF_NOTIFY_RESUME	- resumption notification requested
+ *  TIF_SIGPENDING	- signal pending
+ *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
+ *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
+ */
+#define TIF_NOTIFY_RESUME	0
+#define TIF_SIGPENDING		1
+#define TIF_NEED_RESCHED	2
+#define TIF_SYSCALL_TRACE	8
+#define TIF_USED_FPU		16
+#define TIF_POLLING_NRFLAG	17
+
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_USED_FPU		(1 << TIF_USED_FPU)
+#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+
+/*
+ * Change these and you break ASM code in entry-common.S
+ */
+#define _TIF_WORK_MASK		0x000000ff
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_ARM_THREAD_INFO_H */
diff -Nru a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
--- a/include/asm-arm/uaccess.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-arm/uaccess.h	Tue Feb 26 11:57:56 2002
@@ -32,7 +32,7 @@
 extern unsigned long search_exception_table(unsigned long);
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->addr_limit)
+#define get_fs()	(current_thread_info()->addr_limit)
 #define segment_eq(a,b)	((a) == (b))
 
 #include <asm/proc/uaccess.h>
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-arm/unistd.h	Tue Feb 26 11:57:59 2002
@@ -244,6 +244,19 @@
 #define __NR_security			(__NR_SYSCALL_BASE+223)
 #define __NR_gettid			(__NR_SYSCALL_BASE+224)
 #define __NR_readahead			(__NR_SYSCALL_BASE+225)
+#define __NR_setxattr			(__NR_SYSCALL_BASE+226)
+#define __NR_lsetxattr			(__NR_SYSCALL_BASE+227)
+#define __NR_fsetxattr			(__NR_SYSCALL_BASE+228)
+#define __NR_getxattr			(__NR_SYSCALL_BASE+229)
+#define __NR_lgetxattr			(__NR_SYSCALL_BASE+230)
+#define __NR_fgetxattr			(__NR_SYSCALL_BASE+231)
+#define __NR_listxattr			(__NR_SYSCALL_BASE+232)
+#define __NR_llistxattr			(__NR_SYSCALL_BASE+233)
+#define __NR_flistxattr			(__NR_SYSCALL_BASE+234)
+#define __NR_removexattr		(__NR_SYSCALL_BASE+235)
+#define __NR_lremovexattr		(__NR_SYSCALL_BASE+236)
+#define __NR_fremovexattr		(__NR_SYSCALL_BASE+237)
+#define __NR_tkill			(__NR_SYSCALL_BASE+238)
 
 /*
  * The following SWIs are ARM private.
diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
--- a/include/asm-i386/fixmap.h	Tue Feb 26 11:57:56 2002
+++ b/include/asm-i386/fixmap.h	Tue Feb 26 11:57:56 2002
@@ -65,6 +65,11 @@
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+	__end_of_permanent_fixed_addresses,
+	/* temporary boot-time mappings, used before ioremap() is functional */
+#define NR_FIX_BTMAPS	16
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
 	__end_of_fixed_addresses
 };
 
@@ -86,8 +91,8 @@
  * at the top of mem..
  */
 #define FIXADDR_TOP	(0xffffe000UL)
-#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
-#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+#define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START	(FIXADDR_TOP - __FIXADDR_SIZE)
 
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-i386/hw_irq.h	Tue Feb 26 11:57:59 2002
@@ -35,14 +35,13 @@
  *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
  *  TLB, reschedule and local APIC vectors are performance-critical.
  *
- *  Vectors 0xf0-0xf9 are free (reserved for future Linux use).
+ *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
  */
 #define SPURIOUS_APIC_VECTOR	0xff
 #define ERROR_APIC_VECTOR	0xfe
 #define INVALIDATE_TLB_VECTOR	0xfd
 #define RESCHEDULE_VECTOR	0xfc
-#define TASK_MIGRATION_VECTOR	0xfb
-#define CALL_FUNCTION_VECTOR	0xfa
+#define CALL_FUNCTION_VECTOR	0xfb
 
 /*
  * Local APIC timer IRQ vector is on a different priority level,
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	Tue Feb 26 11:57:59 2002
+++ b/include/asm-i386/io.h	Tue Feb 26 11:57:59 2002
@@ -95,6 +95,14 @@
 extern void iounmap(void *addr);
 
 /*
+ * bt_ioremap() and bt_iounmap() are for temporary early boot-time
+ * mappings, before the real ioremap() is functional.
+ * A boot-time mapping is currently limited to at most 16 pages.
+ */
+extern void *bt_ioremap(unsigned long offset, unsigned long size);
+extern void bt_iounmap(void *addr, unsigned long size);
+
+/*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
  */
 #define isa_virt_to_bus virt_to_phys
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	Tue Feb 26 11:57:59 2002
+++ b/include/linux/dcache.h	Tue Feb 26 11:57:59 2002
@@ -126,6 +126,7 @@
 #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
 
 extern spinlock_t dcache_lock;
+extern rwlock_t dparent_lock;
 
 /**
  * d_drop - drop a dentry
diff -Nru a/include/linux/dnotify.h b/include/linux/dnotify.h
--- a/include/linux/dnotify.h	Tue Feb 26 11:57:56 2002
+++ b/include/linux/dnotify.h	Tue Feb 26 11:57:56 2002
@@ -33,13 +33,13 @@
 static inline void dnotify_parent(struct dentry *dentry, unsigned long event)
 {
 	struct dentry *parent;
-	spin_lock(&dcache_lock);
+	read_lock(&dparent_lock);
 	parent = dentry->d_parent;
 	if (parent->d_inode->i_dnotify_mask & event) {
 		dget(parent);
-		spin_unlock(&dcache_lock);
+		read_unlock(&dparent_lock);
 		__inode_dir_notify(parent->d_inode, event);
 		dput(parent);
 	} else
-		spin_unlock(&dcache_lock);
+		read_unlock(&dparent_lock);
 }
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Tue Feb 26 11:57:58 2002
+++ b/include/linux/fs.h	Tue Feb 26 11:57:58 2002
@@ -377,8 +377,8 @@
 	unsigned long		nrpages;	/* number of total pages */
 	struct address_space_operations *a_ops;	/* methods */
 	struct inode		*host;		/* owner: inode, block_device */
-	struct vm_area_struct	*i_mmap;	/* list of private mappings */
-	struct vm_area_struct	*i_mmap_shared; /* list of shared mappings */
+	list_t			i_mmap;		/* list of private mappings */
+	list_t			i_mmap_shared;	/* list of private mappings */
 	spinlock_t		i_shared_lock;  /* and spinlock protecting it */
 	int			gfp_mask;	/* how to allocate the pages */
 };
@@ -1511,9 +1511,9 @@
 static inline ino_t parent_ino(struct dentry *dentry)
 {
 	ino_t res;
-	spin_lock(&dcache_lock);
+	read_lock(&dparent_lock);
 	res = dentry->d_parent->d_inode->i_ino;
-	spin_unlock(&dcache_lock);
+	read_unlock(&dparent_lock);
 	return res;
 }
 
diff -Nru a/include/linux/lvm.h b/include/linux/lvm.h
--- a/include/linux/lvm.h	Tue Feb 26 11:57:56 2002
+++ b/include/linux/lvm.h	Tue Feb 26 11:57:56 2002
@@ -477,8 +477,16 @@
  * Structure Logical Volume (LV) Version 3
  */
 
-/* core */
-typedef struct lv_v5 {
+struct kern_lv_v5;
+struct user_lv_v5;
+typedef struct user_lv_v5 userlv_t;
+#ifdef __KERNEL__
+typedef struct kern_lv_v5 lv_t;
+#else
+typedef struct user_lv_v5 lv_t;
+#endif
+
+struct user_lv_v5 {
 	char lv_name[NAME_LEN];
 	char vg_name[NAME_LEN];
 	uint lv_access;
@@ -501,15 +509,18 @@
 	uint lv_read_ahead;
 
 	/* delta to version 1 starts here */
-       struct lv_v5 *lv_snapshot_org;
-       struct lv_v5 *lv_snapshot_prev;
-       struct lv_v5 *lv_snapshot_next;
+	lv_t *lv_snapshot_org;
+	lv_t *lv_snapshot_prev;
+	lv_t *lv_snapshot_next;
 	lv_block_exception_t *lv_block_exception;
 	uint lv_remap_ptr;
 	uint lv_remap_end;
 	uint lv_chunk_size;
 	uint lv_snapshot_minor;
-#ifdef __KERNEL__
+};
+
+struct kern_lv_v5{
+	struct user_lv_v5 u;
 	struct kiobuf *lv_iobuf;
 	sector_t blocks[LVM_MAX_SECTORS];
 	struct kiobuf *lv_COW_table_iobuf;
@@ -520,12 +531,8 @@
 	wait_queue_head_t lv_snapshot_wait;
 	int	lv_snapshot_use_rate;
 	struct vg_v3	*vg;
-
 	uint lv_allocated_snapshot_le;
-#else
-	char dummy[200];
-#endif
-} lv_t;
+};
 
 /* disk */
 typedef struct lv_disk_v3 {
@@ -679,13 +686,13 @@
 }
 
 static int inline LVM_GET_COW_TABLE_CHUNKS_PER_PE(vg_t *vg, lv_t *lv) {
-	return vg->pe_size / lv->lv_chunk_size;
+	return vg->pe_size / lv->u.lv_chunk_size;
 }
 
 static int inline LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg_t *vg, lv_t *lv) {
-	ulong chunks = vg->pe_size / lv->lv_chunk_size;
+	ulong chunks = vg->pe_size / lv->u.lv_chunk_size;
 	ulong entry_size = sizeof(lv_COW_table_disk_t);
-	ulong chunk_size = lv->lv_chunk_size * SECTOR_SIZE;
+	ulong chunk_size = lv->u.lv_chunk_size * SECTOR_SIZE;
 	ulong entries = (vg->pe_size * SECTOR_SIZE) /
 		(entry_size + chunk_size);
 
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Tue Feb 26 11:57:56 2002
+++ b/include/linux/mm.h	Tue Feb 26 11:57:56 2002
@@ -61,8 +61,7 @@
 	 * one of the address_space->i_mmap{,shared} lists,
 	 * for shm areas, the list of attaches, otherwise unused.
 	 */
-	struct vm_area_struct *vm_next_share;
-	struct vm_area_struct **vm_pprev_share;
+	list_t shared;
 
 	/* Function pointers to deal with this struct. */
 	struct vm_operations_struct * vm_ops;
@@ -585,7 +584,7 @@
 
 extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
 
-extern struct page * vmalloc_to_page(unsigned long adr);
+extern struct page * vmalloc_to_page(void *addr);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Tue Feb 26 11:57:59 2002
+++ b/include/linux/pci_ids.h	Tue Feb 26 11:57:59 2002
@@ -772,6 +772,7 @@
 #define PCI_VENDOR_ID_3COM		0x10b7
 #define PCI_DEVICE_ID_3COM_3C985	0x0001
 #define PCI_DEVICE_ID_3COM_3C339	0x3390
+#define PCI_DEVICE_ID_3COM_3C359	0x3590
 #define PCI_DEVICE_ID_3COM_3C590	0x5900
 #define PCI_DEVICE_ID_3COM_3C595TX	0x5950
 #define PCI_DEVICE_ID_3COM_3C595T4	0x5951
@@ -1461,9 +1462,9 @@
 #define PCI_VENDOR_ID_OXSEMI		0x1415
 #define PCI_DEVICE_ID_OXSEMI_12PCI840	0x8403
 #define PCI_DEVICE_ID_OXSEMI_16PCI954	0x9501
-#define PCI_DEVICE_ID_OXSEMI_16PCI952	0x950A
 #define PCI_DEVICE_ID_OXSEMI_16PCI95N	0x9511
 #define PCI_DEVICE_ID_OXSEMI_16PCI954PP	0x9513
+#define PCI_DEVICE_ID_OXSEMI_16PCI952	0x9521
 
 #define PCI_VENDOR_ID_AIRONET		0x14b9
 #define PCI_DEVICE_ID_AIRONET_4800_1	0x0001
diff -Nru a/include/linux/rtc.h b/include/linux/rtc.h
--- a/include/linux/rtc.h	Tue Feb 26 11:57:56 2002
+++ b/include/linux/rtc.h	Tue Feb 26 11:57:56 2002
@@ -66,4 +66,17 @@
 #define RTC_WKALM_SET	_IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
 #define RTC_WKALM_RD	_IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
 
+#ifdef __KERNEL__
+
+typedef struct rtc_task {
+	void (*func)(void *private_data);
+	void *private_data;
+} rtc_task_t;
+
+int rtc_register(rtc_task_t *task);
+int rtc_unregister(rtc_task_t *task);
+int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
+
+#endif /* __KERNEL__ */
+
 #endif /* _LINUX_RTC_H_ */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Tue Feb 26 11:57:57 2002
+++ b/include/linux/sched.h	Tue Feb 26 11:57:57 2002
@@ -150,8 +150,7 @@
 extern void update_one_process(struct task_struct *p, unsigned long user,
 			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
-extern void sched_task_migrated(struct task_struct *p);
-extern void smp_migrate_task(int cpu, task_t *task);
+extern void migration_init(void);
 extern unsigned long cache_decay_ticks;
 
 
@@ -286,6 +285,7 @@
 
 	wait_queue_head_t wait_chldexit;	/* for wait4() */
 	struct completion *vfork_done;		/* for vfork() */
+
 	unsigned long rt_priority;
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
@@ -382,7 +382,12 @@
  */
 #define _STK_LIM	(8*1024*1024)
 
+#if CONFIG_SMP
 extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
+#else
+# define set_cpus_allowed(p, new_mask) do { } while (0)
+#endif
+
 extern void set_user_nice(task_t *p, long nice);
 extern int task_prio(task_t *p);
 extern int task_nice(task_t *p);
@@ -460,7 +465,6 @@
 extern unsigned long prof_shift;
 
 extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr));
-extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr));
 extern void FASTCALL(sleep_on(wait_queue_head_t *q));
 extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
 				      signed long timeout));
@@ -474,13 +478,9 @@
 #define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
 #define wake_up_nr(x, nr)		__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
 #define wake_up_all(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0)
-#define wake_up_sync(x)			__wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
-#define wake_up_sync_nr(x, nr)		__wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
 #define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE, 1)
 #define wake_up_interruptible_nr(x, nr)	__wake_up((x),TASK_INTERRUPTIBLE, nr)
 #define wake_up_interruptible_all(x)	__wake_up((x),TASK_INTERRUPTIBLE, 0)
-#define wake_up_interruptible_sync(x)	__wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
-#define wake_up_interruptible_sync_nr(x) __wake_up_sync((x),TASK_INTERRUPTIBLE,  nr)
 asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
 
 extern int in_group_p(gid_t);
diff -Nru a/include/math-emu/op-4.h b/include/math-emu/op-4.h
--- a/include/math-emu/op-4.h	Tue Feb 26 11:57:58 2002
+++ b/include/math-emu/op-4.h	Tue Feb 26 11:57:58 2002
@@ -645,7 +645,7 @@
     X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
     X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
     X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
-  } while (0);
+  } while (0)
 
 #define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)				\
    do {									\
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	Tue Feb 26 11:57:56 2002
+++ b/include/sound/ac97_codec.h	Tue Feb 26 11:57:56 2002
@@ -135,6 +135,7 @@
 struct _snd_ac97 {
 	void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val);
 	unsigned short (*read) (ac97_t *ac97, unsigned short reg);
+	void (*wait) (ac97_t *ac97);
 	void (*init) (ac97_t *ac97);
 	snd_info_entry_t *proc_entry;
 	snd_info_entry_t *proc_regs_entry;
diff -Nru a/include/sound/asound.h b/include/sound/asound.h
--- a/include/sound/asound.h	Tue Feb 26 11:57:59 2002
+++ b/include/sound/asound.h	Tue Feb 26 11:57:59 2002
@@ -127,7 +127,7 @@
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION			SNDRV_PROTOCOL_VERSION(2, 0, 0)
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 1)
 
 typedef unsigned long sndrv_pcm_uframes_t;
 typedef long sndrv_pcm_sframes_t;
@@ -411,6 +411,7 @@
 	SNDRV_PCM_IOCTL_PAUSE = _IOW('A', 0x45, int),
 	SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, sndrv_pcm_uframes_t),
 	SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47),
+	SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48),
 	SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct sndrv_xferi),
 	SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct sndrv_xferi),
 	SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct sndrv_xfern),
@@ -578,7 +579,7 @@
  *                                                                          *
  ****************************************************************************/
 
-#define SNDRV_CTL_VERSION			SNDRV_PROTOCOL_VERSION(2, 0, 0)
+#define SNDRV_CTL_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 0)
 
 struct sndrv_ctl_card_info {
 	int card;			/* card number */
diff -Nru a/include/sound/core.h b/include/sound/core.h
--- a/include/sound/core.h	Tue Feb 26 11:57:59 2002
+++ b/include/sound/core.h	Tue Feb 26 11:57:59 2002
@@ -292,13 +292,21 @@
 /* misc.c */
 
 int snd_task_name(struct task_struct *task, char *name, size_t size);
+#ifdef CONFIG_SND_VERBOSE_PRINTK
+int snd_verbose_printk(const char *file, int line, const char *format);
+#endif
 
 /* --- */
 
+#ifdef CONFIG_SND_VERBOSE_PRINTK
+#define snd_printk(format, args...) do { \
+	printk(snd_verbose_printk(__FILE__, __LINE__, format) ? format + 3 : format, ##args); \
+} while (0)
+#else
 #define snd_printk(format, args...) do { \
-	printk("ALSA %s:%d: ", __FILE__, __LINE__); \
 	printk(format, ##args); \
 } while (0)
+#endif
 
 #ifdef CONFIG_SND_DEBUG
 
diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h
--- a/include/sound/emu10k1.h	Tue Feb 26 11:57:58 2002
+++ b/include/sound/emu10k1.h	Tue Feb 26 11:57:58 2002
@@ -588,7 +588,7 @@
 #define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
 #define A_DBG			 0x53
-#define A_DBG_SINGLE_STEP_ADDR	 0x00020000	/* Set to zero to start dsp */
+#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
 #define A_DBG_ZC		 0x40000000	/* zero tram counter */
 #define A_DBG_STEP_ADDR		 0x000003ff
 #define A_DBG_SATURATION_OCCURED 0x20000000
@@ -657,6 +657,11 @@
 #define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
 #define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
 
+/* Note that these values can vary +/- by a small amount                                        */
+#define SRCS_SPDIFRATE_44	0x0003acd9
+#define SRCS_SPDIFRATE_48	0x00040000
+#define SRCS_SPDIFRATE_96	0x00080000
+
 #define MICIDX                  0x63            /* Microphone recording buffer index register   */
 #define MICIDX_MASK             0x0000ffff      /* 16-bit value                                 */
 #define MICIDX_IDX		0x10000063
@@ -683,15 +688,15 @@
 #define A_MUSTAT2		A_MUCMD2	
 
 #define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
-#define A_SPDIF_48000		0x00000000
-#define A_SPDIF_44100		0x00000040
-#define A_SPDIF_96000		0x00000080
+#define A_SPDIF_48000		0x00000080
+#define A_SPDIF_44100		0x00000000
+#define A_SPDIF_96000		0x00000040
 
 #define A_FXRT2			0x7c
-#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send A	*/
-#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send B	*/
-#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send C	*/
-#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send D	*/
+#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
+#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
+#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
+#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
 
 #define A_SENDAMOUNTS		0x7d
 #define A_FXSENDAMOUNT_E_MASK	0xFF000000
@@ -797,8 +802,8 @@
 };
 
 typedef struct {
-	unsigned long send_routing[3];
-	unsigned char send_volume[3][4];
+	unsigned char send_routing[3][8];
+	unsigned char send_volume[3][8];
 	unsigned short attn[3];
 	snd_kcontrol_t *ctl_send_routing;
 	snd_kcontrol_t *ctl_send_volume;
@@ -806,6 +811,15 @@
 	emu10k1_pcm_t *epcm;
 } emu10k1_pcm_mixer_t;
 
+#define snd_emu10k1_compose_send_routing(route) \
+((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16)
+
+#define snd_emu10k1_compose_audigy_fxrt1(route) \
+(((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 12)) << 24)
+
+#define snd_emu10k1_compose_audigy_fxrt2(route) \
+(((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 12)) << 24)
+
 typedef struct snd_emu10k1_memblk {
 	snd_util_memblk_t mem;
 	/* private part */
@@ -1102,11 +1116,11 @@
 #define GPR_NOISE1	0x59		/* noise source */
 #define GPR_IRQ		0x5a		/* IRQ register */
 #define GPR_DBAC	0x5b		/* TRAM Delay Base Address Counter */
-#define GPR(x)		(FXGPREGBASE + (x))	/* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x)	(TANKMEMDATAREGBASE + (x))	/* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 80 + (x))	/* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + (x))	/* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 80 + (x))	/* x = 0x00 - 0x1f */
+#define GPR(x)		(FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
 
 #define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f? */
 #define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x1f? */
@@ -1171,6 +1185,10 @@
 #define A_EXTIN_AC97_R		0x01	/* AC'97 capture channel - right */
 #define A_EXTIN_SPDIF_CD_L	0x02	/* digital CD left */
 #define A_EXTIN_SPDIF_CD_R	0x03	/* digital CD left */
+#define A_EXTIN_LINE2_L		0x08	/* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R		0x09	/*                           right */
+#define A_EXTIN_AUX2_L		0x0c	/* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R		0x0d	/*                   - right */
 
 /* Audigiy Outputs */
 #define A_EXTOUT_FRONT_L	0x00	/* digital front left */
@@ -1189,9 +1207,38 @@
 /* 0x0d ?? */
 #define A_EXTOUT_AREAR_L	0x0e	/* analog rear left */
 #define A_EXTOUT_AREAR_R	0x0f	/*             right */
-/* 0x10-0x15 ?? */
-#define A_EXTOUT_ADC_CAP_L	0x16	/* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R	0x17	/*                    right */
+#define A_EXTOUT_AC97_L		0x10	/* AC97 left (front) */
+#define A_EXTOUT_AC97_R		0x11	/*      right */
+#define A_EXTOUT_ADC_CAP_L	0x12	/* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R	0x13	/*                    right */
+
+/* Audigy constants */
+#define A_C_00000000	0xc0
+#define A_C_00000001	0xc1
+#define A_C_00000002	0xc2
+#define A_C_00000003	0xc3
+#define A_C_00000004	0xc4
+#define A_C_00000008	0xc5
+#define A_C_00000010	0xc6
+#define A_C_00000020	0xc7
+#define A_C_00000100	0xc8
+#define A_C_00010000	0xc9
+#define A_C_00000800	0xca
+#define A_C_10000000	0xcb
+#define A_C_20000000	0xcc
+#define A_C_40000000	0xcd
+#define A_C_80000000	0xce
+#define A_C_7fffffff	0xcf
+#define A_C_ffffffff	0xd0
+#define A_C_fffffffe	0xd1
+#define A_C_c0000000	0xd2
+#define A_C_4f1bbcdc	0xd3
+#define A_C_5a7ef9db	0xd4
+#define A_C_00100000	0xd5
+/* 0xd6 = 0x7fffffff  (?) ACCUM? */
+/* 0xd7 = 0x0000000   CCR */
+/* 0xd8 = noise1 */
+/* 0xd9 = noise2 */
 
 /* definitions for debug register */
 #define EMU10K1_DBG_ZC			0x80000000	/* zero tram counter */
diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h	Tue Feb 26 11:57:58 2002
+++ b/include/sound/version.h	Tue Feb 26 11:57:58 2002
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated automatically by configure.  */
-#define CONFIG_SND_VERSION "0.9.0beta11"
-#define CONFIG_SND_DATE " (Tue Feb 19 08:14:59 2002 UTC)"
+#define CONFIG_SND_VERSION "0.9.0beta12"
+#define CONFIG_SND_DATE " (Tue Feb 26 09:34:24 2002 UTC)"
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Tue Feb 26 11:57:57 2002
+++ b/init/main.c	Tue Feb 26 11:57:57 2002
@@ -413,7 +413,12 @@
  */
 static void __init do_basic_setup(void)
 {
-
+	/*
+	 * Let the per-CPU migration threads start up:
+	 */
+#if CONFIG_SMP
+	migration_init();
+#endif
 	/*
 	 * Tell the world that we're going to be the grim
 	 * reaper of innocent orphaned children.
diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c
--- a/kernel/exec_domain.c	Tue Feb 26 11:57:59 2002
+++ b/kernel/exec_domain.c	Tue Feb 26 11:57:59 2002
@@ -4,7 +4,7 @@
  * We group personalities into execution domains which have their
  * own handlers for kernel entry points, signal mapping, etc...
  *
- * 2001-05-06	Complete rewrite,  Christoph Hellwig (hch@caldera.de)
+ * 2001-05-06	Complete rewrite,  Christoph Hellwig (hch@infradead.org)
  */
 
 #include <linux/config.h>
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Tue Feb 26 11:57:57 2002
+++ b/kernel/fork.c	Tue Feb 26 11:57:57 2002
@@ -219,11 +219,7 @@
       
 			/* insert tmp into the share list, just after mpnt */
 			spin_lock(&inode->i_mapping->i_shared_lock);
-			if((tmp->vm_next_share = mpnt->vm_next_share) != NULL)
-				mpnt->vm_next_share->vm_pprev_share =
-					&tmp->vm_next_share;
-			mpnt->vm_next_share = tmp;
-			tmp->vm_pprev_share = &mpnt->vm_next_share;
+			list_add_tail(&tmp->shared, &mpnt->shared);
 			spin_unlock(&inode->i_mapping->i_shared_lock);
 		}
 
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Tue Feb 26 11:57:58 2002
+++ b/kernel/kmod.c	Tue Feb 26 11:57:58 2002
@@ -159,7 +159,7 @@
 
 	ret = exec_usermodehelper(modprobe_path, argv, envp);
 	if (ret) {
-		printk(KERN_ERR
+		printk(KERN_DEBUG
 		       "kmod: failed to exec %s -s -k %s, errno = %d\n",
 		       modprobe_path, (char*) module_name, errno);
 	}
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Tue Feb 26 11:57:56 2002
+++ b/kernel/ksyms.c	Tue Feb 26 11:57:56 2002
@@ -107,6 +107,7 @@
 EXPORT_SYMBOL(kfree);
 EXPORT_SYMBOL(vfree);
 EXPORT_SYMBOL(__vmalloc);
+EXPORT_SYMBOL_GPL(vmalloc_to_page);
 EXPORT_SYMBOL(mem_map);
 EXPORT_SYMBOL(remap_page_range);
 EXPORT_SYMBOL(max_mapnr);
@@ -442,7 +443,6 @@
 /* process management */
 EXPORT_SYMBOL(complete_and_exit);
 EXPORT_SYMBOL(__wake_up);
-EXPORT_SYMBOL(__wake_up_sync);
 EXPORT_SYMBOL(wake_up_process);
 EXPORT_SYMBOL(sleep_on);
 EXPORT_SYMBOL(sleep_on_timeout);
@@ -457,6 +457,9 @@
 EXPORT_SYMBOL(set_user_nice);
 EXPORT_SYMBOL(task_nice);
 EXPORT_SYMBOL_GPL(idle_cpu);
+#if CONFIG_SMP
+EXPORT_SYMBOL_GPL(set_cpus_allowed);
+#endif
 EXPORT_SYMBOL(jiffies);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Tue Feb 26 11:57:58 2002
+++ b/kernel/sched.c	Tue Feb 26 11:57:58 2002
@@ -16,12 +16,12 @@
 #include <linux/nmi.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <linux/highmem.h>
 #include <linux/smp_lock.h>
+#include <asm/mmu_context.h>
 #include <linux/interrupt.h>
 #include <linux/completion.h>
-#include <asm/mmu_context.h>
 #include <linux/kernel_stat.h>
-#include <linux/highmem.h>
 
 /*
  * Priority of a process goes from 0 to 139. The 0-99
@@ -127,8 +127,6 @@
 
 struct prio_array {
 	int nr_active;
-	spinlock_t *lock;
-	runqueue_t *rq;
 	unsigned long bitmap[BITMAP_SIZE];
 	list_t queue[MAX_PRIO];
 };
@@ -146,6 +144,8 @@
 	task_t *curr, *idle;
 	prio_array_t *active, *expired, arrays[2];
 	int prev_nr_running[NR_CPUS];
+	task_t *migration_thread;
+	list_t migration_queue;
 } ____cacheline_aligned;
 
 static struct runqueue runqueues[NR_CPUS] __cacheline_aligned;
@@ -156,23 +156,23 @@
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define rt_task(p)		((p)->prio < MAX_RT_PRIO)
 
-static inline runqueue_t *lock_task_rq(task_t *p, unsigned long *flags)
+static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
 {
-	struct runqueue *__rq;
+	struct runqueue *rq;
 
 repeat_lock_task:
 	preempt_disable();
-	__rq = task_rq(p);
-	spin_lock_irqsave(&__rq->lock, *flags);
-	if (unlikely(__rq != task_rq(p))) {
-		spin_unlock_irqrestore(&__rq->lock, *flags);
+	rq = task_rq(p);
+	spin_lock_irqsave(&rq->lock, *flags);
+	if (unlikely(rq != task_rq(p))) {
+		spin_unlock_irqrestore(&rq->lock, *flags);
 		preempt_enable();
 		goto repeat_lock_task;
 	}
-	return __rq;
+	return rq;
 }
 
-static inline void unlock_task_rq(runqueue_t *rq, unsigned long *flags)
+static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
 {
 	spin_unlock_irqrestore(&rq->lock, *flags);
 	preempt_enable();
@@ -184,7 +184,7 @@
 static inline void dequeue_task(struct task_struct *p, prio_array_t *array)
 {
 	array->nr_active--;
-	list_del_init(&p->run_list);
+	list_del(&p->run_list);
 	if (list_empty(array->queue + p->prio))
 		__clear_bit(p->prio, array->bitmap);
 }
@@ -289,31 +289,17 @@
 		cpu_relax();
 		barrier();
 	}
-	rq = lock_task_rq(p, &flags);
+	rq = task_rq_lock(p, &flags);
 	if (unlikely(rq->curr == p)) {
-		unlock_task_rq(rq, &flags);
+		task_rq_unlock(rq, &flags);
 		preempt_enable();
 		goto repeat;
 	}
-	unlock_task_rq(rq, &flags);
+	task_rq_unlock(rq, &flags);
 	preempt_enable();
 }
 
 /*
- * The SMP message passing code calls this function whenever
- * the new task has arrived at the target CPU. We move the
- * new task into the local runqueue.
- *
- * This function must be called with interrupts disabled.
- */
-void sched_task_migrated(task_t *new_task)
-{
-	wait_task_inactive(new_task);
-	new_task->thread_info->cpu = smp_processor_id();
-	wake_up_process(new_task);
-}
-
-/*
  * Kick the remote CPU if the task is running currently,
  * this code is used by the signal code to signal tasks
  * which are in user-mode as quickly as possible.
@@ -337,27 +323,27 @@
  * "current->state = TASK_RUNNING" to mark yourself runnable
  * without the overhead of this.
  */
-static int try_to_wake_up(task_t * p, int synchronous)
+static int try_to_wake_up(task_t * p)
 {
 	unsigned long flags;
 	int success = 0;
 	runqueue_t *rq;
 
-	rq = lock_task_rq(p, &flags);
+	rq = task_rq_lock(p, &flags);
 	p->state = TASK_RUNNING;
 	if (!p->array) {
 		activate_task(p, rq);
-		if ((rq->curr == rq->idle) || (p->prio < rq->curr->prio))
+		if (p->prio < rq->curr->prio)
 			resched_task(rq->curr);
 		success = 1;
 	}
-	unlock_task_rq(rq, &flags);
+	task_rq_unlock(rq, &flags);
 	return success;
 }
 
 int wake_up_process(task_t * p)
 {
-	return try_to_wake_up(p, 0);
+	return try_to_wake_up(p);
 }
 
 void wake_up_forked_process(task_t * p)
@@ -366,6 +352,7 @@
 
 	preempt_disable();
 	rq = this_rq();
+	spin_lock_irq(&rq->lock);
 
 	p->state = TASK_RUNNING;
 	if (!rt_task(p)) {
@@ -378,9 +365,9 @@
 		p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
 		p->prio = effective_prio(p);
 	}
-	spin_lock_irq(&rq->lock);
 	p->thread_info->cpu = smp_processor_id();
 	activate_task(p, rq);
+
 	spin_unlock_irq(&rq->lock);
 	preempt_enable();
 }
@@ -861,44 +848,33 @@
  * started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
  * zero in this (rare) case, and we handle it by continuing to scan the queue.
  */
-static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
-			 	     int nr_exclusive, const int sync)
+static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	struct list_head *tmp;
+	unsigned int state;
+	wait_queue_t *curr;
 	task_t *p;
 
-	list_for_each(tmp,&q->task_list) {
-		unsigned int state;
-		wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
-
+	list_for_each(tmp, &q->task_list) {
+		curr = list_entry(tmp, wait_queue_t, task_list);
 		p = curr->task;
 		state = p->state;
-		if ((state & mode) &&
-				try_to_wake_up(p, sync) &&
-				((curr->flags & WQ_FLAG_EXCLUSIVE) &&
-					!--nr_exclusive))
-			break;
+		if ((state & mode) && try_to_wake_up(p) &&
+			((curr->flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive))
+				break;
 	}
 }
 
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
+void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
-	if (q) {
-		unsigned long flags;
-		wq_read_lock_irqsave(&q->lock, flags);
-		__wake_up_common(q, mode, nr, 0);
-		wq_read_unlock_irqrestore(&q->lock, flags);
-	}
-}
+	unsigned long flags;
 
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)
-{
-	if (q) {
-		unsigned long flags;
-		wq_read_lock_irqsave(&q->lock, flags);
-		__wake_up_common(q, mode, nr, 1);
-		wq_read_unlock_irqrestore(&q->lock, flags);
-	}
+	if (unlikely(!q))
+		return;
+
+	wq_read_lock_irqsave(&q->lock, flags);
+	__wake_up_common(q, mode, nr_exclusive);
+	wq_read_unlock_irqrestore(&q->lock, flags);
 }
 
 void complete(struct completion *x)
@@ -907,7 +883,7 @@
 
 	spin_lock_irqsave(&x->wait.lock, flags);
 	x->done++;
-	__wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, 0);
+	__wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1);
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
@@ -994,34 +970,6 @@
 	return timeout;
 }
 
-/*
- * Change the current task's CPU affinity. Migrate the process to a
- * proper CPU and schedule away if the current CPU is removed from
- * the allowed bitmask.
- */
-void set_cpus_allowed(task_t *p, unsigned long new_mask)
-{
-	new_mask &= cpu_online_map;
-	if (!new_mask)
-		BUG();
-	if (p != current)
-		BUG();
-
-	p->cpus_allowed = new_mask;
-	/*
-	 * Can the task run on the current CPU? If not then
-	 * migrate the process off to a proper CPU.
-	 */
-	if (new_mask & (1UL << smp_processor_id()))
-		return;
-#if CONFIG_SMP
-	current->state = TASK_UNINTERRUPTIBLE;
-	smp_migrate_task(__ffs(new_mask), current);
-
-	schedule();
-#endif
-}
-
 void scheduling_functions_end_here(void) { }
 
 void set_user_nice(task_t *p, long nice)
@@ -1036,7 +984,7 @@
 	 * We have to be careful, if called from sys_setpriority(),
 	 * the task might be in the middle of scheduling on another CPU.
 	 */
-	rq = lock_task_rq(p, &flags);
+	rq = task_rq_lock(p, &flags);
 	if (rt_task(p)) {
 		p->static_prio = NICE_TO_PRIO(nice);
 		goto out_unlock;
@@ -1056,7 +1004,7 @@
 			resched_task(rq->curr);
 	}
 out_unlock:
-	unlock_task_rq(rq, &flags);
+	task_rq_unlock(rq, &flags);
 }
 
 #ifndef __alpha__
@@ -1154,7 +1102,7 @@
 	 * To be able to change p->policy safely, the apropriate
 	 * runqueue lock must be held.
 	 */
-	rq = lock_task_rq(p, &flags);
+	rq = task_rq_lock(p, &flags);
 
 	if (policy < 0)
 		policy = p->policy;
@@ -1189,7 +1137,7 @@
 	retval = 0;
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
-	if (rt_task(p))
+	if (policy != SCHED_OTHER)
 		p->prio = 99 - p->rt_priority;
 	else
 		p->prio = p->static_prio;
@@ -1197,7 +1145,7 @@
 		activate_task(p, task_rq(p));
 
 out_unlock:
-	unlock_task_rq(rq, &flags);
+	task_rq_unlock(rq, &flags);
 out_unlock_tasklist:
 	read_unlock_irq(&tasklist_lock);
 
@@ -1477,7 +1425,7 @@
 
 void __init init_idle(task_t *idle, int cpu)
 {
-	runqueue_t *idle_rq = cpu_rq(cpu), *rq = idle->array->rq;
+	runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(idle->thread_info->cpu);
 	unsigned long flags;
 
 	__save_flags(flags);
@@ -1509,14 +1457,13 @@
 		runqueue_t *rq = cpu_rq(i);
 		prio_array_t *array;
 
-		rq->active = rq->arrays + 0;
+		rq->active = rq->arrays;
 		rq->expired = rq->arrays + 1;
 		spin_lock_init(&rq->lock);
+		INIT_LIST_HEAD(&rq->migration_queue);
 
 		for (j = 0; j < 2; j++) {
 			array = rq->arrays + j;
-			array->rq = rq;
-			array->lock = &rq->lock;
 			for (k = 0; k < MAX_PRIO; k++) {
 				INIT_LIST_HEAD(array->queue + k);
 				__clear_bit(k, array->bitmap);
@@ -1545,3 +1492,173 @@
 	atomic_inc(&init_mm.mm_count);
 	enter_lazy_tlb(&init_mm, current, smp_processor_id());
 }
+
+#if CONFIG_SMP
+
+/*
+ * This is how migration works:
+ *
+ * 1) we queue a migration_req_t structure in the source CPU's
+ *    runqueue and wake up that CPU's migration thread.
+ * 2) we down() the locked semaphore => thread blocks.
+ * 3) migration thread wakes up (implicitly it forces the migrated
+ *    thread off the CPU)
+ * 4) it gets the migration request and checks whether the migrated
+ *    task is still in the wrong runqueue.
+ * 5) if it's in the wrong runqueue then the migration thread removes
+ *    it and puts it into the right queue.
+ * 6) migration thread up()s the semaphore.
+ * 7) we wake up and the migration is done.
+ */
+
+typedef struct {
+	list_t list;
+	task_t *task;
+	struct semaphore sem;
+} migration_req_t;
+
+/*
+ * Change a given task's CPU affinity. Migrate the process to a
+ * proper CPU and schedule it away if the CPU it's executing on
+ * is removed from the allowed bitmask.
+ *
+ * NOTE: the caller must have a valid reference to the task, the
+ * task must not exit() & deallocate itself prematurely.
+ */
+void set_cpus_allowed(task_t *p, unsigned long new_mask)
+{
+	unsigned long flags;
+	migration_req_t req;
+	runqueue_t *rq;
+
+	new_mask &= cpu_online_map;
+	if (!new_mask)
+		BUG();
+
+	rq = task_rq_lock(p, &flags);
+	p->cpus_allowed = new_mask;
+	/*
+	 * Can the task run on the task's current CPU? If not then
+	 * migrate the process off to a proper CPU.
+	 */
+	if (new_mask & (1UL << p->thread_info->cpu)) {
+		task_rq_unlock(rq, &flags);
+		return;
+	}
+
+	init_MUTEX_LOCKED(&req.sem);
+	req.task = p;
+	list_add(&req.list, &rq->migration_queue);
+	task_rq_unlock(rq, &flags);
+	wake_up_process(rq->migration_thread);
+
+	down(&req.sem);
+}
+
+static volatile unsigned long migration_mask;
+
+static int migration_thread(void * unused)
+{
+	struct sched_param param = { sched_priority: 99 };
+	runqueue_t *rq;
+	int ret;
+
+	daemonize();
+	sigfillset(&current->blocked);
+	set_fs(KERNEL_DS);
+	ret = setscheduler(0, SCHED_FIFO, &param);
+
+	/*
+	 * We have to migrate manually - there is no migration thread
+	 * to do this for us yet :-)
+	 *
+	 * We use the following property of the Linux scheduler. At
+	 * this point no other task is running, so by keeping all
+	 * migration threads running, the load-balancer will distribute
+	 * them between all CPUs equally. At that point every migration
+	 * task binds itself to the current CPU.
+	 */
+
+	/* wait for all migration threads to start up. */
+	while (!migration_mask)
+		yield();
+
+	for (;;) {
+		preempt_disable();
+		if (test_and_clear_bit(smp_processor_id(), &migration_mask))
+			current->cpus_allowed = 1 << smp_processor_id();
+		if (test_thread_flag(TIF_NEED_RESCHED))
+			schedule();
+		if (!migration_mask)
+			break;
+		preempt_enable();
+	}
+	rq = this_rq();
+	rq->migration_thread = current;
+	preempt_enable();
+
+	sprintf(current->comm, "migration_CPU%d", smp_processor_id());
+
+	for (;;) {
+		runqueue_t *rq_src, *rq_dest;
+		struct list_head *head;
+		int cpu_src, cpu_dest;
+		migration_req_t *req;
+		unsigned long flags;
+		task_t *p;
+
+		spin_lock_irqsave(&rq->lock, flags);
+		head = &rq->migration_queue;
+		current->state = TASK_INTERRUPTIBLE;
+		if (list_empty(head)) {
+			spin_unlock_irqrestore(&rq->lock, flags);
+			schedule();
+			continue;
+		}
+		req = list_entry(head->next, migration_req_t, list);
+		list_del_init(head->next);
+		spin_unlock_irqrestore(&rq->lock, flags);
+
+		p = req->task;
+		cpu_dest = __ffs(p->cpus_allowed);
+		rq_dest = cpu_rq(cpu_dest);
+repeat:
+		cpu_src = p->thread_info->cpu;
+		rq_src = cpu_rq(cpu_src);
+
+		double_rq_lock(rq_src, rq_dest);
+		if (p->thread_info->cpu != cpu_src) {
+			double_rq_unlock(rq_src, rq_dest);
+			goto repeat;
+		}
+		if (rq_src == rq) {
+			p->thread_info->cpu = cpu_dest;
+			if (p->array) {
+				deactivate_task(p, rq_src);
+				activate_task(p, rq_dest);
+			}
+		}
+		double_rq_unlock(rq_src, rq_dest);
+
+		up(&req->sem);
+	}
+}
+
+void __init migration_init(void)
+{
+	int cpu;
+
+	for (cpu = 0; cpu < smp_num_cpus; cpu++)
+		if (kernel_thread(migration_thread, NULL,
+				CLONE_FS | CLONE_FILES | CLONE_SIGNAL) < 0)
+			BUG();
+
+	migration_mask = (1 << smp_num_cpus) - 1;
+
+	for (cpu = 0; cpu < smp_num_cpus; cpu++)
+		while (!cpu_rq(cpu)->migration_thread)
+			schedule_timeout(2);
+	if (migration_mask)
+		BUG();
+}
+#endif
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Tue Feb 26 11:57:58 2002
+++ b/mm/filemap.c	Tue Feb 26 11:57:58 2002
@@ -1399,7 +1399,7 @@
 		 * virtual addresses, take care about potential aliasing
 		 * before reading the page on the kernel side.
 		 */
-		if (mapping->i_mmap_shared != NULL)
+		if (!list_empty(&mapping->i_mmap_shared))
 			flush_dcache_page(page);
 
 		/*
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Tue Feb 26 11:57:59 2002
+++ b/mm/memory.c	Tue Feb 26 11:57:59 2002
@@ -1032,31 +1032,35 @@
 	return -1;
 }
 
-static void vmtruncate_list(struct vm_area_struct *mpnt, unsigned long pgoff)
+static void vmtruncate_list(list_t *head, unsigned long pgoff)
 {
-	do {
-		unsigned long start = mpnt->vm_start;
-		unsigned long end = mpnt->vm_end;
-		unsigned long len = end - start;
-		unsigned long diff;
+	unsigned long start, end, len, diff;
+	struct vm_area_struct *vma;
+	list_t *curr;
+
+	list_for_each(curr, head) {
+		vma = list_entry(curr, struct vm_area_struct, shared);
+		start = vma->vm_start;
+		end = vma->vm_end;
+		len = end - start;
 
 		/* mapping wholly truncated? */
-		if (mpnt->vm_pgoff >= pgoff) {
-			zap_page_range(mpnt, start, len);
+		if (vma->vm_pgoff >= pgoff) {
+			zap_page_range(vma, start, len);
 			continue;
 		}
 
 		/* mapping wholly unaffected? */
 		len = len >> PAGE_SHIFT;
-		diff = pgoff - mpnt->vm_pgoff;
+		diff = pgoff - vma->vm_pgoff;
 		if (diff >= len)
 			continue;
 
 		/* Ok, partially affected.. */
 		start += diff << PAGE_SHIFT;
 		len = (len - diff) << PAGE_SHIFT;
-		zap_page_range(mpnt, start, len);
-	} while ((mpnt = mpnt->vm_next_share) != NULL);
+		zap_page_range(vma, start, len);
+	}
 }
 
 /*
@@ -1077,14 +1081,14 @@
 		goto do_expand;
 	inode->i_size = offset;
 	spin_lock(&mapping->i_shared_lock);
-	if (!mapping->i_mmap && !mapping->i_mmap_shared)
+	if (list_empty(&mapping->i_mmap) && list_empty(&mapping->i_mmap_shared))
 		goto out_unlock;
 
 	pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	if (mapping->i_mmap != NULL)
-		vmtruncate_list(mapping->i_mmap, pgoff);
-	if (mapping->i_mmap_shared != NULL)
-		vmtruncate_list(mapping->i_mmap_shared, pgoff);
+	if (!list_empty(&mapping->i_mmap))
+		vmtruncate_list(&mapping->i_mmap, pgoff);
+	if (!list_empty(&mapping->i_mmap_shared))
+		vmtruncate_list(&mapping->i_mmap_shared, pgoff);
 
 out_unlock:
 	spin_unlock(&mapping->i_shared_lock);
@@ -1480,8 +1484,9 @@
 /* 
  * Map a vmalloc()-space virtual address to the physical page.
  */
-struct page * vmalloc_to_page(unsigned long addr)
+struct page * vmalloc_to_page(void * vmalloc_addr)
 {
+	unsigned long addr = (unsigned long) vmalloc_addr;
 	struct page *page = NULL;
 	pgd_t *pgd = pgd_offset_k(addr);
 	pmd_t *pmd;
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Tue Feb 26 11:57:56 2002
+++ b/mm/mmap.c	Tue Feb 26 11:57:56 2002
@@ -101,9 +101,7 @@
 		struct inode *inode = file->f_dentry->d_inode;
 		if (vma->vm_flags & VM_DENYWRITE)
 			atomic_inc(&inode->i_writecount);
-		if(vma->vm_next_share)
-			vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
-		*vma->vm_pprev_share = vma->vm_next_share;
+		list_del_init(&vma->shared);
 	}
 }
 
@@ -308,20 +306,14 @@
 	if (file) {
 		struct inode * inode = file->f_dentry->d_inode;
 		struct address_space *mapping = inode->i_mapping;
-		struct vm_area_struct **head;
 
 		if (vma->vm_flags & VM_DENYWRITE)
 			atomic_dec(&inode->i_writecount);
 
-		head = &mapping->i_mmap;
 		if (vma->vm_flags & VM_SHARED)
-			head = &mapping->i_mmap_shared;
-      
-		/* insert vma into inode's share list */
-		if((vma->vm_next_share = *head) != NULL)
-			(*head)->vm_pprev_share = &vma->vm_next_share;
-		*head = vma;
-		vma->vm_pprev_share = head;
+			list_add_tail(&vma->shared, &mapping->i_mmap_shared);
+		else
+			list_add_tail(&vma->shared, &mapping->i_mmap);
 	}
 }
 
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Tue Feb 26 11:57:59 2002
+++ b/mm/shmem.c	Tue Feb 26 11:57:59 2002
@@ -904,7 +904,7 @@
 		if ((desc->error = shmem_getpage(inode, index, &page)))
 			break;
 
-		if (mapping->i_mmap_shared != NULL)
+		if (!list_empty(&mapping->i_mmap_shared))
 			flush_dcache_page(page);
 
 		/*
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	Tue Feb 26 11:57:56 2002
+++ b/mm/vmalloc.c	Tue Feb 26 11:57:56 2002
@@ -6,6 +6,7 @@
  *  SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
  */
 
+#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
@@ -163,6 +164,7 @@
 		ret = 0;
 	} while (address && (address < end));
 	spin_unlock(&init_mm.page_table_lock);
+	flush_cache_all();
 	return ret;
 }
 
@@ -273,6 +275,43 @@
 			if (count == 0)
 				goto finished;
 			*buf = *addr;
+			buf++;
+			addr++;
+			count--;
+		} while (--n > 0);
+	}
+finished:
+	read_unlock(&vmlist_lock);
+	return buf - buf_start;
+}
+
+long vwrite(char *buf, char *addr, unsigned long count)
+{
+	struct vm_struct *tmp;
+	char *vaddr, *buf_start = buf;
+	unsigned long n;
+
+	/* Don't allow overflow */
+	if ((unsigned long) addr + count < count)
+		count = -(unsigned long) addr;
+
+	read_lock(&vmlist_lock);
+	for (tmp = vmlist; tmp; tmp = tmp->next) {
+		vaddr = (char *) tmp->addr;
+		if (addr >= vaddr + tmp->size - PAGE_SIZE)
+			continue;
+		while (addr < vaddr) {
+			if (count == 0)
+				goto finished;
+			buf++;
+			addr++;
+			count--;
+		}
+		n = vaddr + tmp->size - PAGE_SIZE - addr;
+		do {
+			if (count == 0)
+				goto finished;
+			*addr = *buf;
 			buf++;
 			addr++;
 			count--;
diff -Nru a/net/Makefile b/net/Makefile
--- a/net/Makefile	Tue Feb 26 11:57:59 2002
+++ b/net/Makefile	Tue Feb 26 11:57:59 2002
@@ -1,7 +1,7 @@
 #
 # Makefile for the linux networking.
 #
-# 2 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# 2 Sep 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
 
diff -Nru a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
--- a/net/wanrouter/wanmain.c	Tue Feb 26 11:57:57 2002
+++ b/net/wanrouter/wanmain.c	Tue Feb 26 11:57:57 2002
@@ -9,7 +9,7 @@
 *		 o Logical connection management (switched virtual circuits)
 *		 o Protocol encapsulation/decapsulation
 *
-* Author:	Gideon Hack	
+* Author:	Gideon Hack
 *
 * Copyright:	(c) 1995-1999 Sangoma Technologies Inc.
 *
@@ -18,11 +18,11 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
-* Nov 24, 2000  Nenad Corbic	Updated for 2.4.X kernels 
+* Nov 24, 2000  Nenad Corbic	Updated for 2.4.X kernels
 * Nov 07, 2000  Nenad Corbic	Fixed the Mulit-Port PPP for kernels 2.2.16 and
 *  				greater.
 * Aug 2,  2000  Nenad Corbic	Block the Multi-Port PPP from running on
-*  			        kernels 2.2.16 or greater.  The SyncPPP 
+*  			        kernels 2.2.16 or greater.  The SyncPPP
 *  			        has changed.
 * Jul 13, 2000  Nenad Corbic	Added SyncPPP support
 * 				Added extra debugging in device_setup().
@@ -39,7 +39,7 @@
 * Dec 22, 1998  Arnaldo Melo    vmalloc/vfree used in device_setup to allocate
 *                               kernel memory and copy configuration data to
 *                               kernel space (for big firmwares)
-* Jun 02, 1999  Gideon Hack	Updates for Linux 2.0.X and 2.2.X kernels.	
+* Jun 02, 1999  Gideon Hack	Updates for Linux 2.0.X and 2.2.X kernels.
 *****************************************************************************/
 
 #include <linux/version.h>
@@ -55,28 +55,10 @@
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <linux/wanrouter.h>	/* WAN router API definitions */
 
-
-#if defined(LINUX_2_4)
- #include <linux/vmalloc.h>	/* vmalloc, vfree */
- #include <asm/uaccess.h>        /* copy_to/from_user */
- #include <linux/init.h>         /* __initfunc et al. */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
- #include <net/syncppp.h>
-#else
- #include <../drivers/net/wan/syncppp.h>
-#endif
-
-#elif defined(LINUX_2_1) 
- #define LINUX_2_1
- #include <linux/vmalloc.h>	/* vmalloc, vfree */
- #include <asm/uaccess.h>        /* copy_to/from_user */
- #include <linux/init.h>         /* __initfunc et al. */
- #include <../drivers/net/syncppp.h>
-
-#else
- #include <asm/segment.h>	/* kernel <-> user copy */
-#endif
+#include <linux/vmalloc.h>	/* vmalloc, vfree */
+#include <asm/uaccess.h>        /* copy_to/from_user */
+#include <linux/init.h>         /* __initfunc et al. */
+#include <net/syncppp.h>
 
 #define KMEM_SAFETYZONE 8
 
@@ -84,7 +66,7 @@
 static void * dbg_kmalloc(unsigned int size, int prio, int line) {
 	int i = 0;
 	void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
-	char * c1 = v;	
+	char * c1 = v;
 	c1 += sizeof(unsigned int);
 	*((unsigned int *)v) = size;
 
@@ -137,12 +119,11 @@
 #define kfree(x) dbg_kfree(x,__LINE__)
 *****************************************************************************/
 
-
 /*
- * 	Function Prototypes 
+ * 	Function Prototypes
  */
 
-/* 
+/*
  * 	Kernel loadable module interface.
  */
 #ifdef MODULE
@@ -150,8 +131,8 @@
 void cleanup_module (void);
 #endif
 
-/* 
- *	WAN device IOCTL handlers 
+/*
+ *	WAN device IOCTL handlers
  */
 
 static int device_setup(wan_device_t *wandev, wandev_conf_t *u_conf);
@@ -159,9 +140,9 @@
 static int device_shutdown(wan_device_t *wandev);
 static int device_new_if(wan_device_t *wandev, wanif_conf_t *u_conf);
 static int device_del_if(wan_device_t *wandev, char *u_name);
- 
-/* 
- *	Miscellaneous 
+
+/*
+ *	Miscellaneous
  */
 
 static wan_device_t *find_device (char *name);
@@ -181,8 +162,8 @@
 wan_device_t* router_devlist 	= NULL;	/* list of registered devices */
 static int devcnt 		= 0;
 
-/* 
- *	Organize Unique Identifiers for encapsulation/decapsulation 
+/*
+ *	Organize Unique Identifiers for encapsulation/decapsulation
  */
 
 static unsigned char oui_ether[] = { 0x00, 0x00, 0x00 };
@@ -213,18 +194,15 @@
 #ifdef CONFIG_VENDOR_SANGOMA
 	sdladrv_init();
 	wanpipe_init();
-#endif	
- 
+#endif
+
 	return err;
 }
 
-
-#ifdef LINUX_2_4
 static void __exit wanrouter_cleanup (void)
 {
 	wanrouter_proc_cleanup();
 }
-#endif
 
 #else
 
@@ -249,10 +227,10 @@
 
 	printk(KERN_INFO "%s v%u.%u %s\n",
 		fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
-	
+
 	err = wanrouter_proc_init();
-	
-	if (err){ 
+
+	if (err){
 		printk(KERN_INFO
 		"%s: can't create entry in proc filesystem!\n", modname);
 	}
@@ -299,21 +277,21 @@
 	if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC) ||
 	    (wandev->name == NULL))
 		return -EINVAL;
- 		
+
 	namelen = strlen(wandev->name);
 	if (!namelen || (namelen > WAN_DRVNAME_SZ))
 		return -EINVAL;
-		
+
 	if (find_device(wandev->name) != NULL)
 		return -EEXIST;
 
-#ifdef WANDEBUG		
+#ifdef WANDEBUG
 	printk(KERN_INFO "%s: registering WAN device %s\n",
 		modname, wandev->name);
 #endif
 
 	/*
-	 *	Register /proc directory entry 
+	 *	Register /proc directory entry
 	 */
 	err = wanrouter_proc_add(wandev);
 	if (err) {
@@ -327,7 +305,7 @@
 	 *	Initialize fields of the wan_device structure maintained by the
 	 *	router and update local data.
 	 */
-	 
+
 	wandev->ndev = 0;
 	wandev->dev  = NULL;
 	wandev->next = router_devlist;
@@ -364,20 +342,18 @@
 	if (wandev == NULL)
 		return -ENODEV;
 
-#ifdef WANDEBUG		
+#ifdef WANDEBUG
 	printk(KERN_INFO "%s: unregistering WAN device %s\n", modname, name);
 #endif
 
-	if (wandev->state != WAN_UNCONFIGURED) {
+	if (wandev->state != WAN_UNCONFIGURED)
 		device_shutdown(wandev);
-	}
-	
-	if (prev){
+
+	if (prev)
 		prev->next = wandev->next;
-	}else{
+	else
 		router_devlist = wandev->next;
-	}
-	
+
 	--devcnt;
 	wanrouter_proc_delete(wandev);
         MOD_DEC_USE_COUNT;
@@ -457,7 +433,7 @@
 				skb->data[cnt+1], skb->data[cnt+2],
 				skb->data[cnt+3], dev->name);
 			return 0;
-		}	
+		}
 		ethertype = *((unsigned short*)&skb->data[cnt+4]);
 		cnt += 6;
 		break;
@@ -491,23 +467,20 @@
 	struct proc_dir_entry *dent;
 	wan_device_t *wandev;
 
-      #if defined (LINUX_2_1) || defined (LINUX_2_4)
-	if (!capable(CAP_NET_ADMIN)){
+	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
-	}
-      #endif
-		
+
 	if ((cmd >> 8) != ROUTER_IOCTL)
 		return -EINVAL;
-		
+
 	dent = PDE(inode);
 	if ((dent == NULL) || (dent->data == NULL))
 		return -EINVAL;
-		
+
 	wandev = dent->data;
 	if (wandev->magic != ROUTER_MAGIC)
 		return -EINVAL;
-		
+
 	switch (cmd) {
 	case ROUTER_SETUP:
 		err = device_setup(wandev, (void*)arg);
@@ -560,103 +533,62 @@
 	wandev_conf_t *conf;
 	int err = -EINVAL;
 
-	if (wandev->setup == NULL){	/* Nothing to do ? */
+	if (wandev->setup == NULL) {	/* Nothing to do ? */
 		printk(KERN_INFO "%s: ERROR, No setup script: wandev->setup()\n",
 				wandev->name);
 		return 0;
 	}
 
-      #ifdef LINUX_2_0 
-	err = verify_area (VERIFY_READ, u_conf, sizeof(wandev_conf_t));
-	if(err){
-		return err;
-	}
-      #endif	
-
 	conf = kmalloc(sizeof(wandev_conf_t), GFP_KERNEL);
 	if (conf == NULL){
 		printk(KERN_INFO "%s: ERROR, Failed to allocate kernel memory !\n",
 				wandev->name);
 		return -ENOBUFS;
 	}
-		
-      #if defined (LINUX_2_1) || defined (LINUX_2_4)		
-	if(copy_from_user(conf, u_conf, sizeof(wandev_conf_t))) {
+
+	if (copy_from_user(conf, u_conf, sizeof(wandev_conf_t))) {
 		printk(KERN_INFO "%s: Failed to copy user config data to kernel space!\n",
 				wandev->name);
 		kfree(conf);
 		return -EFAULT;
 	}
-      #else
-	memcpy_fromfs ((void *)conf, (void *)u_conf, sizeof(wandev_conf_t));
-      #endif
-	
-	if (conf->magic != ROUTER_MAGIC){
+
+	if (conf->magic != ROUTER_MAGIC) {
 		kfree(conf);
 		printk(KERN_INFO "%s: ERROR, Invalid MAGIC Number\n",
 				wandev->name);
-	        return -EINVAL; 
+	        return -EINVAL;
 	}
 
-	if (conf->data_size && conf->data){
-		if(conf->data_size > 128000 || conf->data_size < 0) {
-			printk(KERN_INFO 
+	if (conf->data_size && conf->data) {
+		if (conf->data_size > 128000 || conf->data_size < 0) {
+			printk(KERN_INFO
 			    "%s: ERROR, Invalid firmware data size %i !\n",
 					wandev->name, conf->data_size);
 			kfree(conf);
-		        return -EINVAL;;
+		        return -EINVAL;
 		}
 
-#if defined (LINUX_2_1) || defined (LINUX_2_4)
 		data = vmalloc(conf->data_size);
-		if (data) {
-			if(!copy_from_user(data, conf->data, conf->data_size)){
-				conf->data=data;
-				err = wandev->setup(wandev,conf);
-			}else{ 
-				printk(KERN_INFO 
-				     "%s: ERROR, Faild to copy from user data !\n",
-				       wandev->name);
-				err = -EFAULT;
-			}
-		}else{ 
-			printk(KERN_INFO 
+		if (!data) {
+			printk(KERN_INFO
 			 	"%s: ERROR, Faild allocate kernel memory !\n",
 				wandev->name);
-			err = -ENOBUFS;
-		}
-			
-		if (data){
-			vfree(data);
-		}
-#else
-                err = verify_area(VERIFY_READ, conf->data, conf->data_size);
-                if (!err) {
-                        data = kmalloc(conf->data_size, GFP_KERNEL);
-                        if (data) {
-                                memcpy_fromfs(data, (void*)conf->data,
-                                        conf->data_size);
-                                conf->data = data;
-                        }else{
-				printk(KERN_INFO 
-				    "%s: ERROR, Faild allocate kernel memory !\n",wandev->name);
-				err = -ENOMEM;
-			}
-                }else{
-			printk(KERN_INFO 
-			 	"%s: ERROR, Faild to copy from user data !\n",wandev->name);
+			kfree(conf);
+			return -ENOBUFS;
 		}
-
-		if (!err){
+		if (!copy_from_user(data, conf->data, conf->data_size)) {
+			conf->data = data;
 			err = wandev->setup(wandev, conf);
+		} else {
+			printk(KERN_INFO
+			     "%s: ERROR, Faild to copy from user data !\n",
+			       wandev->name);
+			err = -EFAULT;
 		}
-		
-        	if (data){
-			kfree(data);
-		}
-#endif
-	}else{
-		printk(KERN_INFO 
+		vfree(data);
+	} else {
+		printk(KERN_INFO
 		    "%s: ERROR, No firmware found ! Firmware size = %i !\n",
 				wandev->name, conf->data_size);
 	}
@@ -670,37 +602,33 @@
  *	o delete all not opened logical channels for this device
  *	o call driver's shutdown() entry point
  */
- 
+
 static int device_shutdown (wan_device_t *wandev)
 {
 	netdevice_t *dev;
 	int err=0;
-		
-	if (wandev->state == WAN_UNCONFIGURED){
+
+	if (wandev->state == WAN_UNCONFIGURED)
 		return 0;
-	}
 
 	printk(KERN_INFO "\n%s: Shutting Down!\n",wandev->name);
-		
+
 	for (dev = wandev->dev; dev;) {
-		if ((err=delete_interface(wandev, dev->name)) != 0){
+		if ((err=delete_interface(wandev, dev->name)) != 0)
 			return err;
-		}
-
 		/* The above function deallocates the current dev
 		 * structure. Therefore, we cannot use dev->priv
 		 * as the next element: wandev->dev points to the
 		 * next element */
 		dev = wandev->dev;
 	}
-	
-	if (wandev->ndev){
+
+	if (wandev->ndev)
 		return -EBUSY;	/* there are opened interfaces  */
-	}	
-	
+
 	if (wandev->shutdown)
 		err=wandev->shutdown(wandev);
-	
+
 	return err;
 }
 
@@ -712,13 +640,6 @@
 {
 	wandev_stat_t stat;
 
-      #ifdef LINUX_2_0
-	int err;
-	err = verify_area(VERIFY_WRITE, u_stat, sizeof(wandev_stat_t));
-        if (err)
-                return err;
-      #endif
-
 	memset(&stat, 0, sizeof(stat));
 
 	/* Ask device driver to update device statistics */
@@ -729,12 +650,8 @@
 	stat.ndev  = wandev->ndev;
 	stat.state = wandev->state;
 
-      #if defined (LINUX_2_1) || defined (LINUX_2_4)
-	if(copy_to_user(u_stat, &stat, sizeof(stat)))
+	if (copy_to_user(u_stat, &stat, sizeof(stat)))
 		return -EFAULT;
-      #else
-        memcpy_tofs((void*)u_stat, (void*)&stat, sizeof(stat));
-      #endif
 
 	return 0;
 }
@@ -760,103 +677,67 @@
 
 	if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL))
 		return -ENODEV;
-	
-#if defined (LINUX_2_1) || defined (LINUX_2_4)	
-	if(copy_from_user(&conf, u_conf, sizeof(wanif_conf_t)))
+
+	if (copy_from_user(&conf, u_conf, sizeof(wanif_conf_t)))
 		return -EFAULT;
-#else
-        err = verify_area(VERIFY_READ, u_conf, sizeof(wanif_conf_t));
-        if (err)
-                return err;
-        memcpy_fromfs((void*)&conf, (void*)u_conf, sizeof(wanif_conf_t));
-#endif
-		
+
 	if (conf.magic != ROUTER_MAGIC)
 		return -EINVAL;
 
-	err = -EPROTONOSUPPORT;
-
-	
+	if (conf.config_id == WANCONFIG_MPPP) {
 #ifdef CONFIG_WANPIPE_MULTPPP
-	if (conf.config_id == WANCONFIG_MPPP){
-
 		pppdev = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
-		if (pppdev == NULL){
+		if (pppdev == NULL)
 			return -ENOBUFS;
-		}
 		memset(pppdev, 0, sizeof(struct ppp_device));
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
 		pppdev->dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
-		if (pppdev->dev == NULL){
+		if (pppdev->dev == NULL) {
 			kfree(pppdev);
 			return -ENOBUFS;
 		}
 		memset(pppdev->dev, 0, sizeof(netdevice_t));
-#endif
-		
 		err = wandev->new_if(wandev, (netdevice_t *)pppdev, &conf);
-		
-		      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
-			dev = pppdev->dev;
-		      #else
-			dev = &pppdev->dev;
-		      #endif
-			
-	}else{
-
-		dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
-		if (dev == NULL){
-			return -ENOBUFS;
-		}
-		memset(dev, 0, sizeof(netdevice_t));	
-		err = wandev->new_if(wandev, dev, &conf);
-	}
-
+		dev = pppdev->dev;
 #else
-	/* Sync PPP is disabled */
-	if (conf.config_id != WANCONFIG_MPPP){
-
+		printk(KERN_INFO "%s: Wanpipe Mulit-Port PPP support has not been compiled in!\n",
+				wandev->name);
+		return -EPROTONOSUPPORT;
+#endif
+	} else {
 		dev = kmalloc(sizeof(netdevice_t), GFP_KERNEL);
-		if (dev == NULL){
+		if (dev == NULL)
 			return -ENOBUFS;
-		}
-		memset(dev, 0, sizeof(netdevice_t));	
+		memset(dev, 0, sizeof(netdevice_t));
 		err = wandev->new_if(wandev, dev, &conf);
-	}else{
-		printk(KERN_INFO "%s: Wanpipe Mulit-Port PPP support has not been compiled in!\n",
-				wandev->name);
-		return err;
 	}
-#endif
-	
+
 	if (!err) {
 		/* Register network interface. This will invoke init()
 		 * function supplied by the driver.  If device registered
 		 * successfully, add it to the interface list.
 		 */
 
-		if (dev->name == NULL){
+		if (dev->name == NULL) {
 			err = -EINVAL;
-		}else if (dev_get(dev->name)){
+		} else if (dev_get(dev->name)) {
 			err = -EEXIST;	/* name already exists */
-		}else{
-				
-			#ifdef WANDEBUG		
+		} else {
+
+			#ifdef WANDEBUG
 			printk(KERN_INFO "%s: registering interface %s...\n",
 				modname, dev->name);
-			#endif				
-			
+			#endif
+
 			err = register_netdev(dev);
 			if (!err) {
 				netdevice_t *slave=NULL;
 				unsigned long smp_flags=0;
-				
+
 				lock_adapter_irq(&wandev->lock, &smp_flags);
-			
-				if (wandev->dev == NULL){
+
+				if (wandev->dev == NULL) {
 					wandev->dev = dev;
-				}else{
+				} else {
 					for (slave=wandev->dev;
 					     *((netdevice_t**)slave->priv);
 					     slave=*((netdevice_t**)slave->priv));
@@ -864,7 +745,7 @@
 					*((netdevice_t**)slave->priv) = dev;
 				}
 				++wandev->ndev;
-				
+
 				unlock_adapter_irq(&wandev->lock, &smp_flags);
 				return 0;	/* done !!! */
 			}
@@ -874,25 +755,23 @@
 	}
 
 	/* This code has moved from del_if() function */
-	if (dev->priv){
+	if (dev->priv) {
 		kfree(dev->priv);
-		dev->priv=NULL;
+		dev->priv = NULL;
 	}
 
-	
-      #ifdef CONFIG_WANPIPE_MULTPPP
-	if (conf.config_id == WANCONFIG_MPPP){
+
+#ifdef CONFIG_WANPIPE_MULTPPP
+	if (conf.config_id == WANCONFIG_MPPP)
 		kfree(pppdev);
-	}else{
+	else
 		kfree(dev);
-	}
-      #else
+#else
 	/* Sync PPP is disabled */
-	if (conf.config_id != WANCONFIG_MPPP){
+	if (conf.config_id != WANCONFIG_MPPP)
 		kfree(dev);
-	}
-      #endif
-	
+#endif
+
 	return err;
 }
 
@@ -910,42 +789,31 @@
 
 	if (wandev->state == WAN_UNCONFIGURED)
 		return -ENODEV;
-	
-      #ifdef LINUX_2_0
-        err = verify_area(VERIFY_READ, u_name, WAN_IFNAME_SZ);
-        if (err)
-		return err;
-      #endif	
 
 	memset(name, 0, sizeof(name));
 
-      #if defined (LINUX_2_1) || defined (LINUX_2_4)
-	if(copy_from_user(name, u_name, WAN_IFNAME_SZ))
+	if (copy_from_user(name, u_name, WAN_IFNAME_SZ))
 		return -EFAULT;
-      #else
-        memcpy_fromfs((void*)name, (void*)u_name, WAN_IFNAME_SZ);
-      #endif
 
 	err = delete_interface(wandev, name);
 	if (err)
-		return(err);
+		return err;
 
 	/* If last interface being deleted, shutdown card
 	 * This helps with administration at leaf nodes
-	 * (You can tell if the person at the other end of the phone 
+	 * (You can tell if the person at the other end of the phone
 	 * has an interface configured) and avoids DoS vulnerabilities
 	 * in binary driver files - this fixes a problem with the current
 	 * Sangoma driver going into strange states when all the network
 	 * interfaces are deleted and the link irrecoverably disconnected.
-	 */ 
+	 */
 
-        if (!wandev->ndev && wandev->shutdown){
+        if (!wandev->ndev && wandev->shutdown)
                 err = wandev->shutdown(wandev);
-	}
+
 	return err;
 }
 
-
 /*
  *	Miscellaneous Functions
  */
@@ -995,18 +863,12 @@
 		dev = *slave;
 	}
 	unlock_adapter_irq(&wandev->lock, &smp_flags);
-	
-	if (dev == NULL){
+
+	if (dev == NULL)
 		return -ENODEV;	/* interface not found */
-	}
-		
-       #ifdef LINUX_2_4
-	if (netif_running(dev)){
-       #else
-	if (dev->start) {
-       #endif
+
+	if (netif_running(dev))
 		return -EBUSY;	/* interface in use */
-	}
 
 	if (wandev->del_if)
 		wandev->del_if(wandev, dev);
@@ -1023,9 +885,9 @@
 	}
 	--wandev->ndev;
 	unlock_adapter_irq(&wandev->lock, &smp_flags);
-	
-	printk(KERN_INFO "%s: unregistering '%s'\n", wandev->name, dev->name); 
-	
+
+	printk(KERN_INFO "%s: unregistering '%s'\n", wandev->name, dev->name);
+
 	/* Due to new interface linking method using dev->priv,
 	 * this code has moved from del_if() function.*/
 	if (dev->priv){
@@ -1035,48 +897,28 @@
 
 	unregister_netdev(dev);
 
-      #ifdef LINUX_2_4
-	kfree(dev);
-      #else
-	if (dev->name){
-		kfree(dev->name);
-	}
 	kfree(dev);
-      #endif
 
 	return 0;
 }
 
 void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
 {
-      #ifdef LINUX_2_0
-	save_flags(*smp_flags);
-	cli();
-      #else
        	spin_lock_irqsave(lock, *smp_flags);
-      #endif
 }
 
 
 void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags)
 {
-      #ifdef LINUX_2_0
-	restore_flags(*smp_flags);
-      #else
 	spin_unlock_irqrestore(lock, *smp_flags);
-      #endif
 }
 
-
-
-#if defined (LINUX_2_1) || defined (LINUX_2_4)
 EXPORT_SYMBOL(register_wan_device);
 EXPORT_SYMBOL(unregister_wan_device);
 EXPORT_SYMBOL(wanrouter_encapsulate);
 EXPORT_SYMBOL(wanrouter_type_trans);
 EXPORT_SYMBOL(lock_adapter_irq);
 EXPORT_SYMBOL(unlock_adapter_irq);
-#endif
 
 /*
  *	End
diff -Nru a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
--- a/net/wanrouter/wanproc.c	Tue Feb 26 11:57:59 2002
+++ b/net/wanrouter/wanproc.c	Tue Feb 26 11:57:59 2002
@@ -31,23 +31,15 @@
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <asm/io.h>
 #include <linux/wanrouter.h>	/* WAN router API definitions */
+#include <linux/seq_file.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>	/* __initfunc et al. */
+#include <asm/uaccess.h>       /* copy_to_user */
 
-
-
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
- #include <linux/init.h>	/* __initfunc et al. */
- #include <asm/uaccess.h>       /* copy_to_user */
- #define PROC_STATS_FORMAT "%30s: %12lu\n"
-#else
- #define PROC_STATS_FORMAT "%30s: %12u\n"
- #include <asm/segment.h>	/* kernel <-> user copy */
-#endif
-
+#define PROC_STATS_FORMAT "%30s: %12lu\n"
 
 /****** Defines and Macros **************************************************/
 
-#define	PROC_BUFSZ	4000	/* buffer size for printing proc info */
-
 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
 			      (prot == WANCONFIG_X25) ? " X25" : \
 			         (prot == WANCONFIG_PPP) ? " PPP" : \
@@ -69,962 +61,346 @@
 
 #ifdef CONFIG_PROC_FS
 
+/* Proc filesystem interface */
+static int router_proc_perms(struct inode *, int);
 
-#ifdef LINUX_2_4  /* Start of LINUX 2.4.X code */
+/* Miscellaneous */
 
+/*
+ *	Structures for interfacing with the /proc filesystem.
+ *	Router creates its own directory /proc/net/router with the folowing
+ *	entries:
+ *	config		device configuration
+ *	status		global device statistics
+ *	<device>	entry for each WAN device
+ */
 
-	/* Proc filesystem interface */
-	static int router_proc_perms(struct inode *, int);
-	static ssize_t router_proc_read(struct file* file, char* buf, size_t count, 					loff_t *ppos);
-
-	/* Methods for preparing data for reading proc entries */
-
-	static int config_get_info(char* buf, char** start, off_t offs, int len);
-	static int status_get_info(char* buf, char** start, off_t offs, int len);
-	static int wandev_get_info(char* buf, char** start, off_t offs, int len);
-
-	/* Miscellaneous */
-
-	/*
-	 *	Structures for interfacing with the /proc filesystem.
-	 *	Router creates its own directory /proc/net/router with the folowing
-	 *	entries:
-	 *	config		device configuration
-	 *	status		global device statistics
-	 *	<device>	entry for each WAN device
-	 */
-
-	/*
-	 *	Generic /proc/net/router/<file> file and inode operations 
-	 */
-	static struct file_operations router_fops =
-	{
-		read:		router_proc_read,
-	};
-
-	static struct inode_operations router_inode =
-	{
-		permission:	router_proc_perms,
-	};
-
-	/*
-	 *	/proc/net/router/<device> file operations
-	 */
-
-	static struct file_operations wandev_fops =
-	{
-		read:		router_proc_read,
-		ioctl:		wanrouter_ioctl,
-	};
-
-	/*
-	 *	/proc/net/router 
-	 */
-
-	static struct proc_dir_entry *proc_router;
-
-	/* Strings */
-	static char conf_hdr[] =
-		"Device name    | port |IRQ|DMA|  mem.addr  |mem.size|"
-		"option1|option2|option3|option4\n";
-		
-	static char stat_hdr[] =
-		"Device name    |protocol|station|interface|clocking|baud rate"
-		"| MTU |ndev|link state\n";
-
-
-	/*
-	 *	Interface functions
-	 */
-
-	/*
-	 *	Initialize router proc interface.
-	 */
-
-	int __init wanrouter_proc_init (void)
-	{
-		struct proc_dir_entry *p;
-		proc_router = proc_mkdir(ROUTER_NAME, proc_net);
-		if (!proc_router)
-			goto fail;
-
-		p = create_proc_entry("config",0,proc_router);
-		if (!p)
-			goto fail_config;
-		p->proc_fops = &router_fops;
-		p->proc_iops = &router_inode;
-		p->get_info = config_get_info;
-		p = create_proc_entry("status",0,proc_router);
-		if (!p)
-			goto fail_stat;
-		p->proc_fops = &router_fops;
-		p->proc_iops = &router_inode;
-		p->get_info = status_get_info;
-		return 0;
-	fail_stat:
-		remove_proc_entry("config", proc_router);
-	fail_config:
-		remove_proc_entry(ROUTER_NAME, proc_net);
-	fail:
-		return -ENOMEM;
-	}
+/*
+ *	Generic /proc/net/router/<file> file and inode operations 
+ */
 
-	/*
-	 *	Clean up router proc interface.
-	 */
-
-	void wanrouter_proc_cleanup (void)
-	{
-		remove_proc_entry("config", proc_router);
-		remove_proc_entry("status", proc_router);
-		remove_proc_entry(ROUTER_NAME,proc_net);
-	}
+static struct inode_operations router_inode =
+{
+	permission:	router_proc_perms,
+};
 
-	/*
-	 *	Add directory entry for WAN device.
-	 */
-
-	int wanrouter_proc_add (wan_device_t* wandev)
-	{
-		if (wandev->magic != ROUTER_MAGIC)
-			return -EINVAL;
-			
-		wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
-		if (!wandev->dent)
-			return -ENOMEM;
-		wandev->dent->proc_fops	= &wandev_fops;
-		wandev->dent->proc_iops	= &router_inode;
-		wandev->dent->get_info	= wandev_get_info;
-		wandev->dent->data	= wandev;
-		return 0;
-	}
+/*
+ *	/proc/net/router 
+ */
 
-	/*
-	 *	Delete directory entry for WAN device.
-	 */
-	 
-	int wanrouter_proc_delete(wan_device_t* wandev)
-	{
-		if (wandev->magic != ROUTER_MAGIC)
-			return -EINVAL;
-		remove_proc_entry(wandev->name, proc_router);
-		return 0;
-	}
+static struct proc_dir_entry *proc_router;
 
-	/****** Proc filesystem entry points ****************************************/
+/* Strings */
 
-	/*
-	 *	Verify access rights.
-	 */
+/*
+ *	Interface functions
+ */
 
-	static int router_proc_perms (struct inode* inode, int op)
-	{
-		return 0;
-	}
+/****** Proc filesystem entry points ****************************************/
 
-	/*
-	 *	Read router proc directory entry.
-	 *	This is universal routine for reading all entries in /proc/net/wanrouter
-	 *	directory.  Each directory entry contains a pointer to the 'method' for
-	 *	preparing data for that entry.
-	 *	o verify arguments
-	 *	o allocate kernel buffer
-	 *	o call get_info() to prepare data
-	 *	o copy data to user space
-	 *	o release kernel buffer
-	 *
-	 *	Return:	number of bytes copied to user space (0, if no data)
-	 *		<0	error
-	 */
-
-	static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
-					loff_t *ppos)
-	{
-		struct inode *inode = file->f_dentry->d_inode;
-		struct proc_dir_entry* dent;
-		char* page;
-		int pos, offs, len;
+/*
+ *	Verify access rights.
+ */
 
-		if (count <= 0)
-			return 0;
-			
-		dent = PDE(inode);
-		if ((dent == NULL) || (dent->get_info == NULL))
-			return 0;
-			
-		page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
-		if (page == NULL)
-			return -ENOBUFS;
-			
-		pos = dent->get_info(page, dent->data, 0, 0);
-		offs = file->f_pos;
-		if (offs < pos) {
-			len = min_t(unsigned int, pos - offs, count);
-			if (copy_to_user(buf, (page + offs), len)) {
-				kfree(page);
-				return -EFAULT;
-			}
-			file->f_pos += len;
-		}
-		else
-			len = 0;
-		kfree(page);
-		return len;
-	}
+static int router_proc_perms (struct inode* inode, int op)
+{
+	return 0;
+}
 
-	/*
-	 *	Prepare data for reading 'Config' entry.
-	 *	Return length of data.
-	 */
-
-	static int config_get_info(char* buf, char** start, off_t offs, int len)
-	{
-		int cnt = sizeof(conf_hdr) - 1;
-		wan_device_t* wandev;
-		strcpy(buf, conf_hdr);
-		for (wandev = router_devlist;
-		     wandev && (cnt < (PROC_BUFSZ - 120));
-		     wandev = wandev->next) {
-			if (wandev->state) cnt += sprintf(&buf[cnt],
-				"%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
-				wandev->name,
-				wandev->ioport,
-				wandev->irq,
-				wandev->dma,
-				wandev->maddr,
-				wandev->msize,
-				wandev->hw_opt[0],
-				wandev->hw_opt[1],
-				wandev->hw_opt[2],
-				wandev->hw_opt[3]);
-		}
+/*
+ *	Iterator
+ */
+static void *r_start(struct seq_file *m, loff_t *pos)
+{
+	wan_device_t *wandev;
+	loff_t l = *pos;
 
-		return cnt;
-	}
+	lock_kernel();
+	if (!l--)
+		return (void *)1;
+	for (wandev = router_devlist; l-- && wandev; wandev = wandev->next)
+		;
+	return wandev;
+}
+static void *r_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	wan_device_t *wandev = v;
+	(*pos)++;
+	return (v == (void *)1) ? router_devlist : wandev->next;
+}
+static void r_stop(struct seq_file *m, void *v)
+{
+	unlock_kernel();
+}
 
-	/*
-	 *	Prepare data for reading 'Status' entry.
-	 *	Return length of data.
-	 */
-
-	static int status_get_info(char* buf, char** start, off_t offs, int len)
-	{
-		int cnt = 0;
-		wan_device_t* wandev;
-
-		//cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
-		strcpy(&buf[cnt], stat_hdr);
-		cnt += sizeof(stat_hdr) - 1;
-
-		for (wandev = router_devlist;
-		     wandev && (cnt < (PROC_BUFSZ - 80));
-		     wandev = wandev->next) {
-			if (!wandev->state) continue;
-			cnt += sprintf(&buf[cnt],
-				"%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
-				wandev->name,
-				PROT_DECODE(wandev->config_id),
-				wandev->config_id == WANCONFIG_FR ? 
-					(wandev->station ? " Node" : " CPE") :
-					(wandev->config_id == WANCONFIG_X25 ?
-					(wandev->station ? " DCE" : " DTE") :
-					(" N/A")),
-				wandev->interface ? " V.35" : " RS-232",
-				wandev->clocking ? "internal" : "external",
-				wandev->bps,
-				wandev->mtu,
-				wandev->ndev);
-
-			switch (wandev->state) {
-
-			case WAN_UNCONFIGURED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
-				break;
-
-			case WAN_DISCONNECTED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
-				break;
-
-			case WAN_CONNECTING:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
-				break;
-
-			case WAN_CONNECTED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
-				break;
-
-			default:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
-				break;
-			}
-		}
-		return cnt;
+static int config_show(struct seq_file *m, void *v)
+{
+	wan_device_t *p = v;
+	if (v == (void *)1) {
+		seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |");
+		seq_puts(m, "mem.size|option1|option2|option3|option4\n");
+		return 0;
 	}
+	if (!p->state)
+		return 0;
+	seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
+			p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
+			p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
+	return 0;
+}
 
-	/*
-	 *	Prepare data for reading <device> entry.
-	 *	Return length of data.
-	 *
-	 *	On entry, the 'start' argument will contain a pointer to WAN device
-	 *	data space.
-	 */
-
-	static int wandev_get_info(char* buf, char** start, off_t offs, int len)
-	{
-		wan_device_t* wandev = (void*)start;
-		int cnt = 0;
-		int rslt = 0;
-
-		if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
-			return 0;
-		if (!wandev->state)
-			return sprintf(&buf[cnt], "device is not configured!\n");
-
-		/* Update device statistics */
-		if (wandev->update) {
-
-			rslt = wandev->update(wandev);
-			if(rslt) {
-				switch (rslt) {
-				case -EAGAIN:
-					return sprintf(&buf[cnt], "Device is busy!\n");
-
-				default:
-					return sprintf(&buf[cnt],
-						"Device is not configured!\n");
-				}
-			}
-		}
-
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total packets received", wandev->stats.rx_packets);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total packets transmitted", wandev->stats.tx_packets);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total bytes received", wandev->stats.rx_bytes);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total bytes transmitted", wandev->stats.tx_bytes);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"bad packets received", wandev->stats.rx_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"packet transmit problems", wandev->stats.tx_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"received frames dropped", wandev->stats.rx_dropped);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"transmit frames dropped", wandev->stats.tx_dropped);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"multicast packets received", wandev->stats.multicast);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"transmit collisions", wandev->stats.collisions);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receive length errors", wandev->stats.rx_length_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver overrun errors", wandev->stats.rx_over_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"CRC errors", wandev->stats.rx_crc_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"frame format errors (aborts)", wandev->stats.rx_frame_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver fifo overrun", wandev->stats.rx_fifo_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver missed packet", wandev->stats.rx_missed_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"aborted frames transmitted", wandev->stats.tx_aborted_errors);
-		return cnt;
+static int status_show(struct seq_file *m, void *v)
+{
+	wan_device_t *p = v;
+	if (v == (void *)1) {
+		seq_puts(m, "Device name    |protocol|station|interface|");
+		seq_puts(m, "clocking|baud rate| MTU |ndev|link state\n");
+		return 0;
 	}
+	if (!p->state)
+		return 0;
+	seq_printf(m, "%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
+		p->name,
+		PROT_DECODE(p->config_id),
+		p->config_id == WANCONFIG_FR ? 
+			(p->station ? " Node" : " CPE") :
+			(p->config_id == WANCONFIG_X25 ?
+			(p->station ? " DCE" : " DTE") :
+			(" N/A")),
+		p->interface ? " V.35" : " RS-232",
+		p->clocking ? "internal" : "external",
+		p->bps,
+		p->mtu,
+		p->ndev);
+
+	switch (p->state) {
+	case WAN_UNCONFIGURED:
+		seq_printf(m, "%-12s\n", "unconfigured");
+		break;
+	case WAN_DISCONNECTED:
+		seq_printf(m, "%-12s\n", "disconnected");
+		break;
+	case WAN_CONNECTING:
+		seq_printf(m, "%-12s\n", "connecting");
+		break;
+	case WAN_CONNECTED:
+		seq_printf(m, "%-12s\n", "connected");
+		break;
+	default:
+		seq_printf(m, "%-12s\n", "invalid");
+		break;
+	}
+	return 0;
+}
 
+static struct seq_operations config_op = {
+	start:	r_start,
+	next:	r_next,
+	stop:	r_stop,
+	show:	config_show
+};
+
+static struct seq_operations status_op = {
+	start:	r_start,
+	next:	r_next,
+	stop:	r_stop,
+	show:	status_show
+};
 
-#else /* ------------------- END OF LINUX 2.4.X VERSION -------------*/
-
-
-
-	/* Proc filesystem interface */
-	static int router_proc_perms(struct inode *, int);
-#ifdef LINUX_2_1
-	static ssize_t router_proc_read(struct file *file, char *buf, size_t count, 					loff_t *ppos);
-#else
-	static int router_proc_read(
-		struct inode* inode, struct file* file, char* buf, int count);
-	static int device_write(
-		struct inode* inode, struct file* file, const char* buf, int count);
-#endif
-
-	/* Methods for preparing data for reading proc entries */
-	static int config_get_info(char* buf, char** start, off_t offs, int len,
-		int dummy);
-	static int status_get_info(char* buf, char** start, off_t offs, int len,
-		int dummy);
-	static int wandev_get_info(char* buf, char** start, off_t offs, int len,
-		int dummy);
-
-	/* Miscellaneous */
-
-	/*
-	 *	Global Data
-	 */
-
-	/*
-	 *	Names of the proc directory entries 
-	 */
-
-	static char name_root[]	= ROUTER_NAME;
-	static char name_conf[]	= "config";
-	static char name_stat[]	= "status";
-
-	/*
-	 *	Structures for interfacing with the /proc filesystem.
-	 *	Router creates its own directory /proc/net/router with the folowing
-	 *	entries:
-	 *	config		device configuration
-	 *	status		global device statistics
-	 *	<device>	entry for each WAN device
-	 */
-
-	/*
-	 *	Generic /proc/net/router/<file> file and inode operations 
-	 */
-#ifdef LINUX_2_1
-	static struct file_operations router_fops =
-	{
-		NULL,			/* lseek   */
-		router_proc_read,	/* read	   */
-		NULL,			/* write   */
-		NULL,			/* readdir */
-		NULL,			/* select  */
-		NULL,			/* ioctl   */
-		NULL,			/* mmap	   */
-		NULL,			/* no special open code	   */
-		NULL,			/* flush */
-		NULL,			/* no special release code */
-		NULL			/* can't fsync */
-	};
-#else
-	static struct file_operations router_fops =
-	{
-		NULL,                   /* lseek   */
-		router_proc_read,       /* read    */
-		NULL,                   /* write   */
-		NULL,                   /* readdir */
-		NULL,                   /* select  */
-		NULL,                   /* ioctl   */
-		NULL,                   /* mmap    */
-		NULL,                   /* no special open code    */
-		NULL,                   /* no special release code */
-		NULL                    /* can't fsync */
-	};
-#endif
+static int config_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &config_op);
+}
 
-	static struct inode_operations router_inode =
-	{
-		&router_fops,
-		NULL,			/* create */
-		NULL,			/* lookup */
-		NULL,			/* link */
-		NULL,			/* unlink */
-		NULL,			/* symlink */
-		NULL,			/* mkdir */
-		NULL,			/* rmdir */
-		NULL,			/* mknod */
-		NULL,			/* rename */
-		NULL,			/* follow link */
-		NULL,			/* readlink */
-		NULL,			/* readpage */
-		NULL,			/* writepage */
-		NULL,			/* bmap */
-		NULL,			/* truncate */
-		router_proc_perms
-	};
-
-	/*
-	 *	/proc/net/router/<device> file and inode operations
-	 */
-
-#ifdef LINUX_2_1
-	static struct file_operations wandev_fops =
-	{
-		NULL,			/* lseek   */
-		router_proc_read,	/* read	   */
-		NULL,			/* write   */
-		NULL,			/* readdir */
-		NULL,			/* select  */
-		wanrouter_ioctl,	/* ioctl   */
-		NULL,			/* mmap	   */
-		NULL,			/* no special open code	   */
-		NULL,			/* flush */
-		NULL,			/* no special release code */
-		NULL			/* can't fsync */
-	};
-#else
-	static struct file_operations wandev_fops =
-	{
-		NULL,                   /* lseek   */
-		router_proc_read,       /* read    */
-		device_write,           /* write   */
-		NULL,                   /* readdir */
-		NULL,                   /* select  */
-		wanrouter_ioctl,        /* ioctl   */
-		NULL,                   /* mmap    */
-		NULL,                   /* no special open code    */
-		NULL,                   /* no special release code */
-		NULL                    /* can't fsync */
-	};
-#endif
+static int status_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &status_op);
+}
 
-	static struct inode_operations wandev_inode =
-	{
-		&wandev_fops,
-		NULL,			/* create */
-		NULL,			/* lookup */
-		NULL,			/* link */
-		NULL,			/* unlink */
-		NULL,			/* symlink */
-		NULL,			/* mkdir */
-		NULL,			/* rmdir */
-		NULL,			/* mknod */
-		NULL,			/* rename */
-		NULL,			/* readlink */
-		NULL,			/* follow_link */
-		NULL,			/* readpage */
-		NULL,			/* writepage */
-		NULL,			/* bmap */
-		NULL,			/* truncate */
-		router_proc_perms
-	};
-
-	/*
-	 * Proc filesystem derectory entries.
-	 */
-
-	/*
-	 *	/proc/net/router 
-	 */
-	 
-	static struct proc_dir_entry proc_router =
-	{
-		0,			/* .low_ino */
-		sizeof(name_root) - 1,	/* .namelen */
-		name_root,		/* .name */
-		0555 | S_IFDIR,		/* .mode */
-		2,			/* .nlink */
-		0,			/* .uid */
-		0,			/* .gid */
-		0,			/* .size */
-		&proc_dir_inode_operations, /* .ops */
-		NULL,			/* .get_info */
-		NULL,			/* .fill_node */
-		NULL,			/* .next */
-		NULL,			/* .parent */
-		NULL,			/* .subdir */
-		NULL,			/* .data */
-	};
-
-	/*
-	 *	/proc/net/router/config 
-	 */
-	 
-	static struct proc_dir_entry proc_router_conf =
-	{
-		0,			/* .low_ino */
-		sizeof(name_conf) - 1,	/* .namelen */
-		name_conf,		/* .name */
-		0444 | S_IFREG,		/* .mode */
-		1,			/* .nlink */
-		0,			/* .uid */
-		0,			/* .gid */
-		0,			/* .size */
-		&router_inode,		/* .ops */
-		&config_get_info,	/* .get_info */
-		NULL,			/* .fill_node */
-		NULL,			/* .next */
-		NULL,			/* .parent */
-		NULL,			/* .subdir */
-		NULL,			/* .data */
-	};
-
-	/*
-	 *	/proc/net/router/status 
-	 */
-	 
-	static struct proc_dir_entry proc_router_stat =
-	{
-		0,			/* .low_ino */
-		sizeof(name_stat) - 1,	/* .namelen */
-		name_stat,		/* .name */
-		0444 | S_IFREG,		/* .mode */
-		1,			/* .nlink */
-		0,			/* .uid */
-		0,			/* .gid */
-		0,			/* .size */
-		&router_inode,		/* .ops */
-		status_get_info,	/* .get_info */
-		NULL,			/* .fill_node */
-		NULL,			/* .next */
-		NULL,			/* .parent */
-		NULL,			/* .subdir */
-		NULL,			/* .data */
-	};
-
-	/* Strings */
-	static char conf_hdr[] =
-		"Device name    | port |IRQ|DMA|  mem.addr  |mem.size|"
-		"option1|option2|option3|option4\n";
-		
-	static char stat_hdr[] =
-		"Device name    |protocol|station|interface|clocking|baud rate| MTU |ndev"
-		"|link state\n";
-
-
-	/*
-	 *	Interface functions
-	 */
-
-	/*
-	 *	Initialize router proc interface.
-	 */
-
-#ifdef LINUX_2_1
-	__initfunc(int wanrouter_proc_init (void))
-	{
-		int err = proc_register(proc_net, &proc_router);
-
-		if (!err) {
-			proc_register(&proc_router, &proc_router_conf);
-			proc_register(&proc_router, &proc_router_stat);
-		}
-		return err;
-	}
-#else
-	int wanrouter_proc_init (void)
-	{
-		int err = proc_register_dynamic(&proc_net, &proc_router);
-
-		if (!err) {
-			proc_register_dynamic(&proc_router, &proc_router_conf);
-			proc_register_dynamic(&proc_router, &proc_router_stat);
-		}
-		return err;
-	}
-#endif
+static struct file_operations config_fops =
+{
+	open:		config_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 
-	/*
-	 *	Clean up router proc interface.
-	 */
-
-	void wanrouter_proc_cleanup (void)
-	{
-		proc_unregister(&proc_router, proc_router_conf.low_ino);
-		proc_unregister(&proc_router, proc_router_stat.low_ino);
-#ifdef LINUX_2_1
-		proc_unregister(proc_net, proc_router.low_ino);
-#else
-		proc_unregister(&proc_net, proc_router.low_ino);
-#endif
-	}
+static struct file_operations status_fops =
+{
+	open:		status_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 
-	/*
-	 *	Add directory entry for WAN device.
-	 */
-
-	int wanrouter_proc_add (wan_device_t* wandev)
-	{
-		if (wandev->magic != ROUTER_MAGIC)
-			return -EINVAL;
-		
-		memset(&wandev->dent, 0, sizeof(wandev->dent));
-		wandev->dent.namelen	= strlen(wandev->name);
-		wandev->dent.name	= wandev->name;
-		wandev->dent.mode	= 0444 | S_IFREG;
-		wandev->dent.nlink	= 1;
-		wandev->dent.ops	= &wandev_inode;
-		wandev->dent.get_info	= &wandev_get_info;
-		wandev->dent.data	= wandev;
-#ifdef LINUX_2_1
-		return proc_register(&proc_router, &wandev->dent);
-#else
-		return proc_register_dynamic(&proc_router, &wandev->dent);
-#endif
-	}
+static void *single_start(struct seq_file *p, loff_t *pos)
+{
+	return *pos == 0 ? p->private : NULL;
+}
+static void *single_next(struct seq_file *p, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+static void single_stop(struct seq_file *p, void *v)
+{
+}
+static int wandev_show(struct seq_file *m, void *v)
+{
+	wan_device_t *wandev = v;
 
-	/*
-	 *	Delete directory entry for WAN device.
-	 */
-	 
-	int wanrouter_proc_delete(wan_device_t* wandev)
-	{
-		if (wandev->magic != ROUTER_MAGIC)
-			return -EINVAL;
-		proc_unregister(&proc_router, wandev->dent.low_ino);
+	if (wandev->magic != ROUTER_MAGIC)
 		return 0;
-	}
-
-	/****** Proc filesystem entry points ****************************************/
-
-	/*
-	 *	Verify access rights.
-	 */
 
-	static int router_proc_perms (struct inode* inode, int op)
-	{
+	if (!wandev->state) {
+		seq_puts(m, "device is not configured!\n");
 		return 0;
 	}
 
-	/*
-	 *	Read router proc directory entry.
-	 *	This is universal routine for reading all entries in /proc/net/wanrouter
-	 *	directory.  Each directory entry contains a pointer to the 'method' for
-	 *	preparing data for that entry.
-	 *	o verify arguments
-	 *	o allocate kernel buffer
-	 *	o call get_info() to prepare data
-	 *	o copy data to user space
-	 *	o release kernel buffer
-	 *
-	 *	Return:	number of bytes copied to user space (0, if no data)
-	 *		<0	error
-	 */
-#ifdef LINUX_2_1
-	static ssize_t router_proc_read(struct file* file, char* buf, size_t count,
-					loff_t *ppos)
-	{
-		struct inode *inode = file->f_dentry->d_inode;
-		struct proc_dir_entry* dent;
-		char* page;
-		int pos, offs, len;
-
-		if (count <= 0)
-			return 0;
-			
-		dent = PDE(inode);
-		if ((dent == NULL) || (dent->get_info == NULL))
+	/* Update device statistics */
+	if (wandev->update) {
+		int err = wandev->update(wandev);
+		if (err == -EAGAIN) {
+			seq_printf(m, "Device is busy!\n");
 			return 0;
-			
-		page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
-		if (page == NULL)
-			return -ENOBUFS;
-			
-		pos = dent->get_info(page, dent->data, 0, 0, 0);
-		offs = file->f_pos;
-		if (offs < pos) {
-			len = min_t(unsigned int, pos - offs, count);
-			if (copy_to_user(buf, (page + offs), len)) {
-				kfree(page);
-				return -EFAULT;
-			}
-			file->f_pos += len;
 		}
-		else
-			len = 0;
-		kfree(page);
-		return len;
-	}
-
-#else
-	static int router_proc_read(
-		struct inode* inode, struct file* file, char* buf, int count)
-	{
-		struct proc_dir_entry* dent;
-		char* page;
-		int err, pos, offs, len;
-
-		if (count <= 0)
+		if (err) {
+			seq_printf(m, "Device is not configured!\n");
 			return 0;
-		dent = PDE(inode);
-		if ((dent == NULL) || (dent->get_info == NULL))
-			return -ENODATA;
-		err = verify_area(VERIFY_WRITE, buf, count);
-		if (err) return err;
-
-		page = kmalloc(PROC_BUFSZ, GFP_KERNEL);
-		if (page == NULL)
-			return -ENOMEM;
-
-		pos = dent->get_info(page, dent->data, 0, 0, 0);
-		offs = file->f_pos;
-		if (offs < pos) {
-			len = min_t(unsigned int, pos - offs, count);
-			memcpy_tofs((void*)buf, (void*)(page + offs), len);
-			file->f_pos += len;
-		}
-		else len = 0;
-		kfree(page);
-		return len;
-	}
-#endif
-
-
-	/*
-	 *	Prepare data for reading 'Config' entry.
-	 *	Return length of data.
-	 */
-
-	static int config_get_info(char* buf, char** start, off_t offs, int len, 
-		int dummy)
-	{
-		int cnt = sizeof(conf_hdr) - 1;
-		wan_device_t* wandev;
-		strcpy(buf, conf_hdr);
-		for (wandev = router_devlist;
-		     wandev && (cnt < (PROC_BUFSZ - 120));
-		     wandev = wandev->next) {
-			if (wandev->state) cnt += sprintf(&buf[cnt],
-				"%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
-				wandev->name,
-				wandev->ioport,
-				wandev->irq,
-				wandev->dma,
-				wandev->maddr,
-				wandev->msize,
-				wandev->hw_opt[0],
-				wandev->hw_opt[1],
-				wandev->hw_opt[2],
-				wandev->hw_opt[3]);
 		}
-
-		return cnt;
 	}
 
-	/*
-	 *	Prepare data for reading 'Status' entry.
-	 *	Return length of data.
-	 */
-
-	static int status_get_info(char* buf, char** start, off_t offs, int len, 
-				int dummy)
-	{
-		int cnt = 0;
-		wan_device_t* wandev;
-
-		//cnt += sprintf(&buf[cnt], "\nSTATUS:\n\n");
-		strcpy(&buf[cnt], stat_hdr);
-		cnt += sizeof(stat_hdr) - 1;
-
-		for (wandev = router_devlist;
-		     wandev && (cnt < (PROC_BUFSZ - 80));
-		     wandev = wandev->next) {
-			if (!wandev->state) continue;
-			cnt += sprintf(&buf[cnt],
-				"%-15s|%-8s|%-7s|%-9s|%-8s|%9u|%5u|%3u |",
-				wandev->name,
-				PROT_DECODE(wandev->config_id),
-				wandev->config_id == WANCONFIG_FR ? 
-					(wandev->station ? " Node" : " CPE") :
-					(wandev->config_id == WANCONFIG_X25 ?
-					(wandev->station ? " DCE" : " DTE") :
-					(" N/A")),
-				wandev->interface ? " V.35" : " RS-232",
-				wandev->clocking ? "internal" : "external",
-				wandev->bps,
-				wandev->mtu,
-				wandev->ndev);
-
-			switch (wandev->state) {
-
-			case WAN_UNCONFIGURED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "unconfigured");
-				break;
-
-			case WAN_DISCONNECTED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "disconnected");
-				break;
-
-			case WAN_CONNECTING:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "connecting");
-				break;
-
-			case WAN_CONNECTED:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "connected");
-				break;
-
-			case WAN_FT1_READY:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "ft1 ready");
-				break;
-
-			default:
-				cnt += sprintf(&buf[cnt], "%-12s\n", "invalid");
-				break;
-			}
-		}
-		return cnt;
+	seq_printf(m, PROC_STATS_FORMAT,
+		"total packets received", wandev->stats.rx_packets);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"total packets transmitted", wandev->stats.tx_packets);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"total bytes received", wandev->stats.rx_bytes);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"total bytes transmitted", wandev->stats.tx_bytes);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"bad packets received", wandev->stats.rx_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"packet transmit problems", wandev->stats.tx_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"received frames dropped", wandev->stats.rx_dropped);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"transmit frames dropped", wandev->stats.tx_dropped);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"multicast packets received", wandev->stats.multicast);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"transmit collisions", wandev->stats.collisions);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"receive length errors", wandev->stats.rx_length_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"receiver overrun errors", wandev->stats.rx_over_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"CRC errors", wandev->stats.rx_crc_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"frame format errors (aborts)", wandev->stats.rx_frame_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"receiver fifo overrun", wandev->stats.rx_fifo_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"receiver missed packet", wandev->stats.rx_missed_errors);
+	seq_printf(m, PROC_STATS_FORMAT,
+		"aborted frames transmitted", wandev->stats.tx_aborted_errors);
+	return 0;
+}
+static struct seq_operations wandev_op = {
+	start:	single_start,
+	next:	single_next,
+	stop:	single_stop,
+	show:	wandev_show,
+};
+static int wandev_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &wandev_op);
+	if (!ret) {
+		struct seq_file *m = file->private_data;
+		m->private = PDE(inode)->data;
 	}
+	return ret;
+}
 
-	/*
-	 *	Prepare data for reading <device> entry.
-	 *	Return length of data.
-	 *
-	 *	On entry, the 'start' argument will contain a pointer to WAN device
-	 *	data space.
-	 */
-
-	static int wandev_get_info(char* buf, char** start, off_t offs, int len, 
-				int dummy)
-	{
-		wan_device_t* wandev = (void*)start;
-		int cnt = 0;
-		int rslt = 0;
+static struct file_operations wandev_fops =
+{
+	open:		wandev_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+	ioctl:		wanrouter_ioctl,
+};
 
-		if ((wandev == NULL) || (wandev->magic != ROUTER_MAGIC))
-			return 0;
-		if (!wandev->state)
-			return sprintf(&buf[cnt], "Device is not configured!\n");
+/*
+ *	Initialize router proc interface.
+ */
 
-		/* Update device statistics */
-		if (wandev->update) {
+int __init wanrouter_proc_init (void)
+{
+	struct proc_dir_entry *p;
+	proc_router = proc_mkdir(ROUTER_NAME, proc_net);
+	if (!proc_router)
+		goto fail;
+
+	p = create_proc_entry("config",0,proc_router);
+	if (!p)
+		goto fail_config;
+	p->proc_fops = &config_fops;
+	p->proc_iops = &router_inode;
+	p = create_proc_entry("status",0,proc_router);
+	if (!p)
+		goto fail_stat;
+	p->proc_fops = &status_fops;
+	p->proc_iops = &router_inode;
+	return 0;
+fail_stat:
+	remove_proc_entry("config", proc_router);
+fail_config:
+	remove_proc_entry(ROUTER_NAME, proc_net);
+fail:
+	return -ENOMEM;
+}
 
-			rslt = wandev->update(wandev);
-			if(rslt) {
-				switch (rslt) {
-				case -EAGAIN:
-					return sprintf(&buf[cnt], "Device is busy!\n");
-
-				default:
-					return sprintf(&buf[cnt],
-						"Device is not configured!\n");
-				}
-			}
-		}
+/*
+ *	Clean up router proc interface.
+ */
 
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total packets received", wandev->stats.rx_packets);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total packets transmitted", wandev->stats.tx_packets);
-#ifdef LINUX_2_1
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total bytes received", wandev->stats.rx_bytes);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"total bytes transmitted", wandev->stats.tx_bytes);
-#endif
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"bad packets received", wandev->stats.rx_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"packet transmit problems", wandev->stats.tx_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"received frames dropped", wandev->stats.rx_dropped);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"transmit frames dropped", wandev->stats.tx_dropped);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"multicast packets received", wandev->stats.multicast);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"transmit collisions", wandev->stats.collisions);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receive length errors", wandev->stats.rx_length_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver overrun errors", wandev->stats.rx_over_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"CRC errors", wandev->stats.rx_crc_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"frame format errors (aborts)", wandev->stats.rx_frame_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver fifo overrun", wandev->stats.rx_fifo_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"receiver missed packet", wandev->stats.rx_missed_errors);
-		cnt += sprintf(&buf[cnt], PROC_STATS_FORMAT,
-			"aborted frames transmitted", wandev->stats.tx_aborted_errors);
+void wanrouter_proc_cleanup (void)
+{
+	remove_proc_entry("config", proc_router);
+	remove_proc_entry("status", proc_router);
+	remove_proc_entry(ROUTER_NAME,proc_net);
+}
 
-		return cnt;
-	}
+/*
+ *	Add directory entry for WAN device.
+ */
 
-#endif /* End of ifdef LINUX_2_4 */
+int wanrouter_proc_add (wan_device_t* wandev)
+{
+	if (wandev->magic != ROUTER_MAGIC)
+		return -EINVAL;
+		
+	wandev->dent = create_proc_entry(wandev->name, 0, proc_router);
+	if (!wandev->dent)
+		return -ENOMEM;
+	wandev->dent->proc_fops	= &wandev_fops;
+	wandev->dent->proc_iops	= &router_inode;
+	wandev->dent->data	= wandev;
+	return 0;
+}
 
+/*
+ *	Delete directory entry for WAN device.
+ */
+ 
+int wanrouter_proc_delete(wan_device_t* wandev)
+{
+	if (wandev->magic != ROUTER_MAGIC)
+		return -EINVAL;
+	remove_proc_entry(wandev->name, proc_router);
+	return 0;
+}
 
 #else
 
@@ -1039,7 +415,6 @@
 
 void wanrouter_proc_cleanup(void)
 {
-	return;
 }
 
 int wanrouter_proc_add(wan_device_t *wandev)
@@ -1054,34 +429,7 @@
 
 #endif
 
-/*============================================================================
- * Write WAN device ???.
- * o Find WAN device associated with this node
- */
-#ifdef LINUX_2_0
-static int device_write(
-        struct inode* inode, struct file* file, const char* buf, int count)
-{
-        int err = verify_area(VERIFY_READ, buf, count);
-        struct proc_dir_entry* dent;
-        wan_device_t* wandev;
-
-        if (err) return err;
-
-        dent = PDE(inode);
-        if ((dent == NULL) || (dent->data == NULL))
-                return -ENODATA;
-
-        wandev = dent->data;
-
-        printk(KERN_ERR "%s: writing %d bytes to %s...\n",
-                name_root, count, dent->name);
-        
-	return 0;
-}
-#endif
-
 /*
  *	End
  */
- 
+
diff -Nru a/sound/Makefile b/sound/Makefile
--- a/sound/Makefile	Tue Feb 26 11:57:58 2002
+++ b/sound/Makefile	Tue Feb 26 11:57:58 2002
@@ -10,6 +10,7 @@
 subdir-$(CONFIG_SOUND_PRIME) += oss
 
 ifeq ($(CONFIG_SOUND_PRIME),y)
+  subdir-m += oss
   obj-y += oss/sounddrivers.o
 endif
 
diff -Nru a/sound/core/Config.in b/sound/core/Config.in
--- a/sound/core/Config.in	Tue Feb 26 11:57:58 2002
+++ b/sound/core/Config.in	Tue Feb 26 11:57:58 2002
@@ -1,6 +1,5 @@
 # ALSA soundcard-configuration
 
-dep_tristate '  RTC Timer support' CONFIG_SND_RTCTIMER $CONFIG_SND
 dep_tristate '  Sequencer support' CONFIG_SND_SEQUENCER $CONFIG_SND
 if [ "$CONFIG_SND_SEQUENCER" != "n" ]; then
   dep_tristate '  Sequencer dummy client' CONFIG_SND_SEQ_DUMMY $CONFIG_SND_SEQUENCER
@@ -13,9 +12,10 @@
     dep_tristate '    OSS Sequencer API' CONFIG_SND_SEQUENCER_OSS $CONFIG_SND_SEQUENCER
   fi
 fi
+dep_tristate '  RTC Timer support' CONFIG_SND_RTCTIMER $CONFIG_SND
+bool '  Verbose printk' CONFIG_SND_VERBOSE_PRINTK
 bool '  Debug' CONFIG_SND_DEBUG
 if [ "$CONFIG_SND_DEBUG" = "y" ]; then
   bool '    Debug memory' CONFIG_SND_DEBUG_MEMORY
-  bool '    Debug full' CONFIG_SND_DEBUG_FULL
   bool '    Debug detection' CONFIG_SND_DEBUG_DETECT
 fi
diff -Nru a/sound/core/Makefile b/sound/core/Makefile
--- a/sound/core/Makefile	Tue Feb 26 11:57:57 2002
+++ b/sound/core/Makefile	Tue Feb 26 11:57:57 2002
@@ -33,16 +33,18 @@
 subdir-$(CONFIG_SND_MIXER_OSS) += oss
 subdir-$(CONFIG_SND_PCM_OSS) += oss
 ifeq ($(filter $(subdir-y),oss),oss)
+  subdir-m += oss
   obj-y += oss/oss.o
 endif
 
 subdir-$(CONFIG_SND_SEQUENCER) += seq
 ifeq ($(CONFIG_SND_SEQUENCER),y)
-  ifeq ($(CONFIG_SND),y)
-     obj-y += seq/sq.o
-  endif
+  subdir-m += seq
+  obj-y += seq/sq.o
 endif
 
+obj-$(CONFIG_SND_SEQUENCER) += snd-timer.o
+
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_DUMMY) += snd-pcm.o snd-timer.o snd.o
 obj-$(CONFIG_SND_VIRMIDI) += snd-rawmidi.o snd.o snd-timer.o
@@ -69,7 +71,7 @@
 obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_OPTI93X) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
-obj-$(CONFIG_SND_SB) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_SB8) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_SB16) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
 obj-$(CONFIG_SND_SBAWE) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
 obj-$(CONFIG_SND_ES968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
@@ -79,7 +81,7 @@
 obj-$(CONFIG_SND_CS4281) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_ENS1370) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
 obj-$(CONFIG_SND_ENS1371) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
-obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
+obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
 obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
 obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
 obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
diff -Nru a/sound/core/control.c b/sound/core/control.c
--- a/sound/core/control.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/control.c	Tue Feb 26 11:57:57 2002
@@ -166,7 +166,7 @@
 			ev->mask = mask;
 			list_add_tail(&ev->list, &ctl->events);
 		} else {
-			snd_printk("No memory available to allocate event\n");
+			snd_printk(KERN_ERR "No memory available to allocate event\n");
 		}
 	_found:
 		wake_up(&ctl->change_sleep);
diff -Nru a/sound/core/device.c b/sound/core/device.c
--- a/sound/core/device.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/device.c	Tue Feb 26 11:57:56 2002
@@ -58,11 +58,11 @@
 		list_del(&dev->list);
 		if (dev->state == SNDRV_DEV_REGISTERED && dev->ops->dev_unregister) {
 			if (dev->ops->dev_unregister(dev))
-				snd_printk("device unregister failure\n");
+				snd_printk(KERN_ERR "device unregister failure\n");
 		} else {
 			if (dev->ops->dev_free) {
 				if (dev->ops->dev_free(dev))
-					snd_printk("device free failure\n");
+					snd_printk(KERN_ERR "device free failure\n");
 			}
 		}
 		snd_magic_kfree(dev);
diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c
--- a/sound/core/hwdep.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/hwdep.c	Tue Feb 26 11:57:56 2002
@@ -321,7 +321,7 @@
 	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
 				       hwdep->card, hwdep->device,
 				       &snd_hwdep_reg, name)) < 0) {
-		snd_printk("unable to register hardware dependant device %i:%i\n",
+		snd_printk(KERN_ERR "unable to register hardware dependant device %i:%i\n",
 			   hwdep->card->number, hwdep->device);
 		snd_hwdep_devices[idx] = NULL;
 		up(&register_mutex);
@@ -331,12 +331,12 @@
 	hwdep->ossreg = 0;
 	if (hwdep->oss_type >= 0) {
 		if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) {
-			snd_printk ("only hwdep device 0 can be registered as OSS direct FM device!\n");
+			snd_printk (KERN_WARNING "only hwdep device 0 can be registered as OSS direct FM device!\n");
 		} else {
 			if (snd_register_oss_device(hwdep->oss_type,
 						    hwdep->card, hwdep->device,
 						    &snd_hwdep_reg, hwdep->oss_dev) < 0) {
-				snd_printk("unable to register OSS compatibility device %i:%i\n",
+				snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
 					   hwdep->card->number, hwdep->device);
 			} else {
 				snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, hwdep->card->number, hwdep->name);
diff -Nru a/sound/core/info.c b/sound/core/info.c
--- a/sound/core/info.c	Tue Feb 26 11:57:59 2002
+++ b/sound/core/info.c	Tue Feb 26 11:57:59 2002
@@ -29,6 +29,7 @@
 #include <sound/info.h>
 #include <sound/version.h>
 #include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
 #ifdef CONFIG_DEVFS_FS
 #include <linux/devfs_fs_kernel.h>
 #endif
@@ -162,31 +163,40 @@
 {
 	snd_info_private_data_t *data;
 	struct snd_info_entry *entry;
+	int ret = -EINVAL;
 
 	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
 	entry = data->entry;
+	lock_kernel();
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
 		switch (orig) {
 		case 0:	/* SEEK_SET */
 			file->f_pos = offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			goto out;
 		case 1:	/* SEEK_CUR */
 			file->f_pos += offset;
-			return file->f_pos;
+			ret = file->f_pos;
+			goto out;
 		case 2:	/* SEEK_END */
 		default:
-			return -EINVAL;
+			goto out;
 		}
 		break;
 	case SNDRV_INFO_CONTENT_DATA:
-		if (entry->c.ops->llseek)
-			return entry->c.ops->llseek(entry,
+		if (entry->c.ops->llseek) {
+			ret = entry->c.ops->llseek(entry,
 						    data->file_private_data,
 						    file, offset, orig);
+			goto out;
+		}
 		break;
 	}
-	return -ENXIO;
+	ret = -ENXIO;
+out:
+	unlock_kernel();
+	return ret;
 }
 
 static ssize_t snd_info_entry_read(struct file *file, char *buffer,
@@ -420,7 +430,7 @@
 			if (entry->c.text.write) {
 				entry->c.text.write(entry, data->wbuffer);
 				if (data->wbuffer->error) {
-					snd_printk("data write error to %s (%i)\n",
+					snd_printk(KERN_WARNING "data write error to %s (%i)\n",
 						entry->name,
 						data->wbuffer->error);
 				}
diff -Nru a/sound/core/init.c b/sound/core/init.c
--- a/sound/core/init.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/init.c	Tue Feb 26 11:57:57 2002
@@ -74,7 +74,7 @@
 	if (idx < 0 || idx >= snd_ecards_limit) {
 		write_unlock(&snd_card_rwlock);
 		if (idx >= snd_ecards_limit)
-			snd_printk("card %i is out of range (0-%i)\n", idx, snd_ecards_limit-1);
+			snd_printk(KERN_ERR "card %i is out of range (0-%i)\n", idx, snd_ecards_limit-1);
 		goto __error;
 	}
 	snd_cards_lock |= 1 << idx;		/* lock it */
@@ -140,26 +140,26 @@
 		snd_mixer_oss_notify_callback(card, 1);
 #endif
 	if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) {
-		snd_printk("unable to free all devices (pre)\n");
+		snd_printk(KERN_ERR "unable to free all devices (pre)\n");
 		/* Fatal, but this situation should never occur */
 	}
 	if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) {
-		snd_printk("unable to free all devices (normal)\n");
+		snd_printk(KERN_ERR "unable to free all devices (normal)\n");
 		/* Fatal, but this situation should never occur */
 	}
 	if (snd_ctl_unregister(card) < 0) {
-		snd_printk("unable to unregister control minors\n");
+		snd_printk(KERN_ERR "unable to unregister control minors\n");
 		/* Not fatal error */
 	}
 	if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) {
-		snd_printk("unable to free all devices (post)\n");
+		snd_printk(KERN_ERR "unable to free all devices (post)\n");
 		/* Fatal, but this situation should never occur */
 	}
 	if (card->private_free)
 		card->private_free(card);
 	snd_info_free_entry(card->proc_id);
 	if (snd_info_card_unregister(card) < 0) {
-		snd_printk("unable to unregister card info\n");
+		snd_printk(KERN_WARNING "unable to unregister card info\n");
 		/* Not fatal error */
 	}
 	write_lock(&snd_card_rwlock);
diff -Nru a/sound/core/memory.c b/sound/core/memory.c
--- a/sound/core/memory.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/memory.c	Tue Feb 26 11:57:56 2002
@@ -68,28 +68,28 @@
 	struct list_head *head;
 	struct snd_alloc_track *t;
 	if (snd_alloc_pages > 0)
-		snd_printk("Not freed snd_alloc_pages = %li\n", snd_alloc_pages);
+		snd_printk(KERN_ERR "Not freed snd_alloc_pages = %li\n", snd_alloc_pages);
 	if (snd_alloc_kmalloc > 0)
-		snd_printk("Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
+		snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
 	if (snd_alloc_vmalloc > 0)
-		snd_printk("Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc);
+		snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc);
 	for (head = snd_alloc_kmalloc_list.prev;
 	     head != &snd_alloc_kmalloc_list; head = head->prev) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != KMALLOC_MAGIC) {
-			snd_printk("Corrupted kmalloc\n");
+			snd_printk(KERN_ERR "Corrupted kmalloc\n");
 			break;
 		}
-		snd_printk("kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
+		snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
 	}
 	for (head = snd_alloc_vmalloc_list.prev;
 	     head != &snd_alloc_vmalloc_list; head = head->prev) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != VMALLOC_MAGIC) {
-			snd_printk("Corrupted vmalloc\n");
+			snd_printk(KERN_ERR "Corrupted vmalloc\n");
 			break;
 		}
-		snd_printk("vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
+		snd_printk(KERN_ERR "vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
 	}
 }
 
@@ -125,12 +125,12 @@
 	unsigned long flags;
 	struct snd_alloc_track *t;
 	if (obj == NULL) {
-		snd_printk("null kfree (called from %p)\n", __builtin_return_address(0));
+		snd_printk(KERN_WARNING "null kfree (called from %p)\n", __builtin_return_address(0));
 		return;
 	}
 	t = snd_alloc_track_entry(obj);
 	if (t->magic != KMALLOC_MAGIC) {
-		snd_printk("bad kfree (called from %p)\n", __builtin_return_address(0));
+		snd_printk(KERN_WARNING "bad kfree (called from %p)\n", __builtin_return_address(0));
 		return;
 	}
 	spin_lock_irqsave(&snd_alloc_kmalloc_lock, flags);
@@ -166,7 +166,7 @@
 {
 	unsigned long *ptr = _ptr;
 	if (ptr == NULL) {
-		snd_printk("null snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
+		snd_printk(KERN_WARNING "null snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
 		return;
 	}
 	*--ptr = 0;
@@ -174,7 +174,7 @@
 		struct snd_alloc_track *t;
 		t = snd_alloc_track_entry(ptr);
 		if (t->magic != KMALLOC_MAGIC) {
-			snd_printk("bad snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
+			snd_printk(KERN_ERR "bad snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
 			return;
 		}
 	}
@@ -204,12 +204,12 @@
 {
 	struct snd_alloc_track *t;
 	if (obj == NULL) {
-		snd_printk("null vfree (called from %p)\n", __builtin_return_address(0));
+		snd_printk(KERN_WARNING "null vfree (called from %p)\n", __builtin_return_address(0));
 		return;
 	}
 	t = snd_alloc_track_entry(obj);
 	if (t->magic != VMALLOC_MAGIC) {
-		snd_printk("bad vfree (called from %p)\n", __builtin_return_address(0));
+		snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0));
 		return;
 	}
 	spin_lock(&snd_alloc_vmalloc_lock);
@@ -516,29 +516,36 @@
 /*
  * A dirty hack... when the kernel code is fixed this should be removed.
  *
- * since pci_alloc_consistent always tries GFP_ATOMIC when the requested
+ * since pci_alloc_consistent always tries GFP_DMA when the requested
  * pci memory region is below 32bit, it happens quite often that even
  * 2 order or pages cannot be allocated.
  *
- * so in the following, GFP_ATOMIC is used only when the first allocation
+ * so in the following, GFP_DMA is used only when the first allocation
  * doesn't match the requested region.
  */
+#ifdef __i386__
+#define get_phys_addr(x) virt_to_phys(x)
+#else /* ppc */
+#define get_phys_addr(x) virt_to_bus(x)
+#endif
 void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
 				    dma_addr_t *dma_handle)
 {
 	void *ret;
 	int gfp = GFP_ATOMIC;
 
+	if (hwdev == NULL)
+		gfp |= GFP_DMA;
 	ret = (void *)__get_free_pages(gfp, get_order(size));
 	if (ret) {
-		if (hwdev && ((virt_to_phys(ret) + size - 1) & ~hwdev->dma_mask)) {
+		if (hwdev && ((get_phys_addr(ret) + size - 1) & ~hwdev->dma_mask)) {
 			free_pages((unsigned long)ret, get_order(size));
 			ret = (void *)__get_free_pages(gfp | GFP_DMA, get_order(size));
 		}
 	}
 	if (ret) {
 		memset(ret, 0, size);
-		*dma_handle = virt_to_phys(ret);
+		*dma_handle = get_phys_addr(ret);
 	}
 	return ret;
 }
diff -Nru a/sound/core/misc.c b/sound/core/misc.c
--- a/sound/core/misc.c	Tue Feb 26 11:57:58 2002
+++ b/sound/core/misc.c	Tue Feb 26 11:57:58 2002
@@ -36,3 +36,18 @@
 	name[idx] = '\0';
 	return 0;
 }
+
+#ifdef CONFIG_SND_VERBOSE_PRINTK
+int snd_verbose_printk(const char *file, int line, const char *format)
+{
+	if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
+		char tmp[] = "<0>ALSA %s:%d: ";
+		tmp[1] = format[1];
+		printk("%sALSA %s:%d: ", tmp, file, line);
+		return 1;
+	} else {
+		printk("ALSA %s:%d: ", file, line);
+		return 0;
+	}
+}
+#endif
diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
--- a/sound/core/pcm_lib.c	Tue Feb 26 11:57:59 2002
+++ b/sound/core/pcm_lib.c	Tue Feb 26 11:57:59 2002
@@ -104,7 +104,7 @@
 		snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp);
 #ifdef CONFIG_SND_DEBUG
 	if (pos > runtime->buffer_size) {
-		snd_printk("BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
+		snd_printk(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
 	} else
 #endif
 	snd_runtime_check(pos <= runtime->buffer_size, return 0);
@@ -170,7 +170,7 @@
 		snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp);
 #ifdef CONFIG_SND_DEBUG
 	if (pos > runtime->buffer_size) {
-		snd_printk("BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
+		snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
 	} else
 #endif
 	snd_runtime_check(pos <= runtime->buffer_size, return 0);
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	Tue Feb 26 11:57:58 2002
+++ b/sound/core/pcm_native.c	Tue Feb 26 11:57:58 2002
@@ -837,6 +837,42 @@
 
 #endif /* CONFIG_PM */
 
+static int snd_pcm_xrun(snd_pcm_substream_t *substream)
+{
+	snd_card_t *card = substream->pcm->card;
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int result;
+
+	snd_power_lock(card);
+	spin_lock_irq(&runtime->lock);
+       _xrun_recovery:
+	switch (runtime->status->state) {
+	case SNDRV_PCM_STATE_XRUN:
+		result = 0;	/* already there */
+		break;
+	case SNDRV_PCM_STATE_RUNNING:
+		result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		break;
+	case SNDRV_PCM_STATE_SUSPENDED:
+		while (snd_power_get_state(card) != SNDRV_CTL_POWER_D0) {
+			if (substream->ffile->f_flags & O_NONBLOCK) {
+				result = -EAGAIN;
+				goto _end;
+			}
+			spin_unlock_irq(&runtime->lock);
+			snd_power_wait(card);
+			spin_lock_irq(&runtime->lock);
+		}
+		goto _xrun_recovery;
+	default:
+		result = -EBADFD;
+	}
+       _end:
+	spin_unlock_irq(&runtime->lock);
+	snd_power_unlock(card);
+	return result;
+}
+
 static inline int snd_pcm_pre_reset(snd_pcm_substream_t * substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1999,6 +2035,10 @@
 		return snd_pcm_link(substream, (long) arg);
 	case SNDRV_PCM_IOCTL_UNLINK:
 		return snd_pcm_unlink(substream);
+	case SNDRV_PCM_IOCTL_RESUME:
+		return snd_pcm_resume(substream);
+	case SNDRV_PCM_IOCTL_XRUN:
+		return snd_pcm_xrun(substream);
 	}
 	snd_printd("unknown ioctl = 0x%x\n", cmd);
 	return -ENOTTY;
@@ -2071,8 +2111,6 @@
 		return snd_pcm_playback_drop(substream);
 	case SNDRV_PCM_IOCTL_DELAY:
 		return snd_pcm_playback_delay(substream, (snd_pcm_sframes_t*) arg);
-	case SNDRV_PCM_IOCTL_RESUME:
-		return snd_pcm_resume(substream);
 	}
 	return snd_pcm_common_ioctl1(substream, cmd, arg);
 }
@@ -2136,8 +2174,6 @@
 		return snd_pcm_capture_drop(substream);
 	case SNDRV_PCM_IOCTL_DELAY:
 		return snd_pcm_capture_delay(substream, (snd_pcm_sframes_t*) arg);
-	case SNDRV_PCM_IOCTL_RESUME:
-		return snd_pcm_resume(substream);
 	}
 	return snd_pcm_common_ioctl1(substream, cmd, arg);
 }
diff -Nru a/sound/core/rawmidi.c b/sound/core/rawmidi.c
--- a/sound/core/rawmidi.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/rawmidi.c	Tue Feb 26 11:57:57 2002
@@ -769,7 +769,7 @@
 	}
 #ifdef CONFIG_SND_DEBUG
 	default:
-		snd_printk("rawmidi: unknown command = 0x%x\n", cmd);
+		snd_printk(KERN_WARNING "rawmidi: unknown command = 0x%x\n", cmd);
 #endif
 	}
 	return -ENOTTY;
@@ -1408,7 +1408,7 @@
 	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
 				       rmidi->card, rmidi->device,
 				       &snd_rawmidi_reg, name)) < 0) {
-		snd_printk("unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
+		snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
 		snd_rawmidi_devices[idx] = NULL;
 		up(&register_mutex);
 		return err;
@@ -1425,7 +1425,7 @@
 	if (rmidi->device == snd_midi_map[rmidi->card->number]) {
 		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
 					    rmidi->card, 0, &snd_rawmidi_reg, name) < 0) {
-			snd_printk("unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
+			snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
 		} else {
 			rmidi->ossreg++;
 			snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);
@@ -1434,7 +1434,7 @@
 	if (rmidi->device == snd_amidi_map[rmidi->card->number]) {
 		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
 					    rmidi->card, 1, &snd_rawmidi_reg, name) < 0) {
-			snd_printk("unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
+			snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
 		} else {
 			rmidi->ossreg++;
 		}
@@ -1532,11 +1532,11 @@
 	/* check device map table */
 	for (i = 0; i < SNDRV_CARDS; i++) {
 		if (snd_midi_map[i] < 0 || snd_midi_map[i] >= SNDRV_RAWMIDI_DEVICES) {
-			snd_printk("invalid midi_map[%d] = %d\n", i, snd_midi_map[i]);
+			snd_printk(KERN_ERR "invalid midi_map[%d] = %d\n", i, snd_midi_map[i]);
 			snd_midi_map[i] = 0;
 		}
 		if (snd_amidi_map[i] < 0 || snd_amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) {
-			snd_printk("invalid amidi_map[%d] = %d\n", i, snd_amidi_map[i]);
+			snd_printk(KERN_ERR "invalid amidi_map[%d] = %d\n", i, snd_amidi_map[i]);
 			snd_amidi_map[i] = 1;
 		}
 	}
diff -Nru a/sound/core/rtctimer.c b/sound/core/rtctimer.c
--- a/sound/core/rtctimer.c	Tue Feb 26 11:57:58 2002
+++ b/sound/core/rtctimer.c	Tue Feb 26 11:57:58 2002
@@ -156,13 +156,13 @@
 	snd_timer_t *timer;
 
 	if (rtctimer_freq < 2 || rtctimer_freq > 8192) {
-		snd_printk("rtctimer: invalid frequency %d\n", rtctimer_freq);
+		snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq);
 		return -EINVAL;
 	}
 	for (order = 1; rtctimer_freq > order; order <<= 1)
 		;
 	if (rtctimer_freq != order) {
-		snd_printk("rtctimer: invalid frequency %d\n", rtctimer_freq);
+		snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq);
 		return -EINVAL;
 	}
 
diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile
--- a/sound/core/seq/Makefile	Tue Feb 26 11:58:00 2002
+++ b/sound/core/seq/Makefile	Tue Feb 26 11:58:00 2002
@@ -32,6 +32,8 @@
 snd-seq-dummy-objs := seq_dummy.o
 snd-seq-virmidi-objs := seq_virmidi.o
 
+obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
+obj-$(CONFIG_SND_SEQUENCER_OSS) += snd-seq-midi-event.o
 obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
 
 # Toplevel Module Dependency
@@ -56,7 +58,7 @@
 obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_OPTI93X) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
-obj-$(CONFIG_SND_SB) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
+obj-$(CONFIG_SND_SB8) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_SB16) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_SBAWE) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o snd-seq-virmidi.o
 obj-$(CONFIG_SND_ES968) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
@@ -66,7 +68,7 @@
 obj-$(CONFIG_SND_CS4281) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_ENS1370) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
 obj-$(CONFIG_SND_ENS1371) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
-obj-$(CONFIG_SND_ES1938) += snd-seq-device.o snd-seq-midi-emul.o snd-seq.o snd-seq-instr.o
+obj-$(CONFIG_SND_ES1938) += snd-seq-device.o snd-seq-midi-emul.o snd-seq.o snd-seq-instr.o snd-seq-midi.o snd-seq-midi-event.o
 obj-$(CONFIG_SND_ES1968) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
 obj-$(CONFIG_SND_FM801) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 obj-$(CONFIG_SND_ICE1712) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
@@ -76,7 +78,7 @@
 obj-$(CONFIG_SND_CS46XX) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
 obj-$(CONFIG_SND_EMU10K1) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-virmidi.o
 obj-$(CONFIG_SND_TRIDENT) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
-obj-$(CONFIG_SND_YMFPCI) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
+obj-$(CONFIG_SND_YMFPCI) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
--- a/sound/core/seq/instr/Makefile	Tue Feb 26 11:57:58 2002
+++ b/sound/core/seq/instr/Makefile	Tue Feb 26 11:57:58 2002
@@ -33,7 +33,7 @@
 obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_OPTI93X) += snd-ainstr-fm.o
-obj-$(CONFIG_SND_SB) += snd-ainstr-fm.o
+obj-$(CONFIG_SND_SB8) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_SB16) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_SBAWE) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_WAVEFRONT) += snd-ainstr-fm.o
@@ -44,6 +44,7 @@
 obj-$(CONFIG_SND_FM801) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_SONICVIBES) += snd-ainstr-fm.o
 obj-$(CONFIG_SND_TRIDENT) += snd-ainstr-simple.o
+obj-$(CONFIG_SND_YMFPCI) += snd-ainstr-fm.o
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
--- a/sound/core/seq/oss/seq_oss.c	Tue Feb 26 11:57:58 2002
+++ b/sound/core/seq/oss/seq_oss.c	Tue Feb 26 11:57:58 2002
@@ -222,7 +222,7 @@
 					  NULL, 0,
 					  &seq_oss_reg,
 					  SNDRV_SEQ_OSS_DEVNAME)) < 0) {
-		snd_printk("can't register device seq\n");
+		snd_printk(KERN_ERR "can't register device seq\n");
 		up(&register_mutex);
 		return rc;
 	}
@@ -230,7 +230,7 @@
 					  NULL, 0,
 					  &seq_oss_reg,
 					  SNDRV_SEQ_OSS_DEVNAME)) < 0) {
-		snd_printk("can't register device music\n");
+		snd_printk(KERN_ERR "can't register device music\n");
 		snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
 		up(&register_mutex);
 		return rc;
@@ -245,11 +245,10 @@
 {
 	down(&register_mutex);
 	debug_printk(("device unregistered\n"));
-	if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
-		
-		snd_printk("error unregister device music\n");
+	if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)		
+		snd_printk(KERN_ERR "error unregister device music\n");
 	if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
-		snd_printk("error unregister device seq\n");
+		snd_printk(KERN_ERR "error unregister device seq\n");
 	up(&register_mutex);
 }
 
diff -Nru a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
--- a/sound/core/seq/oss/seq_oss_init.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/seq/oss/seq_oss_init.c	Tue Feb 26 11:57:56 2002
@@ -184,7 +184,7 @@
 	seq_oss_devinfo_t *dp;
 
 	if ((dp = snd_kcalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
-		snd_printk("can't malloc device info\n");
+		snd_printk(KERN_ERR "can't malloc device info\n");
 		return -ENOMEM;
 	}
 
@@ -193,7 +193,7 @@
 			break;
 	}
 	if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
-		snd_printk("too many applications\n");
+		snd_printk(KERN_ERR "too many applications\n");
 		return -ENOMEM;
 	}
 
@@ -209,14 +209,14 @@
 	snd_seq_oss_midi_setup(dp);
 
 	if (dp->synth_opened == 0 && dp->max_mididev == 0) {
-		snd_printk("no device found\n");
+		snd_printk(KERN_ERR "no device found\n");
 		kfree(dp);
 		return -ENODEV;
 	}
 
 	/* create port */
 	if ((rc = create_port(dp)) < 0) {
-		snd_printk("can't create port\n");
+		snd_printk(KERN_ERR "can't create port\n");
 		free_devinfo(dp);
 		return rc;
 	}
@@ -259,7 +259,7 @@
 
 	/* initialize timer */
 	if ((dp->timer = snd_seq_oss_timer_new(dp)) == NULL) {
-		snd_printk("can't alloc timer\n");
+		snd_printk(KERN_ERR "can't alloc timer\n");
 		delete_seq_queue(dp);
 		delete_port(dp);
 		return -ENOMEM;
diff -Nru a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
--- a/sound/core/seq/oss/seq_oss_midi.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/seq/oss/seq_oss_midi.c	Tue Feb 26 11:57:56 2002
@@ -173,7 +173,7 @@
 	 * allocate midi info record
 	 */
 	if ((mdev = snd_kcalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
-		snd_printk("can't malloc midi info\n");
+		snd_printk(KERN_ERR "can't malloc midi info\n");
 		return -ENOMEM;
 	}
 
@@ -190,7 +190,7 @@
 
 	/* create MIDI coder */
 	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
-		snd_printk("can't malloc midi coder\n");
+		snd_printk(KERN_ERR "can't malloc midi coder\n");
 		kfree(mdev);
 		return -ENOMEM;
 	}
diff -Nru a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
--- a/sound/core/seq/oss/seq_oss_readq.c	Tue Feb 26 11:57:58 2002
+++ b/sound/core/seq/oss/seq_oss_readq.c	Tue Feb 26 11:57:58 2002
@@ -47,12 +47,12 @@
 	seq_oss_readq_t *q;
 
 	if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
-		snd_printk("can't malloc read queue\n");
+		snd_printk(KERN_ERR "can't malloc read queue\n");
 		return NULL;
 	}
 
 	if ((q->q = snd_kcalloc(sizeof(evrec_t) * maxlen, GFP_KERNEL)) == NULL) {
-		snd_printk("can't malloc read queue buffer\n");
+		snd_printk(KERN_ERR "can't malloc read queue buffer\n");
 		kfree(q);
 		return NULL;
 	}
diff -Nru a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
--- a/sound/core/seq/oss/seq_oss_synth.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/seq/oss/seq_oss_synth.c	Tue Feb 26 11:57:56 2002
@@ -111,7 +111,7 @@
 	unsigned long flags;
 
 	if ((rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
-		snd_printk("can't malloc synth info\n");
+		snd_printk(KERN_ERR "can't malloc synth info\n");
 		return -ENOMEM;
 	}
 	rec->seq_device = -1;
@@ -136,7 +136,7 @@
 	if (i >= max_synth_devs) {
 		if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
 			spin_unlock_irqrestore(&register_lock, flags);
-			snd_printk("no more synth slot\n");
+			snd_printk(KERN_ERR "no more synth slot\n");
 			kfree(rec);
 			return -ENOMEM;
 		}
@@ -165,7 +165,7 @@
 	}
 	if (index >= max_synth_devs) {
 		spin_unlock_irqrestore(&register_lock, flags);
-		snd_printk("can't unregister synth\n");
+		snd_printk(KERN_ERR "can't unregister synth\n");
 		return -EINVAL;
 	}
 	synth_devs[index] = NULL;
diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
--- a/sound/core/seq/seq_clientmgr.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/seq/seq_clientmgr.c	Tue Feb 26 11:57:57 2002
@@ -265,7 +265,7 @@
 	down(&register_mutex);
 	switch (client->type) {
 	case NO_CLIENT:
-		snd_printk("Seq: Trying to free unused client %d\n", client->number);
+		snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", client->number);
 		break;
 	case USER_CLIENT:
 	case KERNEL_CLIENT:
@@ -274,7 +274,7 @@
 		break;
 
 	default:
-		snd_printk("Seq: Trying to free client %d with undefined type = %d\n", client->number, client->type);
+		snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", client->number, client->type);
 	}
 	up(&register_mutex);
 
diff -Nru a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
--- a/sound/core/seq/seq_device.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/seq/seq_device.c	Tue Feb 26 11:57:57 2002
@@ -295,7 +295,7 @@
 	if (ops == NULL)
 		return -ENOMEM;
 	if (ops->driver & DRIVER_LOADED) {
-		snd_printk("driver_register: driver '%s' already exists\n", id);
+		snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id);
 		unlock_driver(ops);
 		return -EBUSY;
 	}
@@ -363,7 +363,7 @@
 		return -ENXIO;
 	if (! (ops->driver & DRIVER_LOADED) ||
 	    (ops->driver & DRIVER_LOCKED)) {
-		snd_printk("driver_unregister: cannot unload driver '%s': status=%x\n", id, ops->driver);
+		snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n", id, ops->driver);
 		unlock_driver(ops);
 		return -EBUSY;
 	}
@@ -378,7 +378,7 @@
 
 	ops->driver = 0;
 	if (ops->num_init_devices > 0)
-		snd_printk("free_driver: init_devices > 0!! (%d)\n", ops->num_init_devices);
+		snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n", ops->num_init_devices);
 	up(&ops->reg_mutex);
 
 	unlock_driver(ops);
@@ -423,15 +423,14 @@
 	if (dev->status != SNDRV_SEQ_DEVICE_FREE)
 		return 0; /* already initialized */
 	if (ops->argsize != dev->argsize) {
-		snd_printk("incompatible device '%s' for plug-in '%s'\n", dev->name, ops->id);
-printk(" %d %d\n", ops->argsize, dev->argsize);
+		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize);
 		return -EINVAL;
 	}
 	if (ops->ops.init_device(dev) >= 0) {
 		dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
 		ops->num_init_devices++;
 	} else {
-		snd_printk("init_device failed: %s: %s\n", dev->name, dev->id);
+		snd_printk(KERN_ERR "init_device failed: %s: %s\n", dev->name, dev->id);
 	}
 
 	return 0;
@@ -449,7 +448,7 @@
 	if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
 		return 0; /* not registered */
 	if (ops->argsize != dev->argsize) {
-		snd_printk("incompatible device '%s' for plug-in '%s'\n", dev->name, ops->id);
+		snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize);
 		return -EINVAL;
 	}
 	if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
@@ -457,7 +456,7 @@
 		dev->driver_data = NULL;
 		ops->num_init_devices--;
 	} else {
-		snd_printk("free_device failed: %s: %s\n", dev->name, dev->id);
+		snd_printk(KERN_ERR "free_device failed: %s: %s\n", dev->name, dev->id);
 	}
 
 	return 0;
@@ -517,7 +516,7 @@
 	remove_drivers();
 	snd_info_unregister(info_entry);
 	if (num_ops)
-		snd_printk("drivers not released (%d)\n", num_ops);
+		snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);
 }
 
 module_init(alsa_seq_device_init)
diff -Nru a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
--- a/sound/core/seq/seq_dummy.c	Tue Feb 26 11:57:59 2002
+++ b/sound/core/seq/seq_dummy.c	Tue Feb 26 11:57:59 2002
@@ -206,7 +206,7 @@
 	int i;
 
 	if (ports < 1) {
-		snd_printk("invalid number of ports %d\n", ports);
+		snd_printk(KERN_ERR "invalid number of ports %d\n", ports);
 		return -EINVAL;
 	}
 
diff -Nru a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
--- a/sound/core/seq/seq_instr.c	Tue Feb 26 11:57:59 2002
+++ b/sound/core/seq/seq_instr.c	Tue Feb 26 11:57:59 2002
@@ -132,7 +132,7 @@
 			}				
 			spin_unlock_irqrestore(&list->lock, flags);
 			if (snd_seq_instr_free(instr, 0)<0)
-				snd_printk("instrument free problem\n");
+				snd_printk(KERN_WARNING "instrument free problem\n");
 		}
 		while ((cluster = list->chash[idx]) != NULL) {
 			list->chash[idx] = cluster->next;
@@ -221,7 +221,7 @@
 				schedule_timeout(1);
 			}				
 			if (snd_seq_instr_free(instr, atomic)<0)
-				snd_printk("instrument free problem\n");
+				snd_printk(KERN_WARNING "instrument free problem\n");
 			instr = next;
 		}
 	}
@@ -324,7 +324,7 @@
 		return;
 	spin_lock_irqsave(&list->lock, flags);
 	if (instr->use <= 0) {
-		snd_printk("free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);
+		snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);
 	} else {
 		instr->use--;
 	}
diff -Nru a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
--- a/sound/core/seq/seq_lock.c	Tue Feb 26 11:57:59 2002
+++ b/sound/core/seq/seq_lock.c	Tue Feb 26 11:57:59 2002
@@ -68,12 +68,12 @@
 	int max_count = 5 * HZ;
 
 	if (atomic_read(lockp) < 0) {
-		printk("seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
+		printk(KERN_WARNING "seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
 		return;
 	}
 	while (atomic_read(lockp) > 0) {
 		if (max_count == 0) {
-			snd_printk("seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
+			snd_printk(KERN_WARNING "seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
 			break;
 		}
 		set_current_state(TASK_UNINTERRUPTIBLE);
diff -Nru a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
--- a/sound/core/seq/seq_memory.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/seq/seq_memory.c	Tue Feb 26 11:57:57 2002
@@ -423,7 +423,7 @@
 
 	while (atomic_read(&pool->counter) > 0) {
 		if (max_count == 0) {
-			snd_printk("snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
+			snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
 			break;
 		}
 		set_current_state(TASK_UNINTERRUPTIBLE);
diff -Nru a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
--- a/sound/core/seq/seq_ports.c	Tue Feb 26 11:58:00 2002
+++ b/sound/core/seq/seq_ports.c	Tue Feb 26 11:58:00 2002
@@ -143,7 +143,7 @@
 	snd_assert(client, return NULL);
 
 	if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) {
-		snd_printk("too many ports for client %d\n", client->number);
+		snd_printk(KERN_WARNING "too many ports for client %d\n", client->number);
 		return NULL;
 	}
 
diff -Nru a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
--- a/sound/core/seq/seq_timer.c	Tue Feb 26 11:58:00 2002
+++ b/sound/core/seq/seq_timer.c	Tue Feb 26 11:58:00 2002
@@ -285,7 +285,7 @@
 				t = snd_timer_open(str, &tid, q->queue);
 			}
 			if (t == NULL) {
-				snd_printk("fatal error: cannot create timer\n");
+				snd_printk(KERN_ERR "fatal error: cannot create timer\n");
 				return -ENODEV;
 			}
 		}
diff -Nru a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
--- a/sound/core/seq/seq_virmidi.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/seq/seq_virmidi.c	Tue Feb 26 11:57:56 2002
@@ -431,7 +431,7 @@
 		/* should check presence of port more strictly.. */
 		break;
 	default:
-		snd_printk("seq_mode is not set: %d\n", rdev->seq_mode);
+		snd_printk(KERN_ERR "seq_mode is not set: %d\n", rdev->seq_mode);
 		return -EINVAL;
 	}
 	return 0;
diff -Nru a/sound/core/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	Tue Feb 26 11:57:57 2002
+++ b/sound/core/sound.c	Tue Feb 26 11:57:57 2002
@@ -319,7 +319,7 @@
 #else
 	if (register_chrdev(snd_major, "alsa", &snd_fops)) {
 #endif
-		snd_printk("unable to register native major device number %d\n", snd_major);
+		snd_printk(KERN_ERR "unable to register native major device number %d\n", snd_major);
 #ifdef CONFIG_SND_OSSEMUL
 		snd_oss_cleanup_module();
 #endif
@@ -349,7 +349,7 @@
 	}
 #endif
 #ifndef MODULE
-	printk("Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
+	printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
 #endif
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
 	pm_init();
@@ -391,7 +391,7 @@
 #else
 	if (unregister_chrdev(snd_major, "alsa") != 0)
 #endif
-		snd_printk("unable to unregister major device number %d\n", snd_major);
+		snd_printk(KERN_ERR "unable to unregister major device number %d\n", snd_major);
 #ifdef CONFIG_DEVFS_FS
 	devfs_unregister(devfs_handle);
 #endif
@@ -455,7 +455,7 @@
 EXPORT_SYMBOL(snd_device_register);
 EXPORT_SYMBOL(snd_device_free);
 EXPORT_SYMBOL(snd_device_free_all);
-  /* misc.c */
+  /* isadma.c */
 #ifdef CONFIG_ISA
 EXPORT_SYMBOL(snd_dma_program);
 EXPORT_SYMBOL(snd_dma_disable);
@@ -494,38 +494,10 @@
 EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
   /* misc.c */
 EXPORT_SYMBOL(snd_task_name);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-EXPORT_SYMBOL(try_inc_mod_count);
-EXPORT_SYMBOL(snd_compat_mem_region);
-EXPORT_SYMBOL(snd_compat_request_region);
-EXPORT_SYMBOL(snd_compat_release_resource);
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_PCI)
-EXPORT_SYMBOL(snd_pci_compat_match_device);
-EXPORT_SYMBOL(snd_pci_compat_register_driver);
-EXPORT_SYMBOL(snd_pci_compat_unregister_driver);
-EXPORT_SYMBOL(snd_pci_compat_get_size);
-EXPORT_SYMBOL(snd_pci_compat_get_flags);
-EXPORT_SYMBOL(snd_pci_compat_set_power_state);
-EXPORT_SYMBOL(snd_pci_compat_enable_device);
-EXPORT_SYMBOL(snd_pci_compat_find_capability);
-EXPORT_SYMBOL(snd_pci_compat_alloc_consistent);
-EXPORT_SYMBOL(snd_pci_compat_free_consistent);
-EXPORT_SYMBOL(snd_pci_compat_dma_supported);
-EXPORT_SYMBOL(snd_pci_compat_get_dma_mask);
-EXPORT_SYMBOL(snd_pci_compat_set_dma_mask);
-EXPORT_SYMBOL(snd_pci_compat_get_driver_data);
-EXPORT_SYMBOL(snd_pci_compat_set_driver_data);
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_PM)
-EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
-EXPORT_SYMBOL(pm_send);
+#ifdef CONFIG_SND_VERBOSE_PRINTK
+EXPORT_SYMBOL(snd_verbose_printk);
 #endif
   /* wrappers */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-EXPORT_SYMBOL(snd_wrapper_kill_fasync);
-#endif
 #ifdef CONFIG_SND_DEBUG_MEMORY
 EXPORT_SYMBOL(snd_wrapper_kmalloc);
 EXPORT_SYMBOL(snd_wrapper_kfree);
diff -Nru a/sound/core/timer.c b/sound/core/timer.c
--- a/sound/core/timer.c	Tue Feb 26 11:57:56 2002
+++ b/sound/core/timer.c	Tue Feb 26 11:57:56 2002
@@ -681,7 +681,7 @@
 	snd_assert(timer != NULL, return -ENXIO);
 	down(&register_mutex);
 	if (! list_empty(&timer->open_list_head)) {
-		snd_printk("timer 0x%lx is busy?\n", (long)timer);
+		snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer);
 		list_for_each_safe(p, n, &timer->open_list_head) {
 			list_del_init(p);
 			ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, open_list);
@@ -1318,10 +1318,10 @@
 	}
 	snd_timer_proc_entry = entry;
 	if ((err = snd_timer_register_system()) < 0)
-		snd_printk("unable to register system timer (%i)\n", err);
+		snd_printk(KERN_ERR "unable to register system timer (%i)\n", err);
 	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER,
 					NULL, 0, &snd_timer_reg, "timer"))<0)
-		snd_printk("unable to register timer device (%i)\n", err);
+		snd_printk(KERN_ERR "unable to register timer device (%i)\n", err);
 	return 0;
 }
 
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c	Tue Feb 26 11:57:58 2002
+++ b/sound/drivers/dummy.c	Tue Feb 26 11:57:58 2002
@@ -562,7 +562,7 @@
 	for (dev = cards = 0; dev < SNDRV_CARDS && snd_enable[dev]; dev++) {
 		if (snd_card_dummy_probe(dev) < 0) {
 #ifdef MODULE
-			snd_printk("Dummy soundcard #%i not found or device busy\n", dev + 1);
+			printk(KERN_ERR "Dummy soundcard #%i not found or device busy\n", dev + 1);
 #endif
 			break;
 		}
@@ -570,7 +570,7 @@
 	}
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Dummy soundcard not found or device busy\n");
+		printk(KERN_ERR "Dummy soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
--- a/sound/drivers/mpu401/mpu401.c	Tue Feb 26 11:58:00 2002
+++ b/sound/drivers/mpu401/mpu401.c	Tue Feb 26 11:58:00 2002
@@ -81,7 +81,7 @@
 	if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 				snd_port[dev], 0,
 				snd_irq[dev], snd_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
-		snd_printk("MPU401 not detected at 0x%lx\n", snd_port[dev]);
+		printk(KERN_ERR "MPU401 not detected at 0x%lx\n", snd_port[dev]);
 		snd_card_free(card);
 		return -ENODEV;
 	}
@@ -113,7 +113,7 @@
 	}
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("MPU-401 device not found or device busy\n");
+		printk(KERN_ERR "MPU-401 device not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
--- a/sound/drivers/mtpav.c	Tue Feb 26 11:57:58 2002
+++ b/sound/drivers/mtpav.c	Tue Feb 26 11:57:58 2002
@@ -761,7 +761,7 @@
 
 	snd_mtpav_portscan(mtp_card);
 
-	snd_printk("Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", snd_irq, snd_port);
+	printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", snd_irq, snd_port);
 
 	return 0;
 
diff -Nru a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
--- a/sound/drivers/serial-u16550.c	Tue Feb 26 11:57:57 2002
+++ b/sound/drivers/serial-u16550.c	Tue Feb 26 11:57:57 2002
@@ -891,7 +891,7 @@
 
 	if ((err = snd_uart16550_detect(snd_port[dev])) <= 0) {
 		snd_card_free(card);
-		snd_printk("no UART detected at 0x%lx\n", (long)snd_port[dev]);
+		printk(KERN_ERR "no UART detected at 0x%lx\n", (long)snd_port[dev]);
 		return err;
 	}
 
@@ -940,7 +940,7 @@
 
 	if (cards == 0) {
 #ifdef MODULE
-		snd_printk("serial midi soundcard not found or device busy\n");
+		printk(KERN_ERR "serial midi soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
--- a/sound/drivers/virmidi.c	Tue Feb 26 11:57:58 2002
+++ b/sound/drivers/virmidi.c	Tue Feb 26 11:57:58 2002
@@ -136,7 +136,7 @@
 	for (dev = cards = 0; dev < SNDRV_CARDS && snd_enable[dev]; dev++) {
 		if (snd_card_virmidi_probe(dev) < 0) {
 #ifdef MODULE
-			snd_printk("Card-VirMIDI #%i not found or device busy\n", dev + 1);
+			printk(KERN_ERR "Card-VirMIDI #%i not found or device busy\n", dev + 1);
 #endif
 			break;
 		}
@@ -144,7 +144,7 @@
 	}
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Card-VirMIDI soundcard not found or device busy\n");
+		printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/Config.in b/sound/isa/Config.in
--- a/sound/isa/Config.in	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/Config.in	Tue Feb 26 11:57:57 2002
@@ -3,13 +3,13 @@
 mainmenu_option next_comment
 comment 'ISA devices'
 
-dep_tristate 'Analog Devices SoundPort AD1816A' CONFIG_SND_AD1816A $CONFIG_SND
+dep_tristate 'Analog Devices SoundPort AD1816A' CONFIG_SND_AD1816A $CONFIG_SND $CONFIG_ISAPNP
 dep_tristate 'Generic AD1848/CS4248 driver' CONFIG_SND_AD1848 $CONFIG_SND
 dep_tristate 'Generic Cirrus Logic CS4231 driver' CONFIG_SND_CS4231 $CONFIG_SND
 dep_tristate 'Generic Cirrus Logic CS4232 driver' CONFIG_SND_CS4232 $CONFIG_SND
 dep_tristate 'Generic Cirrus Logic CS4236+ driver' CONFIG_SND_CS4236 $CONFIG_SND
-dep_tristate 'Generic ESS ES968 driver' CONFIG_SND_ES968 $CONFIG_SND
-dep_tristate 'Generic ESS ES1688 driver' CONFIG_SND_ES1688 $CONFIG_SND
+dep_tristate 'Generic ESS ES968 driver' CONFIG_SND_ES968 $CONFIG_SND $CONFIG_ISAPNP
+dep_tristate 'Generic ESS ES688/ES1688 driver' CONFIG_SND_ES1688 $CONFIG_SND
 dep_tristate 'Generic ESS ES18xx driver' CONFIG_SND_ES18XX $CONFIG_SND
 dep_tristate 'Gravis UltraSound Classic' CONFIG_SND_GUSCLASSIC $CONFIG_SND
 dep_tristate 'Gravis UltraSound Extreme' CONFIG_SND_GUSEXTREME $CONFIG_SND
@@ -26,10 +26,10 @@
   bool '  Sound Blaster 16/AWE CSP support' CONFIG_SND_SB16_CSP
 fi
 dep_tristate 'Turtle Beach Maui,Tropez,Tropez+ (Wavefront)' CONFIG_SND_WAVEFRONT $CONFIG_SND
-dep_tristate 'Avance Logic ALS100/ALS120' CONFIG_SND_ALS100 $CONFIG_SND
-dep_tristate 'Aztech Systems AZT2320' CONFIG_SND_AZT2320 $CONFIG_SND
+dep_tristate 'Avance Logic ALS100/ALS120' CONFIG_SND_ALS100 $CONFIG_SND $CONFIG_ISAPNP
+dep_tristate 'Aztech Systems AZT2320' CONFIG_SND_AZT2320 $CONFIG_SND $CONFIG_ISAPNP
 dep_tristate 'C-Media CMI8330' CONFIG_SND_CMI8330 $CONFIG_SND
-dep_tristate 'Diamond Technologies DT-0197H' CONFIG_SND_DT0197H $CONFIG_SND
+dep_tristate 'Diamond Technologies DT-0197H' CONFIG_SND_DT0197H $CONFIG_SND $CONFIG_ISAPNP
 dep_tristate 'Yamaha OPL3-SA2/SA3' CONFIG_SND_OPL3SA2 $CONFIG_SND
 dep_tristate 'Aztech Sound Galaxy' CONFIG_SND_SGALAXY $CONFIG_SND
 
diff -Nru a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
--- a/sound/isa/ad1816a/ad1816a.c	Tue Feb 26 11:57:58 2002
+++ b/sound/isa/ad1816a/ad1816a.c	Tue Feb 26 11:57:58 2002
@@ -36,6 +36,8 @@
 
 #define chip_t ad1816a_t
 
+#define PFX "ad1816a: "
+
 EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("AD1816A, AD1815");
@@ -176,7 +178,7 @@
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 
 	if (pdev->activate(pdev) < 0) {
-		snd_printk("AUDIO isapnp configure failure\n");
+		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
 		return -EBUSY;
 	}
 
@@ -202,7 +204,7 @@
 
 	if (pdev->activate(pdev) < 0) {
 		/* not fatal error */
-		snd_printk("MPU-401 isapnp configure failure\n");
+		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
 		snd_mpu_port[dev] = -1;
 		acard->devmpu = NULL;
 	} else {
@@ -257,7 +259,7 @@
 		return error;
 	}
 #else
-	snd_printk("you have to enable ISA PnP support.\n");
+	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
 	return -ENOSYS;
 #endif	/* __ISAPNP__ */
 
@@ -284,14 +286,14 @@
 		if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 					snd_mpu_port[dev], 0, snd_mpu_irq[dev], SA_INTERRUPT,
 					NULL) < 0)
-			snd_printk("no MPU-401 device at 0x%lx.\n", snd_mpu_port[dev]);
+			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", snd_mpu_port[dev]);
 	}
 
 	if (snd_fm_port[dev] > 0) {
 		if (snd_opl3_create(card,
 				    snd_fm_port[dev], snd_fm_port[dev] + 2,
 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx.\n", snd_fm_port[dev], snd_fm_port[dev] + 2);
+			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", snd_fm_port[dev], snd_fm_port[dev] + 2);
 		} else {
 			if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
 				snd_card_free(card);
@@ -346,11 +348,11 @@
 #ifdef __ISAPNP__
 	cards += isapnp_probe_cards(snd_ad1816a_pnpids, snd_ad1816a_isapnp_detect);
 #else
-	snd_printk("you have to enable ISA PnP support.\n");
+	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
 #endif
 #ifdef MODULE
 	if (!cards)
-		snd_printk("no AD1816A based soundcards found.\n");
+		printk(KERN_ERR "no AD1816A based soundcards found.\n");
 #endif	/* MODULE */
 	return cards ? 0 : -ENODEV;
 }
diff -Nru a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
--- a/sound/isa/ad1848/ad1848.c	Tue Feb 26 11:57:56 2002
+++ b/sound/isa/ad1848/ad1848.c	Tue Feb 26 11:57:56 2002
@@ -135,7 +135,7 @@
 
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("AD1848 soundcard not found or device busy\n");
+		printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c
--- a/sound/isa/als100.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/als100.c	Tue Feb 26 11:57:57 2002
@@ -39,6 +39,8 @@
 
 #define chip_t sb_t
 
+#define PFX "als100: "
+
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
@@ -178,7 +180,7 @@
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("AUDIO isapnp configure failure\n");
+		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
 		return -EBUSY;
 	}
 
@@ -201,7 +203,7 @@
 			1);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("MPU-401 isapnp configure failure\n");
+		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
 		snd_mpu_port[dev] = -1;
 		acard->devmpu = NULL;
 	} else {
@@ -219,7 +221,7 @@
 		isapnp_resource_change(&pdev->resource[0], snd_fm_port[dev], 4);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("OPL isapnp configure failure\n");
+		printk(KERN_ERR PFX "OPL isapnp configure failure\n");
 		snd_fm_port[dev] = -1;
 		acard->devopl = NULL;
 	} else {
@@ -277,7 +279,7 @@
 		return error;
 	}
 #else
-	snd_printk("you have to enable PnP support ...\n");
+	printk(KERN_ERR PFX "you have to enable PnP support ...\n");
 	snd_card_free(card);
 	return -ENOSYS;
 #endif	/* __ISAPNP__ */
@@ -307,14 +309,14 @@
 					snd_mpu_port[dev], 0, 
 					snd_mpu_irq[dev], SA_INTERRUPT,
 					NULL) < 0)
-			snd_printk("no MPU-401 device at 0x%lx\n", snd_mpu_port[dev]);
+			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", snd_mpu_port[dev]);
 	}
 
 	if (snd_fm_port[dev] > 0) {
 		if (snd_opl3_create(card,
 				    snd_fm_port[dev], snd_fm_port[dev] + 2,
 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx\n",
+			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
 				snd_fm_port[dev], snd_fm_port[dev] + 2);
 		} else {
 			if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
@@ -370,11 +372,11 @@
 #ifdef __ISAPNP__
 	cards += isapnp_probe_cards(snd_als100_pnpids, snd_als100_isapnp_detect);
 #else
-	snd_printk("you have to enable ISA PnP support.\n");
+	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
 #endif
 #ifdef MODULE
 	if (!cards)
-		snd_printk("no ALS100 based soundcards found\n");
+		printk(KERN_ERR "no ALS100 based soundcards found\n");
 #endif
 	return cards ? 0 : -ENODEV;
 }
diff -Nru a/sound/isa/azt2320.c b/sound/isa/azt2320.c
--- a/sound/isa/azt2320.c	Tue Feb 26 11:58:00 2002
+++ b/sound/isa/azt2320.c	Tue Feb 26 11:58:00 2002
@@ -50,6 +50,8 @@
 
 #define chip_t cs4231_t
 
+#define PFX "azt2320: "
+
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
@@ -191,7 +193,7 @@
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 
 	if (pdev->activate(pdev) < 0) {
-		snd_printk("AUDIO isapnp configure failure\n");
+		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
 		return -EBUSY;
 	}
 
@@ -217,7 +219,7 @@
 
 	if (pdev->activate(pdev) < 0) {
 		/* not fatal error */
-		snd_printk("MPU-401 isapnp configure failure\n");
+		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
 		snd_mpu_port[dev] = -1;
 		acard->devmpu = NULL;
 	} else {
@@ -329,7 +331,7 @@
 				snd_mpu_port[dev], 0,
 				snd_mpu_irq[dev], SA_INTERRUPT,
 				NULL) < 0)
-			snd_printk("no MPU-401 device at 0x%lx\n",
+			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n",
 				snd_mpu_port[dev]);
 	}
 
@@ -337,7 +339,7 @@
 		if (snd_opl3_create(card,
 				    snd_fm_port[dev], snd_fm_port[dev] + 2,
 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx\n",
+			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
 				snd_fm_port[dev], snd_fm_port[dev] + 2);
 		} else {
 			if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
@@ -393,11 +395,11 @@
 #ifdef __ISAPNP__
 	cards += isapnp_probe_cards(snd_azt2320_pnpids, snd_azt2320_isapnp_detect);
 #else
-	snd_printk("you have to enable ISA PnP support.\n");
+	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
 #endif
 #ifdef MODULE
 	if (!cards)
-		snd_printk("no AZT2320 based soundcards found\n");
+		printk(KERN_ERR "no AZT2320 based soundcards found\n");
 #endif
 	return cards ? 0 : -ENODEV;
 }
diff -Nru a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
--- a/sound/isa/cmi8330.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/cmi8330.c	Tue Feb 26 11:57:57 2002
@@ -488,7 +488,7 @@
 
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("CMI8330 not found or device busy\n");
+		printk(KERN_ERR "CMI8330 not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
--- a/sound/isa/cs423x/cs4231.c	Tue Feb 26 11:57:56 2002
+++ b/sound/isa/cs423x/cs4231.c	Tue Feb 26 11:57:56 2002
@@ -135,7 +135,7 @@
 					snd_mpu_port[dev], 0,
 					snd_mpu_irq[dev], SA_INTERRUPT,
 					NULL) < 0)
-			snd_printk("MPU401 not detected\n");
+			printk(KERN_ERR "cs4231: MPU401 not detected\n");
 	}
 	strcpy(card->driver, "CS4231");
 	strcpy(card->shortname, pcm->name);
@@ -161,7 +161,7 @@
 	}
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("CS4231 soundcard not found or device busy\n");
+		printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/cs423x/cs4231_lib.c	Tue Feb 26 11:57:57 2002
@@ -1335,7 +1335,7 @@
 	}
 	if (chip->res_cport) {
 		release_resource(chip->res_cport);
-		kfree_nocheck(chip->res_port);
+		kfree_nocheck(chip->res_cport);
 	}
 	if (chip->irq >= 0) {
 		disable_irq(chip->irq);
diff -Nru a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
--- a/sound/isa/cs423x/cs4236.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/cs423x/cs4236.c	Tue Feb 26 11:57:57 2002
@@ -309,7 +309,7 @@
 	if (snd_dma2[dev] != SNDRV_AUTO_DMA)
 		isapnp_resource_change(&pdev->dma_resource[1], snd_dma2[dev] < 0 ? 4 : snd_dma2[dev], 1);
 	if (pdev->activate(pdev)<0) {
-		snd_printk(IDENT " isapnp configure failed for WSS (out of resources?)\n");
+		printk(KERN_ERR IDENT " isapnp configure failed for WSS (out of resources?)\n");
 		return -EBUSY;
 	}
 	snd_port[dev] = pdev->resource[0].start;
@@ -331,7 +331,7 @@
 	if (snd_cport[dev] != SNDRV_AUTO_PORT)
 		isapnp_resource_change(&pdev->resource[0], snd_cport[dev], 8);
 	if (pdev->activate(pdev)<0) {
-		snd_printk(IDENT " isapnp configure failed for control (out of resources?)\n");
+		printk(KERN_ERR IDENT " isapnp configure failed for control (out of resources?)\n");
 		acard->wss->deactivate(acard->wss);
 		return -EBUSY;
 	}
@@ -352,7 +352,7 @@
 		if (pdev->activate(pdev)<0) {
 			snd_mpu_port[dev] = SNDRV_AUTO_PORT;
 			snd_mpu_irq[dev] = SNDRV_AUTO_IRQ;
-			snd_printk(IDENT " isapnp configure failed for MPU (out of resources?)\n");
+			printk(KERN_ERR IDENT " isapnp configure failed for MPU (out of resources?)\n");
 		} else {
 			snd_mpu_port[dev] = pdev->resource[0].start;
 			if (pdev->irq_resource[0].flags & IORESOURCE_IRQ) {
@@ -429,7 +429,7 @@
 	card->private_free = snd_card_cs4236_free;
 #ifdef __ISAPNP__
 	if (snd_isapnp[dev] && (err = snd_card_cs4236_isapnp(dev, acard))<0) {
-		snd_printk("isapnp detection failed and probing for " IDENT " is not supported\n");
+		printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n");
 		snd_card_free(card);
 		return -ENXIO;
 	}
@@ -442,7 +442,7 @@
 		snd_sb_port[dev] = SNDRV_AUTO_PORT;
 	if (snd_sb_port[dev] != SNDRV_AUTO_PORT)
 		if ((acard->res_sb_port = request_region(snd_sb_port[dev], 16, IDENT " SB")) == NULL) {
-			snd_printk("unable to register SB port at 0x%lx\n", snd_sb_port[dev]);
+			printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", snd_sb_port[dev]);
 			snd_card_free(card);
 			return -ENOMEM;
 		}
@@ -501,7 +501,7 @@
 		if (snd_opl3_create(card,
 				    snd_fm_port[dev], snd_fm_port[dev] + 2,
 				    OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
-			snd_printk(IDENT ": OPL3 not detected\n");
+			printk(KERN_ERR IDENT ": OPL3 not detected\n");
 		} else {
 			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
 				snd_card_free(card);
@@ -515,7 +515,7 @@
 					snd_mpu_port[dev], 0,
 					snd_mpu_irq[dev],
 					snd_mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0)
-			snd_printk(IDENT ": MPU401 not detected\n");
+			printk(KERN_ERR IDENT ": MPU401 not detected\n");
 	}
 	strcpy(card->driver, pcm->name);
 	strcpy(card->shortname, pcm->name);
@@ -575,7 +575,7 @@
 #endif
 	if (!cards) {
 #ifdef MODULE
-		snd_printk(IDENT " soundcard not found or device busy\n");
+		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/dt0197h.c b/sound/isa/dt0197h.c
--- a/sound/isa/dt0197h.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/dt0197h.c	Tue Feb 26 11:57:59 2002
@@ -36,6 +36,8 @@
 
 #define chip_t sb_t
 
+#define PFX "dt0197h: "
+
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
@@ -150,7 +152,7 @@
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("AUDIO isapnp configure failure\n");
+		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
 		return -EBUSY;
 	}
 
@@ -170,7 +172,7 @@
 			1);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("MPU-401 isapnp configure failure\n");
+		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
 		snd_mpu_port[dev] = -1;
 		acard->devmpu = NULL;
 	} else {
@@ -186,7 +188,7 @@
 		isapnp_resource_change(&pdev->resource[0], snd_fm_port[dev], 4);
 
 	if (pdev->activate(pdev)<0) {
-		snd_printk("OPL isapnp configure failure\n");
+		printk(KERN_ERR PFX "OPL isapnp configure failure\n");
 		snd_fm_port[dev] = -1;
 		acard->devopl = NULL;
 	} else {
@@ -244,7 +246,7 @@
 		return error;
 	}
 #else
-	snd_printk("you have to enable PnP support ...\n");
+	printk(KERN_ERR PFX "you have to enable PnP support ...\n");
 	snd_card_free(card);
 	return -ENOSYS;
 #endif	/* __ISAPNP__ */
@@ -276,7 +278,7 @@
 					snd_mpu_irq[dev],
 					SA_INTERRUPT,
 					NULL) < 0)
-			snd_printk("no MPU-401 device at 0x%lx ?\n",
+			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx ?\n",
 				snd_mpu_port[dev]);
 	}
 
@@ -285,7 +287,7 @@
 				    snd_fm_port[dev],
 				    snd_fm_port[dev] + 2,
 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx ?\n",
+			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx ?\n",
 				snd_fm_port[dev], snd_fm_port[dev] + 2);
 		} else {
 			if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
@@ -341,11 +343,11 @@
 #ifdef __ISAPNP__
 	cards += isapnp_probe_cards(snd_dt0197h_pnpids, snd_dt0197h_isapnp_detect);
 #else
-	snd_printk("you have to enable ISA PnP support.\n");
+	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
 #endif
 #ifdef MODULE
 	if (!cards)
-		snd_printk("no DT-0197H based soundcards found\n");
+		printk(KERN_ERR "no DT-0197H based soundcards found\n");
 #endif
 	return cards ? 0 : -ENODEV;
 }
diff -Nru a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
--- a/sound/isa/es1688/es1688.c	Tue Feb 26 11:57:58 2002
+++ b/sound/isa/es1688/es1688.c	Tue Feb 26 11:57:58 2002
@@ -133,7 +133,7 @@
 	}
 
 	if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
-		snd_printk("opl3 not detected at 0x%lx\n", chip->port);
+		printk(KERN_ERR "es1688: opl3 not detected at 0x%lx\n", chip->port);
 	} else {
 		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
 			snd_card_free(card);
@@ -194,7 +194,7 @@
 	cards += snd_legacy_auto_probe(possible_ports, snd_audiodrive_legacy_auto_probe);
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("ESS AudioDrive ES1688 soundcard not found or device busy\n");
+		printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c
--- a/sound/isa/es18xx.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/es18xx.c	Tue Feb 26 11:57:59 2002
@@ -86,6 +86,8 @@
 #define SNDRV_GET_ID
 #include <sound/initval.h>
 
+#define PFX "es18xx: "
+
 struct _snd_es18xx {
 	unsigned long port;		/* port of ESS chip */
 	unsigned long mpu_port;		/* MPU-401 port of ESS chip */
@@ -1510,7 +1512,7 @@
 static int __init snd_es18xx_probe(es18xx_t *chip)
 {
 	if (snd_es18xx_identify(chip) < 0) {
-                snd_printk("[0x%lx] ESS chip not found\n", chip->port);
+		printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
                 return -ENODEV;
 	}
 
@@ -1752,27 +1754,27 @@
 
 	if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
 		snd_es18xx_free(chip);
-		snd_printk("unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
+		printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
 		return -EBUSY;
 	}
 
 	if (request_irq(irq, snd_es18xx_interrupt, SA_INTERRUPT, "ES18xx", (void *) chip)) {
 		snd_es18xx_free(chip);
-		snd_printk("unable to grap IRQ %d\n", irq);
+		printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
 		return -EBUSY;
 	}
 	chip->irq = irq;
 
 	if (request_dma(dma1, "ES18xx DMA 1")) {
 		snd_es18xx_free(chip);
-		snd_printk("unable to grap DMA1 %d\n", dma1);
+		printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
 		return -EBUSY;
 	}
 	chip->dma1 = dma1;
 
 	if (request_dma(dma2, "ES18xx DMA 2")) {
 		snd_es18xx_free(chip);
-		snd_printk("unable to grap DMA2 %d\n", dma2);
+		printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
 		return -EBUSY;
 	}
 	chip->dma2 = dma2;
@@ -2008,7 +2010,7 @@
 	if (acard->devc->prepare(acard->devc)<0)
 		return -EAGAIN;
 	if (acard->devc->activate(acard->devc)<0) {
-		snd_printk("isapnp control configure failure (out of resources?)\n");
+		printk(KERN_ERR PFX "isapnp control configure failure (out of resources?)\n");
 		return -EAGAIN;
 	}
 	snd_printdd("isapnp: port=0x%lx\n", acard->devc->resource[0].start);
@@ -2031,7 +2033,7 @@
 	if (snd_irq[dev] != SNDRV_AUTO_IRQ)
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 	if (pdev->activate(pdev)<0) {
-		snd_printk("isapnp configure failure (out of resources?)\n");
+		printk(KERN_ERR PFX "isapnp configure failure (out of resources?)\n");
 		acard->devc->deactivate(acard->devc);
 		return -EBUSY;
 	}
@@ -2147,7 +2149,7 @@
 	}
 
 	if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
-		snd_printk("opl3 not detected at 0x%lx\n", chip->port);
+		printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->port);
 	} else {
 		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
 			snd_card_free(card);
@@ -2259,7 +2261,7 @@
 #endif
 	if(!cards) {
 #ifdef MODULE
-		snd_printk("ESS AudioDrive ES18xx soundcard not found or device busy\n");
+		printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
--- a/sound/isa/gus/gusclassic.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/gus/gusclassic.c	Tue Feb 26 11:57:59 2002
@@ -251,7 +251,7 @@
 	cards += snd_legacy_auto_probe(possible_ports, snd_gusclassic_legacy_auto_probe);
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("GUS Classic soundcard not found or device busy\n");
+		printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
--- a/sound/isa/gus/gusextreme.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/gus/gusextreme.c	Tue Feb 26 11:57:59 2002
@@ -316,7 +316,7 @@
 
 	if (snd_opl3_create(card, es1688->port, es1688->port + 2,
 			    OPL3_HW_OPL3, 0, &opl3) < 0) {
-		snd_printk("opl3 not detected at 0x%lx\n", es1688->port);
+		printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
 	} else {
 		if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0) {
 			snd_card_free(card);
@@ -376,7 +376,7 @@
 	cards += snd_legacy_auto_probe(possible_ports, snd_gusextreme_legacy_auto_probe);
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("GUS Extreme soundcard not found or device busy\n");
+		printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
--- a/sound/isa/gus/gusmax.c	Tue Feb 26 11:57:56 2002
+++ b/sound/isa/gus/gusmax.c	Tue Feb 26 11:57:56 2002
@@ -292,13 +292,13 @@
 	}
 	if (!gus->max_flag) {
 		snd_card_free(card);
-		snd_printk("GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
+		printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
 		return -ENODEV;
 	}
 
 	if (request_irq(irq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) {
 		snd_card_free(card);
-		snd_printk("unable to grab IRQ %d\n", irq);
+		printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", irq);
 		return -EBUSY;
 	}
 	maxcard->irq = irq;
@@ -387,7 +387,7 @@
 	cards += snd_legacy_auto_probe(possible_ports, snd_gusmax_legacy_auto_probe);
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("GUS MAX soundcard not found or device busy\n");
+		printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
--- a/sound/isa/gus/interwave.c	Tue Feb 26 11:57:56 2002
+++ b/sound/isa/gus/interwave.c	Tue Feb 26 11:57:56 2002
@@ -948,7 +948,7 @@
 			continue;
 		}
 #ifdef MODULE
-		snd_printk("InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);
+		printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);
 #endif
 	}
 	/* legacy auto configured cards */
@@ -960,7 +960,7 @@
 
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("InterWave soundcard not found or device busy\n");
+		printk(KERN_ERR "InterWave soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
--- a/sound/isa/opl3sa2.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/opl3sa2.c	Tue Feb 26 11:57:59 2002
@@ -893,7 +893,7 @@
 #endif
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Yamaha OPL3-SA soundcard not found or device busy\n");
+		printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
--- a/sound/isa/opti9xx/opti92x-ad1848.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/opti9xx/opti92x-ad1848.c	Tue Feb 26 11:57:57 2002
@@ -2154,9 +2154,9 @@
 	if ((error = snd_card_opti9xx_probe())) {
 #ifdef MODULE
 #ifdef OPTi93X
-		snd_printk("no OPTi 82C93x soundcard found\n");
+		printk(KERN_ERR "no OPTi 82C93x soundcard found\n");
 #else
-		snd_printk("no OPTi 82C92x soundcard found\n");
+		printk(KERN_ERR "no OPTi 82C92x soundcard found\n");
 #endif	/* OPTi93X */
 #endif
 		return error;
diff -Nru a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
--- a/sound/isa/sb/sb16.c	Tue Feb 26 11:57:58 2002
+++ b/sound/isa/sb/sb16.c	Tue Feb 26 11:57:58 2002
@@ -43,6 +43,12 @@
 
 #define chip_t sb_t
 
+#ifdef SNDRV_SBAWE
+#define PFX "sbawe: "
+#else
+#define PFX "sb16: "
+#endif
+
 #ifndef SNDRV_SBAWE
 EXPORT_NO_SYMBOLS;
 #endif
@@ -296,7 +302,7 @@
 	if (snd_irq[dev] != SNDRV_AUTO_IRQ)
 		isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
 	if (pdev->activate(pdev) < 0) {
-		snd_printk("isapnp configure failure (out of resources?)\n");
+		printk(KERN_ERR PFX "isapnp configure failure (out of resources?)\n");
 		return -EBUSY;
 	}
 	snd_port[dev] = pdev->resource[0].start;
@@ -322,7 +328,7 @@
 		isapnp_resource_change(&pdev->resource[2], snd_awe_port[dev] + 0x800, 4);
 	}
 	if (pdev->activate(pdev)<0) {
-		snd_printk("WaveTable isapnp configure failure (out of resources?)\n");
+		printk(KERN_ERR PFX "WaveTable isapnp configure failure (out of resources?)\n");
 		acard->dev->deactivate(acard->dev);		
 		return -EBUSY;
 	}
@@ -402,21 +408,21 @@
 	if (irq == SNDRV_AUTO_IRQ) {
 		if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
 			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
+			printk(KERN_ERR PFX "unable to find a free IRQ\n");
 			return -EBUSY;
 		}
 	}
 	if (dma8 == SNDRV_AUTO_DMA) {
 		if ((dma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
 			snd_card_free(card);
-			snd_printk("unable to find a free 8-bit DMA\n");
+			printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
 			return -EBUSY;
 		}
 	}
 	if (dma16 == SNDRV_AUTO_DMA) {
 		if ((dma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
 			snd_card_free(card);
-			snd_printk("unable to find a free 16-bit DMA\n");
+			printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
 			return -EBUSY;
 		}
 	}
@@ -475,7 +481,7 @@
 		if (snd_opl3_create(card, snd_fm_port[dev], snd_fm_port[dev] + 2,
 				    OPL3_HW_OPL3, snd_fm_port[dev] == snd_port[dev],
 				    &opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx\n",
+			printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
 				   snd_fm_port[dev], snd_fm_port[dev] + 2);
 		} else {
 #ifdef SNDRV_SBAWE_EMU8000
@@ -503,7 +509,7 @@
 			chip->csp = csp->private_data;
 			chip->hardware = SB_HW_16CSP;
 		} else {
-			snd_printk("warning - CSP chip not detected on soundcard #%i\n", dev + 1);
+			printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1);
 		}
 	}
 #endif
@@ -511,7 +517,7 @@
 	if (snd_awe_port[dev] > 0) {
 		if (snd_emu8000_new(card, 1, snd_awe_port[dev],
 				    snd_seq_ports[dev], NULL) < 0) {
-			snd_printk("fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", snd_awe_port[dev]);
+			printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", snd_awe_port[dev]);
 			snd_card_free(card);
 			return -ENXIO;
 		}
@@ -612,7 +618,7 @@
 			continue;
 		}
 #ifdef MODULE
-		snd_printk("Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);
+		printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);
 #endif			
 	}
 	/* legacy auto configured cards */
@@ -624,11 +630,11 @@
 
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Sound Blaster 16 soundcard not found or device busy\n");
+		printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
 #ifdef SNDRV_SBAWE_EMU8000
-		snd_printk("In case, if you have non-AWE card, try snd-card-sb16 module\n");
+		printk(KERN_ERR "In case, if you have non-AWE card, try snd-card-sb16 module\n");
 #else
-		snd_printk("In case, if you have AWE card, try snd-card-sbawe module\n");
+		printk(KERN_ERR "In case, if you have AWE card, try snd-card-sbawe module\n");
 #endif
 #endif
 		return -ENODEV;
diff -Nru a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
--- a/sound/isa/sb/sb8.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/sb/sb8.c	Tue Feb 26 11:57:59 2002
@@ -144,13 +144,13 @@
 		if ((err = snd_opl3_create(card, chip->port + 8, 0,
 					   OPL3_HW_AUTO, 1,
 					   &opl3)) < 0) {
-			snd_printk("no OPL device at 0x%lx\n", chip->port + 8);
+			printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8);
 		}
 	} else {
 		if ((err = snd_opl3_create(card, chip->port, chip->port + 2,
 					   OPL3_HW_AUTO, 1,
 					   &opl3)) < 0) {
-			snd_printk("no OPL device at 0x%lx-0x%lx\n",
+			printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n",
 				   chip->port, chip->port + 2);
 		}
 	}
@@ -211,7 +211,7 @@
 	cards += snd_legacy_auto_probe(possible_ports, snd_card_sb8_legacy_auto_probe);
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Sound Blaster soundcard not found or device busy\n");
+		printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
--- a/sound/isa/sgalaxy.c	Tue Feb 26 11:57:59 2002
+++ b/sound/isa/sgalaxy.c	Tue Feb 26 11:57:59 2002
@@ -305,7 +305,7 @@
 	}
 	if (!cards) {
 #ifdef MODULE
-		snd_printk("Sound Galaxy soundcard not found or device busy\n");
+		printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
--- a/sound/isa/wavefront/wavefront.c	Tue Feb 26 11:57:57 2002
+++ b/sound/isa/wavefront/wavefront.c	Tue Feb 26 11:57:57 2002
@@ -740,7 +740,7 @@
 #endif
 	if (!cards) {
 #ifdef MODULE
-		snd_printk ("No cards found or devices busy\n");
+		printk (KERN_ERR "No WaveFront cards found or devices busy\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/last.c b/sound/last.c
--- a/sound/last.c	Tue Feb 26 11:57:56 2002
+++ b/sound/last.c	Tue Feb 26 11:57:56 2002
@@ -27,14 +27,14 @@
 {
 	int idx, ok = 0;
 	
-	printk("ALSA device list:\n");
+	printk(KERN_INFO "ALSA device list:\n");
 	for (idx = 0; idx < SNDRV_CARDS; idx++)
 		if (snd_cards[idx] != NULL) {
-			printk("  #%i: %s\n", idx, snd_cards[idx]->longname);
+			printk(KERN_INFO "  #%i: %s\n", idx, snd_cards[idx]->longname);
 			ok++;
 		}
 	if (ok == 0)
-		printk("  No soundcards found.\n");
+		printk(KERN_INFO "  No soundcards found.\n");
 	return 0;
 }
 
diff -Nru a/sound/oss/btaudio.c b/sound/oss/btaudio.c
--- a/sound/oss/btaudio.c	Tue Feb 26 11:57:58 2002
+++ b/sound/oss/btaudio.c	Tue Feb 26 11:57:58 2002
@@ -1030,7 +1030,7 @@
         name:     "btaudio",
         id_table: btaudio_pci_tbl,
         probe:    btaudio_probe,
-        remove:   btaudio_remove,
+        remove:   __devexit_p(btaudio_remove),
 };
 
 int btaudio_init_module(void)
diff -Nru a/sound/oss/cs4232.c b/sound/oss/cs4232.c
--- a/sound/oss/cs4232.c	Tue Feb 26 11:57:56 2002
+++ b/sound/oss/cs4232.c	Tue Feb 26 11:57:56 2002
@@ -277,7 +277,7 @@
 	}
 }
 
-void __exit unload_cs4232(struct address_info *hw_config)
+static void __exit unload_cs4232(struct address_info *hw_config)
 {
 	int base = hw_config->io_base, irq = hw_config->irq;
 	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
@@ -460,10 +460,12 @@
 	return 0;
 }
 
-int cs4232_isapnp_remove(struct pci_dev *dev, const struct isapnp_device_id *id)
+static int __exit cs4232_isapnp_remove(struct pci_dev *dev,
+			const struct isapnp_device_id *id)
 {
 	struct address_info *cfg = (struct address_info*)pci_get_drvdata(dev);
-	if (cfg) unload_cs4232(cfg);
+	if (cfg)
+		unload_cs4232(cfg);
 	pci_set_drvdata(dev,NULL);
 	dev->deactivate(dev);
 	return 0;
diff -Nru a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
--- a/sound/oss/emu10k1/main.c	Tue Feb 26 11:57:59 2002
+++ b/sound/oss/emu10k1/main.c	Tue Feb 26 11:57:59 2002
@@ -1127,7 +1127,7 @@
 	name:		"emu10k1",
 	id_table:	emu10k1_pci_tbl,
 	probe:		emu10k1_probe,
-	remove:		emu10k1_remove,
+	remove:		__devexit_p(emu10k1_remove),
 };
 
 static int __init emu10k1_init_module(void)
diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
--- a/sound/oss/i810_audio.c	Tue Feb 26 11:57:58 2002
+++ b/sound/oss/i810_audio.c	Tue Feb 26 11:57:58 2002
@@ -2958,7 +2958,7 @@
 	return -ENODEV;
 }
 
-static void __exit i810_remove(struct pci_dev *pci_dev)
+static void __devexit i810_remove(struct pci_dev *pci_dev)
 {
 	int i;
 	struct i810_card *card = pci_get_drvdata(pci_dev);
@@ -3118,7 +3118,7 @@
 	name:		I810_MODULE_NAME,
 	id_table:	i810_pci_tbl,
 	probe:		i810_probe,
-	remove:		i810_remove,
+	remove:		__devexit_p(i810_remove),
 #ifdef CONFIG_PM
 	suspend:	i810_pm_suspend,
 	resume:		i810_pm_resume,
diff -Nru a/sound/oss/mpu401.c b/sound/oss/mpu401.c
--- a/sound/oss/mpu401.c	Tue Feb 26 11:58:00 2002
+++ b/sound/oss/mpu401.c	Tue Feb 26 11:58:00 2002
@@ -1227,7 +1227,7 @@
 	return ok;
 }
 
-void __exit unload_mpu401(struct address_info *hw_config)
+void unload_mpu401(struct address_info *hw_config)
 {
 	void *p;
 	int n=hw_config->slots[1];
diff -Nru a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
--- a/sound/oss/rme96xx.c	Tue Feb 26 11:57:59 2002
+++ b/sound/oss/rme96xx.c	Tue Feb 26 11:57:59 2002
@@ -1162,7 +1162,7 @@
 
 static int rme96xx_open(struct inode *in, struct file *f)
 {
-	int minor = MINOR(in->i_rdev);
+	int minor = minor(in->i_rdev);
 	struct list_head *list;
 	int devnum = ((minor-3)/16) % devices; /* default = 0 */
 	rme96xx_info *s;
@@ -1490,7 +1490,7 @@
 
 static int rme96xx_mixer_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct list_head *list;
 	rme96xx_info *s;
 
diff -Nru a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
--- a/sound/oss/sonicvibes.c	Tue Feb 26 11:57:59 2002
+++ b/sound/oss/sonicvibes.c	Tue Feb 26 11:57:59 2002
@@ -1235,7 +1235,7 @@
 
 static int sv_open_mixdev(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	struct list_head *list;
 	struct sv_state *s;
 
@@ -1893,7 +1893,7 @@
 
 static int sv_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned char fmtm = ~0, fmts = 0;
 	struct list_head *list;
@@ -2142,7 +2142,7 @@
 
 static int sv_midi_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	struct list_head *list;
@@ -2364,7 +2364,7 @@
 
 static int sv_dmfm_open(struct inode *inode, struct file *file)
 {
-	int minor = MINOR(inode->i_rdev);
+	int minor = minor(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	struct list_head *list;
 	struct sv_state *s;
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Tue Feb 26 11:57:58 2002
+++ b/sound/oss/trident.c	Tue Feb 26 11:57:58 2002
@@ -4149,7 +4149,7 @@
 	goto out;
 }
 
-static void __exit trident_remove(struct pci_dev *pci_dev)
+static void __devexit trident_remove(struct pci_dev *pci_dev)
 {
 	int i;
 	struct trident_card *card = pci_get_drvdata(pci_dev);
@@ -4202,7 +4202,7 @@
 	name:		TRIDENT_MODULE_NAME,
 	id_table:	trident_pci_tbl,
 	probe:		trident_probe,
-	remove:		trident_remove,
+	remove:		__devexit_p(trident_remove),
 	suspend:	trident_suspend,
 	resume:		trident_resume
 };
diff -Nru a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
--- a/sound/oss/via82cxxx_audio.c	Tue Feb 26 11:57:58 2002
+++ b/sound/oss/via82cxxx_audio.c	Tue Feb 26 11:57:58 2002
@@ -311,7 +311,7 @@
  */
 
 static int via_init_one (struct pci_dev *dev, const struct pci_device_id *id);
-static void via_remove_one (struct pci_dev *pdev);
+static void __devexit via_remove_one (struct pci_dev *pdev);
 
 static ssize_t via_dsp_read(struct file *file, char *buffer, size_t count, loff_t *ppos);
 static ssize_t via_dsp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos);
@@ -365,7 +365,7 @@
 	name:		VIA_MODULE_NAME,
 	id_table:	via_pci_tbl,
 	probe:		via_init_one,
-	remove:		via_remove_one,
+	remove:		__devexit_p(via_remove_one),
 };
 
 
@@ -3271,7 +3271,7 @@
 }
 
 
-static void __exit via_remove_one (struct pci_dev *pdev)
+static void __devexit via_remove_one (struct pci_dev *pdev)
 {
 	struct via_info *card;
 
diff -Nru a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
--- a/sound/oss/ymfpci.c	Tue Feb 26 11:57:56 2002
+++ b/sound/oss/ymfpci.c	Tue Feb 26 11:57:56 2002
@@ -2652,7 +2652,7 @@
 	name:		"ymfpci",
 	id_table:	ymf_id_tbl,
 	probe:		ymf_probe_one,
-	remove:         ymf_remove_one,
+	remove:         __devexit_p(ymf_remove_one),
 	suspend:	ymf_suspend,
 	resume:		ymf_resume
 };
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/ac97/ac97_codec.c	Tue Feb 26 11:57:59 2002
@@ -115,7 +115,7 @@
 { 0x43525960, 0xfffffff8, "CS4291",		NULL },
 { 0x48525300, 0xffffff00, "HMP9701",		NULL },
 { 0x49434501, 0xffffffff, "ICE1230",		NULL },
-{ 0x49434511, 0xffffffff, "ICE1232",		NULL }, // only guess --jk
+{ 0x49434511, 0xffffffff, "ICE1232",		NULL }, // alias VIA VT1611A?
 { 0x4e534300, 0xffffffff, "LM4540/43/45/46/48",	NULL }, // only guess --jk
 { 0x4e534331, 0xffffffff, "LM4549",		NULL },
 { 0x53494c22, 0xffffffff, "Si3036",		NULL },
@@ -1393,28 +1393,31 @@
 	ac97->card = card;
 	spin_lock_init(&ac97->reg_lock);
 	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
-	udelay(50);
-
-	/* it's necessary to wait awhile until registers are accessible after RESET */
-	/* because the PCM or MASTER volume registers can be modified, */
-	/* the REC_GAIN register is used for tests */
-	end_time = jiffies + (HZ / 2);
-	do {
-		/* use preliminary reads to settle the communication */
-		snd_ac97_read(ac97, AC97_RESET);
-		snd_ac97_read(ac97, AC97_VENDOR_ID1);
-		snd_ac97_read(ac97, AC97_VENDOR_ID2);
-		/* test if we can write to the PCM volume register */
-		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
-		if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
-			goto __access_ok;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
-	} while (end_time - (signed long)jiffies >= 0);
-	snd_printd("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err);
-	snd_ac97_free(ac97);
-	return -ENXIO;
-
+	if (ac97->wait)
+		ac97->wait(ac97);
+	else {
+		udelay(50);
+
+		/* it's necessary to wait awhile until registers are accessible after RESET */
+		/* because the PCM or MASTER volume registers can be modified, */
+		/* the REC_GAIN register is used for tests */
+		end_time = jiffies + HZ;
+		do {
+			/* use preliminary reads to settle the communication */
+			snd_ac97_read(ac97, AC97_RESET);
+			snd_ac97_read(ac97, AC97_VENDOR_ID1);
+			snd_ac97_read(ac97, AC97_VENDOR_ID2);
+			/* test if we can write to the PCM volume register */
+			snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
+			if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
+				goto __access_ok;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ/100);
+		} while (end_time - (signed long)jiffies >= 0);
+		snd_printd("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err);
+		snd_ac97_free(ac97);
+		return -ENXIO;
+	}
       __access_ok:
 	ac97->caps = snd_ac97_read(ac97, AC97_RESET);
 	ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
--- a/sound/pci/ali5451/ali5451.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/ali5451/ali5451.c	Tue Feb 26 11:57:59 2002
@@ -2253,7 +2253,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("ALi pci audio not found or device busy.\n");
+		printk(KERN_ERR "ALi pci audio not found or device busy.\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/als4000.c b/sound/pci/als4000.c
--- a/sound/pci/als4000.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/als4000.c	Tue Feb 26 11:57:59 2002
@@ -635,7 +635,7 @@
 				        gcr+0x30, 1, pci->irq, 0,
 				        &chip->rmidi)) < 0) {
 		snd_card_free(card);
-		snd_printk("no MPU-401device at 0x%lx ?\n", gcr+0x30);
+		printk(KERN_ERR "als4000: no MPU-401device at 0x%lx ?\n", gcr+0x30);
 		return err;
 	}
 
@@ -650,7 +650,7 @@
 
 	if (snd_opl3_create(card, gcr+0x10, gcr+0x12,
 			    OPL3_HW_AUTO, 1, &opl3) < 0) {
-		snd_printk("no OPL device at 0x%lx-0x%lx ?\n",
+		printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx ?\n",
 			   gcr+0x10, gcr+0x12 );
 	} else {
 		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
@@ -692,7 +692,7 @@
 	
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("no ALS4000 based soundcards found or device busy\n");
+		printk(KERN_ERR "no ALS4000 based soundcards found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c
--- a/sound/pci/cmipci.c	Tue Feb 26 11:57:57 2002
+++ b/sound/pci/cmipci.c	Tue Feb 26 11:57:57 2002
@@ -113,6 +113,7 @@
 
 #define CM_AC3EN1		0x00100000	/* enable AC3: model 037 */
 #define CM_SPD24SEL		0x00020000	/* 24bit spdif: model 037 */
+#define CM_SPDIF_INVERSE	0x00010000
 
 #define CM_ADCBITLEN_MASK	0x0000C000	
 #define CM_ADCBITLEN_16		0x00000000
@@ -131,6 +132,8 @@
 #define CM_CH0_SRATE_176K	0x00000200
 #define CM_CH0_SRATE_88K	0x00000100
 
+#define CM_SPDIF_INVERSE2	0x00000080	/* model 055? */
+
 #define CM_CH1FMT_MASK		0x0000000C
 #define CM_CH1FMT_SHIFT		2
 #define CM_CH0FMT_MASK		0x00000003
@@ -201,6 +204,7 @@
 #define CM_VIDWPPRT		0x00002000
 #define CM_SFILENB		0x00001000
 #define CM_MMODE_MASK		0x00000E00
+#define CM_SPDIF_SELECT		0x00000100	/* for model > 039 ? */
 #define CM_ENCENTER		0x00000080	/* shared with FLINKON? */
 #define CM_FLINKON		0x00000080
 #define CM_FLINKOFF		0x00000040
@@ -347,7 +351,7 @@
 	unsigned int offset;	/* physical address of the buffer */
 	unsigned int fmt;	/* format bits */
 	int ch;			/* channel (0/1) */
-	int is_dac;		/* is dac? */
+	unsigned int is_dac;		/* is dac? */
 	int bytes_per_frame;
 	int shift;
 	int ac3_shift;	/* extra shift: 1 on soft ac3 mode */
@@ -388,6 +392,9 @@
 	unsigned int can_ac3_sw: 1;
 	unsigned int can_ac3_hw: 1;
 	unsigned int can_multi_ch: 1;
+
+	unsigned int spdif_playback_avail: 1;	/* spdif ready? */
+	unsigned int spdif_playback_enabled: 1;	/* spdif switch enabled? */
 	int spdif_counter;	/* for software AC3 */
 
 	unsigned int dig_status;
@@ -1133,11 +1140,13 @@
 		save_mixer_state(cm);
 
 	spin_lock_irqsave(&cm->reg_lock, flags);
+	cm->spdif_playback_avail = up;
 	if (up) {
 		/* they are controlled via "IEC958 Output Switch" */
 		/* snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */
 		/* snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */
-		snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
+		if (cm->spdif_playback_enabled)
+			snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
 		setup_ac3(cm, do_ac3, rate);
 
 		if (rate == 48000)
@@ -2020,7 +2029,7 @@
 	CMIPCI_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1, 0, 0),
 	CMIPCI_SB_VOL_MONO("PC Speaker Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
 	CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15),
-	CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0),
+	CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 1),
 	CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0),
 	CMIPCI_MIXER_SW_MONO("Mic Boost", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1),
 	CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7),
@@ -2132,6 +2141,7 @@
 DEFINE_BIT_SWITCH_ARG(spdif_0, CM_REG_FUNCTRL1, CM_SPDF_0, 0);
 DEFINE_BIT_SWITCH_ARG(spdo_48k, CM_REG_MISC_CTRL, CM_SPDF_AC97|CM_SPDIF48K, 0);
 #endif
+DEFINE_BIT_SWITCH_ARG(spdif_in_1_2, CM_REG_MISC_CTRL, CM_SPDIF_SELECT, 0, 0);
 DEFINE_BIT_SWITCH_ARG(spdif_enable, CM_REG_LEGACY_CTRL, CM_ENSPDOUT, 0, 0);
 DEFINE_BIT_SWITCH_ARG(spdo2dac, CM_REG_FUNCTRL1, CM_SPDO2DAC, 0, 1);
 DEFINE_BIT_SWITCH_ARG(spdi_valid, CM_REG_MISC, CM_SPDVALID, 1, 0);
@@ -2140,7 +2150,8 @@
 DEFINE_SWITCH_ARG(spdo_5v, CM_REG_MISC_CTRL, CM_SPDO5V, 0, 0, 0); /* inverse: 0 = 5V */
 DEFINE_BIT_SWITCH_ARG(spdif_loop, CM_REG_FUNCTRL1, CM_SPDFLOOP, 0, 1);
 DEFINE_BIT_SWITCH_ARG(spdi_monitor, CM_REG_MIXER1, CM_CDPLAY, 1, 0);
-DEFINE_BIT_SWITCH_ARG(spdi_phase, CM_REG_MISC, 0x04, 0, 0);
+DEFINE_BIT_SWITCH_ARG(spdi_phase, CM_REG_CHFORMAT, CM_SPDIF_INVERSE, 0, 0);
+DEFINE_BIT_SWITCH_ARG(spdi_phase2, CM_REG_CHFORMAT, CM_SPDIF_INVERSE2, 0, 0);
 #if CM_CH_PLAY == 1
 DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* reversed */
 #else
@@ -2179,9 +2190,20 @@
 
 static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
+	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
 	int changed;
 	changed = _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable);
 	changed |= _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdo2dac);
+	if (changed) {
+		if (ucontrol->value.integer.value[0]) {
+			if (chip->spdif_playback_avail)
+				snd_cmipci_set_bit(chip, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
+		} else {
+			if (chip->spdif_playback_avail)
+				snd_cmipci_clear_bit(chip, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
+		}
+	}
+	chip->spdif_playback_enabled = ucontrol->value.integer.value[0];
 	return changed;
 }
 
@@ -2213,17 +2235,19 @@
 	DEFINE_MIXER_SWITCH("IEC958 5V", spdo_5v),
 	DEFINE_MIXER_SWITCH("IEC958 Loop", spdif_loop),
 	DEFINE_MIXER_SWITCH("IEC958 In Monitor", spdi_monitor),
-	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
 };
 
 /* only for model 033/037 */
 static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = {
 	DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
+	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
 };
 
-/* only for model 039 */
+/* only for model 039 or later */
 static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
 	DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass),
+	DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_1_2),
+	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
 };
 
 /* card control switches */
@@ -2283,7 +2307,7 @@
 		cm->spdif_pcm_ctl = kctl;
 		if (cm->chip_version <= 37) {
 			sw = snd_cmipci_old_mixer_switches;
-			for (idx = 0; idx < num_controls(snd_cmipci_extra_mixer_switches); idx++, sw++) {
+			for (idx = 0; idx < num_controls(snd_cmipci_old_mixer_switches); idx++, sw++) {
 				err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 				if (err < 0)
 					return err;
@@ -2573,10 +2597,10 @@
 
 		if (snd_opl3_create(card, iosynth, iosynth + 2,
 				    OPL3_HW_OPL3, 0, &cm->opl3) < 0) {
-			snd_printk("no OPL device at 0x%lx\n", iosynth);
+			printk(KERN_ERR "cmipci: no OPL device at 0x%lx\n", iosynth);
 		} else {
 			if ((err = snd_opl3_hwdep_new(cm->opl3, 0, 1, &cm->opl3hwdep)) < 0)
-				snd_printk("cannot create OPL3 hwdep\n");
+				printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n");
 		}
 	}
 
@@ -2609,7 +2633,7 @@
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
 					       iomidi, 0,
 					       cm->irq, 0, &cm->rmidi)) < 0) {
-			snd_printk("cmipci: no UART401 device at 0x%lx\n", iomidi);
+			printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi);
 		}
 	}
 
@@ -2711,7 +2735,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("C-Media PCI soundcard not found or device busy\n");
+		printk(KERN_ERR "C-Media PCI soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/cs4281.c	Tue Feb 26 11:57:59 2002
@@ -268,7 +268,7 @@
 #define BA0_SERC1_SO1EN		(1<<0)	/* Primary Output Port Enable */
 
 #define BA0_SERC2		0x042c	/* Serial Port Configuration 2 */
-#define BA0_SERC2_SI1F(x)	(((x)&7)>>1) */ Primary Input Port Format */
+#define BA0_SERC2_SI1F(x)	(((x)&7)>>1) /* Primary Input Port Format */
 #define BA0_SERC2_AC97		(1<<1)
 #define BA0_SERC2_SI1EN		(1<<0)	/* Primary Input Port Enable */
 
@@ -1910,7 +1910,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("CS4281 soundcard not found or device busy\n");
+		printk(KERN_ERR "CS4281 soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
--- a/sound/pci/cs46xx/cs46xx.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/cs46xx/cs46xx.c	Tue Feb 26 11:57:59 2002
@@ -183,7 +183,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("Sound Fusion CS46xx soundcard not found or device busy\n");
+		printk(KERN_ERR "Sound Fusion CS46xx soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
--- a/sound/pci/emu10k1/emu10k1.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/emu10k1/emu10k1.c	Tue Feb 26 11:57:56 2002
@@ -210,7 +210,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("EMU10K1/Audigy soundcard not found or device busy\n");
+		printk(KERN_ERR "EMU10K1/Audigy soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
--- a/sound/pci/emu10k1/emu10k1_main.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/emu10k1/emu10k1_main.c	Tue Feb 26 11:57:59 2002
@@ -218,6 +218,10 @@
 	 */
 	outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
 
+	/* Enable analog/digital outs on audigy */
+	if (emu->audigy)
+		outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
+
 #if 0
 	{
 	unsigned int tmp;
@@ -274,7 +278,7 @@
 	snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K);
 	snd_emu10k1_ptr_write(emu, TCB, 0, 0);
 	if (emu->audigy)
-		snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP_ADDR);
+		snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP);
 	else
 		snd_emu10k1_ptr_write(emu, DBG, 0, 0x8000);
 
@@ -625,18 +629,10 @@
 	}
 	
 	emu->fx8010.fxbus_mask = 0x303f;
-	if (extin_mask == 0) {
-		if (emu->audigy)
-			extin_mask = 0x000f;
-		else
-			extin_mask = 0x1fcf;
-	}
-	if (extout_mask == 0) {
-		if (emu->audigy)
-			extout_mask = 0x3fff;
-		else
-			extout_mask = 0x3fff;
-	}
+	if (extin_mask == 0)
+		extin_mask = 0x1fcf;
+	if (extout_mask == 0)
+		extout_mask = 0x3fff;
 	emu->fx8010.extin_mask = extin_mask;
 	emu->fx8010.extout_mask = extout_mask;
 
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/emu10k1/emufx.c	Tue Feb 26 11:57:56 2002
@@ -95,12 +95,12 @@
 	/* 0x05 */ NULL,
 	/* 0x06 */ NULL,
 	/* 0x07 */ NULL,
-	/* 0x08 */ NULL,
-	/* 0x09 */ NULL,
+	/* 0x08 */ "Line/Mic 2 Left",
+	/* 0x09 */ "Line/Mic 2 Right",
 	/* 0x0a */ NULL,
 	/* 0x0b */ NULL,
-	/* 0x0c */ NULL,
-	/* 0x0d */ NULL,
+	/* 0x0c */ "Aux2 Left",
+	/* 0x0d */ "Aux2 Right",
 	/* 0x0e */ NULL,
 	/* 0x0f */ NULL
 };
@@ -141,14 +141,14 @@
 };
 
 static char *audigy_outs[32] = {
-	/* 0x00 */ NULL,
-	/* 0x01 */ NULL,
-	/* 0x02 */ NULL,
-	/* 0x03 */ NULL,
+	/* 0x00 */ "Digital Front Left",
+	/* 0x01 */ "Digital Front Right",
+	/* 0x02 */ "Digital Center",
+	/* 0x03 */ "Digital LEF",
 	/* 0x04 */ "Headphone Left",
 	/* 0x05 */ "Headphone Right",
-	/* 0x06 */ NULL,
-	/* 0x07 */ NULL,
+	/* 0x06 */ "Digital Rear Left",
+	/* 0x07 */ "Digital Rear Right",
 	/* 0x08 */ "Front Left",
 	/* 0x09 */ "Front Right",
 	/* 0x0a */ "Center",
@@ -157,14 +157,14 @@
 	/* 0x0d */ NULL,
 	/* 0x0e */ "Rear Left",
 	/* 0x0f */ "Rear Right",
-	/* 0x10 */ NULL,
-	/* 0x11 */ NULL,
-	/* 0x12 */ NULL,
-	/* 0x13 */ NULL,
+	/* 0x10 */ "AC97 Front Left",
+	/* 0x11 */ "AC97 Front Right",
+	/* 0x12 */ "ADC Caputre Left",
+	/* 0x13 */ "ADC Capture Right",
 	/* 0x14 */ NULL,
 	/* 0x15 */ NULL,
-	/* 0x16 */ "ADC Capture Left",
-	/* 0x17 */ "ADC Capture Right",
+	/* 0x16 */ NULL,
+	/* 0x17 */ NULL,
 	/* 0x18 */ NULL,
 	/* 0x19 */ NULL,
 	/* 0x1a */ NULL,
@@ -1034,7 +1034,7 @@
 	/* stop FX processor - this may be dangerous, but it's better to miss
 	   some samples than generate wrong ones - [jk] */
 	if (emu->audigy)
-		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP_ADDR);
+		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
 	else
 		snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
 	/* ok, do the main job */
@@ -1220,36 +1220,34 @@
 	ptr = 0;
 	nctl = 0;
 	playback = 10;
-	capture = playback + 6; /* 5+1 channels */
-	gpr = capture + 2; /* so far only a stereo capture */
+	capture = playback + 10; /* we reserve 10 voices */
+	gpr = capture + 10;
 	tmp = 0x80;
 	
 	/* stop FX processor */
-	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP_ADDR);
-
-#define A_C_ZERO	0x0c0
+	snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
 
 	/* Wave Playback */
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_ZERO, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_ZERO, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
 	gpr += 2;
 
 	/* Wave Surround Playback */
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_ZERO, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_ZERO, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Surround Playback Volume", gpr, 0);
 	gpr += 2;
 
 	/* Wave Center Playback */
 	/* Center = sub = Left/2 + Right/2 */
 	A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_FXBUS(FXBUS_PCM_LEFT), 0xcd, A_FXBUS(FXBUS_PCM_RIGHT));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_ZERO, A_GPR(gpr), A_GPR(tmp));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_GPR(tmp));
 	snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Center Playback Volume", gpr, 0);
 	gpr++;
 
 	/* Wave LFE Playback */
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_ZERO, A_GPR(gpr), A_GPR(tmp));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_GPR(tmp));
 	snd_emu10k1_init_mono_control(&controls[nctl++], "Wave LFE Playback Volume", gpr, 0);
 	gpr++;
 
@@ -1260,8 +1258,8 @@
 	gpr += 2;
 
 	/* Wave Capture */
-	A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_ZERO, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
-	A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_ZERO, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
+	A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
+	A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Capture Volume", gpr, 0);
 	gpr += 2;
 
@@ -1271,14 +1269,20 @@
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Capture Volume", gpr, 0);
 	gpr += 2;
 
+	/* Surround Playback */
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 80);
+	gpr += 2;
+
 	/* Center Playback */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
-	snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0);
+	snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 80);
 	gpr++;
 
 	/* LFE Playback */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE));
-	snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
+	snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 80);
 	gpr++;
 
 	/*
@@ -1286,54 +1290,70 @@
 	 */
 #define A_ADD_VOLUME_IN(var,vol,input) \
 A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
-	if (emu->fx8010.extin_mask & ((1<<A_EXTIN_AC97_L)|(1<<A_EXTIN_AC97_R))) {
-		/* AC'97 Playback Volume */
-		A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_AC97_L);
-		A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_AC97_R);
-		snd_emu10k1_init_stereo_control(&controls[nctl++], "AC97 Playback Volume", gpr, 0);
-		gpr += 2;
-		/* AC'97 Capture Volume */
-		A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
-		A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
-		snd_emu10k1_init_stereo_control(&controls[nctl++], "AC97 Capture Volume", gpr, 100);
-		gpr += 2;
-	}
 
-	if (emu->fx8010.extin_mask & ((1<<A_EXTIN_SPDIF_CD_L)|(1<<A_EXTIN_SPDIF_CD_R))) {
-		/* Audigy CD Playback Volume */
-		A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_SPDIF_CD_L);
-		A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_SPDIF_CD_R);
-		snd_emu10k1_init_stereo_control(&controls[nctl++], "Audigy CD Playback Volume", gpr, 0);
-		gpr += 2;
-		/* Audigy CD Capture Volume */
-		A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
-		A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
-		snd_emu10k1_init_stereo_control(&controls[nctl++], "Audigy CD Capture Volume", gpr, 100);
-		gpr += 2;
-	}
+	/* AC'97 Playback Volume */
+	A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_AC97_L);
+	A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_AC97_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "AC97 Playback Volume", gpr, 0);
+	gpr += 2;
+	/* AC'97 Capture Volume */
+	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
+	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "AC97 Capture Volume", gpr, 100);
+	gpr += 2;
+
+	/* Audigy CD Playback Volume */
+	A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_SPDIF_CD_L);
+	A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_SPDIF_CD_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Audigy CD Playback Volume", gpr, 0);
+	gpr += 2;
+	/* Audigy CD Capture Volume */
+	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
+	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Audigy CD Capture Volume", gpr, 0);
+	gpr += 2;
+
+	/* Line2 Playback Volume */
+	A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_LINE2_L);
+	A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_LINE2_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Line2 Playback Volume", gpr, 0);
+	gpr += 2;
+	/* Line2 Capture Volume */
+	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
+	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Line2 Capture Volume", gpr, 0);
+	gpr += 2;
+
+	/* Aux2 Playback Volume */
+	A_ADD_VOLUME_IN(playback, gpr, A_EXTIN_AUX2_L);
+	A_ADD_VOLUME_IN(playback+1, gpr+1, A_EXTIN_AUX2_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Aux2 Playback Volume", gpr, 0);
+	gpr += 2;
+	/* Aux2 Capture Volume */
+	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
+	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Aux2 Capture Volume", gpr, 0);
+	gpr += 2;
 
 	/*
 	 * outputs
 	 */
-#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_ZERO, A_C_ZERO, A_GPR(src))
-#define A_PUT_MONO_OUTPUT(out,src) \
-	if (emu->fx8010.extout_mask & (1<<(out))) A_PUT_OUTPUT(out,src)
+#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src))
 #define A_PUT_STEREO_OUTPUT(out1,out2,src) \
-	if (emu->fx8010.extout_mask & ((1<<(out1))|(1<<(out2)))) {\
-		A_PUT_OUTPUT(out1,src);\
-		A_PUT_OUTPUT(out2,src+1);}
+	{A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
 
 	/* digital outputs */
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback);
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2);
-	A_PUT_MONO_OUTPUT(A_EXTOUT_CENTER, playback+4);
-	A_PUT_MONO_OUTPUT(A_EXTOUT_LFE, playback+5);
+	A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4);
+	A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5);
 
 	/* analog speakers */
-	A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback);
+	//A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback);
+	A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback);
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2);
-	A_PUT_MONO_OUTPUT(A_EXTOUT_ACENTER, playback+4);
-	A_PUT_MONO_OUTPUT(A_EXTOUT_ALFE, playback+5);
+	A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4);
+	A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5);
 
 	/* headphone */
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback);
@@ -1946,7 +1966,7 @@
 {
 	/* stop processor */
 	if (emu->audigy)
-		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP_ADDR);
+		snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP);
 	else
 		snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
 }
@@ -2127,7 +2147,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (emu->audigy)
-			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP_ADDR);
+			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP);
 		else
 			snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP);
 		return 0;
@@ -2160,12 +2180,12 @@
 		if (addr > 0x1ff)
 			return -EINVAL;
 		if (emu->audigy)
-			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP_ADDR | addr);
+			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr);
 		else
 			snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr);
 		udelay(10);
 		if (emu->audigy)
-			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP_ADDR | A_DBG_STEP_ADDR | addr);
+			snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr);
 		else
 			snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr);
 		return 0;
diff -Nru a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
--- a/sound/pci/emu10k1/emumixer.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/emu10k1/emumixer.c	Tue Feb 26 11:57:58 2002
@@ -107,12 +107,40 @@
         put:            snd_emu10k1_spdif_put
 };
 
-/* FIXME: audigy has more routing/effects */
+
+static void update_emu10k1_fxrt(emu10k1_t *emu, int voice, unsigned char *route)
+{
+	if (emu->audigy) {
+		snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
+				      snd_emu10k1_compose_audigy_fxrt1(route));
+		snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
+				      snd_emu10k1_compose_audigy_fxrt2(route));
+	} else {
+		snd_emu10k1_ptr_write(emu, FXRT, voice,
+				      snd_emu10k1_compose_send_routing(route));
+	}
+}
+
+static void update_emu10k1_send_volume(emu10k1_t *emu, int voice, unsigned char *volume)
+{
+	snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
+	snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
+	snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
+	snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
+	if (emu->audigy) {
+		unsigned int val = ((unsigned int)volume[4] << 24) |
+			((unsigned int)volume[5] << 16) |
+			((unsigned int)volume[6] << 8) |
+			(unsigned int)volume[7];
+		snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
+	}
+}
+
 static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 3*4;
+	uinfo->count = emu->audigy ? 3*8 : 3*4;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
 	return 0;
@@ -125,13 +153,14 @@
 	emu10k1_pcm_mixer_t *mix = (emu10k1_pcm_mixer_t *)kcontrol->private_value;
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	int voice, idx;
+	int num_efx = emu->audigy ? 8 : 4;
+	int mask = emu->audigy ? 0x3f : 0x0f;
 
 	spin_lock_irqsave(&emu->reg_lock, flags);
 	for (voice = 0; voice < 3; voice++)
-		for (idx = 0; idx < 4; idx++)
-			ucontrol->value.integer.value[(voice * 4) + idx] = emu->audigy ?
-				((mix->send_routing[voice] >> (idx * 8)) & 0x3f) :
-				((mix->send_routing[voice] >> (idx * 4)) & 0x0f);
+		for (idx = 0; idx < num_efx; idx++)
+			ucontrol->value.integer.value[(voice * num_efx) + idx] = 
+				mix->send_routing[voice][idx] & mask;
 	spin_unlock_irqrestore(&emu->reg_lock, flags);
         return 0;
 }
@@ -143,44 +172,27 @@
 	emu10k1_pcm_mixer_t *mix = (emu10k1_pcm_mixer_t *)kcontrol->private_value;
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	int change = 0, voice, idx, val;
+	int num_efx = emu->audigy ? 8 : 4;
+	int mask = emu->audigy ? 0x3f : 0x0f;
 
 	spin_lock_irqsave(&emu->reg_lock, flags);
 	for (voice = 0; voice < 3; voice++)
-		for (idx = 0; idx < 4; idx++) {
-			val = ucontrol->value.integer.value[(voice * 4) + idx];
-			if (emu->audigy) {
-				int shift = idx * 8;
-				val &= 0x3f;
-				if (((mix->send_routing[voice] >> shift) & 0x3f) != val) {
-					mix->send_routing[voice] &= ~(0x3f << shift);
-					mix->send_routing[voice] |= val << shift;
-					change = 1;
-				}
-			} else {
-				int shift = idx * 4;
-				val = ucontrol->value.integer.value[(voice * 4) + idx] & 15;
-				if (((mix->send_routing[voice] >> shift) & 15) != val) {
-					mix->send_routing[voice] &= ~(15 << shift);
-					mix->send_routing[voice] |= val << shift;
-					change = 1;
-				}
+		for (idx = 0; idx < num_efx; idx++) {
+			val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
+			if (mix->send_routing[voice][idx] != val) {
+				mix->send_routing[voice][idx] = val;
+				change = 1;
 			}
 		}	
 	if (change && mix->epcm) {
 		if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
-			if (emu->audigy) {
-				snd_emu10k1_ptr_write(emu, A_FXRT1, mix->epcm->voices[0]->number, mix->send_routing[1]);
-				snd_emu10k1_ptr_write(emu, A_FXRT1, mix->epcm->voices[1]->number, mix->send_routing[2]);
-			} else {
-				snd_emu10k1_ptr_write(emu, FXRT, mix->epcm->voices[0]->number, mix->send_routing[1] << 16);
-				snd_emu10k1_ptr_write(emu, FXRT, mix->epcm->voices[1]->number, mix->send_routing[2] << 16);
-			}
+			update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
+					    &mix->send_routing[1][0]);
+			update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
+					    &mix->send_routing[2][0]);
 		} else if (mix->epcm->voices[0]) {
-			if (emu->audigy) {
-				snd_emu10k1_ptr_write(emu, A_FXRT1, mix->epcm->voices[0]->number, mix->send_routing[0]);
-			} else {
-				snd_emu10k1_ptr_write(emu, FXRT, mix->epcm->voices[0]->number, mix->send_routing[0] << 16);
-			}
+			update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
+					    &mix->send_routing[0][0]);
 		}
 	}
 	spin_unlock_irqrestore(&emu->reg_lock, flags);
@@ -199,8 +211,9 @@
 
 static int snd_emu10k1_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 3*4;
+	uinfo->count = emu->audigy ? 3*8 : 3*4;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = 255;
 	return 0;
@@ -213,10 +226,11 @@
 	emu10k1_pcm_mixer_t *mix = (emu10k1_pcm_mixer_t *)kcontrol->private_value;
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	int idx;
+	int num_efx = emu->audigy ? 8 : 4;
 
 	spin_lock_irqsave(&emu->reg_lock, flags);
-	for (idx = 0; idx < 3*4; idx++)
-		ucontrol->value.integer.value[idx] = mix->send_volume[idx/4][idx%4];
+	for (idx = 0; idx < 3*num_efx; idx++)
+		ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
 	spin_unlock_irqrestore(&emu->reg_lock, flags);
         return 0;
 }
@@ -228,34 +242,25 @@
 	emu10k1_pcm_mixer_t *mix = (emu10k1_pcm_mixer_t *)kcontrol->private_value;
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	int change = 0, idx, val;
+	int num_efx = emu->audigy ? 8 : 4;
 
 	spin_lock_irqsave(&emu->reg_lock, flags);
-	for (idx = 0; idx < 3*4; idx++) {
+	for (idx = 0; idx < 3*num_efx; idx++) {
 		val = ucontrol->value.integer.value[idx] & 255;
-		if (mix->send_volume[idx/4][idx%4] != val) {
-			mix->send_volume[idx/4][idx%4] = val;
+		if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
+			mix->send_volume[idx/num_efx][idx%num_efx] = val;
 			change = 1;
 		}
 	}
 	if (change && mix->epcm) {
-		u32 voice;
 		if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
-			voice = mix->epcm->voices[0]->number;
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, mix->send_volume[1][0]);
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, mix->send_volume[1][1]);
-			snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, mix->send_volume[1][2]);
-			snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, mix->send_volume[1][3]);
-			voice = mix->epcm->voices[1]->number;
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, mix->send_volume[2][0]);
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, mix->send_volume[2][1]);
-			snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, mix->send_volume[2][2]);
-			snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, mix->send_volume[2][3]);
+			update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
+						   &mix->send_volume[1][0]);
+			update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
+						   &mix->send_volume[2][0]);
 		} else if (mix->epcm->voices[0]) {
-			voice = mix->epcm->voices[0]->number;
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, mix->send_volume[0][0]);
-			snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, mix->send_volume[0][1]);
-			snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, mix->send_volume[0][2]);
-			snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, mix->send_volume[0][3]);
+			update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
+						   &mix->send_volume[0][0]);
 		}
 	}
 	spin_unlock_irqrestore(&emu->reg_lock, flags);
@@ -380,6 +385,71 @@
 	put:		snd_emu10k1_shared_spdif_put
 };
 
+#if 0 // XXX: not working yet..
+/*
+ * Audigy analog / digital switches
+ */
+static int audigy_output_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int audigy_output_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = (unsigned int)kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & mask ? 0 : 1;
+        return 0;
+}
+
+static int audigy_output_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int mask = (unsigned int)kcontrol->private_value;
+	unsigned int reg, oreg;
+	int change;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	reg = oreg = inl(emu->port + A_IOCFG);
+	reg &= ~mask;
+	reg |= ucontrol->value.integer.value[0] & 1 ? 0 : mask;
+	change = (reg != oreg);
+	if (change)
+		outl(reg, emu->port + A_IOCFG);
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+        return change;
+}
+
+static snd_kcontrol_new_t audigy_output_analog =
+{
+	iface:		SNDRV_CTL_ELEM_IFACE_MIXER,
+	name:		"Audigy Analog Output Switch",
+	info:		audigy_output_info,
+	get:		audigy_output_get,
+	put:		audigy_output_put,
+	private_value:	0x40,
+};
+
+static snd_kcontrol_new_t audigy_output_digital =
+{
+	iface:		SNDRV_CTL_ELEM_IFACE_MIXER,
+	name:		"Audigy Digital Output Switch",
+	info:		audigy_output_info,
+	get:		audigy_output_get,
+	put:		audigy_output_put,
+	private_value:	0x04,
+};
+#endif // XXX
+
+
+/*
+ */
 static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
 {
 	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
@@ -407,6 +477,7 @@
 
 	for (pcm = 0; pcm < 32; pcm++) {
 		emu10k1_pcm_mixer_t *mix;
+		int v;
 		
 		mix = &emu->pcm_mixer[pcm];
 		mix->epcm = NULL;
@@ -417,11 +488,10 @@
 		kctl->id.index = pcm;
 		if ((err = snd_ctl_add(card, kctl)))
 			return err;
-		if (emu->audigy) {
-			mix->send_routing[0] = mix->send_routing[1] = mix->send_routing[2] = 0x3210;
-		} else {
-			mix->send_routing[0] = mix->send_routing[1] = mix->send_routing[2] = 0x03020100;
-		}
+		for (v = 0; v < 4; v++)
+			mix->send_routing[0][v] = 
+				mix->send_routing[1][v] = 
+				mix->send_routing[2][v] = v;
 		
 		if ((kctl = mix->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
 			return -ENOMEM;
@@ -457,10 +527,23 @@
 			return err;
 	}
 
-	if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
-		return -ENOMEM;
-	if ((err = snd_ctl_add(card, kctl)))
-		return err;
+	if (emu->audigy) {
+#if 0 // XXX
+		if ((kctl = snd_ctl_new1(&audigy_output_analog, emu)) == NULL)
+			return -ENOMEM;
+		if ((err = snd_ctl_add(card, kctl)))
+			return err;
+		if ((kctl = snd_ctl_new1(&audigy_output_digital, emu)) == NULL)
+			return -ENOMEM;
+		if ((err = snd_ctl_add(card, kctl)))
+			return err;
+#endif // XXX
+	} else {
+		if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
+			return -ENOMEM;
+		if ((err = snd_ctl_add(card, kctl)))
+			return err;
+	}
 
 	return 0;
 }
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/emu10k1/emupcm.c	Tue Feb 26 11:57:56 2002
@@ -237,8 +237,8 @@
 	emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
 	unsigned int silent_page, tmp;
 	int voice, stereo, w_16;
-	unsigned char attn, send_a, send_b, send_c, send_d;
-	unsigned short send_routing;
+	unsigned char attn, send_amount[8];
+	unsigned char send_routing[8];
 	unsigned long flags;
 	unsigned int pitch_target;
 
@@ -260,15 +260,16 @@
 	/* volume parameters */
 	if (extra) {
 		attn = 0;
-		send_routing = emu->audigy ? 0x03020100 : 0x3210;
-		send_a = send_b = send_c = send_d = 0x00;
+		memset(send_routing, 0, sizeof(send_routing));
+		send_routing[0] = 0;
+		send_routing[1] = 1;
+		send_routing[2] = 2;
+		send_routing[3] = 3;
+		memset(send_amount, 0, sizeof(send_amount));
 	} else {
 		tmp = stereo ? (master ? 1 : 2) : 0;
-		send_a = mix->send_volume[tmp][0];
-		send_b = mix->send_volume[tmp][1];
-		send_c = mix->send_volume[tmp][2];
-		send_d = mix->send_volume[tmp][3];
-		send_routing = mix->send_routing[tmp];
+		memcpy(send_routing, &mix->send_routing[tmp][0], 8);
+		memcpy(send_amount, &mix->send_volume[tmp][0], 8);
 	}
 
 	if (master) {
@@ -290,16 +291,29 @@
 
 	// setup routing
 	if (emu->audigy) {
-		snd_emu10k1_ptr_write(emu, A_FXRT1, voice, send_routing);
-		snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, 0); /* no effects */
-		snd_emu10k1_ptr_write(emu, A_FXRT2, voice, 0); /* channels EFGH */
+		snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
+				      ((unsigned int)send_routing[3] << 24) |
+				      ((unsigned int)send_routing[2] << 16) |
+				      ((unsigned int)send_routing[1] << 8) |
+				      (unsigned int)send_routing[0]);
+		snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
+				      ((unsigned int)send_routing[7] << 24) |
+				      ((unsigned int)send_routing[6] << 16) |
+				      ((unsigned int)send_routing[5] << 8) |
+				      (unsigned int)send_routing[4]);
+		snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice,
+				      ((unsigned int)send_amount[4] << 24) |
+				      ((unsigned int)send_amount[5] << 16) |
+				      ((unsigned int)send_amount[6] << 8) |
+				      (unsigned int)send_amount[7]);
 	} else
-		snd_emu10k1_ptr_write(emu, FXRT, voice, send_routing << 16);
+		snd_emu10k1_ptr_write(emu, FXRT, voice,
+				      snd_emu10k1_compose_send_routing(send_routing));
 	// Stop CA
 	// Assumption that PT is already 0 so no harm overwriting
-	snd_emu10k1_ptr_write(emu, PTRX, voice, (send_a << 8) | send_b);
-	snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_d << 24));
-	snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_c << 24));
+	snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
+	snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
+	snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
 	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
 	snd_emu10k1_ptr_write(emu, CCCA, voice, evoice->epcm->ccca_start_addr |
 			      emu10k1_select_interprom(pitch_target) |
@@ -753,7 +767,7 @@
 	emu10k1_pcm_t *epcm;
 	emu10k1_pcm_mixer_t *mix;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	int err;
+	int i, err;
 
 	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
 	if (epcm == NULL)
@@ -773,8 +787,8 @@
 		return err;
 	}
 	mix = &emu->pcm_mixer[substream->number];
-	mix->send_routing[0] = mix->send_routing[1] = mix->send_routing[2] =
-		emu->audigy ? 0x03020100 : 0x3210;
+	for (i = 0; i < 4; i++)
+		mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
 	memset(&mix->send_volume, 0, sizeof(mix->send_volume));
 	mix->send_volume[0][0] = mix->send_volume[0][1] =
 	mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
diff -Nru a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
--- a/sound/pci/emu10k1/emuproc.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/emu10k1/emuproc.c	Tue Feb 26 11:57:58 2002
@@ -250,6 +250,7 @@
 		}
 	}
 	emu->proc_entry = entry;
+	entry = NULL;
 	if ((entry = snd_info_create_card_entry(emu->card, "fx8010_gpr", emu->card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
@@ -262,6 +263,7 @@
 		}
 	}
 	emu->proc_entry_fx8010_gpr = entry;
+	entry = NULL;
 	if (!emu->audigy && (entry = snd_info_create_card_entry(emu->card, "fx8010_tram_data", emu->card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
@@ -274,6 +276,7 @@
 		}
 	}
 	emu->proc_entry_fx8010_tram_data = entry;
+	entry = NULL;
 	if (!emu->audigy && (entry = snd_info_create_card_entry(emu->card, "fx8010_tram_addr", emu->card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
@@ -286,6 +289,7 @@
 		}
 	}
 	emu->proc_entry_fx8010_tram_addr = entry;
+	entry = NULL;
 	if ((entry = snd_info_create_card_entry(emu->card, "fx8010_code", emu->card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
@@ -298,6 +302,7 @@
 		}
 	}
 	emu->proc_entry_fx8010_code = entry;
+	entry = NULL;
 	if ((entry = snd_info_create_card_entry(emu->card, "fx8010_acode", emu->card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = emu;
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/ens1370.c	Tue Feb 26 11:57:58 2002
@@ -2049,7 +2049,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("Ensoniq AudioPCI soundcard not found or device busy\n");
+		printk(KERN_ERR "Ensoniq AudioPCI soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c
--- a/sound/pci/es1938.c	Tue Feb 26 11:58:00 2002
+++ b/sound/pci/es1938.c	Tue Feb 26 11:58:00 2002
@@ -1626,7 +1626,7 @@
 			    SLSB_REG(chip, FMLOWADDR),
 			    SLSB_REG(chip, FMHIGHADDR),
 			    OPL3_HW_OPL3, 1, &opl3) < 0) {
-	        snd_printk("OPL3 not detected at 0x%lx\n",
+		printk(KERN_ERR "es1938: OPL3 not detected at 0x%lx\n",
 			   SLSB_REG(chip, FMLOWADDR));
 	} else {
 	        if ((err = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
@@ -1640,7 +1640,7 @@
 	}
 	if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 				chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) {
-		snd_printk("unable to initialize MPU-401\n");
+		printk(KERN_ERR "es1938: unable to initialize MPU-401\n");
 	}
 #ifndef LINUX_2_2
 	chip->gameport.io = chip->game_port;
@@ -1683,7 +1683,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("ESS Solo-1 soundcard not found or device busy\n");
+		printk(KERN_ERR "ESS Solo-1 soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c	Tue Feb 26 11:58:00 2002
+++ b/sound/pci/es1968.c	Tue Feb 26 11:58:00 2002
@@ -2720,7 +2720,7 @@
 	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 				       chip->io_port + ESM_MPU401_PORT, 1,
 				       chip->irq, 0, &chip->rmidi)) < 0) {
-		printk(KERN_INFO "es1968: skipping MPU-401 MIDI support..\n");
+		printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
 	}
 
 	/* card switches */
@@ -2783,7 +2783,7 @@
 
         if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("ESS Maestro soundcard not found or device busy\n");
+		printk(KERN_ERR "ESS Maestro soundcard not found or device busy\n");
 #endif
 		return err;
 	}
@@ -2792,7 +2792,7 @@
 	   leave the speaking emitting an annoying noise, so we catch
 	   shutdown events. */ 
 	if (register_reboot_notifier(&snd_es1968_nb)) {
-		snd_printk("reboot notifier registration failed; may make noise at shutdown.\n");
+		printk(KERN_ERR "reboot notifier registration failed; may make noise at shutdown.\n");
 	}
 #endif
 	return 0;
diff -Nru a/sound/pci/fm801.c b/sound/pci/fm801.c
--- a/sound/pci/fm801.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/fm801.c	Tue Feb 26 11:57:58 2002
@@ -1104,7 +1104,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("ForteMedia FM801 soundcard not found or device busy\n");
+		printk(KERN_ERR "ForteMedia FM801 soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/ice1712.c b/sound/pci/ice1712.c
--- a/sound/pci/ice1712.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/ice1712.c	Tue Feb 26 11:57:59 2002
@@ -1718,7 +1718,7 @@
 	if (rpcm)
 		*rpcm = pcm;
 
-	printk("Consumer PCM code does not work well at the moment --jk\n");
+	printk(KERN_WARNING "Consumer PCM code does not work well at the moment --jk\n");
 
 	return 0;
 }
@@ -2410,7 +2410,7 @@
 		ac97.private_data = ice;
 		ac97.private_free = snd_ice1712_mixer_free_ac97;
 		if ((err = snd_ac97_mixer(ice->card, &ac97, &ice->ac97)) < 0) {
-			snd_printk("ice1712: cannot initialize ac97 for consumer, skipped\n");
+			printk(KERN_WARNING "ice1712: cannot initialize ac97 for consumer, skipped\n");
 			// return err;
 		} else {
 			if ((err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_digmix_route_ac97, ice))) < 0)
@@ -2428,7 +2428,7 @@
 		ac97.private_data = ice;
 		ac97.private_free = snd_ice1712_mixer_free_ac97;
 		if ((err = snd_ac97_mixer(ice->card, &ac97, &ice->ac97)) < 0) {
-			snd_printk("ice1712: cannot initialize pro ac97, skipped\n");
+			printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n");
 			// return err;
 		}
 		return 0;
@@ -4329,7 +4329,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("ICE1712 soundcard not found or device busy\n");
+		printk(KERN_ERR "ICE1712 soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/intel8x0.c	Tue Feb 26 11:57:56 2002
@@ -35,6 +35,7 @@
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
+#include <sound/mpu401.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
 
@@ -52,10 +53,24 @@
 		"{SiS,SI7012},"
 		"{NVidia,NForce Audio}}");
 
+#define SUPPORT_JOYSTICK 1
+#define SUPPORT_MIDI 1
+
 static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int snd_ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+#ifdef SUPPORT_JOYSTICK
+static int snd_joystick_port[SNDRV_CARDS] =
+#ifdef CONFIG_ISA
+	{0x200};	/* enable as default */
+#else
+	{0};	/* disabled */
+#endif
+#endif
+#ifdef SUPPORT_MIDI
+static int snd_mpu_port[SNDRV_CARDS]; /* disabled */
+#endif
 
 MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(snd_index, "Index value for Intel i8x0 soundcard.");
@@ -69,6 +84,16 @@
 MODULE_PARM(snd_ac97_clock, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(snd_ac97_clock, "AC'97 codec clock (0 = auto-detect).");
 MODULE_PARM_SYNTAX(snd_ac97_clock, SNDRV_ENABLED ",default:0");
+#ifdef SUPPORT_JOYSTICK
+MODULE_PARM(snd_joystick_port, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(snd_joystick_port, "Joystick port address for Intel i8x0 soundcard. (0 = disabled)");
+MODULE_PARM_SYNTAX(snd_joystick_port, SNDRV_ENABLED ",allows:{{0},{0x200}},dialog:list");
+#endif
+#ifdef SUPPORT_MIDI
+MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(snd_mpu_port, "MPU401 port # for Intel i8x0 driver.");
+MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x300}},dialog:list");
+#endif
 
 /*
  *  Direct registers
@@ -231,6 +256,8 @@
 	ac97_t *ac97;
 	ac97_t *ac97sec;
 
+	snd_rawmidi_t *rmidi;
+
 	spinlock_t reg_lock;
 	spinlock_t ac97_lock;
 	snd_info_entry_t *proc_entry;
@@ -256,9 +283,9 @@
 	{ 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 82801BA */
 	{ 0x8086, 0x2485, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* ICH3 */
 	{ 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
-	{ 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7012 */
 	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* NFORCE */
+	{ 0x764d, 0x1022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
 	{ 0, }
 };
 
@@ -1087,6 +1114,7 @@
 {
 	snd_card_t *card = chip->card;
 
+	chip->in_suspend = 1;
 	snd_power_lock(card);
 	if (card->power_state == SNDRV_CTL_POWER_D3hot)
 		goto __skip;
@@ -1364,6 +1392,7 @@
 	{ PCI_DEVICE_ID_INTEL_ICH3, "Intel ICH3" },
 	{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia NForce" },
+	{ 0x1022, "AMD-8111" },
 	{ 0, 0 },
 };
 
@@ -1416,6 +1445,16 @@
 		}
 	}
 	
+	if (snd_mpu_port[dev] == 0x300 || snd_mpu_port[dev] == 0x330) {
+		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
+					       snd_mpu_port[dev], 0,
+					       -1, 0, &chip->rmidi)) < 0) {
+			printk(KERN_ERR "intel8x0: no UART401 device at 0x%x, skipping.\n", snd_mpu_port[dev]);
+			snd_mpu_port[dev] = 0;
+		}
+	} else
+		snd_mpu_port[dev] = 0;
+
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->port, chip->irq);
 
@@ -1450,16 +1489,77 @@
 #endif
 };
 
+
+#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
+/*
+ * initialize joystick/midi addresses
+ */
+
+static int __devinit snd_intel8x0_joystick_probe(struct pci_dev *pci,
+						 const struct pci_device_id *id)
+{
+	static int dev = 0;
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!snd_enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	if (snd_joystick_port[dev] > 0 || snd_mpu_port[dev] > 0) {
+		u16 val;
+		pci_read_config_word(pci, 0xe6, &val);
+		if (snd_joystick_port[dev] > 0)
+			val |= 0x100;
+		if (snd_mpu_port[dev] == 0x300 || snd_mpu_port[dev] == 0x330)
+			val |= 0x20;
+		pci_write_config_word(pci, 0xe6, val | 0x100);
+
+		if (snd_mpu_port[dev] == 0x300 || snd_mpu_port[dev] == 0x330) {
+			u8 b;
+			pci_read_config_byte(pci, 0xe2, &b);
+			if (snd_mpu_port[dev] == 0x300)
+				b |= 0x08;
+			else
+				b &= ~0x08;
+			pci_write_config_byte(pci, 0xe2, b);
+		}
+	}
+	return 0;
+}
+
+static struct pci_device_id snd_intel8x0_joystick_ids[] __devinitdata = {
+	{ 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 82801AA */
+	{ 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 82901AB */
+	{ 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2 */
+	{ 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2M */
+	{ 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* ICH3 */
+	// { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 440MX */
+	// { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* SI7012 */
+	{ 0x10de, 0x01b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* NFORCE */
+	{ 0, }
+};
+
+static struct pci_driver joystick_driver = {
+	name: "Intel ICH Joystick",
+	id_table: snd_intel8x0_joystick_ids,
+	probe: snd_intel8x0_joystick_probe,
+};
+#endif
+
 static int __init alsa_card_intel8x0_init(void)
 {
 	int err;
 
         if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-                snd_printk("Intel ICH soundcard not found or device busy\n");
+		printk(KERN_ERR "Intel ICH soundcard not found or device busy\n");
 #endif
                 return err;
         }
+#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
+	pci_module_init(&joystick_driver);
+#endif
         return 0;
 
 }
@@ -1467,6 +1567,9 @@
 static void __exit alsa_card_intel8x0_exit(void)
 {
 	pci_unregister_driver(&driver);
+#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
+	pci_unregister_driver(&joystick_driver);
+#endif
 }
 
 module_init(alsa_card_intel8x0_init)
diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
--- a/sound/pci/korg1212/korg1212.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/korg1212/korg1212.c	Tue Feb 26 11:57:56 2002
@@ -1953,27 +1953,27 @@
 
         korg1212->res_iomem = request_mem_region(korg1212->iomem, iomem_size, "korg1212");
         if (korg1212->res_iomem == NULL) {
-                PRINTK("unable to grab region 0x%lx-0x%lx\n",
+		snd_printk("unable to grab region 0x%lx-0x%lx\n",
                            korg1212->iomem, korg1212->iomem + iomem_size - 1);
                 return -EBUSY;
         }
 
         korg1212->res_ioport = request_region(korg1212->ioport, ioport_size, "korg1212");
         if (korg1212->res_ioport == NULL) {
-                PRINTK("unable to grab region 0x%lx-0x%lx\n",
+		snd_printk("unable to grab region 0x%lx-0x%lx\n",
                            korg1212->ioport, korg1212->ioport + ioport_size - 1);
                 return -EBUSY;
         }
 
         korg1212->res_iomem2 = request_mem_region(korg1212->iomem2, iomem2_size, "korg1212");
         if (korg1212->res_iomem2 == NULL) {
-                PRINTK("unable to grab region 0x%lx-0x%lx\n",
+		snd_printk("unable to grab region 0x%lx-0x%lx\n",
                            korg1212->iomem2, korg1212->iomem2 + iomem2_size - 1);
                 return -EBUSY;
         }
 
         if ((korg1212->iobase = (unsigned long) ioremap(korg1212->iomem, iomem_size)) == 0) {
-                PRINTK("unable to remap memory region 0x%lx-0x%lx\n", korg1212->iobase,
+		snd_printk("unable to remap memory region 0x%lx-0x%lx\n", korg1212->iobase,
                            korg1212->iobase + iomem_size - 1);
                 return -EBUSY;
         }
@@ -1983,7 +1983,7 @@
                           "korg1212", (void *) korg1212);
 
         if (err) {
-                PRINTK("unable to grab IRQ %d\n", pci->irq);
+		snd_printk("unable to grab IRQ %d\n", pci->irq);
                 return -EBUSY;
         }
 
@@ -2034,7 +2034,7 @@
 	korg1212->sharedBufferPhy = (unsigned long)phys_addr;
 
         if (korg1212->sharedBufferPtr == NULL) {
-                PRINTK("can not allocate shared buffer memory (%d bytes)\n", sizeof(KorgSharedBuffer));
+		snd_printk("can not allocate shared buffer memory (%d bytes)\n", sizeof(KorgSharedBuffer));
                 return -ENOMEM;
         }
 
@@ -2050,7 +2050,7 @@
 	korg1212->PlayDataPhy = (u32)phys_addr;
 
         if (korg1212->playDataBufsPtr == NULL) {
-                PRINTK("can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+		snd_printk("can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
 
@@ -2063,7 +2063,7 @@
 	korg1212->RecDataPhy = (u32)phys_addr;
 
         if (korg1212->recordDataBufsPtr == NULL) {
-                PRINTK("can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+		snd_printk("can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
 
@@ -2091,7 +2091,7 @@
 	korg1212->dspMemPhy = (u32)phys_addr;
 
         if (korg1212->dspMemPtr == NULL) {
-                PRINTK("can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
+		snd_printk("can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
                 return -ENOMEM;
         }
 
@@ -2114,7 +2114,7 @@
         if (snd_korg1212_downloadDSPCode(korg1212))
         	return -EBUSY;
 
-        PRINTK("dspMemPhy       = %08x U[%08x]\n"
+	printk(KERN_INFO "dspMemPhy       = %08x U[%08x]\n"
                "PlayDataPhy     = %08x L[%08x]\n"
                "RecDataPhy      = %08x L[%08x]\n"
                "VolumeTablePhy  = %08x L[%08x]\n"
@@ -2312,7 +2312,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		PRINTK("No Korg 1212IO cards found\n");
+		printk(KERN_ERR "No Korg 1212IO cards found\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/maestro3.c	Tue Feb 26 11:57:56 2002
@@ -2676,7 +2676,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("Maestro3/Allegro soundcard not found or device busy\n");
+		printk(KERN_ERR "Maestro3/Allegro soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/nm256/nm256.c	Tue Feb 26 11:57:58 2002
@@ -331,7 +331,7 @@
 	offset -= chip->buffer_start;
 #ifdef SNDRV_CONFIG_DEBUG
 	if (offset < 0 || offset >= chip->buffer_size) {
-		printk("nm256: write_buffer invalid offset = %d size = %d\n", offset, size);
+		snd_printk("write_buffer invalid offset = %d size = %d\n", offset, size);
 		return;
 	}
 #endif
@@ -1436,10 +1436,10 @@
 		pval = snd_nm256_readw(chip, NM_MIXER_PRESENCE);
 		if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
 			if (! force_load) {
-				printk(KERN_INFO "nm256: no ac97 is found!\n");
-				printk(KERN_INFO "  force the driver to load by passing in the module parameter\n");
-				printk(KERN_INFO "    snd_force_ac97=1\n");
-				printk(KERN_INFO "  or try sb16 or cs423x drivers instead.\n");
+				printk(KERN_ERR "nm256: no ac97 is found!\n");
+				printk(KERN_ERR "  force the driver to load by passing in the module parameter\n");
+				printk(KERN_ERR "    snd_force_ac97=1\n");
+				printk(KERN_ERR "  or try sb16 or cs423x drivers instead.\n");
 				err = -ENXIO;
 				goto __error;
 			}
@@ -1477,8 +1477,8 @@
 	chip->buffer_start = chip->buffer_end - chip->buffer_size;
 	chip->buffer_addr += chip->buffer_start;
 
-	snd_printd("NM256: Mapping port 1 from 0x%x - 0x%x\n",
-		   chip->buffer_start, chip->buffer_end);
+	printk(KERN_INFO "nm256: Mapping port 1 from 0x%x - 0x%x\n",
+	       chip->buffer_start, chip->buffer_end);
 
 	chip->res_buffer = request_mem_region(chip->buffer_addr,
 					      chip->buffer_size,
@@ -1652,7 +1652,7 @@
 	int err;
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("NeoMagic 256 audio soundchip not found or device busy\n");
+		printk(KERN_ERR "NeoMagic 256 audio soundchip not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/rme96.c b/sound/pci/rme96.c
--- a/sound/pci/rme96.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/rme96.c	Tue Feb 26 11:57:58 2002
@@ -2486,7 +2486,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("No RME Digi96 cards found\n");
+		printk(KERN_ERR "No RME Digi96 cards found\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
--- a/sound/pci/rme9652/rme9652.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/rme9652/rme9652.c	Tue Feb 26 11:57:59 2002
@@ -392,7 +392,7 @@
 	if (offset < period_size) {
 		if (offset > rme9652->max_jitter) {
 			if (frag)
-				printk("Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", status, offset);
+				printk(KERN_ERR "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", status, offset);
 		} else if (!frag)
 			return 0;
 		offset -= rme9652->max_jitter;
@@ -401,7 +401,7 @@
 	} else {
 		if (offset > period_size + rme9652->max_jitter) {
 			if (!frag)
-				printk("Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", status, offset);
+				printk(KERN_ERR "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", status, offset);
 		} else if (frag)
 			return period_size;
 		offset -= rme9652->max_jitter;
@@ -1887,8 +1887,7 @@
 #endif
 		}
 
-		snd_printk("%s: no buffers available\n",
-			   rme9652->card_name);
+		printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name);
 		return -ENOMEM;
 	}
 
@@ -1901,24 +1900,16 @@
 
 	/* Align to bus-space 64K boundary */
 
-	cb_bus = cb_addr;
-	cb_bus = (cb_bus + 0xFFFF) & ~0xFFFFl;
-
-	pb_bus = pb_addr;
-	pb_bus = (pb_bus + 0xFFFF) & ~0xFFFFl;
+	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
+	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
 
 	/* Tell the card where it is */
 
 	rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
 	rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
 
-#if 0 // not all architectures have this macro
-	rme9652->capture_buffer = bus_to_virt(cb_bus);
-	rme9652->playback_buffer = bus_to_virt(pb_bus);
-#else
-	rme9652->capture_buffer += cb_bus - cb_addr;
-	rme9652->playback_buffer += pb_bus - pb_addr;
-#endif
+	rme9652->capture_buffer = cb + (cb_bus - cb_addr);
+	rme9652->playback_buffer = pb + (pb_bus - pb_addr);
 
 	return 0;
 }
@@ -2732,7 +2723,7 @@
 {
 	if (pci_module_init(&driver) < 0) {
 #ifdef MODULE
-		snd_printk("RME Digi9652/Digi9636: no cards found\n");
+		printk(KERN_ERR "RME Digi9652/Digi9636: no cards found\n");
 #endif
 		return -ENODEV;
 	}
diff -Nru a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
--- a/sound/pci/sonicvibes.c	Tue Feb 26 11:57:57 2002
+++ b/sound/pci/sonicvibes.c	Tue Feb 26 11:57:57 2002
@@ -1551,7 +1551,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("S3 SonicVibes soundcard not found or device busy\n");
+		printk(KERN_ERR "S3 SonicVibes soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
--- a/sound/pci/trident/trident.c	Tue Feb 26 11:57:56 2002
+++ b/sound/pci/trident/trident.c	Tue Feb 26 11:57:56 2002
@@ -223,7 +223,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("Trident 4DWave PCI soundcard not found or device busy\n");
+		printk(KERN_ERR "Trident 4DWave PCI soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/via686.c b/sound/pci/via686.c
--- a/sound/pci/via686.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/via686.c	Tue Feb 26 11:57:58 2002
@@ -246,6 +246,16 @@
 	return -EIO;
 }
  
+static void snd_via686a_codec_wait(ac97_t *ac97)
+{
+	via686a_t *chip = snd_magic_cast(via686a_t, ac97->private_data, return);
+	int err;
+	err = snd_via686a_codec_ready(chip, ac97->num);
+	/* here we need to wait fairly for long time.. */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ/2);
+}
+
 static void snd_via686a_codec_write(ac97_t *ac97,
 				    unsigned short reg,
 				    unsigned short val)
@@ -811,6 +821,7 @@
 	ac97.write = snd_via686a_codec_write;
 	ac97.read = snd_via686a_codec_read;
 	ac97.init = snd_via686a_codec_init;
+	ac97.wait = snd_via686a_codec_wait;
 	ac97.private_data = chip;
 	ac97.private_free = snd_via686a_mixer_free_ac97;
 	ac97.clock = chip->ac97_clock;
@@ -1178,7 +1189,7 @@
 	pci_write_config_byte(pci, 0x43, legacy_cfg);
 	if (legacy & 0x02) {
 		if (check_region(snd_mpu_port[dev], 2)) {
-			snd_printk("unable to get MPU-401 port at 0x%lx, skipping\n", snd_mpu_port[dev]);
+			printk(KERN_WARNING "unable to get MPU-401 port at 0x%lx, skipping\n", snd_mpu_port[dev]);
 			legacy &= ~0x02;
 			pci_write_config_byte(pci, 0x42, legacy);
 			goto __skip_mpu;
@@ -1187,7 +1198,7 @@
 					snd_mpu_port[dev], 0,
 					pci->irq, 0,
 					&chip->rmidi) < 0) {
-			snd_printk("unable to initialize MPU-401 at 0x%lx, skipping\n", snd_mpu_port[dev]);
+			printk(KERN_WARNING "unable to initialize MPU-401 at 0x%lx, skipping\n", snd_mpu_port[dev]);
 			legacy &= ~0x02;
 			pci_write_config_byte(pci, 0x42, legacy);
 			goto __skip_mpu;
@@ -1239,7 +1250,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("VIA 82C686A soundcard not found or device busy\n");
+		printk(KERN_ERR "VIA 82C686A soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/via8233.c b/sound/pci/via8233.c
--- a/sound/pci/via8233.c	Tue Feb 26 11:57:58 2002
+++ b/sound/pci/via8233.c	Tue Feb 26 11:57:58 2002
@@ -877,7 +877,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("VIA 8233 soundcard not found or device busy\n");
+		printk(KERN_ERR "VIA 8233 soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
--- a/sound/pci/ymfpci/ymfpci.c	Tue Feb 26 11:57:59 2002
+++ b/sound/pci/ymfpci/ymfpci.c	Tue Feb 26 11:57:59 2002
@@ -197,7 +197,7 @@
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
 					       snd_mpu_port[dev], 0,
 					       pci->irq, 0, &chip->rawmidi)) < 0) {
-			printk(KERN_INFO "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", snd_mpu_port[dev]);
+			printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", snd_mpu_port[dev]);
 		} else {
 			legacy_ctrl &= ~0x10; /* disable MPU401 irq */
 			pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
@@ -208,7 +208,7 @@
 					   snd_fm_port[dev],
 					   snd_fm_port[dev] + 2,
 					   OPL3_HW_OPL3, 0, &opl3)) < 0) {
-			printk(KERN_INFO "ymfpci: cannot initialize FM OPL3 at 0x%lx, skipping...\n", snd_fm_port[dev]);
+			printk(KERN_WARNING "ymfpci: cannot initialize FM OPL3 at 0x%lx, skipping...\n", snd_fm_port[dev]);
 		} else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
 			snd_card_free(card);
 			snd_printk("cannot create opl3 hwdep\n");
@@ -216,7 +216,7 @@
 		}
 	}
 	if ((err = snd_ymfpci_joystick(chip)) < 0) {
-		printk(KERN_INFO "ymfpci: cannot initialize joystick, skipping...\n");
+		printk(KERN_WARNING "ymfpci: cannot initialize joystick, skipping...\n");
 	}
 	strcpy(card->driver, str);
 	sprintf(card->shortname, "Yamaha DS-XG PCI (%s)", str);
@@ -287,7 +287,7 @@
 
 	if ((err = pci_module_init(&driver)) < 0) {
 #ifdef MODULE
-		snd_printk("Yamaha DS-XG PCI soundcard not found or device busy\n");
+		printk(KERN_ERR "Yamaha DS-XG PCI soundcard not found or device busy\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/ppc/keywest.c b/sound/ppc/keywest.c
--- a/sound/ppc/keywest.c	Tue Feb 26 11:57:59 2002
+++ b/sound/ppc/keywest.c	Tue Feb 26 11:57:59 2002
@@ -179,7 +179,7 @@
 	i2c_device = find_compatible_devices("i2c", "keywest");
 	
 	if (i2c_device == 0) {
-		snd_printk("No Keywest i2c devices found.\n");
+		printk(KERN_ERR "pmac: No Keywest i2c devices found.\n");
 		return -ENODEV;
 	}
 	
diff -Nru a/sound/ppc/powermac.c b/sound/ppc/powermac.c
--- a/sound/ppc/powermac.c	Tue Feb 26 11:57:59 2002
+++ b/sound/ppc/powermac.c	Tue Feb 26 11:57:59 2002
@@ -150,7 +150,7 @@
 	int err;
 	if ((err = snd_pmac_probe() < 0)) {
 #ifdef MODULE
-		snd_printk("no PMac soundchip found\n");
+		printk(KERN_ERR "no PMac soundchip found\n");
 #endif
 		return err;
 	}
diff -Nru a/sound/sound_core.c b/sound/sound_core.c
--- a/sound/sound_core.c	Tue Feb 26 11:57:59 2002
+++ b/sound/sound_core.c	Tue Feb 26 11:57:59 2002
@@ -17,7 +17,7 @@
  *	plug into this. The fact they dont all go via OSS doesn't mean 
  *	they don't have to implement the OSS API. There is a lot of logic
  *	to keeping much of the OSS weight out of the code in a compatibility
- *	module, but its up to the driver to rember to load it...
+ *	module, but it's up to the driver to rember to load it...
  *
  *	The code provides a set of functions for registration of devices
  *	by type. This is done rather than providing a single call so that
@@ -171,10 +171,10 @@
 		return r;
 	}
 	
-	if (r == low)
+	if (r < SOUND_STEP)
 		sprintf (name_buf, "%s", name);
 	else
-		sprintf (name_buf, "%s%d", name, (r - low) / SOUND_STEP);
+		sprintf (name_buf, "%s%d", name, r / SOUND_STEP);
 	s->de = devfs_register (devfs_handle, name_buf,
 				DEVFS_FL_NONE, SOUND_MAJOR, s->unit_minor,
 				S_IFCHR | mode, fops, NULL);
@@ -215,7 +215,7 @@
  *	15	*16		unused
  */
 
-static struct sound_unit *chains[16];
+static struct sound_unit *chains[SOUND_STEP];
 
 /**
  *	register_sound_special - register a special sound node
@@ -229,17 +229,22 @@
  
 int register_sound_special(struct file_operations *fops, int unit)
 {
-	char *name;
+	const int chain = unit % (SOUND_STEP-1);
+	int max_unit = 128 + chain;
+	const char *name;
+	char _name[16];
 
-	switch (unit) {
+	switch (chain) {
 	    case 0:
 		name = "mixer";
 		break;
 	    case 1:
 		name = "sequencer";
-		break;
+		if (unit >= SOUND_STEP)
+			goto __unknown;
+		max_unit = unit + 1;
 	    case 2:
-		name = "midi00";
+		name = "midi";
 		break;
 	    case 3:
 		name = "dsp";
@@ -247,17 +252,11 @@
 	    case 4:
 		name = "audio";
 		break;
-	    case 5:
-		name = "unknown5";
-		break;
-	    case 6:		/* Was once sndstat */
-		name = "unknown6";
-		break;
-	    case 7:
-		name = "unknown7";
-		break;
 	    case 8:
 		name = "sequencer2";
+		if (unit >= SOUND_STEP)
+			goto __unknown;
+		max_unit = unit + 1;
 		break;
 	    case 9:
 		name = "dmmidi";
@@ -265,9 +264,6 @@
 	    case 10:
 		name = "dmfm";
 		break;
-	    case 11:
-		name = "unknown11";
-		break;
 	    case 12:
 		name = "adsp";
 		break;
@@ -278,10 +274,16 @@
 		name = "admmidi";
 		break;
 	    default:
-		name = "unknown";
+	    	{
+		    __unknown:
+			sprintf(_name, "unknown%d", chain);
+		    	if (unit >= SOUND_STEP)
+		    		strcat(_name, "-");
+		    	name = _name;
+		}
 		break;
 	}
-	return sound_insert_unit(&chains[unit&15], fops, -1, unit, unit+1,
+	return sound_insert_unit(&chains[chain], fops, -1, unit, max_unit,
 				 name, S_IRUSR | S_IWUSR);
 }
  
diff -Nru a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
--- a/sound/synth/emux/emux_synth.c	Tue Feb 26 11:57:59 2002
+++ b/sound/synth/emux/emux_synth.c	Tue Feb 26 11:57:59 2002
@@ -629,6 +629,25 @@
 /*
  * calculate pitch parameter
  */
+static unsigned char pan_volumes[256] = {
+0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
+0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
+0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
+0x77,0x79,0x7b,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x89,0x8b,0x8d,0x8f,0x90,0x92,
+0x94,0x96,0x97,0x99,0x9a,0x9c,0x9e,0x9f,0xa1,0xa2,0xa4,0xa5,0xa7,0xa8,0xaa,0xab,
+0xad,0xae,0xaf,0xb1,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbe,0xbf,0xc0,
+0xc1,0xc2,0xc3,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,
+0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdc,0xdd,0xde,0xdf,
+0xdf,0xe0,0xe1,0xe2,0xe2,0xe3,0xe4,0xe4,0xe5,0xe6,0xe6,0xe7,0xe8,0xe8,0xe9,0xe9,
+0xea,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,0xf1,0xf1,
+0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf7,
+0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,
+0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
 static int
 calc_pan(snd_emux_voice_t *vp)
 {
@@ -646,6 +665,16 @@
 	}
 	LIMITVALUE(pan, 0, 255);
 
+#if 1
+	/* using volume table */
+	if (vp->apan != (int)pan_volumes[pan]) {
+		vp->apan = pan_volumes[pan];
+		vp->aaux = pan_volumes[255 - pan];
+		return 1;
+	}
+	return 0;
+#else
+	/* assuming linear volume */
 	if (pan != vp->apan) {
 		vp->apan = pan;
 		if (pan == 0)
@@ -655,6 +684,7 @@
 		return 1;
 	} else
 		return 0;
+#endif
 }
 
 
