diff -u --recursive --new-file v2.3.37/linux/CREDITS linux/CREDITS
--- v2.3.37/linux/CREDITS	Thu Jan  6 12:57:47 2000
+++ linux/CREDITS	Fri Jan  7 11:55:28 2000
@@ -287,9 +287,9 @@
 E: knan@mo.himolde.no
 D: Misc kernel hacks
 
-N: Zoltan Boszormenyi
-E: zboszor@mol.hu
-D: MTRR emulation with Cyrix style ARR registers
+N: Zoltįn Böszörményi
+E: zboszor@mail.externet.hu
+D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
 
 N: John Boyd
 E: boyd@cis.ohio-state.edu
@@ -2401,7 +2401,8 @@
 S: USA
 
 N: Eric Youngdale
-E: eric@aib.com
+E: eric@andante.org
+W: http://www.andante.org
 D: General kernel hacker
 D: SCSI iso9660 and ELF
 S: 17 Canterbury Square #101
diff -u --recursive --new-file v2.3.37/linux/Documentation/Changes linux/Documentation/Changes
--- v2.3.37/linux/Documentation/Changes	Tue Dec 14 01:27:23 1999
+++ linux/Documentation/Changes	Fri Jan  7 11:43:09 2000
@@ -188,7 +188,7 @@
    You must use binutils 2.9.1.0.7 or later. Latest release is 2.9.1.0.25.
 Beware that binutils 2.9.1 (note the absence of a suffix) from the FSF
 does not work. If you are upgrading from earlier versions, you should
-consider upgrading to the latest 2.9.5.0.x release.
+consider upgrading to the latest 2.9.5.0.x (beta) release.
 
 Gnu C
 =====
@@ -526,10 +526,10 @@
 Installation notes:
 ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/release.binutils-2.9.1.0.25
 
-The 2.9.5.0.16 release:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.16.tar.bz2
+The 2.9.5.0.22 release:
+ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.22.tar.bz2
 Installation notes:
-ftp://ftp.varesearch.com/pub/support/hjl/binutils/release.binutils-2.9.5.0.16
+ftp://ftp.varesearch.com/pub/support/hjl/binutils/release.binutils-2.9.5.0.22
 
 Gnu C
 =====
@@ -815,15 +815,15 @@
 version.  Remember, you might need to use the --force option to get the
 upgrade to install.  ftp://contrib.redhat.com/ ,
 ftp://developer.redhat.com/ , or ftp://updates.redhat.com/  will have
-almost everything you need, and Red Hat 5.2 ships with most necessary
+almost everything you need, and Red Hat 6.1 ships with most necessary
 software.
 
    Those of you running Debian (or a different distribution that
 supports .deb packages) can look in the "unstable" and
 "project/experimental" directories of your favorite Debian mirror.  The
-Debian 2.0 release ships with most packages you need as well.
+Debian 2.2 release will ship with most packages you need as well.
 
-Please send info about any other packages that 2.2 "broke" or about any
-new features of 2.2 that require extra or new packages for use to Chris
+Please send info about any other packages that 2.3 "broke" or about any
+new features of 2.3 that require extra or new packages for use to Chris
 Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu).
 
diff -u --recursive --new-file v2.3.37/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.37/linux/Documentation/Configure.help	Tue Jan  4 13:57:16 2000
+++ linux/Documentation/Configure.help	Fri Jan  7 11:43:09 2000
@@ -2537,7 +2537,7 @@
   drive, PLIP link (Parallel Line Internet Protocol is mainly used to
   create a mini network by connecting the parallel ports of two local
   machines) etc., then you need to say Y here; please read
-  Documentation/parport.txt and drivers/misc/BUGS-parport.
+  Documentation/parport.txt and drivers/parport/BUGS-parport.
 
   For extensive information about drivers for many devices attaching
   to the parallel port see http://www.torque.net/linux-pp.html on the
@@ -7487,8 +7487,17 @@
   read the Token-Ring mini-HOWTO, available from
   http://metalab.unc.edu/mdw/linux.html#howto .
 
-  Also read the file linux/Documentation/networking/sktr.txt or check
+  Also read the file linux/Documentation/networking/tms380tr.txt or check
   http://www.auk.cx/tms380tr/
+
+SMC ISA TokenRing adapter support
+CONFIG_SMCTR
+  This is support for the ISA SMC Token Ring cards, specifically
+  SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A (8115T/A) adapters.
+
+  If you have such an adapter and would like to use it, say Y or M and
+  read the Token-Ring mini-HOWTO, available from
+  http://metalab.unc.edu/mdw/linux.html#howto .
 
 Traffic Shaper (EXPERIMENTAL)
 CONFIG_SHAPER
diff -u --recursive --new-file v2.3.37/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v2.3.37/linux/Documentation/devices.tex	Sat Oct  9 11:47:49 1999
+++ linux/Documentation/devices.tex	Fri Jan  7 12:59:38 2000
@@ -926,10 +926,10 @@
 \begin{devicelist}
 \major{29}{}{char }{Universal frame buffer}
 	\minor{0}{/dev/fb0}{First frame buffer}
-	\minor{32}{/dev/fb1}{Second frame buffer}
-	\minor{64}{/dev/fb2}{Third frame buffer}
+	\minor{1}{/dev/fb1}{Second frame buffer}
+	\minor{2}{/dev/fb2}{Third frame buffer}
 	\minordots
-	\minor{224}{/dev/fb7}{Eighth frame buffer}
+	\minor{31}{/dev/fb31}{32nd frame buffer}
 \end{devicelist}
 
 \noindent
diff -u --recursive --new-file v2.3.37/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.3.37/linux/Documentation/devices.txt	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/devices.txt	Fri Jan  7 12:59:38 2000
@@ -613,11 +613,12 @@
 		disks (see major number 3) except that the limit on
 		partitions is 15, like SCSI.
 
- 29 char	Universal frame buffer
+ 29 char	Universal frame buffers
 		  0 = /dev/fb0		First frame buffer
-		 32 = /dev/fb1		Second frame buffer
+		  1 = /dev/fb1		Second frame buffer
+		  2 = /dev/fb2		Third frame buffer
 		    ...
-		224 = /dev/fb7		Eighth frame buffer
+		 31 = /dev/fb31		32nd frame buffer
 
 		All additional minor numbers are reserved.
 
diff -u --recursive --new-file v2.3.37/linux/Documentation/fb/framebuffer.txt linux/Documentation/fb/framebuffer.txt
--- v2.3.37/linux/Documentation/fb/framebuffer.txt	Mon Oct 11 15:38:14 1999
+++ linux/Documentation/fb/framebuffer.txt	Fri Jan  7 12:59:38 2000
@@ -2,7 +2,7 @@
 			-----------------------
 
 Maintained by Geert Uytterhoeven <geert@linux-m68k.org>
-Last revised: October 7, 1999
+Last revised: January 2, 2000
 
 
 0. Introduction
@@ -294,7 +294,11 @@
 -------------
 
 For more specific information about the frame buffer device and its
-applications, please refer to the following documentation:
+applications, please refer to the Linux-fbdev website:
+
+    http://www.linux-fbdev.org/
+
+and to the following documentation:
 
   - The manual pages for fbset: fbset(8), fb.modes(5)
   - The manual pages for XFree86: XF68_FBDev(1), XF86Config(4/5)
diff -u --recursive --new-file v2.3.37/linux/Documentation/kmod.txt linux/Documentation/kmod.txt
--- v2.3.37/linux/Documentation/kmod.txt	Wed Jun 24 14:30:07 1998
+++ linux/Documentation/kmod.txt	Thu Jan  6 16:17:18 2000
@@ -45,3 +45,24 @@
 
 - kmod reports errors through the normal kernel mechanisms, which avoids
   the chicken and egg problem of kerneld and modular Unix domain sockets
+
+
+Keith Owens <kaos@ocs.com.au> December 1999
+
+The combination of kmod and modprobe can loop, especially if modprobe uses a
+system call that requires a module.  If modules.dep does not exist and modprobe
+was started with the -s option (kmod does this), modprobe tries to syslog() a
+message.  syslog() needs Unix sockets, if Unix sockets are modular then kmod
+runs "modprobe -s net-pf-1".  This runs a second copy of modprobe which
+complains that modules.dep does not exist, tries to use syslog() and starts yet
+another copy of modprobe.  This is not the only possible kmod/modprobe loop,
+just the most common.
+
+To detect loops caused by "modprobe needs a service which is in a module", kmod
+limits the number of concurrent kmod issued modprobes.  See MAX_KMOD_CONCURRENT
+in kernel/kmod.c.  When this limit is exceeded, the kernel issues message "kmod:
+runaway modprobe loop assumed and stopped".
+
+Note for users building a heavily modularised system.  It is a good idea to
+create modules.dep after installing the modules and before booting a kernel for
+the first time.  "depmod -ae m.n.p" where m.n.p is the new kernel version.
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/cops.txt linux/Documentation/networking/cops.txt
--- v2.3.37/linux/Documentation/networking/cops.txt	Thu Jan  7 08:41:55 1999
+++ linux/Documentation/networking/cops.txt	Thu Jan  6 14:46:18 2000
@@ -1,5 +1,5 @@
 Text File for the COPS LocalTalk Linux driver (cops.c).
-	By Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+	By Jay Schulist <jschlst@turbolinux.com>
 
 This driver has two modes and they are: Dayna mode and Tangent mode.
 Each mode corresponds with the type of card. It has been found
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/ethertap.txt linux/Documentation/networking/ethertap.txt
--- v2.3.37/linux/Documentation/networking/ethertap.txt	Wed May 20 18:54:34 1998
+++ linux/Documentation/networking/ethertap.txt	Thu Jan  6 14:46:18 2000
@@ -1,6 +1,6 @@
 Documentation on setup and use of EtherTap.
 
-Contact Jay Schulist <Jay.Schulist@spacs.k12.wi.us> if you
+Contact Jay Schulist <jschlst@turbolinux.com> if you
 have questions or need futher assistance.
 
 Introduction
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/filter.txt linux/Documentation/networking/filter.txt
--- v2.3.37/linux/Documentation/networking/filter.txt	Thu Apr 29 11:53:41 1999
+++ linux/Documentation/networking/filter.txt	Thu Jan  6 14:46:18 2000
@@ -1,5 +1,5 @@
 filter.txt: Linux Socket Filtering
-Written by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+Written by: Jay Schulist <jschlst@turbolinux.com>
 
 Introduction
 ============
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/ipddp.txt linux/Documentation/networking/ipddp.txt
--- v2.3.37/linux/Documentation/networking/ipddp.txt	Thu Apr 29 11:53:41 1999
+++ linux/Documentation/networking/ipddp.txt	Thu Jan  6 14:46:18 2000
@@ -1,7 +1,7 @@
 Text file for ipddp.c:
 	AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 
-This text file writen by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+This text file writen by Jay Schulist <jschlst@turbolinux.com>
 
 Introduction
 ------------
@@ -38,7 +38,7 @@
 
 To enable AppleTalk-IP decapsulation/encapsulation you will need the 
 proper tools. You can get the tools for decapsulation from
-http://spacs1.spacs.k12.wi.us/~jschlst/MacGate and for encapsulation
+http://spacs1.spacs.k12.wi.us/~jschlst/index.html and for encapsulation
 from http://www.maths.unm.edu/~bradford/ltpc.html
 
 I will briefly describe the operation of the tools, but you will
@@ -72,7 +72,7 @@
 
 Further Assistance
 -------------------
-You can contact me (Jay Schulist <Jay.Schulist@spacs.k12.wi.us>) with any
+You can contact me (Jay Schulist <jschlst@turbolinux.com>) with any
 questions regarding decapsulation or encapsulation. Bradford W. Johnson
 <johns393@maroon.tc.umn.edu> originally wrote the ipddp.c driver for IP
 encapsulation in AppleTalk.
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/sktr.txt linux/Documentation/networking/sktr.txt
--- v2.3.37/linux/Documentation/networking/sktr.txt	Wed Jun 24 14:26:12 1998
+++ linux/Documentation/networking/sktr.txt	Wed Dec 31 16:00:00 1969
@@ -1,147 +0,0 @@
-Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
-	Text file by: Jay Schulist <jschlst@samba.anu.edu.au>
-
-The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
-SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
-SK NET TR4/16 ISA card.
-
-Latest information on this driver can be obtained on the Linux-SNA WWW site.
-Please point your browser to: 
-http://samba.anu.edu.au/linux-sna/documents/drivers/SysKonnect/
-
-Many thanks to Christoph Goos for his excellent work on this driver and
-SysKonnect for donating the adapters to Linux-SNA for the testing and maintaince
-of this device driver.
-
-Important information to be noted:
-1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be 
-   patient.
-2. This driver works very well when autoprobing for adapters. Why even 
-   think about those nasty io/int/dma settings of modprobe when the driver 
-   will do it all for you!
-
-This driver is rather simple to use. Select Y to Token Ring adapter support
-in the kernel configuration. A choice for SysKonnect Token Ring adapters will
-appear. This drives supports all SysKonnect ISA and PCI adapters. Choose this
-option. I personally recommend compiling the driver as a module (M), but if you
-you would like to compile it staticly answer Y instead.
-
-This driver supports multiple adapters without the need to load multiple copies
-of the driver. You should be able to load up to 7 adapters without any kernel
-modifications, if you are in need of more please contact the maintainer of this
-driver.
-
-Load the driver either by lilo/loadlin or as a module. When a module using the
-following command will suffice for most:
-
-# modprobe sktr
-
-This will produce output similar to the following: (Output is user specific)
-
-sktr.c: v1.01 08/29/97 by Christoph Goos
-tr0: SK NET TR 4/16 PCI found at 0x6100, using IRQ 17.
-tr1: SK NET TR 4/16 PCI found at 0x6200, using IRQ 16.
-tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
-
-Now just setup the device via ifconfig and set and routes you may have. After
-this you are ready to start sending some tokens.
-
-Errata:
-For anyone wondering where to pick up the SysKonnect adapters please browse
-to http://www.syskonnect.com
-
-This driver is under the GNU General Public License. Its Firmware image is 
-included as an initialized C-array and is licensed by SysKonnect to the Linux 
-users of this driver. However no waranty about its fitness is expressed or 
-implied by SysKonnect.
-
-Below find attached the setting for the SK NET TR 4/16 ISA adapters
--------------------------------------------------------------------
-
-                    ***************************
-                    ***   C O N T E N T S   ***
-                    ***************************
-
-                1) Location of DIP-Switch W1
-                2) Default settings
-                3) DIP-Switch W1 description
-
-
-  ==============================================================
-  CHAPTER 1     LOCATION OF DIP-SWITCH
-  ==============================================================
-
-UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
-žUÄÄÄÄÄÄæ                         UÄÄÄÄÄæ            UÄÄÄæ         ž
-žAÄÄÄÄÄÄU                      W1 AÄÄÄÄÄU     UÄÄÄÄæ ž   ž         ž
-žUÄÄÄÄÄÄæ                                     ž    ž ž   ž      UÄÄÅæ
-žAÄÄÄÄÄÄU              UÄÄÄÄÄÄÄÄÄÄÄæ          AÄÄÄÄU ž   ž      ž  žž
-žUÄÄÄÄÄÄæ              ž           ž          UÄÄÄæ  AÄÄÄU      AÄÄÅU
-žAÄÄÄÄÄÄU              ž TMS380C26 ž          ž   ž                ž
-žUÄÄÄÄÄÄæ              ž           ž          AÄÄÄU                AÄæ
-žAÄÄÄÄÄÄU              ž           ž                               ž ž
-ž                      AÄÄÄÄÄÄÄÄÄÄÄU                               ž ž
-ž                                                                  ž ž
-ž                                                                  AÄU
-ž                                                                  ž
-ž                                                                  ž
-ž                                                                  ž
-ž                                                                  ž
-AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
-             AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU  AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
-
-  ==============================================================
-  CHAPTER 2     DEFAULT SETTINGS
-  ==============================================================
-
-          W1    1  2  3  4  5  6  7  8
-        +------------------------------+
-        | ON    X                      |
-        | OFF      X  X  X  X  X  X  X |
-        +------------------------------+
-
-        W1.1 = ON               Adapter drives address lines SA17..19
-        W1.2 - 1.5 = OFF        BootROM disabled
-        W1.6 - 1.8 = OFF        I/O address 0A20h
-
-  ==============================================================
-  CHAPTER 3     DIP SWITCH W1 DESCRIPTION
-  ==============================================================
-
-      UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄæ  ON
-      ž 1 ž 2 ž 3 ž 4 ž 5 ž 6 ž 7 ž 8 ž
-      AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU  OFF
-      |AD | BootROM Addr. |  I/O      |
-      +-+-+-------+-------+-----+-----+
-        |         |             |
-        |         |             +------ 6     7     8
-        |         |                     ON    ON    ON       1900h
-        |         |                     ON    ON    OFF      0900h
-        |         |                     ON    OFF   ON       1980h
-        |         |                     ON    OFF   OFF      0980h
-        |         |                     OFF   ON    ON       1b20h
-        |         |                     OFF   ON    OFF      0b20h
-        |         |                     OFF   OFF   ON       1a20h
-        |         |                     OFF   OFF   OFF      0a20h    (+)
-        |         |
-        |         |
-        |         +-------- 2     3     4     5
-        |                   OFF   x     x     x       disabled  (+)
-        |                   ON    ON    ON    ON      C0000
-        |                   ON    ON    ON    OFF     C4000
-        |                   ON    ON    OFF   ON      C8000
-        |                   ON    ON    OFF   OFF     CC000
-        |                   ON    OFF   ON    ON      D0000
-        |                   ON    OFF   ON    OFF     D4000
-        |                   ON    OFF   OFF   ON      D8000
-        |                   ON    OFF   OFF   OFF     DC000
-        |
-        |
-        +----- 1
-               OFF    adapter does NOT drive SA<17..19>
-               ON     adapter drives SA<17..19>  (+)
-
-
-        (+) means default setting
-
-                       ********************************
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/smctr.txt linux/Documentation/networking/smctr.txt
--- v2.3.37/linux/Documentation/networking/smctr.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/smctr.txt	Thu Jan  6 14:47:29 2000
@@ -0,0 +1,68 @@
+Text File for the SMC TokenCard TokenRing Linux driver (smctr.c).
+        By Jay Schulist <jschlst@turbolinux.com>
+
+The Linux SMC Token Ring driver works with the SMC TokenCard Elite (8115T) 
+ISA adapters. Preliminary support for the SMC TokenCard Elite/A (8115T/A) 
+MCA adapter has been started but is not complete. (Contact me for information
+if you have the proper setup to finish the MCA parts).
+
+Latest information on this driver can be obtained on the Linux-SNA WWW site.
+Please point your browser to: http://www.linux-sna.org
+
+This driver is rather simple to use. Select Y to Token Ring adapter support
+in the kernel configuration. A choice for SMC Token Ring adapters will
+appear. This drives supports all SMC ISA/MCA adapters. Choose this
+option. I personally recommend compiling the driver as a module (M), but if you
+you would like to compile it staticly answer Y instead.
+
+This driver supports multiple adapters without the need to load multiple copies
+of the driver. You should be able to load up to 7 adapters without any kernel
+modifications, if you are in need of more please contact the maintainer of this
+driver.
+
+Load the driver either by lilo/loadlin or as a module. When a module using the
+following command will suffice for most:
+
+# modprobe smctr
+smctr.c: v1.00 12/6/99 by jschlst@turbolinux.com
+tr0: SMC TokenCard 8115T at Io 0x300, Irq 10, Rom 0xd8000, Ram 0xcc000.
+
+Now just setup the device via ifconfig and set and routes you may have. After
+this you are ready to start sending some tokens.
+
+Errata:
+1). For anyone wondering where to pick up the SMC adapters please browse
+    to http://www.smc.com
+
+2). If you are the first/only Token Ring Client on a Token Ring LAN, please
+    specify the ringspeed with the ringspeed=[4/16] module option. If no
+    ringspeed is specified the driver will attempt to autodetect the ring
+    speed and/or if the adapter is the first/only station on the ring take
+    the appropriate actions. 
+
+    NOTE: Default ring speed is 16MB UTP.
+
+3). PnP support for this adapter sucks. I recommend hard setting the 
+    IO/MEM/IRQ by the jumpers on the adapter. If this is not possible
+    load the module with the following io=[ioaddr] mem=[mem_addr]
+    irq=[irq_num].
+
+    The following IRQ, IO, and MEM settings are supported.
+
+    IO ports:
+    0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+    0x320, 0x340, 0x360, 0x380.
+
+    IRQs:
+    2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15
+
+    Memory addresses:
+    0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000,
+    0xB8000, 0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000,
+    0xD0000, 0xD4000, 0xD8000, 0xDC000, 0xE0000, 0xE4000,
+    0xE8000, 0xEC000, 0xF0000, 0xF4000, 0xF8000, 0xFC000
+
+This driver is under the GNU General Public License. Its Firmware image is
+included as an initialized C-array and is licensed by SMC to the Linux
+users of this driver. However no waranty about its fitness is expressed or
+implied by SMC.
diff -u --recursive --new-file v2.3.37/linux/Documentation/networking/tms380tr.txt linux/Documentation/networking/tms380tr.txt
--- v2.3.37/linux/Documentation/networking/tms380tr.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/tms380tr.txt	Thu Jan  6 14:47:29 2000
@@ -0,0 +1,147 @@
+Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
+	Text file by: Jay Schulist <jschlst@turbolinux.com>
+
+The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
+SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
+SK NET TR4/16 ISA card.
+
+Latest information on this driver can be obtained on the Linux-SNA WWW site.
+Please point your browser to: 
+http://www.linux-sna.org
+
+Many thanks to Christoph Goos for his excellent work on this driver and
+SysKonnect for donating the adapters to Linux-SNA for the testing and maintaince
+of this device driver.
+
+Important information to be noted:
+1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be 
+   patient.
+2. This driver works very well when autoprobing for adapters. Why even 
+   think about those nasty io/int/dma settings of modprobe when the driver 
+   will do it all for you!
+
+This driver is rather simple to use. Select Y to Token Ring adapter support
+in the kernel configuration. A choice for SysKonnect Token Ring adapters will
+appear. This drives supports all SysKonnect ISA and PCI adapters. Choose this
+option. I personally recommend compiling the driver as a module (M), but if you
+you would like to compile it staticly answer Y instead.
+
+This driver supports multiple adapters without the need to load multiple copies
+of the driver. You should be able to load up to 7 adapters without any kernel
+modifications, if you are in need of more please contact the maintainer of this
+driver.
+
+Load the driver either by lilo/loadlin or as a module. When a module using the
+following command will suffice for most:
+
+# modprobe sktr
+
+This will produce output similar to the following: (Output is user specific)
+
+sktr.c: v1.01 08/29/97 by Christoph Goos
+tr0: SK NET TR 4/16 PCI found at 0x6100, using IRQ 17.
+tr1: SK NET TR 4/16 PCI found at 0x6200, using IRQ 16.
+tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
+
+Now just setup the device via ifconfig and set and routes you may have. After
+this you are ready to start sending some tokens.
+
+Errata:
+For anyone wondering where to pick up the SysKonnect adapters please browse
+to http://www.syskonnect.com
+
+This driver is under the GNU General Public License. Its Firmware image is 
+included as an initialized C-array and is licensed by SysKonnect to the Linux 
+users of this driver. However no waranty about its fitness is expressed or 
+implied by SysKonnect.
+
+Below find attached the setting for the SK NET TR 4/16 ISA adapters
+-------------------------------------------------------------------
+
+                    ***************************
+                    ***   C O N T E N T S   ***
+                    ***************************
+
+                1) Location of DIP-Switch W1
+                2) Default settings
+                3) DIP-Switch W1 description
+
+
+  ==============================================================
+  CHAPTER 1     LOCATION OF DIP-SWITCH
+  ==============================================================
+
+UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
+žUÄÄÄÄÄÄæ                         UÄÄÄÄÄæ            UÄÄÄæ         ž
+žAÄÄÄÄÄÄU                      W1 AÄÄÄÄÄU     UÄÄÄÄæ ž   ž         ž
+žUÄÄÄÄÄÄæ                                     ž    ž ž   ž      UÄÄÅæ
+žAÄÄÄÄÄÄU              UÄÄÄÄÄÄÄÄÄÄÄæ          AÄÄÄÄU ž   ž      ž  žž
+žUÄÄÄÄÄÄæ              ž           ž          UÄÄÄæ  AÄÄÄU      AÄÄÅU
+žAÄÄÄÄÄÄU              ž TMS380C26 ž          ž   ž                ž
+žUÄÄÄÄÄÄæ              ž           ž          AÄÄÄU                AÄæ
+žAÄÄÄÄÄÄU              ž           ž                               ž ž
+ž                      AÄÄÄÄÄÄÄÄÄÄÄU                               ž ž
+ž                                                                  ž ž
+ž                                                                  AÄU
+ž                                                                  ž
+ž                                                                  ž
+ž                                                                  ž
+ž                                                                  ž
+AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
+             AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU  AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
+
+  ==============================================================
+  CHAPTER 2     DEFAULT SETTINGS
+  ==============================================================
+
+          W1    1  2  3  4  5  6  7  8
+        +------------------------------+
+        | ON    X                      |
+        | OFF      X  X  X  X  X  X  X |
+        +------------------------------+
+
+        W1.1 = ON               Adapter drives address lines SA17..19
+        W1.2 - 1.5 = OFF        BootROM disabled
+        W1.6 - 1.8 = OFF        I/O address 0A20h
+
+  ==============================================================
+  CHAPTER 3     DIP SWITCH W1 DESCRIPTION
+  ==============================================================
+
+      UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄæ  ON
+      ž 1 ž 2 ž 3 ž 4 ž 5 ž 6 ž 7 ž 8 ž
+      AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU  OFF
+      |AD | BootROM Addr. |  I/O      |
+      +-+-+-------+-------+-----+-----+
+        |         |             |
+        |         |             +------ 6     7     8
+        |         |                     ON    ON    ON       1900h
+        |         |                     ON    ON    OFF      0900h
+        |         |                     ON    OFF   ON       1980h
+        |         |                     ON    OFF   OFF      0980h
+        |         |                     OFF   ON    ON       1b20h
+        |         |                     OFF   ON    OFF      0b20h
+        |         |                     OFF   OFF   ON       1a20h
+        |         |                     OFF   OFF   OFF      0a20h    (+)
+        |         |
+        |         |
+        |         +-------- 2     3     4     5
+        |                   OFF   x     x     x       disabled  (+)
+        |                   ON    ON    ON    ON      C0000
+        |                   ON    ON    ON    OFF     C4000
+        |                   ON    ON    OFF   ON      C8000
+        |                   ON    ON    OFF   OFF     CC000
+        |                   ON    OFF   ON    ON      D0000
+        |                   ON    OFF   ON    OFF     D4000
+        |                   ON    OFF   OFF   ON      D8000
+        |                   ON    OFF   OFF   OFF     DC000
+        |
+        |
+        +----- 1
+               OFF    adapter does NOT drive SA<17..19>
+               ON     adapter drives SA<17..19>  (+)
+
+
+        (+) means default setting
+
+                       ********************************
diff -u --recursive --new-file v2.3.37/linux/Documentation/sound/via82cxxx.txt linux/Documentation/sound/via82cxxx.txt
--- v2.3.37/linux/Documentation/sound/via82cxxx.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/via82cxxx.txt	Thu Jan  6 14:46:18 2000
@@ -0,0 +1,146 @@
+			Via motherboard audio driver
+	Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+
+Driver software and documentation distributed under the GNU GENERAL
+PUBLIC LICENSE (GPL) Version 2. See the "COPYING" file distributed with
+this software for more info.
+
+
+
+Introduction
+------------------------------------------------------------------------
+The via82cxxx audio driver found in the drivers/sound directory
+of the kernel source tree is a PCI audio driver for audio chips
+found on Via-based motherboards, such as the MVP4.
+
+Currently the driver provides audio via SoundBlaster Pro compatibility,
+and MIDI via MPU-401 compatibility.  An AC97 mixing device is also
+supported, and is generally preferred over the SoundBlaster mixer.
+
+IMPORTANT NOTE:  Some users report that the SoundBlaster mixer does
+not work at all -- use the AC97 mixer if possible.
+
+Please send bug reports to the mailing list linux-via@gtf.org.
+To subscribe, e-mail majordomo@gtf.org with "subscribe linux-via" in the
+body of the message.
+
+
+Thanks
+------------------------------------------------------------------------
+Via for providing e-mail support, specs, and NDA's source code.
+
+MandrakeSoft for providing hacking time.
+
+AC97 mixer interface fixes and debugging by Ron Cemer <roncemer@gte.net>
+
+
+
+Installation
+------------------------------------------------------------------------
+If the driver is being statically compiled into the kernel, no
+configuration should be necessary.
+
+If the driver is being compiled as a module, generally two lines must
+be added to your /etc/conf.modules (or /etc/modules.conf) file:
+
+	alias sound via82cxxx
+	options sb support=1
+
+The second line is very important:  it tells the required 'sb' module
+not to load SoundBlaster support, but to instead let the Via driver
+do so at a later time.
+
+
+
+Driver notes
+------------------------------------------------------------------------
+This driver by default supports all PCI audio devices which report
+a vendor id of 0x1106, and a device id of 0x3058.  Subsystem vendor
+and device ids are not examined.
+
+Only supports a single sound chip, as this is a motherboard chipset.
+Some architecture remains for multiple cards, feel free to submit
+a patch to clean some of that up.  Ideally, 
+
+No consideration for SMP, this chipset is not known to be found on
+any SMP motherboards.  However, this will change when we start handling
+our own interrupts in "native mode."
+
+GNU indent formatting options:  -kr -i8 -pcs
+
+
+
+Tested Hardware
+------------------------------------------------------------------------
+The following is an _incomplete_ list of motherboards supported by this
+audio driver.  If your motherboard (or notebook) is not listed here,
+please e-mail the maintainer with details.
+
+	AOpen MX59 Pro (Apollo MVP4)
+
+
+
+The Future
+------------------------------------------------------------------------
+Via has graciously donated e-mail support and source code to help further
+the development of this driver.  Their assistance has been invaluable
+in the design and coding of the next major version of this driver.
+
+This audio chip supports a DirectSound(tm)-style hardware interface,
+with a single 16-bit stereo input channel, and a single 16-bit stereo
+output channel.  Data is transferred to/from the hardware using
+table-driven scatter-gather DMA buffers.
+
+Work is currently underway to support this "native mode" of the chip.
+When complete, SoundBlaster legacy mode will be completely removed.
+After a round of testing, this code will become version 2.0.0.
+
+Following the 2.0.0 release, the last major task to complete is
+MIDI support.  MPU-401 legacy support is available currently, but
+not well tested at all.
+
+The Via audio chip apparently provides a second PCM scatter-gather
+DMA channel just for FM data, but does not have a full hardware MIDI
+processor.  I haven't put much thought towards a solution here, but it
+might involve using SoftOSS midi wave table, or simply disabling MIDI
+support altogether and using the FM PCM channel as a second (input? output?)
+
+
+
+General To-do List (patches/suggestions welcome)
+------------------------------------------------------------------------
+Better docs
+
+Code review by sound guru(s)
+
+Native DSP audio driver using scatter-gather DMA, as described above
+
+Native MIDI driver, as described above
+
+
+
+Known bugs (patches/suggestions welcome)
+------------------------------------------------------------------------
+1) Two MIDI devices are loaded by the sound driver.  Eliminate one of them. 
+Sample /proc/sound output:
+
+	Midi devices:
+	0: Sound Blaster
+	1: VIA 82Cxxx Audio driver 1.1.2
+
+2) Two mixer devices are loaded by the sound driver.  Eliminate one of
+them.  At least one bug report says that SB mixer does not work at all,
+only AC97 mixer.  Sample /proc/sound output:
+
+	Mixers:
+	0: via82cxxxAC97Mixer
+	1: Sound Blaster
+
+3) After unloading the driver, a SoundBlaster MIDI device is still 
+listed in /proc/sound.  Investigate what is not being unloaded,
+and fix it.  Sample /proc/sound output, after 'rmmod via82cxxx':
+
+	Midi devices:
+	0: Sound Blaster
+
+
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/API.html linux/Documentation/video4linux/API.html
--- v2.3.37/linux/Documentation/video4linux/API.html	Mon Jul  5 20:04:47 1999
+++ linux/Documentation/video4linux/API.html	Thu Jan  6 14:46:18 2000
@@ -30,7 +30,7 @@
 information
 <P>
 <TABLE>
-<TR><TD><b>name[32]</b><TD>Cannonical name for this interface</TD>
+<TR><TD><b>name[32]</b><TD>Canonical name for this interface</TD>
 <TR><TD><b>type</b><TD>Type of interface</TD>
 <TR><TD><b>channels</b><TD>Number of radio/tv channels if appropriate</TD>
 <TR><TD><b>audios</b><TD>Number of audio devices if appropriate</TD>
@@ -125,7 +125,7 @@
 <P>
 Some capture devices can capture a subfield of the image they actually see.
 This is indicated when VIDEO_TYPE_SUBCAPTURE is defined.
-The video_capture describes the time and spacial subfields to capture.
+The video_capture describes the time and special subfields to capture.
 The video_capture structure contains the following fields.
 <P>
 <TABLE>
@@ -235,7 +235,7 @@
 <P>
 <TABLE>
 <TR><TD><b>tuner</b><TD>Number of the tuner</TD>
-<TR><TD><b>name</b><TD>Cannonical name for this tuner (eg FM/AM/TV)</TD>
+<TR><TD><b>name</b><TD>Canonical name for this tuner (eg FM/AM/TV)</TD>
 <TR><TD><b>rangelow</b><TD>Lowest tunable frequency</TD>
 <TR><TD><b>rangehigh</b><TD>Highest tunable frequency</TD>
 <TR><TD><b>flags</b><TD>Flags describing the tuner</TD>
@@ -279,7 +279,7 @@
 <P>
 <TABLE>
 <TR><TD><b>audio</b><TD>The channel number</TD>
-<TR><TD><b>volume</b><TD>The voume level</TD>
+<TR><TD><b>volume</b><TD>The volume level</TD>
 <TR><TD><b>bass</b><TD>The bass level</TD>
 <TR><TD><b>treble</b><TD>The treble level</TD>
 <TR><TD><b>flags</b><TD>Flags describing the audio channel</TD>
@@ -359,13 +359,13 @@
 System (RDS) data by means of a read() on the device.  The data is packed in
 groups of three, as follows:
 <TABLE>
-<TR><TD>First Octet</TD><TD>Least Siginificant Byte of RDS Block</TD></TR>
-<TR><TD>Second Octet</TD><TD>Most Siginificant Byte of RDS Block
+<TR><TD>First Octet</TD><TD>Least Significant Byte of RDS Block</TD></TR>
+<TR><TD>Second Octet</TD><TD>Most Significant Byte of RDS Block
 <TR><TD>Third Octet</TD><TD>Bit 7:</TD><TD>Error bit.  Indicates that
-an uncorrectable error occured during reception of this block.</TD></TR>
+an uncorrectable error occurred during reception of this block.</TD></TR>
 <TR><TD>&nbsp;</TD><TD>Bit 6:</TD><TD>Corrected bit.  Indicates that  
 an error was corrected for this data block.</TD></TR>
-<TR><TD>&nbsp;</TD><TD>Bits 5-3:</TD><TD>Reeived Offset.  Indicates the  
+<TR><TD>&nbsp;</TD><TD>Bits 5-3:</TD><TD>Received Offset.  Indicates the  
 offset received by the sync system.</TD></TR>
 <TR><TD>&nbsp;</TD><TD>Bits 2-0:</TD><TD>Offset Name.  Indicates the  
 offset applied to this data.</TD></TR>
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/README.buz linux/Documentation/video4linux/README.buz
--- v2.3.37/linux/Documentation/video4linux/README.buz	Mon Jul  5 20:04:47 1999
+++ linux/Documentation/video4linux/README.buz	Thu Jan  6 14:46:18 2000
@@ -41,7 +41,7 @@
   various kernel versions floating around in the net,
   you may obtain one e.g. from:
   http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz
-  You also have to compile your driber AFTER installing that patch
+  You also have to compile your driver AFTER installing that patch
   in order to get it working
 
   or
@@ -91,9 +91,9 @@
 they are needed for uncompressed image grabbing only!!!
 
 v4l_nbufs is the number of buffers to allocate, a value of 2 (the default)
-should be sufficient in allmost all cases. Only special applications
+should be sufficient in almost all cases. Only special applications
 (streaming captures) will need more buffers and then mostly the
-MJPEG capturing features of the Buz will be more apropriate.
+MJPEG capturing features of the Buz will be more appropriate.
 So leave this parameter at it's default unless you know what you do.
 
 The things for v4l_bufsize are more complicated:
@@ -107,7 +107,7 @@
   the necessary memory during boot time or
 - start your kernel with the mem=xxx option, where xxx is your
   real memory minus the memory needed for the buffers.
-In that case, usefull settings for v4l_bufsize are
+In that case, useful settings for v4l_bufsize are
 - 1296 [Kb] for grabbing 24 bit images of max size 768*576
 - 1728 [Kb] for 32bit images of same size (4*768*576 = 1728 Kb!)
 You may reduce these numbers accordingly if you know you are only
@@ -137,7 +137,7 @@
 --------------
 
 The driver tries to detect if you have a triton or natome chipset
-in order to take special messures for these chipsets.
+in order to take special measures for these chipsets.
 If this detection fails but you are sure you have such a chipset,
 set the corresponding variable to 1.
 This is a very special option and may go away in the future.
@@ -151,7 +151,7 @@
 tools working with Video for Linux should work with (hopefully)
 no problems.
 
-A description of the Video for Linux programming interace can be found at:
+A description of the Video for Linux programming interface can be found at:
 http://roadrunner.swansea.linux.org.uk/v4lapi.shtml
 
 Besides the Video for Linux interface, the driver has a "proprietary"
@@ -162,7 +162,7 @@
 BUZIOC_G_PARAMS
 BUZIOC_S_PARAMS
 
-Get and set the parameters of the buz. The user should allways
+Get and set the parameters of the buz. The user should always
 do a BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default
 settings, change what he likes and then make a BUZIOC_S_PARAMS call.
 A typical application should at least set the members
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/bttv/Insmod-options linux/Documentation/video4linux/bttv/Insmod-options
--- v2.3.37/linux/Documentation/video4linux/bttv/Insmod-options	Tue Jan  4 13:57:16 2000
+++ linux/Documentation/video4linux/bttv/Insmod-options	Thu Jan  6 14:46:18 2000
@@ -20,7 +20,7 @@
 		autoload=0/1	autoload helper modules (tuner, audio).
 				default is 1 (on).
 
-	remap, card, radio and pll accept up to four comma-separted arguments
+	remap, card, radio and pll accept up to four comma-separated arguments
 	(for multiple boards).
 
 msp3400.o
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/bttv/PROBLEMS linux/Documentation/video4linux/bttv/PROBLEMS
--- v2.3.37/linux/Documentation/video4linux/bttv/PROBLEMS	Mon Jul  5 20:04:47 1999
+++ linux/Documentation/video4linux/bttv/PROBLEMS	Thu Jan  6 14:46:18 2000
@@ -4,7 +4,7 @@
 
 - The memory of some S3 cards is not recognized right:
   
-  First of all, if you are not using Xfree-3.2 or newer, upgrade AT LEAST to
+  First of all, if you are not using XFree-3.2 or newer, upgrade AT LEAST to
   XFree-3.2A! This solved the problem for most people.
 
   Start up X11 like this: "XF86_S3 -probeonly" and write down where the
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README
--- v2.3.37/linux/Documentation/video4linux/bttv/README	Tue Jan  4 13:57:16 2000
+++ linux/Documentation/video4linux/bttv/README	Thu Jan  6 14:46:18 2000
@@ -36,7 +36,7 @@
 Make bttv work with your card
 -----------------------------
 
-Of cource you have to load the modules as very first thing.  The
+Of course you have to load the modules as very first thing.  The
 separate bttv bundle comes with a script called "update".  I use this
 one to load a new version while doing driver hacking.  You can use it
 too, but check the module arguments first.  They work for my setup,
@@ -49,7 +49,7 @@
 MAKEDEV:	a script to create the special files for v4l
 CARDLIST:	List of all supported cards
 
-Loading just the bttv modules is'nt enouth for most cards.  The
+Loading just the bttv modules isn't enough for most cards.  The
 drivers for the i2c tuner/sound chips must also be loaded.  bttv tries
 to load them automagically by calling request_module() now, but this
 obviously works only with kmod enabled.
@@ -59,15 +59,15 @@
 specified the wrong (or no) card type.  A list of supported cards is
 in CARDLIST.
 
-If your card is'nt listed in CARDLIST, you should read the Sound-FAQ.
+If your card isn't listed in CARDLIST, you should read the Sound-FAQ.
 
 
-Still does'nt work?
+Still doesn't work?
 -------------------
 
 I do NOT have a lab with 30+ different grabber boards and a
 PAL/NTSC/SECAM test signal generator at home, so I often can't
-reproduce your problems.  This makes debugging very difficuilt for me.
+reproduce your problems.  This makes debugging very difficult for me.
 If you have some knowledge and spare time, please try to fix this
 yourself (patches very welcome of course...)  You know: The linux
 slogan is "Do it yourself".
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/bttv/Sound-FAQ linux/Documentation/video4linux/bttv/Sound-FAQ
--- v2.3.37/linux/Documentation/video4linux/bttv/Sound-FAQ	Tue Jan  4 13:57:16 2000
+++ linux/Documentation/video4linux/bttv/Sound-FAQ	Thu Jan  6 14:46:18 2000
@@ -38,7 +38,7 @@
 How sound works in detail
 =========================
 
-Still does'nt work?  Looks like some driver hacking is required.
+Still doesn't work?  Looks like some driver hacking is required.
 Below is a do-it-yourself description for you.
 
 The bt8xx chips have 32 general purpose pins, and registers to control
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/radiotrack.txt linux/Documentation/video4linux/radiotrack.txt
--- v2.3.37/linux/Documentation/video4linux/radiotrack.txt	Sun Aug 23 13:32:25 1998
+++ linux/Documentation/video4linux/radiotrack.txt	Thu Jan  6 14:46:18 2000
@@ -10,7 +10,7 @@
 (legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from
 Frans Brinkman (brinkman@esd.nl) in 1996.  The results reported here are from
 experiments that the author performed on his own setup, so your mileage may
-vary... I make no guarantees, claims or warrantees to the suitability or
+vary... I make no guarantees, claims or warranties to the suitability or
 validity of this information.  No other documentation on the AIMS
 Lab (http://www.aimslab.com/) RadioTrack card was made available to the
 author.  This document is offered in the hopes that it might help users who
diff -u --recursive --new-file v2.3.37/linux/Documentation/video4linux/zr36120.txt linux/Documentation/video4linux/zr36120.txt
--- v2.3.37/linux/Documentation/video4linux/zr36120.txt	Tue Dec  7 09:32:39 1999
+++ linux/Documentation/video4linux/zr36120.txt	Thu Jan  6 14:46:18 2000
@@ -31,20 +31,20 @@
 on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
 which (s)he connected reversely. So we have to clock on the SDA
 and r/w data on the SCL pin. Life is fun... Each cardtype now has
-a bit which signifies if you have a card with the same deficiancy.
+a bit which signifies if you have a card with the same deficiency.
 
-Oh, for the completness of this story I must mention that my
+Oh, for the completeness of this story I must mention that my
 card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
-GIRQ0 as some other cards have. This is also incorperated in
+GIRQ0 as some other cards have. This is also incorporated in
 the driver be clearing/setting the 'useirq1' bit in the tvcard
 description.
 
-Another problems of contingious capturing data with a Zoran chip
+Another problems of continuous capturing data with a Zoran chip
 is something nasty inside the chip. It effectively halves the
 fps we ought to get... Here is the scenario: capturing frames
 to memory is done in the so-called snapshot mode. In this mode
 the Zoran stops after capturing a frame worth of data and wait
-till the application set GRAB bit to indicate readyness for the
+till the application set GRAB bit to indicate readiness for the
 next frame. After detecting a set bit, the chip neetly waits
 till the start of a frame, captures it and it goes back to off.
 Smart ppl will notice the problem here. Its the waiting on the
@@ -101,7 +101,7 @@
 	mknod /dev/video3 c 81 3
 	mknod /dev/video4 c 81 4
 
-After makeing/checking the devices do:
+After making/checking the devices do:
 	modprobe i2c
 	modprobe videodev
 	modprobe saa7110	(optional)
diff -u --recursive --new-file v2.3.37/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.37/linux/MAINTAINERS	Thu Jan  6 12:57:47 2000
+++ linux/MAINTAINERS	Thu Jan  6 16:17:18 2000
@@ -135,7 +135,7 @@
 
 APPLETALK NETWORK LAYER
 P:	Jay Schulist
-M:	Jay.Schulist@spacs.k12.wi.us
+M:	jschlst@turbolinux.com
 L:	linux-atalk@netspace.org
 S:	Maintained
 
@@ -469,7 +469,7 @@
 
 IPX/SPX NETWORK LAYER
 P:	Jay Schulist
-M:	Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+M:	jschlst@turbolinux.com
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
@@ -580,8 +580,8 @@
 S:	Maintained
 
 MODULE SUPPORT [GENERAL], KERNELD
-P:	Richard Henderson
-M:	richard@gnu.ai.mit.edu
+P:	Keith Owens
+M:	kaos@ocs.com.au
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
@@ -869,8 +869,15 @@
 
 SPX NETWORK LAYER
 P:	Jay Schulist
-M:	Jay.Schulist@spacs.k12.wi.us
+M:	jschlst@turbolinux.com
 L:	linux-net@vger.rutgers.edu
+S:	Supported
+
+SNA NETWORK LAYER
+P:	Jay Schulist
+M:	jschlst@turbolinux.com
+L:	linux-sna@turbolinux.com
+W:	http://www.linux-sna.org
 S:	Supported
 
 STALLION TECHNOLOGIES MULTIPORT SERIAL BOARDS
diff -u --recursive --new-file v2.3.37/linux/Makefile linux/Makefile
--- v2.3.37/linux/Makefile	Thu Jan  6 12:57:47 2000
+++ linux/Makefile	Fri Jan  7 17:03:11 2000
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 37
+SUBLEVEL = 38
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -401,7 +401,7 @@
 	if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \
 	if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \
 	\
-	ls *.o > $$MODLIB/.allmods; \
+	ls -1 -U *.o | sort > $$MODLIB/.allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \
 	if [ -s $$MODLIB/.misc ]; then inst_mod $$MODLIB/.misc misc; fi; \
 	rm -f $$MODLIB/.misc $$MODLIB/.allmods; \
diff -u --recursive --new-file v2.3.37/linux/README linux/README
--- v2.3.37/linux/README	Thu Jul  1 10:54:08 1999
+++ linux/README	Thu Jan  6 14:46:18 2000
@@ -9,7 +9,7 @@
 bugs.  It is *strongly* recommended that you back up the previous kernel
 before installing any new 2.3.xx release.
 
-If you need to use a proven and stable Linux kernel, please use 2.0.37
+If you need to use a proven and stable Linux kernel, please use 2.0.38
 or 2.2.xx.  All features which will be in the 2.3.xx releases will be
 contained in 2.4.xx when the code base has stabilized again. 
 
diff -u --recursive --new-file v2.3.37/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.3.37/linux/arch/alpha/kernel/osf_sys.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Fri Jan  7 11:43:09 2000
@@ -33,7 +33,6 @@
 #include <linux/file.h>
 #include <linux/types.h>
 #include <linux/ipc.h>
-#include <linux/shm.h>
 
 #include <asm/fpu.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.3.37/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S
--- v2.3.37/linux/arch/i386/boot/compressed/head.S	Sun Mar 29 11:31:16 1998
+++ linux/arch/i386/boot/compressed/head.S	Fri Jan  7 11:52:27 2000
@@ -53,9 +53,9 @@
 	xorl %eax,%eax			# Back to 0
 	mov  %cx,%ax			# SP low 16 bits
 	movl %eax,%esp
-	pushl 0				# Clear NT
+	pushl $0			# Clear NT
 	popfl
-	ljmp $(__KERNEL_CS), $0x100000    # Into C and sanity
+	ljmp $(__KERNEL_CS), $0x100000	# Into C and sanity
 
 2:
 #endif
diff -u --recursive --new-file v2.3.37/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.37/linux/arch/i386/config.in	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/config.in	Thu Jan  6 15:01:56 2000
@@ -122,7 +122,7 @@
 bool 'ACPI support' CONFIG_ACPI
 if [ "$CONFIG_ACPI" != "n" ]; then
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-     bool '  Enter S1 for sleep' CONFIG_ACPI_S1_SLEEP
+      bool '  Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP
    fi
 fi
 
diff -u --recursive --new-file v2.3.37/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.37/linux/arch/i386/kernel/acpi.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/kernel/acpi.c	Fri Jan  7 11:51:56 2000
@@ -23,6 +23,7 @@
  * for the user-level ACPI stuff
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.3.37/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.3.37/linux/arch/i386/kernel/head.S	Mon Dec 20 18:48:21 1999
+++ linux/arch/i386/kernel/head.S	Fri Jan  7 11:32:27 2000
@@ -133,9 +133,9 @@
 	movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
 	movzwl CL_OFFSET,%esi
 	addl $(CL_BASE_ADDR),%esi
-	movl $2048,%ecx
+	movl $512,%ecx
 	rep
-	movsb
+	movsl
 1:
 #ifdef __SMP__
 checkCPUtype:
diff -u --recursive --new-file v2.3.37/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.3.37/linux/arch/i386/kernel/mtrr.c	Tue Dec  7 09:32:40 1999
+++ linux/arch/i386/kernel/mtrr.c	Fri Jan  7 11:43:09 2000
@@ -139,41 +139,41 @@
 	       Changed locking to spin with reschedule.
 	       Made use of new <smp_call_function>.
   v1.28
-    19990201   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990201   Zoltįn Böszörményi <zboszor@mail.externet.hu>
 	       Extended the driver to be able to use Cyrix style ARRs.
     19990204   Richard Gooch <rgooch@atnf.csiro.au>
 	       Restructured Cyrix support.
   v1.29
-    19990204   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990204   Zoltįn Böszörményi <zboszor@mail.externet.hu>
 	       Refined ARR support: enable MAPEN in set_mtrr_prepare()
 	       and disable MAPEN in set_mtrr_done().
     19990205   Richard Gooch <rgooch@atnf.csiro.au>
 	       Minor cleanups.
   v1.30
-    19990208   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990208   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Protect plain 6x86s (and other processors without the
                Page Global Enable feature) against accessing CR4 in
                set_mtrr_prepare() and set_mtrr_done().
     19990210   Richard Gooch <rgooch@atnf.csiro.au>
 	       Turned <set_mtrr_up> and <get_mtrr> into function pointers.
   v1.31
-    19990212   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990212   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Major rewrite of cyrix_arr_init(): do not touch ARRs,
                leave them as the BIOS have set them up.
                Enable usage of all 8 ARRs.
                Avoid multiplications by 3 everywhere and other
                code clean ups/speed ups.
-    19990213   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990213   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Set up other Cyrix processors identical to the boot cpu.
                Since Cyrix don't support Intel APIC, this is l'art pour l'art.
                Weigh ARRs by size:
                If size <= 32M is given, set up ARR# we were given.
                If size >  32M is given, set up ARR7 only if it is free,
                fail otherwise.
-    19990214   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990214   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Also check for size >= 256K if we are to set up ARR7,
                mtrr_add() returns the value it gets from set_mtrr()
-    19990218   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990218   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Remove Cyrix "coma bug" workaround from here.
                Moved to linux/arch/i386/kernel/setup.c and
                linux/include/asm-i386/bugs.h
@@ -187,7 +187,7 @@
     19990305   Richard Gooch <rgooch@atnf.csiro.au>
 	       Temporarily disable AMD support now MTRR capability flag is set.
   v1.32
-    19990308   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990308   Zoltįn Böszörményi <zboszor@mail.externet.hu>
 	       Adjust my changes (19990212-19990218) to Richard Gooch's
 	       latest changes. (19990228-19990305)
   v1.33
@@ -201,23 +201,23 @@
     19990512   Richard Gooch <rgooch@atnf.csiro.au>
 	       Minor cleanups.
   v1.35
-    19990707   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990707   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Check whether ARR3 is protected in cyrix_get_free_region()
                and mtrr_del(). The code won't attempt to delete or change it
                from now on if the BIOS protected ARR3. It silently skips ARR3
                in cyrix_get_free_region() or returns with an error code from
                mtrr_del().
-    19990711   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990711   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
                if ARR3 isn't protected. This is needed because if SMM is active
                and ARR3 isn't protected then deleting and setting ARR3 again
                may lock up the processor. With SMM entirely disabled, it does
                not happen.
-    19990812   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990812   Zoltįn Böszörményi <zboszor@mail.externet.hu>
                Rearrange switch() statements so the driver accomodates to
                the fact that the AMD Athlon handles its MTRRs the same way
                as Intel does.
-    19990814   Zoltan Boszormenyi <zboszor@mol.hu>
+    19990814   Zoltįn Böszörményi <zboszor@mail.externet.hu>
 	       Double check for Intel in mtrr_add()'s big switch() because
 	       that revision check is only valid for Intel CPUs.
     19990819   Alan Cox <alan@redhat.com>
@@ -957,11 +957,11 @@
     wait_barrier_execute = TRUE;
     wait_barrier_cache_enable = TRUE;
     atomic_set (&undone_count, smp_num_cpus - 1);
-    /*  Flush and disable the local CPU's cache	and start the ball rolling on
-	other CPUs  */
-    set_mtrr_prepare (&ctxt);
+    /*  Start the ball rolling on other CPUs  */
     if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
 	panic ("mtrr: timed out waiting for other CPUs\n");
+    /* Flush and disable the local CPU's cache */
+    set_mtrr_prepare (&ctxt);
     /*  Wait for all other CPUs to flush and disable their caches  */
     while (atomic_read (&undone_count) > 0) barrier ();
     /* Set up for completion wait and then release other CPUs to change MTRRs*/
@@ -1481,8 +1481,6 @@
     mtrr_close,  /*  Release           */
     NULL,        /*  Fsync             */
     NULL,        /*  Fasync            */
-    NULL,        /*  CheckMediaChange  */
-    NULL,        /*  Revalidate        */
     NULL,        /*  Lock              */
 };
 
diff -u --recursive --new-file v2.3.37/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.3.37/linux/arch/i386/kernel/pci-pc.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/kernel/pci-pc.c	Fri Jan  7 16:59:40 2000
@@ -633,9 +633,8 @@
 	unsigned char bus, devfn;
 
 	DBG("PCI: Sorting device list...\n");
-	while (pci_devices.next != &pci_devices) {
+	while (!list_empty(&pci_devices)) {
 		ln = pci_devices.next;
-		list_del(ln);
 		dev = pci_dev_g(ln);
 		idx = found = 0;
 		while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
diff -u --recursive --new-file v2.3.37/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.37/linux/arch/i386/kernel/setup.c	Wed Dec 29 13:13:12 1999
+++ linux/arch/i386/kernel/setup.c	Thu Jan  6 14:46:18 2000
@@ -7,8 +7,8 @@
  *  and Martin Mares, November 1997.
  *
  *  Force Cyrix 6x86(MX) and M II processors to report MTRR capability
- *  and fix against Cyrix "coma bug" by
- *      Zoltan Boszormenyi <zboszor@mol.hu> February 1999.
+ *  and Cyrix "coma bug" recognition by
+ *      Zoltįn Böszörményi <zboszor@mail.externet.hu> February 1999.
  * 
  *  Force Centaur C6 processors to report MTRR capability.
  *      Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
diff -u --recursive --new-file v2.3.37/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c
--- v2.3.37/linux/arch/m68k/atari/stram.c	Tue Dec  7 09:32:41 1999
+++ linux/arch/m68k/atari/stram.c	Fri Jan  7 11:38:05 2000
@@ -1230,18 +1230,9 @@
 }
 
 
-static struct file_operations stram_fops = {
-	NULL,                   /* lseek - default */
-	block_read,             /* read - general block-dev read */
-	block_write,            /* write - general block-dev write */
-	NULL,                   /* readdir - bad */
-	NULL,                   /* select */
-	NULL,                   /* ioctl */
-	NULL,                   /* mmap */
-	stram_open,             /* open */
-	NULL,			/* flush */
-	stram_release,          /* release */
-	block_fsync             /* fsync */
+static struct block_device_operations stram_fops = {
+	open:		stram_open,
+	release:	stram_release,
 };
 
 int __init stram_device_init(void)
diff -u --recursive --new-file v2.3.37/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.37/linux/arch/ppc/kernel/pmac_setup.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Fri Jan  7 11:55:28 2000
@@ -198,32 +198,12 @@
 
 #ifdef CONFIG_SCSI
 /* Find the device number for the disk (if any) at target tgt
-   on host adaptor host.
-   XXX this really really should be in drivers/scsi/sd.c. */
+   on host adaptor host.  We just need to get the prototype from
+   sd.h */
 #include <linux/blkdev.h>
 #include "../../../drivers/scsi/scsi.h"
 #include "../../../drivers/scsi/sd.h"
-#include "../../../drivers/scsi/hosts.h"
 
-#define SD_MAJOR(i)		(!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
-#define SD_MAJOR_NUMBER(i)	SD_MAJOR((i) >> 8)
-#define SD_MINOR_NUMBER(i)	((i) & 255)
-#define MKDEV_SD_PARTITION(i)	MKDEV(SD_MAJOR_NUMBER(i), SD_MINOR_NUMBER(i))
-#define MKDEV_SD(index)		MKDEV_SD_PARTITION((index) << 4)
-
-__init
-kdev_t sd_find_target(void *host, int tgt)
-{
-    Scsi_Disk *dp;
-    int i;
-#ifdef CONFIG_BLK_DEV_SD
-    for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
-        if (dp->device != NULL && dp->device->host == host
-            && dp->device->id == tgt)
-            return MKDEV_SD(i);
-#endif /* CONFIG_BLK_DEV_SD */
-    return 0;
-}
 #endif
 
 /*
diff -u --recursive --new-file v2.3.37/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.37/linux/arch/sparc/kernel/sparc_ksyms.c	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Fri Jan  7 11:15:27 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.83 1999/11/19 04:11:28 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.84 2000/01/07 18:15:14 jj Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -116,6 +116,12 @@
 EXPORT_SYMBOL_PRIVATE(_global_cli);
 #endif
 #endif
+
+/* rw semaphores */
+EXPORT_SYMBOL_NOVERS(___down_read);
+EXPORT_SYMBOL_NOVERS(___down_write);
+EXPORT_SYMBOL_NOVERS(___up_read);
+EXPORT_SYMBOL_NOVERS(___up_write);
 
 EXPORT_SYMBOL(page_offset);
 EXPORT_SYMBOL(sparc_valid_addr_bitmap);
diff -u --recursive --new-file v2.3.37/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.37/linux/arch/sparc/kernel/sys_sunos.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/sparc/kernel/sys_sunos.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.107 1999/12/27 06:08:37 anton Exp $
+/* $Id: sys_sunos.c,v 1.108 2000/01/06 23:51:46 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.37/linux/arch/sparc/lib/rwsem.S linux/arch/sparc/lib/rwsem.S
--- v2.3.37/linux/arch/sparc/lib/rwsem.S	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc/lib/rwsem.S	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: rwsem.S,v 1.1 1999/12/28 11:50:39 jj Exp $
+/* $Id: rwsem.S,v 1.2 2000/01/05 01:00:38 davem Exp $
  * Assembly part of rw semaphores.
  *
  * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.3.37/linux/arch/sparc64/kernel/pci.c	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc64/kernel/pci.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.12 2000/01/01 03:32:50 davem Exp $
+/* $Id: pci.c,v 1.13 2000/01/06 23:51:49 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -161,25 +161,19 @@
  */
 static void __init pci_reorder_devs(void)
 {
-	struct pci_dev **pci_onboard = &pci_devices;
-	struct pci_dev **pci_tail = &pci_devices;
-	struct pci_dev *pdev = pci_devices, *pci_other = NULL;
+	struct list_head *pci_onboard = &pci_devices;
+	struct list_head *walk = pci_onboard->next;
+
+	while (walk != pci_onboard) {
+		struct pci_dev *pdev = pci_dev_g(walk);
+		struct list_head *walk_next = walk->next;
 
-	while (pdev) {
 		if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
-			if (pci_other) {
-				*pci_onboard = pdev;
-				pci_onboard = &pdev->next;
-				pdev = pdev->next;
-				*pci_onboard = pci_other;
-				*pci_tail = pdev;
-				continue;
-			} else
-				pci_onboard = &pdev->next;
-		} else if (!pci_other)
-			pci_other = pdev;
-		pci_tail = &pdev->next;
-		pdev = pdev->next;
+			list_del(walk);
+			list_add(walk, pci_onboard);
+		}
+
+		walk = walk_next;
 	}
 }
 
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.3.37/linux/arch/sparc64/kernel/pci_common.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/pci_common.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.5 1999/12/20 05:02:11 davem Exp $
+/* $Id: pci_common.c,v 1.6 2000/01/06 23:51:49 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -59,29 +59,8 @@
  */
 static void pci_device_delete(struct pci_dev *pdev)
 {
-	struct pci_dev **dpp;
-
-	/* First, unlink from list of all devices. */
-	dpp = &pci_devices;
-	while (*dpp != NULL) {
-		if (*dpp == pdev) {
-			*dpp = pdev->next;
-			pdev->next = NULL;
-			break;
-		}
-		dpp = &(*dpp)->next;
-	}
-
-	/* Next, unlink from bus sibling chain. */
-	dpp = &pdev->bus->devices;
-	while (*dpp != NULL) {
-		if (*dpp == pdev) {
-			*dpp = pdev->sibling;
-			pdev->sibling = NULL;
-			break;
-		}
-		dpp = &(*dpp)->sibling;
-	}
+	list_del(&pdev->global_list);
+	list_del(&pdev->bus_list);
 
 	/* Ok, all references are gone, free it up. */
 	kfree(pdev);
@@ -175,23 +154,31 @@
 				    struct pci_pbm_info *pbm,
 				    int prom_node)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
 	/* This loop is coded like this because the cookie
 	 * fillin routine can delete devices from the tree.
 	 */
-	pdev = pbus->devices;
-	while (pdev != NULL) {
-		struct pci_dev *next = pdev->sibling;
+	walk = walk->next;
+	while (walk != &pbus->devices) {
+		struct pci_dev *pdev = pci_dev_b(walk);
+		struct list_head *walk_next = walk->next;
 
 		pdev_cookie_fillin(pbm, pdev, prom_node);
 
-		pdev = next;
+		walk = walk_next;
 	}
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next) {
-		struct pcidev_cookie *pcp = pbus->self->sysdata;
-		pci_fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
+	walk = &pbus->children;
+	walk = walk->next;
+	while (walk != &pbus->children) {
+		struct pci_bus *this_pbus = pci_bus_b(walk);
+		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
+		struct list_head *walk_next = walk->next;
+
+		pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
+
+		walk = walk_next;
 	}
 }
 
@@ -315,13 +302,14 @@
 void __init pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
-		pdev_record_assignments(pbm, pdev);
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+		pdev_record_assignments(pbm, pci_dev_b(walk));
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_record_assignments(pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_record_assignments(pbm, pci_bus_b(walk));
 }
 
 static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
@@ -415,13 +403,14 @@
 void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
 				  struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
-		pdev_assign_unassigned(pbm, pdev);
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+		pdev_assign_unassigned(pbm, pci_dev_b(walk));
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_assign_unassigned(pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_assign_unassigned(pbm, pci_bus_b(walk));
 }
 
 static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
@@ -566,13 +555,14 @@
 void __init pci_fixup_irq(struct pci_pbm_info *pbm,
 			  struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
-		pdev_fixup_irq(pdev);
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+		pdev_fixup_irq(pci_dev_b(walk));
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_fixup_irq(pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_fixup_irq(pbm, pci_bus_b(walk));
 }
 
 /* Generic helper routines for PCI error reporting. */
@@ -580,9 +570,10 @@
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+		struct pci_dev *pdev = pci_dev_b(walk);
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -597,17 +588,19 @@
 		}
 	}
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_scan_for_target_abort(p, pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
 }
 
 void pci_scan_for_master_abort(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+		struct pci_dev *pdev = pci_dev_b(walk);
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -621,17 +614,19 @@
 		}
 	}
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_scan_for_master_abort(p, pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
 }
 
 void pci_scan_for_parity_error(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct pci_dev *pdev;
+	struct list_head *walk = &pbus->devices;
 
-	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+		struct pci_dev *pdev = pci_dev_b(walk);
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -646,6 +641,7 @@
 		}
 	}
 
-	for (pbus = pbus->children; pbus; pbus = pbus->next)
-		pci_scan_for_parity_error(p, pbm, pbus);
+	walk = &pbus->children;
+	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+		pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
 }
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.37/linux/arch/sparc64/kernel/pci_sabre.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/pci_sabre.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.7 1999/12/19 09:17:51 davem Exp $
+/* $Id: pci_sabre.c,v 1.8 2000/01/06 23:51:49 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1032,12 +1032,15 @@
 
 static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
 {
-	struct pci_dev *pdev;
-	u16 word;
+	struct list_head *walk = &sabre_bus->devices;
+
+	for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
+		struct pci_dev *pdev = pci_dev_b(walk);
 
-	for (pdev = sabre_bus->devices; pdev; pdev = pdev->sibling) {
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
+			u16 word;
+
 			sabre_read_word(pdev, PCI_COMMAND, &word);
 			word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
 				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
@@ -1054,7 +1057,8 @@
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
 	static int once = 0;
-	struct pci_bus *sabre_bus, *pbus;
+	struct pci_bus *sabre_bus;
+	struct list_head *walk;
 
 	/* Unlike for PSYCHO, we can only have one SABRE
 	 * in a system.  Having multiple SABREs is thus
@@ -1077,7 +1081,9 @@
 				 &p->pbm_A);
 	apb_init(p, sabre_bus);
 
-	for (pbus = sabre_bus->children; pbus; pbus = pbus->next) {
+	walk = &sabre_bus->children;
+	for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
+		struct pci_bus *pbus = pci_bus_b(walk);
 		struct pci_pbm_info *pbm;
 
 		if (pbus->number == p->pbm_A.pci_first_busno) {
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.3.37/linux/arch/sparc64/kernel/sparc64_ksyms.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Fri Jan  7 11:15:27 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.68 1999/12/17 12:32:05 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.70 2000/01/07 18:15:18 jj Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -80,6 +80,7 @@
 extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
 extern int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
 extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
+extern long sparc32_open(const char * filename, int flags, int mode);
                 
 extern void bcopy (const char *, char *, int);
 extern int __ashrdi3(int, int);
@@ -123,6 +124,11 @@
 EXPORT_SYMBOL_PRIVATE(write_unlock);
 #endif
 
+/* rw semaphores */
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
+
 /* Kernel wide locking */
 EXPORT_SYMBOL(kernel_flag);
 
@@ -275,6 +281,7 @@
 EXPORT_SYMBOL(prom_cpu_nodes);
 EXPORT_SYMBOL(sys_ioctl);
 EXPORT_SYMBOL(sys32_ioctl);
+EXPORT_SYMBOL(sparc32_open);
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);
 #endif
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.3.37/linux/arch/sparc64/kernel/sys_sparc.c	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc64/kernel/sys_sparc.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.31 1999/12/21 14:09:25 jj Exp $
+/* $Id: sys_sparc.c,v 1.32 2000/01/05 01:00:40 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.37/linux/arch/sparc64/kernel/sys_sparc32.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.126 1999/12/21 14:09:21 jj Exp $
+/* $Id: sys_sparc32.c,v 1.127 2000/01/04 23:54:41 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3998,4 +3998,38 @@
 		ret = -EFAULT;
 
 	return ret;
+}
+
+/* This is just a version for 32-bit applications which does
+ * not force O_LARGEFILE on.
+ */
+
+asmlinkage long sparc32_open(const char * filename, int flags, int mode)
+{
+	char * tmp;
+	int fd, error;
+
+	tmp = getname(filename);
+	fd = PTR_ERR(tmp);
+	if (!IS_ERR(tmp)) {
+		fd = get_unused_fd();
+		if (fd >= 0) {
+			struct file * f;
+			lock_kernel();
+			f = filp_open(tmp, flags, mode);
+			unlock_kernel();
+			error = PTR_ERR(f);
+			if (IS_ERR(f))
+				goto out_error;
+			fd_install(fd, f);
+		}
+out:
+		putname(tmp);
+	}
+	return fd;
+
+out_error:
+	put_unused_fd(fd);
+	fd = error;
+	goto out;
 }
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.37/linux/arch/sparc64/kernel/sys_sunos32.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.33 1999/12/15 14:24:25 davem Exp $
+/* $Id: sys_sunos32.c,v 1.35 2000/01/06 23:51:50 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -762,7 +762,6 @@
 /* XXXXXXXXXXXXXXXXXXXX */
 asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  ret = -ENODEV;
 	int  server_fd;
 	char *the_name;
 	struct nfs_mount_data linux_nfs_mount;
@@ -1267,15 +1266,14 @@
 	return rval;
 }
 
-asmlinkage int sunos_open(u32 filename, int flags, int mode)
+extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+
+asmlinkage int sunos_open(u32 fname, int flags, int mode)
 {
-	int ret;
+	const char *filename = (const char *)(long)fname;
 
-	lock_kernel();
 	current->personality |= PER_BSD;
-	ret = sys_open ((char *)A(filename), flags, mode);
-	unlock_kernel();
-	return ret;
+	return sparc32_open(filename, flags, mode);
 }
 
 #define SUNOS_EWOULDBLOCK 35
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.3.37/linux/arch/sparc64/kernel/systbls.S	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/systbls.S	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.61 1999/12/21 14:09:15 jj Exp $
+/* $Id: systbls.S,v 1.62 2000/01/04 23:54:43 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -20,7 +20,7 @@
 	.globl sys_call_table32
 sys_call_table32:
 /*0*/	.word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
-/*5*/	.word sys_open, sys_close, sys32_wait4, sys_creat, sys_link
+/*5*/	.word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
 /*15*/	.word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
diff -u --recursive --new-file v2.3.37/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.37/linux/arch/sparc64/solaris/fs.c	Wed Dec 29 13:13:15 1999
+++ linux/arch/sparc64/solaris/fs.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.14 1999/09/22 09:28:49 davem Exp $
+/* $Id: fs.c,v 1.15 2000/01/04 23:54:47 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -575,20 +575,24 @@
 	return error;
 }
 
-asmlinkage int solaris_open(u32 filename, int flags, u32 mode)
+extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+
+asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
 {
-	int (*sys_open)(const char *,int,int) = 
-		(int (*)(const char *,int,int))SYS(open);
+	const char *filename = (const char *)(long)fname;
 	int fl = flags & 0xf;
 
-/*	if (flags & 0x2000) - allow LFS			*/
+	/* Translate flags first. */
+	if (flags & 0x2000) fl |= O_LARGEFILE;
 	if (flags & 0x8050) fl |= O_SYNC;
 	if (flags & 0x80) fl |= O_NONBLOCK;
 	if (flags & 0x100) fl |= O_CREAT;
 	if (flags & 0x200) fl |= O_TRUNC;
 	if (flags & 0x400) fl |= O_EXCL;
 	if (flags & 0x800) fl |= O_NOCTTY;
-	return sys_open((const char *)A(filename), fl, mode);
+	flags = fl;
+
+	return sparc32_open(filename, flags, mode);
 }
 
 #define SOL_F_SETLK	6
diff -u --recursive --new-file v2.3.37/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c
--- v2.3.37/linux/drivers/acorn/block/fd1772.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/acorn/block/fd1772.c	Fri Jan  7 11:38:05 2000
@@ -1570,22 +1570,13 @@
 	}
 }
 
-static struct file_operations floppy_fops =
+static struct block_device_operations floppy_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	fd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	check_floppy_change,	/* media_change */
-	floppy_revalidate,	/* revalidate */
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			fd_ioctl,
+	check_media_change:	check_floppy_change,
+	revalidate:		floppy_revalidate,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.3.37/linux/drivers/acorn/block/mfmhd.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/block/mfmhd.c	Fri Jan  7 11:38:05 2000
@@ -1365,22 +1365,11 @@
 	hardsect_size[MAJOR_NR] = mfm_sectsizes;
 }
 
-static struct file_operations mfm_fops =
+static struct block_device_operations mfm_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	mfm_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	mfm_open,		/* open */
-	NULL,			/* flush */
-	mfm_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
+	open:		mfm_open,
+	release:	mfm_release,
+	ioctl:		mfm_ioctl,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/ap1000/ap.c linux/drivers/ap1000/ap.c
--- v2.3.37/linux/drivers/ap1000/ap.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/ap1000/ap.c	Fri Jan  7 11:38:05 2000
@@ -244,18 +244,10 @@
   wake_up(&busy_wait);  
 } 
 
-static struct file_operations ap_fops = {
-	NULL,                   /* lseek - default */
-	block_read,             /* read - general block-dev read */
-	block_write,            /* write - general block-dev write */
-	NULL,                   /* readdir - bad */
-	NULL,                   /* poll */
-	ap_ioctl,               /* ioctl */
-	NULL,                   /* mmap */
-	ap_open,                /* open */
-	NULL,			/* flush */
-	ap_release,		/* module needs to decrement use count */
-	block_fsync,            /* fsync */
+static struct block_device_operations ap_fops = {
+	open:		ap_open,
+	release:	ap_release,
+	ioctl:		ap_ioctl,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c
--- v2.3.37/linux/drivers/ap1000/ddv.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/ap1000/ddv.c	Fri Jan  7 11:38:05 2000
@@ -875,18 +875,10 @@
 	};
 }
 
-static struct file_operations ddv_fops = {
-        NULL,                   /* lseek - default */
-        block_read,         /* read */
-        block_write,        /* write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* poll */
-        ddv_ioctl,               /* ioctl */
-        NULL,                   /* mmap */
-        ddv_open,                /* open */
-	NULL,			/* flush */
-	ddv_release,
-        block_fsync          /* fsync */
+static struct block_device_operations ddv_fops = {
+        open:		ddv_open,
+	release:	ddv_release,
+        ioctl:		ddv_ioctl,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.37/linux/drivers/block/Config.in	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/Config.in	Thu Jan  6 14:46:18 2000
@@ -98,7 +98,7 @@
 	    if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
 	       bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
 	       if [ "$CONFIG_X86" = "y" ]; then
-		  bool '      VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX
+		  bool '    VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX
 	       fi
 	    fi
          fi
diff -u --recursive --new-file v2.3.37/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.37/linux/drivers/block/DAC960.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/DAC960.c	Fri Jan  7 11:38:05 2000
@@ -75,24 +75,14 @@
 /*
   DAC960_FileOperations is the File Operations structure for DAC960 Logical
   Disk Devices.
+  Leonard, no offence, but _where_ did this C dialect come from?
 */
 
-static FileOperations_T
-  DAC960_FileOperations =
-    { llseek:		    NULL,
-      read:		    block_read,
-      write:		    block_write,
-      readdir:		    NULL,
-      poll:		    NULL,
-      ioctl:		    DAC960_IOCTL,
-      mmap:		    NULL,
-      open:		    DAC960_Open,
-      release:		    DAC960_Release,
-      fsync:		    block_fsync,
-      fasync:		    NULL,
-      check_media_change:   NULL,
-      revalidate:	    NULL };
-
+static struct block_device_operations DAC960_FileOperations = { 
+	open:		DAC960_Open,
+	release:	DAC960_Release,
+	ioctl:		DAC960_IOCTL,
+};
 
 /*
   DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry.
diff -u --recursive --new-file v2.3.37/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.3.37/linux/drivers/block/acsi.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/acsi.c	Fri Jan  7 11:38:05 2000
@@ -1770,21 +1770,12 @@
 }
 #endif /* CONFIG_ATARI_SLM_MODULE */
 
-static struct file_operations acsi_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,	/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	acsi_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	acsi_open,		/* open */
-	NULL,			/* flush */
-	acsi_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	acsi_media_change,	/* media_change */
-	acsi_revalidate,	/* revalidate */
+static struct block_device_operations acsi_fops = {
+	open:			acsi_open,
+	release:		acsi_release,
+	ioctl:			acsi_ioctl,
+	check_media_change:	acsi_media_change,
+	revalidate:		acsi_revalidate,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.3.37/linux/drivers/block/amiflop.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/amiflop.c	Fri Jan  7 11:38:05 2000
@@ -1750,21 +1750,11 @@
 	return 0;
 }
 
-static struct file_operations floppy_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	fd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release, 	/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	amiga_floppy_change,	/* check_media_change */
-	NULL,			/* revalidate */
+static struct block_device_operations floppy_fops = {
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			fd_ioctl,
+	check_media_change:	amiga_floppy_change,
 };
 
 void __init amiga_floppy_setup (char *str, int *ints)
diff -u --recursive --new-file v2.3.37/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.3.37/linux/drivers/block/ataflop.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/ataflop.c	Fri Jan  7 11:38:05 2000
@@ -1958,21 +1958,12 @@
 	return 0;
 }
 
-static struct file_operations floppy_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	fd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release, 	/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	check_floppy_change,	/* media_change */
-	floppy_revalidate,	/* revalidate */
+static struct block_device_operations floppy_fops = {
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			fd_ioctl,
+	check_media_change:	check_floppy_change,
+	revalidate:		floppy_revalidate,
 };
 
 int __init atari_floppy_init (void)
diff -u --recursive --new-file v2.3.37/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.3.37/linux/drivers/block/cpqarray.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/cpqarray.c	Fri Jan  7 11:38:05 2000
@@ -196,21 +196,11 @@
 
 }
 
-struct file_operations ida_fops  = {
-	NULL,                        /* lseek - default */
-	block_read,                  /* read - general block-dev read */
-	block_write,                 /* write - general block-dev write */
-	NULL,                        /* readdir - bad */
-	NULL,                        /* select */
-	ida_ioctl,                  /* ioctl */
-	NULL,                        /* mmap */
-	ida_open,                     /* open code */
-	NULL,
-	ida_release,                  /* release */
-	block_fsync,	              /* fsync */
-	NULL,                        /* fasync */
-	NULL,			/* Disk change */
-	frevalidate_logvol,	/* revalidate */
+static struct block_device_operations ida_fops  = {
+	open:		ida_open,
+	release:	ida_release,
+	ioctl:		ida_ioctl,
+	revalidate:	frevalidate_logvol,
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- v2.3.37/linux/drivers/block/cy82c693.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/cy82c693.c	Fri Jan  7 11:53:06 2000
@@ -274,8 +274,13 @@
 	unsigned int addrCtrl;
 
 	/* select primary or secondary channel */
-	if (hwif->index > 0)  /* drive is on the secondary channel */
-		dev = dev->next;
+	if (hwif->index > 0) {  /* drive is on the secondary channel */
+		dev = pci_find_slot(dev, dev->devfn+1);
+		if (!dev) {
+			printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n");
+			return;
+		}
+	}
 
 #if CY82C693_DEBUG_LOGS
 	/* for debug let's show the register values */
diff -u --recursive --new-file v2.3.37/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.37/linux/drivers/block/floppy.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/floppy.c	Fri Jan  7 11:38:05 2000
@@ -3827,21 +3827,12 @@
 	return 0;
 }
 
-static struct file_operations floppy_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,		       	/* readdir - bad */
-	NULL,			/* poll */
-	fd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	check_floppy_change,	/* media_change */
-	floppy_revalidate,	/* revalidate */
+static struct block_device_operations floppy_fops = {
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			fd_ioctl,
+	check_media_change:	check_floppy_change,
+	revalidate:		floppy_revalidate,
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.3.37/linux/drivers/block/hd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/hd.c	Fri Jan  7 11:38:05 2000
@@ -793,18 +793,10 @@
 	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
 }
 
-static struct file_operations hd_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	hd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	hd_open,		/* open */
-	NULL,			/* flush */
-	hd_release,		/* release */
-	block_fsync		/* fsync */
+static struct block_device_operations hd_fops = {
+	open:		hd_open,
+	release:	hd_release,
+	ioctl:		hd_ioctl,
 };
 
 int __init hd_init(void)
diff -u --recursive --new-file v2.3.37/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.3.37/linux/drivers/block/ide-tape.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide-tape.c	Fri Jan  7 11:43:09 2000
@@ -5674,8 +5674,6 @@
 	idetape_chrdev_release,	/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.37/linux/drivers/block/ide.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide.c	Fri Jan  7 11:38:05 2000
@@ -3348,21 +3348,12 @@
 		*p = (*p)->next;
 }
 
-struct file_operations ide_fops[] = {{
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	ide_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	ide_open,		/* open */
-	NULL,			/* flush */
-	ide_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	ide_check_media_change,	/* check_media_change */
-	ide_revalidate_disk	/* revalidate */
+struct block_device_operations ide_fops[] = {{
+	open:			ide_open,
+	release:		ide_release,
+	ioctl:			ide_ioctl,
+	check_media_change:	ide_check_media_change,
+	revalidate:		ide_revalidate_disk
 }};
 
 EXPORT_SYMBOL(ide_hwifs);
diff -u --recursive --new-file v2.3.37/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.3.37/linux/drivers/block/loop.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/loop.c	Fri Jan  7 11:38:05 2000
@@ -668,17 +668,10 @@
 	return err;
 }
 
-static struct file_operations lo_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	lo_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	lo_open,		/* open */
-	NULL,			/* flush */
-	lo_release		/* release */
+static struct block_device_operations lo_fops = {
+	open:		lo_open,
+	release:	lo_release,
+	ioctl:		lo_ioctl,
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.37/linux/drivers/block/md.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/md.c	Fri Jan  7 11:38:05 2000
@@ -681,42 +681,11 @@
   return 0;
 }
 
-
-static ssize_t md_read (struct file *file, char *buf, size_t count,
-			loff_t *ppos)
+static struct block_device_operations md_fops=
 {
-  int minor=MINOR(file->f_dentry->d_inode->i_rdev);
-
-  if (!md_dev[minor].pers)	/* Check if device is being run */
-    return -ENXIO;
-
-  return block_read(file, buf, count, ppos);
-}
-
-static ssize_t md_write (struct file *file, const char *buf,
-			 size_t count, loff_t *ppos)
-{
-  int minor=MINOR(file->f_dentry->d_inode->i_rdev);
-
-  if (!md_dev[minor].pers)	/* Check if device is being run */
-    return -ENXIO;
-
-  return block_write(file, buf, count, ppos);
-}
-
-static struct file_operations md_fops=
-{
-  NULL,
-  md_read,
-  md_write,
-  NULL,
-  NULL,
-  md_ioctl,
-  NULL,
-  md_open,
-  NULL,
-  md_release,
-  block_fsync
+	open:		md_open,
+	release:	md_release,
+	ioctl:		md_ioctl,
 };
 
 int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size)
diff -u --recursive --new-file v2.3.37/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.3.37/linux/drivers/block/nbd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/nbd.c	Fri Jan  7 11:38:05 2000
@@ -446,18 +446,11 @@
 	return 0;
 }
 
-static struct file_operations nbd_fops =
+static struct block_device_operations nbd_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	nbd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	nbd_open,		/* open */
-	NULL,			/* flush */
-	nbd_release		/* release */
+	open:		nbd_open,
+	release:	nbd_release,
+	ioctl:		nbd_ioctl,
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.3.37/linux/drivers/block/paride/pd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/paride/pd.c	Fri Jan  7 11:38:05 2000
@@ -354,21 +354,12 @@
         NULL            /* next */
 };
 
-static struct file_operations pd_fops = {
-        NULL,                   /* lseek - default */
-        block_read,             /* read - general block-dev read */
-        block_write,            /* write - general block-dev write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* select */
-        pd_ioctl,               /* ioctl */
-        NULL,                   /* mmap */
-        pd_open,                /* open */
-	NULL,			/* flush */
-        pd_release,             /* release */
-        block_fsync,            /* fsync */
-        NULL,                   /* fasync */
-        pd_check_media,         /* media change ? */
-        pd_revalidate           /* revalidate new media */
+static struct block_device_operations pd_fops = {
+        open:			pd_open,
+        release:		pd_release,
+        ioctl:			pd_ioctl,
+        check_media_change:	pd_check_media,
+        revalidate:		pd_revalidate
 };
 
 void pd_init_units( void )
diff -u --recursive --new-file v2.3.37/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.3.37/linux/drivers/block/paride/pf.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/paride/pf.c	Fri Jan  7 11:38:05 2000
@@ -311,21 +311,11 @@
 
 /* kernel glue structures */
 
-static struct file_operations pf_fops = {
-        NULL,                   /* lseek - default */
-        block_read,             /* read - general block-dev read */
-        block_write,            /* write - general block-dev write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* select */
-        pf_ioctl,               /* ioctl */
-        NULL,                   /* mmap */
-        pf_open,                /* open */
-	NULL,			/* flush */
-        pf_release,             /* release */
-        block_fsync,            /* fsync */
-        NULL,                   /* fasync */
-        pf_check_media,         /* media change ? */
-        NULL                    /* revalidate new media */
+static struct block_device_operations pf_fops = {
+	open:			pf_open,
+	release:		pf_release,
+	ioctl:			pf_ioctl,
+	check_media_change:	pf_check_media,
 };
 
 void pf_init_units( void )
diff -u --recursive --new-file v2.3.37/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.3.37/linux/drivers/block/paride/pg.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/paride/pg.c	Fri Jan  7 11:43:09 2000
@@ -272,8 +272,6 @@
 	pg_release,             /* release */
 	NULL,                   /* fsync */
 	NULL,                   /* fasync */
-	NULL,                   /* media change ? */
-	NULL                    /* revalidate new media */
 };
 
 void pg_init_units( void )
diff -u --recursive --new-file v2.3.37/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.3.37/linux/drivers/block/paride/pt.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/paride/pt.c	Fri Jan  7 11:43:09 2000
@@ -274,8 +274,6 @@
         pt_release,             /* release */
         NULL,                   /* fsync */
         NULL,                   /* fasync */
-        NULL,                   /* media change ? */
-        NULL                    /* revalidate new media */
 };
 
 void pt_init_units( void )
diff -u --recursive --new-file v2.3.37/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.3.37/linux/drivers/block/ps2esdi.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/ps2esdi.c	Fri Jan  7 11:38:05 2000
@@ -147,19 +147,11 @@
 	{0, 0, 0, 0, 0, 0},
 	{0, 0, 0, 0, 0, 0}};
 
-static struct file_operations ps2esdi_fops =
+static struct block_device_operations ps2esdi_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	ps2esdi_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	ps2esdi_open,		/* open */
-	NULL,			/* flush */
-	ps2esdi_release,	/* release */
-	block_fsync		/* fsync */
+	open:		ps2esdi_open,
+	release:	ps2esdi_release,
+	ioctl:		ps2esdi_ioctl,
 };
 
 static struct gendisk ps2esdi_gendisk =
diff -u --recursive --new-file v2.3.37/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.37/linux/drivers/block/rd.c	Wed Dec 29 13:13:15 1999
+++ linux/drivers/block/rd.c	Fri Jan  7 11:38:05 2000
@@ -379,18 +379,10 @@
 	return 0;
 }
 
-static struct file_operations fd_fops = {
-	NULL,		/* lseek - default */
-	block_read,	/* read - block dev read */
-	block_write,	/* write - block dev write */
-	NULL,		/* readdir - not here! */
-	NULL,		/* poll */
-	rd_ioctl, 	/* ioctl */
-	NULL,		/* mmap */
-	rd_open,	/* open */
-	NULL,		/* flush */
-	rd_release,	/* module needs to decrement use count */
-	block_fsync	/* fsync */ 
+static struct block_device_operations fd_fops = {
+	open:		rd_open,
+	release:	rd_release,
+	ioctl:		rd_ioctl,
 };
 
 /* Before freeing the module, invalidate all of the protected buffers! */
diff -u --recursive --new-file v2.3.37/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
--- v2.3.37/linux/drivers/block/swim3.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/swim3.c	Fri Jan  7 11:38:05 2000
@@ -1030,21 +1030,12 @@
 {
 }
 
-static struct file_operations floppy_fops = {
-	NULL,			/* lseek */
-	floppy_read,		/* read */
-	floppy_write,		/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	floppy_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	floppy_check_change,	/* check_media_change */
-	floppy_revalidate,	/* revalidate */
+static struct block_device_operations floppy_fops = {
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			floppy_ioctl,
+	check_media_change:	floppy_check_change,
+	revalidate:		floppy_revalidate,
 };
 
 int swim3_init(void)
diff -u --recursive --new-file v2.3.37/linux/drivers/block/swim_iop.c linux/drivers/block/swim_iop.c
--- v2.3.37/linux/drivers/block/swim_iop.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/swim_iop.c	Fri Jan  7 11:38:05 2000
@@ -121,21 +121,12 @@
 static void do_fd_request(request_queue_t * q);
 static void start_request(struct floppy_state *fs);
 
-static struct file_operations floppy_fops = {
-	NULL,			/* lseek */
-	floppy_read,		/* read */
-	floppy_write,		/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	floppy_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	floppy_open,		/* open */
-	NULL,			/* flush */
-	floppy_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	floppy_check_change,	/* check_media_change */
-	floppy_revalidate,	/* revalidate */
+static struct block_device_operations floppy_fops = {
+	open:			floppy_open,
+	release:		floppy_release,
+	ioctl:			floppy_ioctl,
+	check_media_change:	floppy_check_change,
+	revalidate:		floppy_revalidate,
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.3.37/linux/drivers/block/xd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/xd.c	Fri Jan  7 11:38:05 2000
@@ -147,18 +147,10 @@
 	(void *) xd_info,	/* internal */
 	NULL		/* next */
 };
-static struct file_operations xd_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	xd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	xd_open,		/* open */
-	NULL,			/* flush */
-	xd_release,		/* release */
-	block_fsync		/* fsync */
+static struct block_device_operations xd_fops = {
+	open:		xd_open,
+	release:	xd_release,
+	ioctl:		xd_ioctl,
 };
 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_open);
diff -u --recursive --new-file v2.3.37/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.3.37/linux/drivers/block/z2ram.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/z2ram.c	Fri Jan  7 11:38:05 2000
@@ -331,22 +331,10 @@
     return 0;
 }
 
-static struct file_operations z2_fops =
+static struct block_device_operations z2_fops =
 {
-	NULL,                   /* lseek - default */
-	block_read,             /* read - general block-dev read */
-	block_write,            /* write - general block-dev write */
-	NULL,                   /* readdir - bad */
-	NULL,                   /* poll */
-	NULL,                   /* ioctl */
-	NULL,                   /* mmap */
-	z2_open,                /* open */
-	NULL,			/* flush */
-	z2_release,             /* release */
-	block_fsync,            /* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
+	open:		z2_open,
+	release:	z2_release,
 };
 
 int __init 
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.3.37/linux/drivers/cdrom/aztcd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/aztcd.c	Fri Jan  7 11:38:05 2000
@@ -371,21 +371,11 @@
 
 int       aztcd_init(void);
 
-static struct file_operations azt_fops = {
-	NULL,                   /* lseek - default */
-	block_read,             /* read - general block-dev read */
-	block_write,            /* write - general block-dev write */
-	NULL,                   /* readdir - bad */
-	NULL,                   /* poll */
-	aztcd_ioctl,            /* ioctl */
-	NULL,                   /* mmap */
-	aztcd_open,             /* open */
-	NULL,			/* flush */
-	aztcd_release,          /* release */
-	NULL,                   /* fsync */
-	NULL,                   /* fasync*/
-	check_aztcd_media_change, /*media change*/
-	NULL                    /* revalidate*/
+static struct block_device_operations azt_fops = {
+	open:			aztcd_open,
+	release:		aztcd_release,
+	ioctl:			aztcd_ioctl,
+	check_media_change:	check_aztcd_media_change,
 };
 
 /* Aztcd State Machine: Controls Drive Operating State */
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.3.37/linux/drivers/cdrom/cdrom.c	Tue Jan  4 13:57:16 2000
+++ linux/drivers/cdrom/cdrom.c	Fri Jan  7 11:38:05 2000
@@ -291,22 +291,12 @@
 #endif /* CONFIG_SYSCTL */ 
 static struct cdrom_device_info *topCdromPtr = NULL;
 
-struct file_operations cdrom_fops =
+struct block_device_operations cdrom_fops =
 {
-	NULL,                           /* lseek */
-	block_read,                     /* read - general block-dev read */
-	block_write,                    /* write - general block-dev write */
-	NULL,                           /* readdir */
-	NULL,                           /* poll */
-	cdrom_ioctl,                    /* ioctl */
-	NULL,                           /* mmap */
-	cdrom_open,                     /* open */
-	NULL,				/* flush */
-	cdrom_release,                  /* release */
-	NULL,                           /* fsync */
-	NULL,                           /* fasync */
-	cdrom_media_changed,            /* media_change */
-	NULL                            /* revalidate */
+	open:			cdrom_open,
+	release:		cdrom_release,
+	ioctl:			cdrom_ioctl,
+	check_media_change:	cdrom_media_changed,
 };
 
 /* This macro makes sure we don't have to check on cdrom_device_ops
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.3.37/linux/drivers/cdrom/gscd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/gscd.c	Fri Jan  7 11:38:05 2000
@@ -160,21 +160,11 @@
 static int  AudioEnd_f;
  
 
-static struct file_operations gscd_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	gscd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	gscd_open,		/* open */
-	NULL,			/* flush */
-	gscd_release,		/* release */
-	NULL,                   /* fsync */
-	NULL,                   /* fasync*/
-	check_gscd_med_chg,     /* media change */
-	NULL                    /* revalidate */
+static struct block_device_operations gscd_fops = {
+	open:			gscd_open,
+	release:		gscd_release,
+	ioctl:			gscd_ioctl,
+	check_media_change:	check_gscd_med_chg,
 };
 
 /* 
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.3.37/linux/drivers/cdrom/optcd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/optcd.c	Fri Jan  7 11:38:05 2000
@@ -2008,21 +2008,11 @@
 }
 
 
-static struct file_operations opt_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	opt_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	opt_open,		/* open */
-	NULL,			/* flush */
-	opt_release,		/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	opt_media_change,	/* media change */
-	NULL			/* revalidate */
+static struct block_device_operations opt_fops = {
+	open:			opt_open,
+	release:		opt_release,
+	ioctl:			opt_ioctl,
+	check_media_change:	opt_media_change,
 };
 
 #ifndef MODULE
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.3.37/linux/drivers/cdrom/sjcd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/sjcd.c	Fri Jan  7 11:38:05 2000
@@ -1436,21 +1436,11 @@
 /*
  * A list of file operations allowed for this cdrom.
  */
-static struct file_operations sjcd_fops = {
-  NULL,               /* lseek - default */
-  block_read,         /* read - general block-dev read */
-  block_write,        /* write - general block-dev write */
-  NULL,               /* readdir - bad */
-  NULL,               /* poll */
-  sjcd_ioctl,         /* ioctl */
-  NULL,               /* mmap */
-  sjcd_open,          /* open */
-  NULL,		      /* flush */
-  sjcd_release,       /* release */
-  NULL,               /* fsync */
-  NULL,               /* fasync */
-  sjcd_disk_change,   /* media change */
-  NULL                /* revalidate */
+static struct block_device_operations sjcd_fops = {
+	open:			sjcd_open,
+	release:		sjcd_release,
+	ioctl:			sjcd_ioctl,
+	check_media_change:	sjcd_disk_change,
 };
 
 static int blksize = 2048;
diff -u --recursive --new-file v2.3.37/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.3.37/linux/drivers/cdrom/sonycd535.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/sonycd535.c	Fri Jan  7 11:38:05 2000
@@ -1468,22 +1468,12 @@
 }
 
 
-static struct file_operations cdu_fops =
+static struct block_device_operations cdu_fops =
 {
-	NULL,						/* lseek - default */
-	block_read,					/* read - general block-dev read */
-	block_write,					/* write - general block-dev write */
-	NULL,						/* readdir - bad */
-	NULL,						/* poll */
-	cdu_ioctl,					/* ioctl */
-	NULL,						/* mmap */
-	cdu_open,					/* open */
-	NULL,						/* flush */
-	cdu_release,					/* release */
-	NULL,						/* fsync */
-	NULL,						/* fasync */
-	cdu535_check_media_change,			/* check media change */
-	NULL						/* revalidate */
+	open:			cdu_open,
+	release:		cdu_release,
+	ioctl:			cdu_ioctl,
+	check_media_change:	cdu535_check_media_change,
 };
 
 static int sonycd535_block_size = CDU535_BLOCK_SIZE;
diff -u --recursive --new-file v2.3.37/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.3.37/linux/drivers/char/dsp56k.c	Thu Nov 11 20:11:33 1999
+++ linux/drivers/char/dsp56k.c	Fri Jan  7 11:43:09 2000
@@ -513,8 +513,6 @@
 	dsp56k_release,
 	NULL,    /* no special dsp56k_fsync */
 	NULL,    /* no special dsp56k_fasync */
-	NULL,    /* no special dsp56k_check_media_change */
-	NULL     /* no special dsp56k_revalidate */
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.3.37/linux/drivers/char/dtlk.c	Wed May 12 13:27:37 1999
+++ linux/drivers/char/dtlk.c	Fri Jan  7 11:43:09 2000
@@ -115,8 +115,6 @@
 	dtlk_release,
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.3.37/linux/drivers/char/h8.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/char/h8.c	Fri Jan  7 11:43:09 2000
@@ -109,18 +109,7 @@
 static char  driver_version[] = "X0.0";/* no spaces */
 
 static struct file_operations h8_fops = {
-        NULL,           /* lseek */
-        NULL,
-        NULL,           /* write */
-        NULL,           /* readdir */
-        NULL,
-        NULL,
-        NULL,           /* mmap */
-        NULL,
-	NULL,		/* flush */
-        NULL,
-        NULL,           /* fsync */
-        NULL            /* fasync */
+	/* twelve lines of crap^WNULLs were here */
 };
 
 static struct miscdevice h8_device = {
diff -u --recursive --new-file v2.3.37/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
--- v2.3.37/linux/drivers/char/ip2main.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/char/ip2main.c	Fri Jan  7 11:43:09 2000
@@ -195,12 +195,6 @@
 	ip2_ipl_ioctl,
 	NULL,
 	ip2_ipl_open,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	/* NULL, NULL 2.2 */
 }; 
 
 static long irq_counter = 0;
diff -u --recursive --new-file v2.3.37/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.3.37/linux/drivers/char/isicom.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/char/isicom.c	Fri Jan  7 11:43:09 2000
@@ -121,8 +121,6 @@
 	ISILoad_release,
 	NULL,	/*	fsync	*/
 	NULL,	/*	fasync	*/
-	NULL,	/*	check_media_change	*/
-	NULL,	/*	revalidate	*/
 };
 
 struct miscdevice isiloader_device = {
diff -u --recursive --new-file v2.3.37/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.3.37/linux/drivers/char/istallion.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/istallion.c	Fri Jan  7 11:43:09 2000
@@ -789,8 +789,6 @@
 	stli_memclose,	/* release */
 	NULL,		/* fsync */
 	NULL,		/* fasync */
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
 	NULL		/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.3.37/linux/drivers/char/msp3400.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/char/msp3400.c	Fri Jan  7 11:43:09 2000
@@ -1255,8 +1255,6 @@
         msp3400c_mixer_release,
         NULL,  /* fsync */
         NULL,  /* fasync */
-        NULL,  /* check_media_change */
-        NULL,  /* revalidate */
         NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.3.37/linux/drivers/char/pc110pad.c	Tue Dec  7 09:32:43 1999
+++ linux/drivers/char/pc110pad.c	Fri Jan  7 11:43:09 2000
@@ -639,8 +639,6 @@
 	close_pad,
 	NULL,		/* fsync */
 	fasync_pad,
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
 	NULL		/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.3.37/linux/drivers/char/pcwd.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/pcwd.c	Fri Jan  7 11:43:09 2000
@@ -582,8 +582,6 @@
 	pcwd_close,	/* Release */
 	NULL,		/* Fsync */
 	NULL,		/* Fasync */
-	NULL,		/* CheckMediaChange */
-	NULL,		/* Revalidate */
 	NULL,		/* Lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.3.37/linux/drivers/char/ppdev.c	Tue Dec  7 09:32:43 1999
+++ linux/drivers/char/ppdev.c	Fri Jan  7 11:54:31 2000
@@ -50,7 +50,7 @@
 #include <linux/ctype.h>
 #include <linux/poll.h>
 #include <asm/uaccess.h>
-#include "ppdev.h"
+#include <linux/ppdev.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
 #define CHRDEV "ppdev"
diff -u --recursive --new-file v2.3.37/linux/drivers/char/ppdev.h linux/drivers/char/ppdev.h
--- v2.3.37/linux/drivers/char/ppdev.h	Mon Oct 11 15:38:14 1999
+++ linux/drivers/char/ppdev.h	Wed Dec 31 16:00:00 1969
@@ -1,81 +0,0 @@
-/*
- * linux/drivers/char/ppdev.h
- *
- * User-space parallel port device driver (header file).
- *
- * Copyright (C) 1998-9 Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Added PPGETTIME/PPSETTIME, Fred Barnes, 1999
- */
-
-#define PP_MAJOR	99
-
-#define PP_IOCTL	'p'
-
-/* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */
-#define PPSETMODE	_IOW(PP_IOCTL, 0x80, int)
-
-/* Read status */
-#define PPRSTATUS	_IOR(PP_IOCTL, 0x81, unsigned char)
-#define PPWSTATUS	OBSOLETE__IOW(PP_IOCTL, 0x82, unsigned char)
-
-/* Read/write control */
-#define PPRCONTROL	_IOR(PP_IOCTL, 0x83, unsigned char)
-#define PPWCONTROL	_IOW(PP_IOCTL, 0x84, unsigned char)
-
-struct ppdev_frob_struct {
-	unsigned char mask;
-	unsigned char val;
-};
-#define PPFCONTROL      _IOW(PP_IOCTL, 0x8e, struct ppdev_frob_struct)
-
-/* Read/write data */
-#define PPRDATA		_IOR(PP_IOCTL, 0x85, unsigned char)
-#define PPWDATA		_IOW(PP_IOCTL, 0x86, unsigned char)
-
-/* Read/write econtrol (not used) */
-#define PPRECONTROL	OBSOLETE__IOR(PP_IOCTL, 0x87, unsigned char)
-#define PPWECONTROL	OBSOLETE__IOW(PP_IOCTL, 0x88, unsigned char)
-
-/* Read/write FIFO (not used) */
-#define PPRFIFO		OBSOLETE__IOR(PP_IOCTL, 0x89, unsigned char)
-#define PPWFIFO		OBSOLETE__IOW(PP_IOCTL, 0x8a, unsigned char)
-
-/* Claim the port to start using it */
-#define PPCLAIM		_IO(PP_IOCTL, 0x8b)
-
-/* Release the port when you aren't using it */
-#define PPRELEASE	_IO(PP_IOCTL, 0x8c)
-
-/* Yield the port (release it if another driver is waiting,
- * then reclaim) */
-#define PPYIELD		_IO(PP_IOCTL, 0x8d)
-
-/* Register device exclusively (must be before PPCLAIM). */
-#define PPEXCL		_IO(PP_IOCTL, 0x8f)
-
-/* Data line direction: non-zero for input mode. */
-#define PPDATADIR	_IOW(PP_IOCTL, 0x90, int)
-
-/* Negotiate a particular IEEE 1284 mode. */
-#define PPNEGOT		_IOW(PP_IOCTL, 0x91, int)
-
-/* Set control lines when an interrupt occurs. */
-#define PPWCTLONIRQ	_IOW(PP_IOCTL, 0x92, unsigned char)
-
-/* Clear (and return) interrupt count. */
-#define PPCLRIRQ	_IOR(PP_IOCTL, 0x93, int)
-
-/* Set the IEEE 1284 phase that we're in (e.g. IEEE1284_PH_FWD_IDLE) */
-#define PPSETPHASE	_IOW(PP_IOCTL, 0x94, int)
-
-/* Set and get port timeout (struct timeval's) */
-#define PPGETTIME	_IOR(PP_IOCTL, 0x95, struct timeval)
-#define PPSETTIME	_IOW(PP_IOCTL, 0x96, struct timeval)
-
-
diff -u --recursive --new-file v2.3.37/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.37/linux/drivers/char/serial.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/char/serial.c	Fri Jan  7 11:43:09 2000
@@ -199,8 +199,6 @@
 #include <linux/pci.h>
 #endif
 
-#include <linux/sysrq.h>
-
 /*
  * All of the compatibilty code so we can compile serial.c against
  * older kernels is hidden in serial_compat.h
diff -u --recursive --new-file v2.3.37/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.3.37/linux/drivers/char/stallion.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/stallion.c	Fri Jan  7 11:43:09 2000
@@ -755,8 +755,6 @@
 	stl_memclose,	/* release */
 	NULL,		/* fsync */
 	NULL,		/* fasync */
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
 	NULL		/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/char/sx.c linux/drivers/char/sx.c
--- v2.3.37/linux/drivers/char/sx.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/sx.c	Fri Jan  7 11:43:09 2000
@@ -545,8 +545,6 @@
 	sx_fw_release,
 	NULL,	/*	fsync	*/
 	NULL,	/*	fasync	*/
-	NULL,	/*	check_media_change	*/
-	NULL,	/*	revalidate	*/
 };
 
 struct miscdevice sx_fw_device = {
diff -u --recursive --new-file v2.3.37/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.3.37/linux/drivers/char/tpqic02.c	Tue Jul  6 10:11:40 1999
+++ linux/drivers/char/tpqic02.c	Fri Jan  7 11:43:09 2000
@@ -2777,8 +2777,6 @@
 	qic02_tape_release,		/* release */
 	NULL,				/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL				/* revalidate */
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.3.37/linux/drivers/i2o/i2o_block.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/i2o/i2o_block.c	Fri Jan  7 11:38:05 2000
@@ -1006,23 +1006,13 @@
 	0
 };
 
-static struct file_operations i2ob_fops =
+static struct block_device_operations i2ob_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	i2ob_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	i2ob_open,		/* open */
-	NULL,			/* flush */
-	i2ob_release,		/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	i2ob_media_change,	/* Media Change */
-	i2ob_revalidate,	/* Revalidate */
-	NULL			/* File locks */
+	open:			i2ob_open,
+	release:		i2ob_release,
+	ioctl:			i2ob_ioctl,
+	check_media_change:	i2ob_media_change,
+	revalidate:		i2ob_revalidate,
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.37/linux/drivers/net/Space.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/Space.c	Thu Jan  6 15:01:56 2000
@@ -570,6 +570,7 @@
 extern int ibmtr_probe(struct net_device *);
 extern int olympic_probe(struct net_device *);
 extern int tms380tr_probe(struct net_device *);
+extern int smctr_probe(struct net_device *);
 
 static int
 trif_probe(struct net_device *dev)
diff -u --recursive --new-file v2.3.37/linux/drivers/net/cops.c linux/drivers/net/cops.c
--- v2.3.37/linux/drivers/net/cops.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/cops.c	Thu Jan  6 14:46:18 2000
@@ -1,7 +1,7 @@
 /*      cops.c: LocalTalk driver for Linux.
  *
  *	Authors:
- *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *      - Jay Schulist <jschlst@turbolinux.com>
  *
  *	With more than a little help from;
  *	- Alan Cox <Alan.Cox@linux.org> 
@@ -33,7 +33,7 @@
  */
 
 static const char *version =
-"cops.c:v0.04 6/7/98 Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n";
+"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@turbolinux.com>\n";
 /*
  *  Sources:
  *      COPS Localtalk SDK. This provides almost all of the information
diff -u --recursive --new-file v2.3.37/linux/drivers/net/cops.h linux/drivers/net/cops.h
--- v2.3.37/linux/drivers/net/cops.h	Thu Jan  7 08:46:59 1999
+++ linux/drivers/net/cops.h	Thu Jan  6 14:46:18 2000
@@ -1,7 +1,7 @@
 /*      cops.h: LocalTalk driver for Linux.
  *
  *      Authors:
- *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *      - Jay Schulist <jschlst@turbolinux.com>
  */
 
 #ifndef __LINUX_COPSLTALK_H
diff -u --recursive --new-file v2.3.37/linux/drivers/net/cops_ffdrv.h linux/drivers/net/cops_ffdrv.h
--- v2.3.37/linux/drivers/net/cops_ffdrv.h	Wed May 20 18:54:56 1998
+++ linux/drivers/net/cops_ffdrv.h	Thu Jan  6 14:46:18 2000
@@ -21,7 +21,7 @@
 /*      cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *      - Jay Schulist <jschlst@turbolinux.com>
  */
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.3.37/linux/drivers/net/cops_ltdrv.h linux/drivers/net/cops_ltdrv.h
--- v2.3.37/linux/drivers/net/cops_ltdrv.h	Wed May 20 18:54:57 1998
+++ linux/drivers/net/cops_ltdrv.h	Thu Jan  6 14:46:18 2000
@@ -20,7 +20,7 @@
 /*      cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *      - Jay Schulist <jschlst@turbolinux.com>
  */
  
 #include <linux/config.h>
diff -u --recursive --new-file v2.3.37/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.3.37/linux/drivers/net/de4x5.c	Tue Dec  7 09:32:43 1999
+++ linux/drivers/net/de4x5.c	Thu Jan  6 16:17:19 2000
@@ -2260,18 +2260,21 @@
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j;
     struct bus_type *lp = &bus;
+    struct list_head *walk = &dev->bus_list;
 
-    for (; (dev=dev->sibling)!= NULL;) {
-	pb = dev->bus->number;
-	vendor = dev->vendor;
-	device = dev->device << 8;
+    for (walk = walk->next; walk != &dev->bus_list; walk = walk->next) {
+	struct pci_dev *this_dev = pci_dev_b(walk);
+
+	pb = this_dev->bus->number;
+	vendor = this_dev->vendor;
+	device = this_dev->device << 8;
 	if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
 
 	/* Get the chip configuration revision register */
-	pcibios_read_config_dword(pb, dev->devfn, PCI_REVISION_ID, &cfrv);
+	pcibios_read_config_dword(pb, this_dev->devfn, PCI_REVISION_ID, &cfrv);
 
 	/* Set the device number information */
-	lp->device = PCI_SLOT(dev->devfn);
+	lp->device = PCI_SLOT(this_dev->devfn);
 	lp->bus_num = pb;
 	    
 	/* Set the chipset information */
@@ -2281,14 +2284,14 @@
 	lp->chipset = device;
 
 	/* Get the board I/O address (64 bits on sparc64) */
-	iobase = dev->resource[0].start;
+	iobase = this_dev->resource[0].start;
 
 	/* Fetch the IRQ to be used */
-	irq = dev->irq;
+	irq = this_dev->irq;
 	if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
 	    
 	/* Check if I/O accesses are enabled */
-	pcibios_read_config_word(pb, dev->devfn, PCI_COMMAND, &status);
+	pcibios_read_config_word(pb, this_dev->devfn, PCI_COMMAND, &status);
 	if (!(status & PCI_COMMAND_IO)) continue;
 
 	/* Search for a valid SROM attached to this DECchip */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/ipddp.c linux/drivers/net/ipddp.c
--- v2.3.37/linux/drivers/net/ipddp.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ipddp.c	Thu Jan  6 14:46:18 2000
@@ -4,7 +4,7 @@
  *
  *	Authors:
  *      - DDP-IP Encap by: Bradford W. Johnson <johns393@maroon.tc.umn.edu>
- *	- DDP-IP Decap by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *	- DDP-IP Decap by: Jay Schulist <jschlst@turbolinux.com>
  *
  *	Derived from:
  *	- Almost all code already existed in net/appletalk/ddp.c I just
@@ -14,7 +14,7 @@
  *        Written 1993-94 by Donald Becker.
  *	- dummy.c: A dummy net driver. By Nick Holloway.
  *	- MacGate: A user space Daemon for Appletalk-IP Decap for
- *	  Linux by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *	  Linux by Jay Schulist <jschlst@turbolinux.com>
  *
  *      Copyright 1993 United States Government as represented by the
  *      Director, National Security Agency.
@@ -113,7 +113,7 @@
 		printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", 
 			dev->name);
 	if(ipddp_mode == IPDDP_DECAP)
-		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n", 
+		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@turbolinux.com>\n", 
 			dev->name);
 
 	/* Fill in the device structure with ethernet-generic values. */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.3.37/linux/drivers/net/irda/Config.in	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/Config.in	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
 dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
 
 comment 'FIR device drivers'
-dep_tristate 'NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate 'NSC PC87108/PC97338' CONFIG_NSC_FIR  $CONFIG_IRDA
 dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
 dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
 dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.3.37/linux/drivers/net/irda/Makefile	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/Makefile	Thu Jan  6 14:46:18 2000
@@ -29,10 +29,10 @@
 endif
 
 ifeq ($(CONFIG_NSC_FIR),y)
-L_OBJS += pc87108.o
+L_OBJS += nsc_fir.o
 else
   ifeq ($(CONFIG_NSC_FIR),m)
-  M_OBJS += pc87108.o
+  M_OBJS += nsc_fir.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.3.37/linux/drivers/net/irda/actisys.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/actisys.c	Thu Jan  6 14:46:18 2000
@@ -8,7 +8,7 @@
  * Authors:       Dag Brattli <dagb@cs.uit.no> (initially)
  *		  Jean Tourrilhes <jt@hpl.hp.com> (new version)
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Fri Dec 17 09:16:09 1999
+ * Modified at:   Fri Dec 17 09:10:43 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.3.37/linux/drivers/net/irda/esi.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/esi.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Fri Dec 17 09:17:05 1999
+ * Modified at:   Fri Dec 17 09:14:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.3.37/linux/drivers/net/irda/girbil.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/girbil.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb  6 21:02:33 1999
- * Modified at:   Fri Dec 17 09:16:52 1999
+ * Modified at:   Fri Dec 17 09:13:20 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.37/linux/drivers/net/irda/irport.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/irda/irport.c	Thu Jan  6 14:46:18 2000
@@ -6,11 +6,11 @@
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Tue Dec 21 21:51:23 1999
+ * Modified at:   Wed Jan  5 13:59:38 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
- *     Copyright (c) 1997, 1998, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -153,16 +153,16 @@
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct irport_cb));
-   
 	spin_lock_init(&self->lock);
 
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 	self->priv = self;
+	self->index = i;
 
 	/* Initialize IO */
-	self->io.iobase   = iobase;
-        self->io.irq      = irq;
+	self->io.iobase    = iobase;
+        self->io.irq       = irq;
         self->io.io_ext    = IO_EXTENT;
         self->io.fifo_size = 16;
 
@@ -218,6 +218,7 @@
 		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
 		return NULL;
 	}
+
 	self->netdev = dev;
 
 	/* May be overridden by piggyback drivers */
@@ -275,7 +276,9 @@
 	
 	if (self->rx_buff.head)
 		kfree(self->rx_buff.head);
-	
+
+	/* Remove ourselves */
+	dev_self[self->index] = NULL;
 	kfree(self);
 
 	return 0;
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.37/linux/drivers/net/irda/irtty.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/irda/irtty.c	Thu Jan  6 14:46:18 2000
@@ -6,12 +6,12 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Tue Dec 21 21:50:59 1999
+ * Modified at:   Wed Jan  5 14:00:13 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.37/linux/drivers/net/irda/litelink.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/litelink.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri May  7 12:50:33 1999
- * Modified at:   Fri Dec 17 09:16:23 1999
+ * Modified at:   Fri Dec 17 09:14:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/nsc_fir.c linux/drivers/net/irda/nsc_fir.c
--- v2.3.37/linux/drivers/net/irda/nsc_fir.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/nsc_fir.c	Fri Jan  7 11:51:56 2000
@@ -0,0 +1,1825 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc_fir.c
+ * Version:       1.0
+ * Description:   Driver for the NSC PC'108 and PC'338 IrDA chipsets
+ * Status:        Stable.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Nov  7 21:43:15 1998
+ * Modified at:   Wed Jan  5 13:59:21 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsų admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Notice that all functions that needs to access the chip in _any_
+ *     way, must save BSR register on entry, and restore it on exit. 
+ *     It is _very_ important to follow this policy!
+ *
+ *         __u8 bank;
+ *     
+ *         bank = inb(iobase+BSR);
+ *  
+ *         do_your_stuff_here();
+ *
+ *         outb(bank, iobase+BSR);
+ *
+ *    If you find bugs in this file, its very likely that the same bug
+ *    will also be in w83977af_ir.c since the implementations are quite
+ *    similar.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/nsc_fir.h>
+
+#define CHIP_IO_EXTENT 8
+#define BROKEN_DONGLE_ID
+
+/* 
+ * Define if you have multiple NSC IrDA controllers in your machine. Not
+ * enabled by default since some single chips detects at multiple addresses
+ */
+#undef  CONFIG_NSC_FIR_MULTIPLE 
+
+static char *driver_name = "nsc_fir";
+
+/* Module parameters */
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
+static int dongle_id = 0;
+
+static unsigned int io[]  = { 0x2f8, 0x2f8, 0x2f8, 0x2f8, 0x2f8 };
+static unsigned int io2[] = { 0x150, 0x398, 0xea, 0x15c, 0x2e };
+static unsigned int irq[] = { 3, 3, 3, 3, 3 };
+static unsigned int dma[] = { 0, 0, 0, 0, 3 };
+
+static struct nsc_fir_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
+
+static char *dongle_types[] = {
+	"Differential serial interface",
+	"Differential serial interface",
+	"Reserved",
+	"Reserved",
+	"Sharp RY5HD01",
+	"Reserved",
+	"Single-ended serial interface",
+	"Consumer-IR only",
+	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+	"IBM31T1100 or Temic TFDS6000/TFDS6500",
+	"Reserved",
+	"Reserved",
+	"HP HSDL-1100/HSDL-2100",
+	"HP HSDL-1100/HSDL-2100"
+	"Supports SIR Mode only",
+	"No dongle connected",
+};
+
+/* Some prototypes */
+static int  nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr, 
+			 unsigned int irq, unsigned int dma);
+#ifdef MODULE
+static int  nsc_fir_close(struct nsc_fir_cb *self);
+#endif /* MODULE */
+static int  nsc_fir_probe(int iobase, int board_addr, int irq, int dma);
+static void nsc_fir_pio_receive(struct nsc_fir_cb *self);
+static int  nsc_fir_dma_receive(struct nsc_fir_cb *self); 
+static int  nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase);
+static int  nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
+static int  nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
+static int  nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase);
+static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 baud);
+static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int  nsc_fir_is_receiving(struct nsc_fir_cb *self);
+static int  nsc_fir_read_dongle_id (int iobase);
+static void nsc_fir_init_dongle_interface (int iobase, int dongle_id);
+
+static int  nsc_fir_net_init(struct net_device *dev);
+static int  nsc_fir_net_open(struct net_device *dev);
+static int  nsc_fir_net_close(struct net_device *dev);
+static int  nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev);
+#ifdef CONFIG_APM
+static int nsc_fir_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+/*
+ * Function nsc_fir_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+int __init nsc_fir_init(void)
+{
+	int ret = -ENODEV;
+	int ioaddr;
+	int i;
+
+#ifdef CONFIG_APM
+	apm_register_callback(nsc_fir_apmproc);
+#endif /* CONFIG_APM */
+
+	for (i=0; (io[i] < 2000) && (i < 5); i++) {
+		ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
+			continue;
+		if (nsc_fir_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
+		{
+#ifdef CONFIG_NSC_FIR_MULTIPLE
+			ret = 0;
+#else
+		        return 0;
+#endif
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Function nsc_fir_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void nsc_fir_cleanup(void)
+{
+	int i;
+
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_APM
+	apm_unregister_callback(nsc_fir_apmproc);
+#endif /* CONFIG_APM */
+
+
+	for (i=0; i < 5; i++) {
+		if (dev_self[i])
+			nsc_fir_close(dev_self[i]);
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_fir_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int 
+nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr, 
+	     unsigned int irq, unsigned int dma)
+{
+	struct net_device *dev;
+	struct nsc_fir_cb *self;
+	int dongle_id;
+	int ret;
+	int err;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	if ((dongle_id = nsc_fir_probe(iobase, board_addr, irq, dma)) == -1)
+		return -1;
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc(sizeof(struct nsc_fir_cb), GFP_KERNEL);
+	if (self == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate memory for "
+		       "control block!\n");
+		return -ENOMEM;
+	}
+	memset(self, 0, sizeof(struct nsc_fir_cb));
+	spin_lock_init(&self->lock);
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+
+	/* Initialize IO */
+	self->io.iobase    = iobase;
+        self->io.irq       = irq;
+        self->io.io_ext    = CHIP_IO_EXTENT;
+        self->io.dma       = dma;
+        self->io.fifo_size = 32;
+
+	/* Lock the port that we need */
+	ret = check_region(self->io.iobase, self->io.io_ext);
+	if (ret < 0) { 
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.iobase);
+		/* nsc_fir_cleanup(self->self);  */
+		return -ENODEV;
+	}
+	request_region(self->io.iobase, self->io.io_ext, driver_name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&self->qos);
+	
+	/* The only value we must override it the baudrate */
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8);
+	
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
+	
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 14384;
+
+	/* Allocate memory if needed */
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
+	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Tx queue info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
+
+	/* Override the network functions we need to use */
+	dev->init            = nsc_fir_net_init;
+	dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
+	dev->open            = nsc_fir_net_open;
+	dev->stop            = nsc_fir_net_close;
+	dev->do_ioctl        = nsc_fir_net_ioctl;
+	dev->get_stats	     = nsc_fir_net_get_stats;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
+
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+	
+	self->io.dongle_id = dongle_id;
+	nsc_fir_init_dongle_interface(iobase, dongle_id);
+
+	return 0;
+}
+
+#ifdef MODULE
+/*
+ * Function nsc_fir_close (self)
+ *
+ *    Close driver instance
+ *
+ */
+static int nsc_fir_close(struct nsc_fir_cb *self)
+{
+	int iobase;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+        iobase = self->io.iobase;
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+	}
+
+	/* Release the PORT that this driver is using */
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		   self->io.iobase);
+	release_region(self->io.iobase, self->io.io_ext);
+
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+
+	kfree(self);
+
+	return 0;
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_fir_init_807 (iobase, board_addr, irq, dma)
+ *
+ *    Initialize the NSC '108 chip
+ *
+ */
+static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
+{
+	__u8 temp=0;
+
+	outb(2, board_addr);      /* Mode Control Register (MCTL) */
+	outb(0x00, board_addr+1); /* Disable device */
+	
+	/* Base Address and Interrupt Control Register (BAIC) */
+	outb(0, board_addr);
+	switch (iobase) {
+	case 0x3e8: outb(0x14, board_addr+1); break;
+	case 0x2e8: outb(0x15, board_addr+1); break;
+		case 0x3f8: outb(0x16, board_addr+1); break;
+	case 0x2f8: outb(0x17, board_addr+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid base_address");
+	}
+	
+	/* Control Signal Routing Register (CSRT) */
+	switch (irq) {
+	case 3:  temp = 0x01; break;
+	case 4:  temp = 0x02; break;
+	case 5:  temp = 0x03; break;
+	case 7:  temp = 0x04; break;
+	case 9:  temp = 0x05; break;
+	case 11: temp = 0x06; break;
+	case 15: temp = 0x07; break;
+	default: ERROR(__FUNCTION__ "(), invalid irq");
+	}
+	outb(1, board_addr);
+	
+	switch (dma) {	
+	case 0: outb(0x08+temp, board_addr+1); break;
+	case 1: outb(0x10+temp, board_addr+1); break;
+	case 3: outb(0x18+temp, board_addr+1); break;
+	default: ERROR(__FUNCTION__ "(), invalid dma");
+	}
+	
+	outb(2, board_addr);      /* Mode Control Register (MCTL) */
+	outb(0x03, board_addr+1); /* Enable device */
+}
+
+/*
+ * Function nsc_fir_init_338 (iobase, board_addr, irq, dma)
+ *
+ *    Initialize the NSC '338 chip. Remember that the 87338 needs two 
+ *    consecutive writes to the data registers while CPU interrupts are
+ *    disabled. The 97338 does not require this, but shouldn't be any
+ *    harm if we do it anyway.
+ */
+static void nsc_fir_init_338(int iobase, int board_addr, int irq, int dma)
+{
+	/* No init yet */
+}
+
+static int nsc_fir_find_chip(int board_addr)
+{
+	__u8 index, id;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Read index register */
+	index = inb(board_addr);
+	if (index == 0xff) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no chip at 0x%03x\n", 
+			   board_addr);
+		return -1;
+	}
+
+	/* Read chip identification register (SID) for the PC97338 */
+	outb(8, board_addr);
+	id = inb(board_addr+1);
+	if ((id & 0xf0) == PC97338) {
+		MESSAGE("%s, Found NSC PC97338 chip, revision=%d\n", 
+			driver_name, id & 0x0f);
+		return PC97338;		
+	} 
+
+	/* Read device identification (DID) for the PC87108 */
+	outb(5, board_addr);
+	id = inb(board_addr+1);
+	if ((id & 0xf0) == PC87108) {
+		MESSAGE("%s, Found NSC PC87108 chip, revision=%d\n", 
+			driver_name, id & 0x0f);
+		return PC87108;
+	}
+
+	return -1;
+}
+
+/*
+ * Function nsc_fir_probe (iobase, board_addr, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
+{
+	int version;
+	__u8 chip;
+
+	chip = nsc_fir_find_chip(board_addr);
+	switch (chip) {
+	case PC87108:
+		nsc_fir_init_807(iobase, board_addr, irq, dma);
+		break;
+	case PC97338:
+		nsc_fir_init_338(iobase, board_addr, irq, dma);
+		break;
+	default:
+		/* Found no chip */
+		return -1;
+	}
+
+	/* Read the Module ID */
+	switch_bank(iobase, BANK3);
+	version = inb(iobase+MID);
+
+	/* Should be 0x2? */
+	if (0x20 != (version & 0xf0)) {
+		ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+		return -1;
+	}
+	MESSAGE("%s, Found chip at base=0x%04x\n", driver_name, board_addr);
+
+	/* Switch to advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_EXT_SL, iobase+ECR1);
+	switch_bank(iobase, BANK0);
+
+	/* Check if user has supplied the dongle id or not */
+	if (!dongle_id) {
+		dongle_id = nsc_fir_read_dongle_id(iobase);
+		
+		MESSAGE("%s, Found dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	} else {
+		MESSAGE("%s, Using dongle: %s\n", driver_name,
+			dongle_types[dongle_id]);
+	}
+	
+	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
+	switch_bank(iobase, BANK0);	
+	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+	/* IRCR2: FEND_MD is set */
+	switch_bank(iobase, BANK5);
+ 	outb(0x2a, iobase+4);
+
+	/* Make sure that some defaults are OK */
+	switch_bank(iobase, BANK6);
+	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+	outb(0x0a, iobase+1); /* Set MIR pulse width */
+	outb(0x0d, iobase+2); /* Set SIR pulse width */
+	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+	MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
+	/* Enable receive interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_RXHDL_IE, iobase+IER);
+
+	return dongle_id;
+}
+
+/*
+ * Function nsc_fir_read_dongle_id (void)
+ *
+ * Try to read dongle indentification. This procedure needs to be executed
+ * once after power-on/reset. It also needs to be used whenever you suspect
+ * that the user may have plugged/unplugged the IrDA Dongle.
+ * 
+ */
+static int nsc_fir_read_dongle_id (int iobase)
+{
+	int dongle_id;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+	outb(0x00, iobase+7);
+	
+	/* ID0, 1, and 2 are pulled up/down very slowly */
+	udelay(50);
+	
+	/* IRCFG1: read the ID bits */
+	dongle_id = inb(iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+	if (dongle_id == 0x0a)
+		dongle_id = 0x09;
+#endif
+	
+	/* Go back to  bank 0 before returning */
+	switch_bank(iobase, BANK0);
+
+	outb(bank, iobase+BSR);
+
+	return dongle_id;
+}
+
+/*
+ * Function nsc_fir_init_dongle_interface (iobase, dongle_id)
+ *
+ *     This function initializes the dongle for the transceiver that is
+ *     used. This procedure needs to be executed once after
+ *     power-on/reset. It also needs to be used whenever you suspect that
+ *     the dongle is changed. 
+ */
+static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
+{
+	int bank;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG4: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x05: /* Reserved, but this is what the Thinkpad reports */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		/* 
+		 * Set irsl0 as input, irsl[1-2] as output, and separate 
+		 * inputs are used for SIR and MIR/FIR 
+		 */
+		outb(0x48, iobase+7); 
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+			   dongle_types[dongle_id]); 
+
+		switch_bank(iobase, BANK0);
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", 
+			   dongle_id);
+	}
+	
+	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+	outb(0x00, iobase+4);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+	
+} /* set_up_dongle_interface */
+
+/*
+ * Function nsc_fir_change_dongle_speed (iobase, speed, dongle_id)
+ *
+ *    Change speed of the attach dongle
+ *
+ */
+static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
+{
+	unsigned long flags;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank(iobase, BANK7);
+	
+	/* IRCFG1: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+	case 0x05: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+			   dongle_types[dongle_id]); 
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		switch_bank(iobase, BANK7);
+		outb_p(0x01, iobase+4);
+
+		if (speed == 4000000) {
+			save_flags(flags);
+			cli();
+			outb(0x81, iobase+4);
+			outb(0x80, iobase+4);
+			restore_flags(flags);
+		} else
+			outb_p(0x00, iobase+4);
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+			   dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		break;
+	case 0x0F: /* No dongle connected */
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+			   dongle_types[dongle_id]);
+
+		switch_bank(iobase, BANK0); 
+		outb(0x62, iobase+MCR);
+		break;
+	default: 
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_change_speed (self, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
+{
+	struct net_device *dev = self->netdev;
+	__u8 mcr = MCR_SIR;
+	int iobase; 
+	__u8 bank;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
+
+	ASSERT(self != NULL, return;);
+
+	iobase = self->io.iobase;
+
+	/* Update accounting for new speed */
+	self->io.speed = speed;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER);
+
+	/* Select Bank 2 */
+	switch_bank(iobase, BANK2);
+
+	outb(0x00, iobase+BGDH);
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+BGDL); break;
+	case 19200:  outb(0x06, iobase+BGDL); break;
+	case 38400:  outb(0x03, iobase+BGDL); break;
+	case 57600:  outb(0x02, iobase+BGDL); break;
+	case 115200: outb(0x01, iobase+BGDL); break;
+	case 576000:
+		switch_bank(iobase, BANK5);
+		
+		/* IRCR2: MDRS is set */
+		outb(inb(iobase+4) | 0x04, iobase+4);
+	       
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+		mcr = MCR_MIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		mcr = MCR_FIR;
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
+		break;
+	}
+
+	/* Set appropriate speed mode */
+	switch_bank(iobase, BANK0);
+	outb(mcr | MCR_TX_DFR, iobase+MCR);
+
+	/* Give some hits to the transceiver */
+	nsc_fir_change_dongle_speed(iobase, speed, self->io.dongle_id);
+
+	/* Set FIFO threshold to TX17, RX16 */
+	switch_bank(iobase, BANK0);
+	outb(0x00, iobase+FCR);
+	outb(FCR_FIFO_EN, iobase+FCR);
+	outb(FCR_RXTH|     /* Set Rx FIFO threshold */
+	     FCR_TXTH|     /* Set Tx FIFO threshold */
+	     FCR_TXSR|     /* Reset Tx FIFO */
+	     FCR_RXSR|     /* Reset Rx FIFO */
+	     FCR_FIFO_EN,  /* Enable FIFOs */
+	     iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+	
+	self->netdev->tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	switch_bank(iobase, BANK0); 
+	if (speed > 115200) {
+		/* Install FIR xmit handler */
+		dev->hard_start_xmit = nsc_fir_hard_xmit_fir;
+		outb(IER_SFIF_IE, iobase+IER);
+		nsc_fir_dma_receive(self);
+	} else {
+		/* Install SIR xmit handler */
+		dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
+		outb(IER_RXHDL_IE, iobase+IER);
+	}
+    	
+	/* Restore BSR */
+	outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_hard_xmit (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+{
+	struct nsc_fir_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	
+	self = (struct nsc_fir_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.iobase;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+	
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+	
+	spin_lock_irqsave(&self->lock, flags);
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	self->tx_buff.data = self->tx_buff.head;
+	
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
+	
+	/* Add interrupt on tx low level (will fire immediately) */
+	switch_bank(iobase, BANK0);
+	outb(IER_TXLDL_IE, iobase+IER);
+	
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
+{
+	struct nsc_fir_cb *self;
+	unsigned long flags;
+	int iobase;
+	__u32 speed;
+	__u8 bank;
+	int mtt, diff;
+	
+	self = (struct nsc_fir_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.iobase;
+
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		self->new_speed = speed;
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Register and copy this frame to DMA memory */
+	self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
+	self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
+	self->tx_fifo.tail += skb->len;
+
+	memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data, 
+	       skb->len);
+	
+	self->tx_fifo.len++;
+	self->tx_fifo.free++;
+
+	/* Start transmit only if there is currently no transmit going on */
+	if (self->tx_fifo.len == 1) {
+		mtt = irda_get_mtt(skb);
+		if (mtt) {
+			/* Check how much time we have used already */
+			do_gettimeofday(&self->now);
+			diff = self->now.tv_usec - self->stamp.tv_usec;
+			if (diff < 0) 
+				diff += 1000000;
+			
+			/* Check if the mtt is larger than the time we have
+			 * already used by all the protocol processing
+			 */
+			if (mtt > diff) {
+				mtt -= diff;
+				if (mtt > 125) {
+					/* Adjust for timer resolution */
+					mtt = mtt / 125 + 1;
+					
+					/* Setup timer */
+					switch_bank(iobase, BANK4);
+					outb(mtt & 0xff, iobase+TMRL);
+					outb((mtt >> 8) & 0x0f, iobase+TMRH);
+					
+					/* Start timer */
+					outb(IRCR1_TMR_EN, iobase+IRCR1);
+					self->io.direction = IO_XMIT;
+					
+					/* Enable timer interrupt */
+					switch_bank(iobase, BANK0);
+					outb(IER_TMR_IE, iobase+IER);
+					
+					/* Timer will take care of the rest */
+					goto out; 
+				} else
+					udelay(mtt);
+			}
+		}
+		
+		/* Enable DMA interrupt */
+		switch_bank(iobase, BANK0);
+		outb(IER_DMA_IE, iobase+IER);
+		nsc_fir_dma_xmit(self, iobase);
+	}
+	/* Not busy transmitting anymore if window is not full */
+	if (self->tx_fifo.len < MAX_WINDOW)
+		dev->tbusy = 0;
+ out:
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function nsc_fir_dma_xmit (self, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
+{
+	int bsr;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	self->io.direction = IO_XMIT;
+	
+	/* Choose transmit DMA channel  */ 
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+	
+	setup_dma(self->io.dma, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].start, 
+		  self->tx_fifo.queue[self->tx_fifo.ptr].len, 
+		  DMA_TX_MODE);
+
+	/* Enable DMA and SIR interaction pulse */
+ 	switch_bank(iobase, BANK0);	
+	outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_pio_xmit (self, iobase)
+ *
+ *    Transmit data using PIO. Returns the number of bytes that actually
+ *    got transfered
+ *
+ */
+static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
+{
+	int actual = 0;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	switch_bank(iobase, BANK0);
+	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
+
+		fifo_size -= 17;
+	}
+
+	/* Fill FIFO with current frame */
+	while ((fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual++], iobase+TXD);
+	}
+        
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+		   fifo_size, actual, len);
+	
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+
+	return actual;
+}
+
+/*
+ * Function nsc_fir_dma_xmit_complete (self)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
+{
+	int iobase;
+	__u8 bank;
+	int ret = TRUE;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	iobase = self->io.iobase;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+        outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	/* Check for underrrun! */
+	if (inb(iobase+ASCR) & ASCR_TXUR) {
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
+		
+		/* Clear bit, by writing 1 into it */
+		outb(ASCR_TXUR, iobase+ASCR);
+	} else {
+		self->stats.tx_packets++;
+		self->stats.tx_bytes += self->tx_buff.len;
+	}
+	
+	if (self->new_speed) {
+		nsc_fir_change_speed(self, self->new_speed);
+		self->new_speed = 0;
+	}
+
+	/* Finished with this frame, so prepare for next */
+	self->tx_fifo.ptr++;
+	self->tx_fifo.len--;
+
+	/* Any frames to be sent back-to-back? */
+	if (self->tx_fifo.len) {
+		nsc_fir_dma_xmit(self, iobase);
+		
+		/* Not finished yet! */
+		ret = FALSE;
+	}
+
+	/* Not busy transmitting anymore */
+	self->netdev->tbusy = 0;
+
+	/* Tell the network layer, that we can accept more frames */
+	mark_bh(NET_BH);
+
+	/* Restore bank */
+	outb(bank, iobase+BSR);
+	
+	return ret;
+}
+
+/*
+ * Function nsc_fir_dma_receive (self)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int nsc_fir_dma_receive(struct nsc_fir_cb *self) 
+{
+	int iobase;
+	__u8 bsr;
+
+	ASSERT(self != NULL, return -1;);
+
+	iobase = self->io.iobase;
+
+	/* Reset Tx FIFO info */
+	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+	self->tx_fifo.tail = self->tx_buff.head;
+
+	/* Save current bank */
+	bsr = inb(iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	/* Reset Rx FIFO. This will also flush the ST_FIFO */
+	switch_bank(iobase, BANK0);
+	outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+	
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+		  DMA_RX_MODE);
+
+	/* Enable DMA */
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+	/* Restore bank register */
+	outb(bsr, iobase+BSR);
+	
+	return 0;
+}
+
+/*
+ * Function nsc_fir_dma_receive_complete (self)
+ *
+ *    Finished with receiving frames
+ *
+ *    
+ */
+static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
+{
+	struct sk_buff *skb;
+	struct st_fifo *st_fifo;
+	__u8 bank;
+	__u8 status;
+	int len;
+
+	st_fifo = &self->st_fifo;
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* Read status FIFO */
+	switch_bank(iobase, BANK5);
+	while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+		st_fifo->entries[st_fifo->tail].status = status;
+
+		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		
+		st_fifo->tail++;
+		st_fifo->len++;
+	}
+	/* Try to process all entries in status FIFO */
+	while (st_fifo->len) {
+		/* Get first entry */
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
+		st_fifo->head++;
+		st_fifo->len--;
+
+		/* Check for errors */
+		if (status & FRM_ST_ERR_MSK) {
+			if (status & FRM_ST_LOST_FR) {
+				/* Add number of lost frames to stats */
+				self->stats.rx_errors += len;	
+			} else {
+				/* Skip frame */
+				self->stats.rx_errors++;
+				
+				self->rx_buff.data += len;
+			
+				if (status & FRM_ST_MAX_LEN)
+					self->stats.rx_length_errors++;
+				
+				if (status & FRM_ST_PHY_ERR) 
+					self->stats.rx_frame_errors++;
+				
+				if (status & FRM_ST_BAD_CRC) 
+					self->stats.rx_crc_errors++;
+			}
+			/* The errors below can be reported in both cases */
+			if (status & FRM_ST_OVR1)
+				self->stats.rx_fifo_errors++;		       
+			
+			if (status & FRM_ST_OVR2)
+				self->stats.rx_fifo_errors++;
+		} else {
+			/* Check if we have transfered all data to memory */
+			switch_bank(iobase, BANK0);
+			if (inb(iobase+LSR) & LSR_RXDA) {
+				/* Put this entry back in fifo */
+				st_fifo->head--;
+				st_fifo->len++;
+				st_fifo->entries[st_fifo->head].status = status;
+				st_fifo->entries[st_fifo->head].len = len;
+				
+				/* Restore bank register */
+				outb(bank, iobase+BSR);
+				
+				return FALSE; 	/* I'll be back! */
+			}
+
+			/* 
+			 * Remember when we received this frame, so we can
+			 * reduce the min turn time a bit since we will know
+			 * how much time we have used for protocol processing
+			 */
+			do_gettimeofday(&self->stamp);
+
+			skb = dev_alloc_skb(len+1);
+			if (skb == NULL)  {
+				WARNING(__FUNCTION__ "(), memory squeeze, "
+					"dropping frame.\n");
+				
+				/* Restore bank register */
+				outb(bank, iobase+BSR);
+				
+				return FALSE;
+			}
+			
+			/* Make sure IP header gets aligned */
+			skb_reserve(skb, 1); 
+
+			/* Copy frame without CRC */
+			if (self->io.speed < 4000000) {
+				skb_put(skb, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
+			} else {
+				skb_put(skb, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
+			}
+
+			/* Move to next frame */
+			self->rx_buff.data += len;
+			self->stats.rx_packets++;
+
+			skb->dev = self->netdev;
+			skb->mac.raw  = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx(skb);
+		}
+	}
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	return TRUE;
+}
+
+/*
+ * Function nsc_fir_pio_receive (self)
+ *
+ *    Receive all data in receiver FIFO
+ *
+ */
+static void nsc_fir_pio_receive(struct nsc_fir_cb *self) 
+{
+	__u8 byte = 0x00;
+	int iobase;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	
+	iobase = self->io.iobase;
+	
+	/*  Receive all characters in Rx FIFO */
+	do {
+		byte = inb(iobase+RXD);
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  byte);
+	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
+}
+
+/*
+ * Function nsc_fir_sir_interrupt (self, eir)
+ *
+ *    Handle SIR interrupt
+ *
+ */
+static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
+{
+	int actual;
+	__u8 new_ier = 0;
+
+	/* Check if transmit FIFO is low on data */
+	if (eir & EIR_TXLDL_EV) {
+		/* Write data left in transmit buffer */
+		actual = nsc_fir_pio_write(self->io.iobase, 
+					   self->tx_buff.data, 
+					   self->tx_buff.len, 
+					   self->io.fifo_size);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
+		
+		self->io.direction = IO_XMIT;
+
+		/* Check if finished */
+		if (self->tx_buff.len > 0)
+			new_ier |= IER_TXLDL_IE;
+		else { 
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
+			
+		        mark_bh(NET_BH);	
+
+			new_ier |= IER_TXEMP_IE;
+		}
+			
+	}
+	/* Check if transmission has completed */
+	if (eir & EIR_TXEMP_EV) {
+		/* Check if we need to change the speed? */
+		if (self->new_speed) {
+			IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
+			nsc_fir_change_speed(self, self->new_speed);
+			self->new_speed = 0;
+		}
+
+		/* Turn around and get ready to receive some data */
+		self->io.direction = IO_RECV;
+		new_ier |= IER_RXHDL_IE;
+	}
+
+	/* Rx FIFO threshold or timeout */
+	if (eir & EIR_RXHDL_EV) {
+		nsc_fir_pio_receive(self);
+
+		/* Keep receiving */
+		new_ier |= IER_RXHDL_IE;
+	}
+	return new_ier;
+}
+
+/*
+ * Function nsc_fir_fir_interrupt (self, eir)
+ *
+ *    Handle MIR/FIR interrupt
+ *
+ */
+static __u8 nsc_fir_fir_interrupt(struct nsc_fir_cb *self, int iobase, int eir)
+{
+	__u8 new_ier = 0;
+	__u8 bank;
+
+	bank = inb(iobase+BSR);
+	
+	/* Status event, or end of frame detected in FIFO */
+	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+		if (nsc_fir_dma_receive_complete(self, iobase)) {
+
+			/* Wait for next status FIFO interrupt */
+			new_ier |= IER_SFIF_IE;
+		} else {
+			/* DMA not finished yet */
+
+			/* Set timer value, resolution 125 us */
+			switch_bank(iobase, BANK4);
+			outb(0x0f, iobase+TMRL); /* 125 us * 15 */
+			outb(0x00, iobase+TMRH);
+
+			/* Start timer */
+			outb(IRCR1_TMR_EN, iobase+IRCR1);
+
+			new_ier |= IER_TMR_IE;
+		}
+	} else if (eir & EIR_TMR_EV) { /* Timer finished */
+		/* Disable timer */
+		switch_bank(iobase, BANK4);
+		outb(0, iobase+IRCR1);
+
+		/* Clear timer event */
+		switch_bank(iobase, BANK0);
+		outb(ASCR_CTE, iobase+ASCR);
+
+		/* Check if this is a TX timer interrupt */
+		if (self->io.direction == IO_XMIT) {
+			nsc_fir_dma_xmit(self, iobase);
+
+			/*  Interrupt on DMA */
+			new_ier |= IER_DMA_IE;
+		} else {
+			/* Check if DMA has now finished */
+			nsc_fir_dma_receive_complete(self, iobase);
+
+			new_ier |= IER_SFIF_IE;
+		}
+	} else if (eir & EIR_DMA_EV) { /* Finished with transmission */
+		if (nsc_fir_dma_xmit_complete(self)) {		
+			/* Check if there are more frames to be transmitted */
+			if (irda_device_txqueue_empty(self->netdev)) {
+				/* Prepare for receive */
+				nsc_fir_dma_receive(self);
+			
+				new_ier = IER_LS_IE|IER_SFIF_IE;
+			}
+		} else {
+			/*  Not finished yet, so interrupt on DMA again */
+			new_ier |= IER_DMA_IE;
+		}
+	}
+	outb(bank, iobase+BSR);
+
+	return new_ier;
+}
+
+/*
+ * Function nsc_fir_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct nsc_fir_cb *self;
+	__u8 bsr, eir, ier;
+	int iobase;
+
+	if (!dev) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
+		       driver_name, irq);
+		return;
+	}
+	self = (struct nsc_fir_cb *) dev->priv;
+
+	spin_lock(&self->lock);	
+	dev->interrupt = 1;
+
+	iobase = self->io.iobase;
+
+	bsr = inb(iobase+BSR); 	/* Save current bank */
+
+	switch_bank(iobase, BANK0);	
+	ier = inb(iobase+IER); 
+	eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */ 
+
+	outb(0, iobase+IER); /* Disable interrupts */
+	
+	if (eir) {
+		/* Dispatch interrupt handler for the current speed */
+		if (self->io.speed > 115200)
+			ier = nsc_fir_fir_interrupt(self, iobase, eir);
+		else
+			ier = nsc_fir_sir_interrupt(self, eir);
+	}
+
+	outb(ier, iobase+IER);   /* Restore interrupts */
+	outb(bsr, iobase+BSR);   /* Restore bank register */
+
+	dev->interrupt = 0;
+	spin_unlock(&self->lock);
+}
+
+/*
+ * Function nsc_fir_is_receiving (self)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
+{
+	int status = FALSE;
+	int iobase;
+	__u8 bank;
+
+	ASSERT(self != NULL, return FALSE;);
+
+	if (self->io.speed > 115200) {
+		iobase = self->io.iobase;
+
+		/* Check if rx FIFO is not empty */
+		bank = inb(iobase+BSR);
+		switch_bank(iobase, BANK2);
+		if ((inb(iobase+RXFLV) & 0x3f) != 0) {
+			/* We are receiving something */
+			status =  TRUE;
+		}
+		outb(bank, iobase+BSR);
+	} else 
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+
+/*
+ * Function nsc_fir_net_init (dev)
+ *
+ *    Initialize network device
+ *
+ */
+static int nsc_fir_net_init(struct net_device *dev)
+{
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Setup to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function nsc_fir_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int nsc_fir_net_open(struct net_device *dev)
+{
+	struct nsc_fir_cb *self;
+	int iobase;
+	__u8 bank;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct nsc_fir_cb *) dev->priv;
+	
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.iobase;
+
+	if (request_irq(self->io.irq, nsc_fir_interrupt, 0, dev->name, 
+			(void *) dev)) 
+	{
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ, and clean up on 
+	 * failure.
+	 */
+	if (request_dma(self->io.dma, dev->name)) {
+		free_irq(self->io.irq, self);
+		return -EAGAIN;
+	}
+	
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+	
+	/* turn on interrupts */
+	switch_bank(iobase, BANK0);
+	outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_fir_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int nsc_fir_net_close(struct net_device *dev)
+{
+	struct nsc_fir_cb *self;
+	int iobase;
+	__u8 bank;
+
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct nsc_fir_cb *) dev->priv;
+	
+	ASSERT(self != NULL, return 0;);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+	
+	iobase = self->io.iobase;
+
+	disable_dma(self->io.dma);
+
+	/* Save current bank */
+	bank = inb(iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER); 
+       
+	free_irq(self->io.irq, dev);
+	free_dma(self->io.dma);
+
+	/* Restore bank register */
+	outb(bank, iobase+BSR);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function nsc_fir_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct nsc_fir_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		nsc_fir_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = nsc_fir_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev)
+{
+	struct nsc_fir_cb *self = (struct nsc_fir_cb *) dev->priv;
+	
+	return &self->stats;
+}
+
+#ifdef CONFIG_APM
+static void nsc_fir_suspend(struct nsc_fir_cb *self)
+{
+	int i = 10;
+
+	MESSAGE("%s, Suspending\n", driver_name);
+
+	if (self->suspend)
+		return;
+
+	self->suspend = 1;
+}
+
+
+static void nsc_fir_wakeup(struct nsc_fir_cb *self)
+{
+	struct net_device *dev = self->netdev;
+	unsigned long flags;
+
+	if (!self->suspend)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	restore_flags(flags);
+	MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int nsc_fir_apmproc(apm_event_t event)
+{
+	static int down = 0;          /* Filter out double events */
+	int i;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		if (!down) {			
+			for (i = 0; i < 4; i++) {
+				if (dev_self[i])
+					nsc_fir_suspend(dev_self[i]);
+			}
+		}
+		down = 1;
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+		if (down) {
+			for (i = 0; i < 4; i++) {
+				if (dev_self[i])
+					nsc_fir_wakeup(dev_self[i]);
+			}
+		}
+		down = 0;
+		break;
+	}
+	return 0;
+}
+#endif /* CONFIG_APM */
+
+#ifdef MODULE
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("NSC FIR IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dongle_id, "i");
+
+int init_module(void)
+{
+	return nsc_fir_init();
+}
+
+void cleanup_module(void)
+{
+	nsc_fir_cleanup();
+}
+#endif /* MODULE */
+
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/old_belkin.c linux/drivers/net/irda/old_belkin.c
--- v2.3.37/linux/drivers/net/irda/old_belkin.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/old_belkin.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental...
  * Author:        Jean Tourrilhes <jt@hpl.hp.com>
  * Created at:    22/11/99
- * Modified at:   Fri Dec 17 09:17:30 1999
+ * Modified at:   Fri Dec 17 09:13:32 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.37/linux/drivers/net/irda/pc87108.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/irda/pc87108.c	Wed Dec 31 16:00:00 1969
@@ -1,1592 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      pc87108.c
- * Version:       0.8
- * Description:   FIR/MIR driver for the NS PC87108 chip
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Tue Dec 21 21:51:54 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- *     Copyright (c) 1998 Actisys Corp., www.actisys.com
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsų admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- *     Notice that all functions that needs to access the chip in _any_
- *     way, must save BSR register on entry, and restore it on exit. 
- *     It is _very_ important to follow this policy!
- *
- *         __u8 bank;
- *     
- *         bank = inb(iobase+BSR);
- *  
- *         do_your_stuff_here();
- *
- *         outb(bank, iobase+BSR);
- *
- *    If you find bugs in this file, its very likely that the same bug
- *    will also be in w83977af_ir.c since the implementations are quite
- *    similar.
- *     
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/malloc.h>
-#include <linux/init.h>
-#include <linux/rtnetlink.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irlap_frame.h>
-#include <net/irda/irda_device.h>
-
-#include <net/irda/pc87108.h>
-
-#define BROKEN_DONGLE_ID
-
-static char *driver_name = "pc87108";
-static int qos_mtt_bits = 0x07;  /* 1 ms or more */
-
-#define CHIP_IO_EXTENT 8
-
-static unsigned int io[]  = { 0x2f8, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x150, 0, 0, 0 };
-static unsigned int irq[] = { 3, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
-
-static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL};
-
-static char *dongle_types[] = {
-	"Differential serial interface",
-	"Differential serial interface",
-	"Reserved",
-	"Reserved",
-	"Sharp RY5HD01",
-	"Reserved",
-	"Single-ended serial interface",
-	"Consumer-IR only",
-	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
-	"IBM31T1100 or Temic TFDS6000/TFDS6500",
-	"Reserved",
-	"Reserved",
-	"HP HSDL-1100/HSDL-2100",
-	"HP HSDL-1100/HSDL-2100"
-	"Supports SIR Mode only",
-	"No dongle connected",
-};
-
-/* Some prototypes */
-static int  pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
-			 unsigned int irq, unsigned int dma);
-#ifdef MODULE
-static int  pc87108_close(struct pc87108 *self);
-#endif /* MODULE */
-static int  pc87108_probe(int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive(struct pc87108 *self);
-static int  pc87108_dma_receive(struct pc87108 *self); 
-static int  pc87108_dma_receive_complete(struct pc87108 *self, int iobase);
-static int  pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write(struct pc87108 *self, int iobase);
-static void pc87108_change_speed(struct pc87108 *self, __u32 baud);
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int  pc87108_is_receiving(struct pc87108 *self);
-static int  pc87108_read_dongle_id (int iobase);
-static void pc87108_init_dongle_interface (int iobase, int dongle_id);
-
-static int  pc87108_net_init(struct net_device *dev);
-static int  pc87108_net_open(struct net_device *dev);
-static int  pc87108_net_close(struct net_device *dev);
-static int  pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-
-/*
- * Function pc87108_init ()
- *
- *    Initialize chip. Just try to find out how many chips we are dealing with
- *    and where they are
- */
-int __init pc87108_init(void)
-{
-	int i;
-
-	for (i=0; (io[i] < 2000) && (i < 4); i++) {
-		int ioaddr = io[i];
-		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
-			continue;
-		if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
-			return 0;
-	}
-	return -ENODEV;
-}
-
-/*
- * Function pc87108_cleanup ()
- *
- *    Close all configured chips
- *
- */
-#ifdef MODULE
-static void pc87108_cleanup(void)
-{
-	int i;
-
-        IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	for (i=0; i < 4; i++) {
-		if (dev_self[i])
-			pc87108_close(dev_self[i]);
-	}
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_open (iobase, irq)
- *
- *    Open driver instance
- *
- */
-static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
-			unsigned int irq, unsigned int dma)
-{
-	struct net_device *dev;
-	struct pc87108 *self;
-	int dongle_id;
-	int ret;
-	int err;
-
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
-		return -1;
-
-	/*
-	 *  Allocate new instance of the driver
-	 */
-	self = kmalloc(sizeof(struct pc87108), GFP_KERNEL);
-	if (self == NULL) {
-		printk(KERN_ERR "IrDA: Can't allocate memory for "
-		       "IrDA control block!\n");
-		return -ENOMEM;
-	}
-	memset(self, 0, sizeof(struct pc87108));
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
-
-	/* Initialize IO */
-	self->io.iobase    = iobase;
-        self->io.irq       = irq;
-        self->io.io_ext    = CHIP_IO_EXTENT;
-        self->io.dma       = dma;
-        self->io.fifo_size = 32;
-
-	/* Lock the port that we need */
-	ret = check_region(self->io.iobase, self->io.io_ext);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      self->io.iobase);
-		/* pc87108_cleanup(self->self);  */
-		return -ENODEV;
-	}
-	request_region(self->io.iobase, self->io.io_ext, driver_name);
-
-	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&self->qos);
-	
-	/* The only value we must override it the baudrate */
-	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-	
-	self->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&self->qos);
-	
-	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
-
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	self->rx_buff.truesize = 14384; 
-	self->tx_buff.truesize = 4000;
-
-	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-						      GFP_KERNEL|GFP_DMA);
-		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
-	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-						      GFP_KERNEL|GFP_DMA);
-		if (self->tx_buff.head == NULL) {
-			kfree(self->rx_buff.head);
-			return -ENOMEM;
-		}
-		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
-	}
-
-	self->rx_buff.in_frame = FALSE;
-	self->rx_buff.state = OUTSIDE_FRAME;
-	self->tx_buff.data = self->tx_buff.head;
-	self->rx_buff.data = self->rx_buff.head;
-	
-	if (!(dev = dev_alloc("irda%d", &err))) {
-		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
-		return -ENOMEM;
-	}
-	dev->priv = (void *) self;
-	self->netdev = dev;
-
-	/* Override the network functions we need to use */
-	dev->init            = pc87108_net_init;
-	dev->hard_start_xmit = pc87108_hard_xmit;
-	dev->open            = pc87108_net_open;
-	dev->stop            = pc87108_net_close;
-	dev->do_ioctl        = pc87108_net_ioctl;
-
-	rtnl_lock();
-	err = register_netdevice(dev);
-	rtnl_unlock();
-	if (err) {
-		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
-		return -1;
-	}
-
-	MESSAGE("IrDA: Registered device %s\n", dev->name);
-	
-	self->io.dongle_id = dongle_id;
-	pc87108_init_dongle_interface(iobase, dongle_id);
-
-	return 0;
-}
-
-#ifdef MODULE
-/*
- * Function pc87108_close (self)
- *
- *    Close driver instance
- *
- */
-static int pc87108_close(struct pc87108 *self)
-{
-	int iobase;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return -1;);
-
-        iobase = self->io.iobase;
-
-	/* Remove netdevice */
-	if (self->netdev) {
-		rtnl_lock();
-		unregister_netdevice(self->netdev);
-		rtnl_unlock();
-	}
-
-	/* Release the PORT that this driver is using */
-	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
-		   self->io.iobase);
-	release_region(self->io.iobase, self->io.io_ext);
-
-	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
-	
-	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
-
-	kfree(self);
-
-	return 0;
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int pc87108_probe(int iobase, int board_addr, int irq, int dma) 
-{
-	int version;
-	__u8 temp=0;
-	int dongle_id;
-	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Base Address and Interrupt Control Register BAIC */
-	outb(0, board_addr);
-	switch (iobase) {
-	case 0x3E8: outb(0x14, board_addr+1); break;
-	case 0x2E8: outb(0x15, board_addr+1); break;
-	case 0x3F8: outb(0x16, board_addr+1); break;
-	case 0x2F8: outb(0x17, board_addr+1); break;
-	default:    ERROR(__FUNCTION__ "(), invalid base_address");
-	}
-	
-	/* Control Signal Routing Register CSRT */
-	switch (irq) {
-	case 3:  temp = 0x01; break;
-	case 4:  temp = 0x02; break;
-	case 5:  temp = 0x03; break;
-	case 7:  temp = 0x04; break;
-	case 9:  temp = 0x05; break;
-	case 11: temp = 0x06; break;
-	case 15: temp = 0x07; break;
-	default: ERROR(__FUNCTION__ "(), invalid irq");
-	}
-	outb(1, board_addr);
-	
-	switch (dma) {	
-	case 0: outb(0x08+temp, board_addr+1); break;
-	case 1: outb(0x10+temp, board_addr+1); break;
-	case 3: outb(0x18+temp, board_addr+1); break;
-	default: IRDA_DEBUG(0, __FUNCTION__ "(), invalid dma");
-	}
-
-	/* Mode Control Register MCTL */
-	outb(2, board_addr);
-	outb(0x03, board_addr+1);
-		
-	/* read the Module ID */
-	switch_bank(iobase, BANK3);
-	version = inb(iobase+MID);
-	
-	/* should be 0x2? */
-	if (0x20 != (version & 0xf0)) {
-		ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version);
-		return -1;
-	}
-	
-	/* Switch to advanced mode */
-	switch_bank(iobase, BANK2);
-	outb(ECR1_EXT_SL, iobase+ECR1);
-	switch_bank(iobase, BANK0);
-
-	dongle_id = pc87108_read_dongle_id(iobase);
-	IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
-		   dongle_types[dongle_id]);
-	
-	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
-	switch_bank(iobase, BANK0);	
-	outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-	
-	/* Set FIFO size to 32 */
-	switch_bank(iobase, BANK2);
-	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
-
-	/* IRCR2: FEND_MD is set */
-	switch_bank(iobase, BANK5);
-	outb(0x2a, iobase+4);
-
-	/* Make sure that some defaults are OK */
-	switch_bank(iobase, BANK6);
-	outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
-	outb(0x0a, iobase+1); /* Set MIR pulse width */
-	outb(0x0d, iobase+2); /* Set SIR pulse width */
-	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
-
-	/* Receiver frame length */
-	switch_bank(iobase, BANK4);
-	outb(2048 & 0xff, iobase+6);
-	outb((2048 >> 8) & 0x1f, iobase+7);
-
-	/* Transmitter frame length */
-	outb(2048 & 0xff, iobase+4);
-	outb((2048 >> 8) & 0x1f, iobase+5);
-	
-	IRDA_DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
-
-	/* Enable receive interrupts */
-	switch_bank(iobase, BANK0);
-	outb(IER_RXHDL_IE, iobase+IER);
-
-	return dongle_id;
-}
-
-/*
- * Function pc87108_read_dongle_id (void)
- *
- * Try to read dongle indentification. This procedure needs to be executed
- * once after power-on/reset. It also needs to be used whenever you suspect
- * that the user may have plugged/unplugged the IrDA Dongle.
- * 
- */
-static int pc87108_read_dongle_id (int iobase)
-{
-	int dongle_id;
-	__u8 bank;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	bank = inb(iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank(iobase, BANK7);
-	
-	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
-	outb(0x00, iobase+7);
-	
-	/* ID0, 1, and 2 are pulled up/down very slowly */
-	udelay(50);
-	
-	/* IRCFG1: read the ID bits */
-	dongle_id = inb(iobase+4) & 0x0f;
-
-#ifdef BROKEN_DONGLE_ID
-	if (dongle_id == 0x0a)
-		dongle_id = 0x09;
-#endif
-	
-	/* Go back to  bank 0 before returning */
-	switch_bank(iobase, BANK0);
-
-	IRDA_DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
-
-	outb(bank, iobase+BSR);
-
-	return dongle_id;
-}
-
-/*
- * Function pc87108_init_dongle_interface (iobase, dongle_id)
- *
- *     This function initializes the dongle for the transceiver that is
- *     used. This procedure needs to be executed once after
- *     power-on/reset. It also needs to be used whenever you suspect that
- *     the dongle is changed. 
- */
-static void pc87108_init_dongle_interface (int iobase, int dongle_id)
-{
-	int bank;
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank(iobase, BANK7);
-	
-	/* IRCFG4: set according to dongle_id */
-	switch (dongle_id) {
-	case 0x00: /* same as */
-	case 0x01: /* Differential serial interface */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x02: /* same as */
-	case 0x03: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x04: /* Sharp RY5HD01 */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x05: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x06: /* Single-ended serial interface */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x07: /* Consumer-IR only */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
-		break;
-	case 0x0A: /* same as */
-	case 0x0B: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x0C: /* same as */
-	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
-		/* 
-		 * Set irsl0 as input, irsl[1-2] as output, and separate 
-		 * inputs are used for SIR and MIR/FIR 
-		 */
-		outb(0x48, iobase+7); 
-		break;
-	case 0x0E: /* Supports SIR Mode only */
-		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
-		break;
-	case 0x0F: /* No dongle connected */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
-		       dongle_types[dongle_id]); 
-		IRDA_DEBUG(0, "***\n");
-
-		switch_bank(iobase, BANK0);
-		outb(0x62, iobase+MCR);
-		break;
-	default: 
-		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", 
-			   dongle_id);
-	}
-	
-	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
-	outb(0x00, iobase+4);
-
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-	
-} /* set_up_dongle_interface */
-
-/*
- * Function pc87108_change_dongle_speed (iobase, speed, dongle_id)
- *
- *    Change speed of the attach dongle
- *
- */
-static void pc87108_change_dongle_speed(int iobase, int speed, int dongle_id)
-{
-	unsigned long flags;
-	__u8 bank;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Select Bank 7 */
-	switch_bank(iobase, BANK7);
-	
-	/* IRCFG1: set according to dongle_id */
-	switch (dongle_id) {
-	case 0x00: /* same as */
-	case 0x01: /* Differential serial interface */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x02: /* same as */
-	case 0x03: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x04: /* Sharp RY5HD01 */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-	case 0x05: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x06: /* Single-ended serial interface */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x07: /* Consumer-IR only */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
-		       dongle_types[dongle_id]); 
-	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		switch_bank(iobase, BANK7);
-		outb_p(0x01, iobase+4);
-
-		if (speed == 4000000) {
-			save_flags(flags);
-			cli();
-			outb(0x81, iobase+4);
-			outb(0x80, iobase+4);
-			restore_flags(flags);
-		}
-		else
-			outb_p(0x00, iobase+4);
-		break;
-	case 0x0A: /* same as */
-	case 0x0B: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-		       dongle_types[dongle_id]); 
-		break;
-	case 0x0C: /* same as */
-	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
-		break;
-	case 0x0E: /* Supports SIR Mode only */
-		break;
-	case 0x0F: /* No dongle connected */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-		       dongle_types[dongle_id]);
-
-		switch_bank(iobase, BANK0); 
-		outb(0x62, iobase+MCR);
-		break;
-	default: 
-		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
-	}
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_change_speed (self, baud)
- *
- *    Change the speed of the device
- *
- */
-static void pc87108_change_speed(struct pc87108 *self, __u32 speed)
-{
-	__u8 mcr = MCR_SIR;
-	__u8 bank;
-	int iobase; 
-
-	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
-
-	ASSERT(self != NULL, return;);
-
-	iobase = self->io.iobase;
-
-	/* Update accounting for new speed */
-	self->io.speed = speed;
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Disable interrupts */
-	switch_bank(iobase, BANK0);
-	outb(0, iobase+IER);
-
-	  /* Select Bank 2 */
-	switch_bank(iobase, BANK2);
-
-	outb(0x00, iobase+BGDH);
-	switch (speed) {
-	case 9600:   outb(0x0c, iobase+BGDL); break;
-	case 19200:  outb(0x06, iobase+BGDL); break;
-	case 37600:  outb(0x03, iobase+BGDL); break;
-	case 57600:  outb(0x02, iobase+BGDL); break;
-	case 115200: outb(0x01, iobase+BGDL); break;
-	case 576000:
-		switch_bank(iobase, BANK5);
-		
-		/* IRCR2: MDRS is set */
-		outb(inb(iobase+4) | 0x04, iobase+4);
-	       
-		mcr = MCR_MIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
-		break;
-	case 1152000:
-		mcr = MCR_MIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
-		break;
-	case 4000000:
-		mcr = MCR_FIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
-		break;
-	default:
-		mcr = MCR_FIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
-			   speed);
-		break;
-	}
-
-	/* Set appropriate speed mode */
-	switch_bank(iobase, BANK0);
-	outb(mcr | MCR_TX_DFR, iobase+MCR);
-
-	/* Give some hits to the transceiver */
-	pc87108_change_dongle_speed(iobase, speed, self->io.dongle_id);
-
-	/* Set FIFO threshold to TX17, RX16 */
-	switch_bank(iobase, BANK0);
-	outb(FCR_RXTH|     /* Set Rx FIFO threshold */
-	      FCR_TXTH|     /* Set Tx FIFO threshold */
-	      FCR_TXSR|     /* Reset Tx FIFO */
-	      FCR_RXSR|     /* Reset Rx FIFO */
-	      FCR_FIFO_EN,  /* Enable FIFOs */
-	      iobase+FCR);
-	/* outb(0xa7, iobase+FCR); */
-	
-	/* Set FIFO size to 32 */
-	switch_bank(iobase, BANK2);
-	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
-	
-	self->netdev->tbusy = 0;
-	
-	/* Enable some interrupts so we can receive frames */
-	switch_bank(iobase, BANK0); 
-	if (speed > 115200) {
-		outb(IER_SFIF_IE, iobase+IER);
-		pc87108_dma_receive(self);
-	} else
-		outb(IER_RXHDL_IE, iobase+IER);
-    	
-	/* Restore BSR */
-	outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_hard_xmit (skb, dev)
- *
- *    Transmit the frame!
- *
- */
-static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct pc87108 *self;
-	int iobase;
-	__u32 speed;
-	__u8 bank;
-	int mtt;
-	
-	self = (struct pc87108 *) dev->priv;
-
-	ASSERT(self != NULL, return 0;);
-
-	iobase = self->io.iobase;
-
-	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, 
-		   (int) skb->len);
-	
-	/* Lock transmit buffer */
-	if (irda_lock((void *) &dev->tbusy) == FALSE)
-		return -EBUSY;
-
-	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed)
-		self->new_speed = speed;
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Decide if we should use PIO or DMA transfer */
-	if (self->io.speed > 115200) {
-		self->tx_buff.data = self->tx_buff.head;
-		memcpy(self->tx_buff.data, skb->data, skb->len);
-		self->tx_buff.len = skb->len;
-
-		mtt = irda_get_mtt(skb);
-	        if (mtt > 50) {
-			/* Adjust for timer resolution */
-			mtt = mtt / 125 + 1;
-
-			/* Setup timer */
-			switch_bank(iobase, BANK4);
-			outb(mtt & 0xff, iobase+TMRL);
-			outb((mtt >> 8) & 0x0f, iobase+TMRH);
-			
-			/* Start timer */
-			outb(IRCR1_TMR_EN, iobase+IRCR1);
-			self->io.direction = IO_XMIT;
-			
-			/* Enable timer interrupt */
-			switch_bank(iobase, BANK0);
-			outb(IER_TMR_IE, iobase+IER);
-		} else {
-			/* Use udelay for delays less than 50 us. */
-			if (mtt)
-				udelay(mtt);
-
-			/* Enable DMA interrupt */
-			switch_bank(iobase, BANK0);
-	 		outb(IER_DMA_IE, iobase+IER);
-	     		pc87108_dma_write(self, iobase);
-		}
-        } else {
-		self->tx_buff.data = self->tx_buff.head;
-
-	        self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
-						   self->tx_buff.truesize);
-				
-		/* Add interrupt on tx low level (will fire immediately) */
-		switch_bank(iobase, BANK0);
-		outb(IER_TXLDL_IE, iobase+IER);
-	}
-	dev_kfree_skb(skb);
-
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-
-	return 0;
-}
-
-/*
- * Function pc87108_dma_xmit (self, iobase)
- *
- *    Transmit data using DMA
- *
- */
-static void pc87108_dma_write(struct pc87108 *self, int iobase)
-{
-	int bsr;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bsr = inb(iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
-	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
-		  DMA_MODE_WRITE);
-	
-	self->io.direction = IO_XMIT;
-	
-	/* Choose transmit DMA channel  */ 
-	switch_bank(iobase, BANK2);
-	outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
-	     iobase+ECR1);
-	
-	/* Enable DMA */
- 	switch_bank(iobase, BANK0);	
-	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
-	/* Restore bank register */
-	outb(bsr, iobase+BSR);
-}
-
-/*
- * Function pc87108_pio_xmit (self, iobase)
- *
- *    Transmit data using PIO. Returns the number of bytes that actually
- *    got transfered
- *
- */
-static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
-{
-	int actual = 0;
-	__u8 bank;
-	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	switch_bank(iobase, BANK0);
-	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
-		IRDA_DEBUG(4, __FUNCTION__ 
-			   "(), warning, FIFO not empty yet!\n");
-
-		fifo_size -= 17;
-		IRDA_DEBUG(4, __FUNCTION__ "(), %d bytes left in tx fifo\n", 
-			   fifo_size);
-	}
-
-	/* Fill FIFO with current frame */
-	while ((fifo_size-- > 0) && (actual < len)) {
-		/* Transmit next byte */
-		outb(buf[actual++], iobase+TXD);
-	}
-        
-	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-		   fifo_size, actual, len);
-	
-	/* Restore bank */
-	outb(bank, iobase+BSR);
-
-	return actual;
-}
-
-/*
- * Function pc87108_dma_xmit_complete (self)
- *
- *    The transfer of a frame in finished. This function will only be called 
- *    by the interrupt handler
- *
- */
-static void pc87108_dma_xmit_complete(struct pc87108 *self)
-{
-	int iobase;
-	__u8 bank;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-
-	iobase = self->io.iobase;
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-	
-	/* Check for underrrun! */
-	if (inb(iobase+ASCR) & ASCR_TXUR) {
-		self->stats.tx_errors++;
-		self->stats.tx_fifo_errors++;
-		
-		/* Clear bit, by writing 1 into it */
-		outb(ASCR_TXUR, iobase+ASCR);
-	} else {
-		self->stats.tx_packets++;
-		self->stats.tx_bytes +=  self->tx_buff.len;
-	}
-	
-	if (self->new_speed) {
-		pc87108_change_speed(self, self->new_speed);
-		self->new_speed = 0;
-	}
-
-	/* Unlock tx_buff and request another frame */
-	self->netdev->tbusy = 0; /* Unlock */
-	
-	/* Tell the network layer, that we can accept more frames */
-	mark_bh(NET_BH);
-
-	/* Restore bank */
-	outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_dma_receive (self)
- *
- *    Get ready for receiving a frame. The device will initiate a DMA
- *    if it starts to receive a frame.
- *
- */
-static int pc87108_dma_receive(struct pc87108 *self) 
-{
-	int iobase;
-	__u8 bsr;
-
-	ASSERT(self != NULL, return -1;);
-
-	IRDA_DEBUG(4, __FUNCTION__ "\n");
-
-	iobase = self->io.iobase;
-
-	/* Save current bank */
-	bsr = inb(iobase+BSR);
-
-	/* Disable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
-	self->rx_buff.data = self->rx_buff.head;
-
-	setup_dma(self->io.dma, self->rx_buff.data, 
-		  self->rx_buff.truesize, DMA_MODE_READ);
-	
-	/* driver->media_busy = FALSE; */
-	self->io.direction = IO_RECV;
-
-	/* Reset Rx FIFO. This will also flush the ST_FIFO */
-	outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
-
-	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
-	switch_bank(iobase, BANK2);
-	outb((inb(iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, 
-	     iobase+ECR1);
-	
-	/* enable DMA */
-	switch_bank(iobase, BANK0);
-	outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
-	/* Restore bank register */
-	outb(bsr, iobase+BSR);
-	
-	IRDA_DEBUG(4, __FUNCTION__ "(), done!\n");	
-	
-	return 0;
-}
-
-/*
- * Function pc87108_dma_receive_complete (self)
- *
- *    Finished with receiving frames
- *
- *    
- */
-static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase)
-{
-	struct sk_buff *skb;
-	struct st_fifo *st_fifo;
-	__u8 bank;
-	__u8 status;
-	int len;
-
-	st_fifo = &self->st_fifo;
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-	
-	/* Read status FIFO */
-	switch_bank(iobase, BANK5);
-	while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
-		st_fifo->entries[st_fifo->tail].status = status;
-
-		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
-		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-		
-		st_fifo->tail++;
-		st_fifo->len++;
-	}
-	
-	/* Try to process all entries in status FIFO */
-	switch_bank(iobase, BANK0);
-	while (st_fifo->len) {
-      
-		/* Get first entry */
-		status = st_fifo->entries[st_fifo->head].status;
-		len    = st_fifo->entries[st_fifo->head].len;
-		st_fifo->head++;
-		st_fifo->len--;
-
-		/* Check for errors */
-		if (status & FRM_ST_ERR_MSK) {
-			if (status & FRM_ST_LOST_FR) {
-				/* Add number of lost frames to stats */
-				self->stats.rx_errors += len;	
-			} else {
-				/* Skip frame */
-				self->stats.rx_errors++;
-				
-				self->rx_buff.data += len;
-			
-				if (status & FRM_ST_MAX_LEN)
-					self->stats.rx_length_errors++;
-				
-				if (status & FRM_ST_PHY_ERR) 
-					self->stats.rx_frame_errors++;
-				
-				if (status & FRM_ST_BAD_CRC) 
-					self->stats.rx_crc_errors++;
-			}
-			/* The errors below can be reported in both cases */
-			if (status & FRM_ST_OVR1)
-				self->stats.rx_fifo_errors++;
-			
-			if (status & FRM_ST_OVR2)
-				self->stats.rx_fifo_errors++;
-			
-		} else {
-			/* Check if we have transfered all data to memory */
-			if (inb(iobase+LSR) & LSR_RXDA) {
-				/* Put this entry back in fifo */
-				st_fifo->head--;
-				st_fifo->len++;
-				st_fifo->entries[st_fifo->head].status = status;
-				st_fifo->entries[st_fifo->head].len = len;
-
-				/* Restore bank register */
-				outb(bank, iobase+BSR);
-			
-				return FALSE; 	/* I'll be back! */
-			}
-
-			/* Should be OK then */			
-			skb = dev_alloc_skb(len+1);
-			if (skb == NULL)  {
-				printk(KERN_INFO __FUNCTION__ 
-					"(), memory squeeze, dropping frame.\n");
-				/* Restore bank register */
-				outb(bank, iobase+BSR);
-
-				return FALSE;
-			}
-			
-			/* Make sure IP header gets aligned */
-			skb_reserve(skb, 1); 
-
-			/* Copy frame without CRC */
-			if (self->io.speed < 4000000) {
-				skb_put(skb, len-2);
-				memcpy(skb->data, self->rx_buff.data, len-2);
-			} else {
-				skb_put(skb, len-4);
-				memcpy(skb->data, self->rx_buff.data, len-4);
-			}
-
-			/* Move to next frame */
-			self->rx_buff.data += len;
-			self->stats.rx_packets++;
-
-			skb->dev = self->netdev;
-			skb->mac.raw  = skb->data;
-			skb->protocol = htons(ETH_P_IRDA);
-			netif_rx(skb);
-		}
-	}
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-
-	return TRUE;
-}
-
-/*
- * Function pc87108_pio_receive (self)
- *
- *    Receive all data in receiver FIFO
- *
- */
-static void pc87108_pio_receive(struct pc87108 *self) 
-{
-	__u8 byte = 0x00;
-	int iobase;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	
-	iobase = self->io.iobase;
-	
-	/*  Receive all characters in Rx FIFO */
-	do {
-		byte = inb(iobase+RXD);
-		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, byte);
-	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
-}
-
-/*
- * Function pc87108_sir_interrupt (self, eir)
- *
- *    Handle SIR interrupt
- *
- */
-static __u8 pc87108_sir_interrupt(struct pc87108 *self, int eir)
-{
-	int actual;
-	__u8 new_ier = 0;
-
-	/* Transmit FIFO low on data */
-	if (eir & EIR_TXLDL_EV) {
-		/* Write data left in transmit buffer */
-		actual = pc87108_pio_write(self->io.iobase, 
-					   self->tx_buff.data, 
-					   self->tx_buff.len, 
-					   self->io.fifo_size);
-		self->tx_buff.data += actual;
-		self->tx_buff.len  -= actual;
-		
-		self->io.direction = IO_XMIT;
-
-		/* Check if finished */
-		if (self->tx_buff.len > 0)
-			new_ier |= IER_TXLDL_IE;
-		else { 
-			self->netdev->tbusy = 0; /* Unlock */
-			self->stats.tx_packets++;
-
-			/* Check if we need to change the speed? */
-			if (self->new_speed) {
-				IRDA_DEBUG(2, __FUNCTION__ 
-					   "(), Changing speed!\n");
-				pc87108_change_speed(self, self->new_speed);
-				self->new_speed = 0;
-			}
-			
-		        mark_bh(NET_BH);	
-
-			new_ier |= IER_TXEMP_IE;
-		}
-			
-	}
-	/* Check if transmission has completed */
-	if (eir & EIR_TXEMP_EV) {
-		/* Check if we need to change the speed? */
-		if (self->new_speed) {
-			IRDA_DEBUG(2, __FUNCTION__ 
-				   "(), Changing speed!\n");
-			pc87108_change_speed(self, self->new_speed);
-			self->new_speed = 0;
-		}
-
-		/* Turn around and get ready to receive some data */
-		self->io.direction = IO_RECV;
-		new_ier |= IER_RXHDL_IE;
-	}
-
-	/* Rx FIFO threshold or timeout */
-	if (eir & EIR_RXHDL_EV) {
-		pc87108_pio_receive(self);
-
-		/* Keep receiving */
-		new_ier |= IER_RXHDL_IE;
-	}
-	return new_ier;
-}
-
-/*
- * Function pc87108_fir_interrupt (self, eir)
- *
- *    Handle MIR/FIR interrupt
- *
- */
-static __u8 pc87108_fir_interrupt(struct pc87108 *self, int iobase,
-				  int eir)
-{
-	__u8 new_ier = 0;
-	__u8 bank;
-
-	bank = inb(iobase+BSR);
-	
-	/* Status event, or end of frame detected in FIFO */
-	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
-		if (pc87108_dma_receive_complete(self, iobase)) {
-
-			/* Wait for next status FIFO interrupt */
-			new_ier |= IER_SFIF_IE;
-		} else {
-			/* DMA not finished yet */
-
-			/* Set timer value, resolution 125 us */
-			switch_bank(iobase, BANK4);
-			outb(0x0f, iobase+TMRL); /* 125 us */
-			outb(0x00, iobase+TMRH);
-
-			/* Start timer */
-			outb(IRCR1_TMR_EN, iobase+IRCR1);
-
-			new_ier |= IER_TMR_IE;
-		}
-	}
-	/* Timer finished */
-	if (eir & EIR_TMR_EV) {
-		/* Disable timer */
-		switch_bank(iobase, BANK4);
-		outb(0, iobase+IRCR1);
-
-		/* Clear timer event */
-		switch_bank(iobase, BANK0);
-		outb(ASCR_CTE, iobase+ASCR);
-
-		/* Check if this is a TX timer interrupt */
-		if (self->io.direction == IO_XMIT) {
-			pc87108_dma_write(self, iobase);
-
-			/*  Interrupt on DMA */
-			new_ier |= IER_DMA_IE;
-		} else {
-			/* Check if DMA has now finished */
-			pc87108_dma_receive_complete(self, iobase);
-
-			new_ier |= IER_SFIF_IE;
-		}
-	}	
-	/* Finished with transmission */
-	if (eir & EIR_DMA_EV) {
-		pc87108_dma_xmit_complete(self);
-		
-		/* Check if there are more frames to be transmitted */
-		if (irda_device_txqueue_empty(self->netdev)) {
-			/* Prepare for receive */
-			pc87108_dma_receive(self);
-			
-			new_ier = IER_LS_IE|IER_SFIF_IE;
-		}
-	}
-	outb(bank, iobase+BSR);
-
-	return new_ier;
-}
-
-/*
- * Function pc87108_interrupt (irq, dev_id, regs)
- *
- *    An interrupt from the chip has arrived. Time to do some work
- *
- */
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct pc87108 *self;
-	__u8 bsr, eir, ier;
-	int iobase;
-
-	if (!dev) {
-		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
-		return;
-	}
-	self = (struct pc87108 *) dev->priv;
-
-	dev->interrupt = 1;
-
-	iobase = self->io.iobase;
-
-	/* Save current bank */
-	bsr = inb(iobase+BSR);
-
-	switch_bank(iobase, BANK0);	
-	ier = inb(iobase+IER); 
-	eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */ 
-
-	outb(0, iobase+IER); /* Disable interrupts */
-	
-	if (eir) {
-		/* Dispatch interrupt handler for the current speed */
-		if (self->io.speed > 115200)
-			ier = pc87108_fir_interrupt(self, iobase, eir);
-		else
-			ier = pc87108_sir_interrupt(self, eir);
-	}
-
-	outb(ier, iobase+IER);   /* Restore interrupts */
-	outb(bsr, iobase+BSR);   /* Restore bank register */
-
-	dev->interrupt = 0;
-}
-
-/*
- * Function pc87108_is_receiving (self)
- *
- *    Return TRUE is we are currently receiving a frame
- *
- */
-static int pc87108_is_receiving(struct pc87108 *self)
-{
-	int status = FALSE;
-	int iobase;
-	__u8 bank;
-
-	ASSERT(self != NULL, return FALSE;);
-
-	if (self->io.speed > 115200) {
-		iobase = self->io.iobase;
-
-		/* Check if rx FIFO is not empty */
-		bank = inb(iobase+BSR);
-		switch_bank(iobase, BANK2);
-		if ((inb(iobase+RXFLV) & 0x3f) != 0) {
-			/* We are receiving something */
-			status =  TRUE;
-		}
-		outb(bank, iobase+BSR);
-	} else 
-		status = (self->rx_buff.state != OUTSIDE_FRAME);
-	
-	return status;
-}
-
-/*
- * Function pc87108_net_init (dev)
- *
- *    Initialize network device
- *
- */
-static int pc87108_net_init(struct net_device *dev)
-{
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup(dev);
-
-	/* Insert overrides below this line! */
-
-	return 0;
-}
-
-
-/*
- * Function pc87108_net_open (dev)
- *
- *    Start the device
- *
- */
-static int pc87108_net_open(struct net_device *dev)
-{
-	struct pc87108 *self;
-	int iobase;
-	__u8 bank;
-	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-	
-	ASSERT(dev != NULL, return -1;);
-	self = (struct pc87108 *) dev->priv;
-	
-	ASSERT(self != NULL, return 0;);
-	
-	iobase = self->io.iobase;
-
-	if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name, 
-			(void *) dev)) 
-	{
-		return -EAGAIN;
-	}
-	/*
-	 * Always allocate the DMA channel after the IRQ,
-	 * and clean up on failure.
-	 */
-	if (request_dma(self->io.dma, dev->name)) {
-		free_irq(self->io.irq, self);
-		return -EAGAIN;
-	}
-	
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-	
-	/* turn on interrupts */
-	switch_bank(iobase, BANK0);
-	outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
-
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* 
-	 * Open new IrLAP layer instance, now that everything should be
-	 * initialized properly 
-	 */
-	self->irlap = irlap_open(dev, &self->qos);
-
-	MOD_INC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function pc87108_net_close (dev)
- *
- *    Stop the device
- *
- */
-static int pc87108_net_close(struct net_device *dev)
-{
-	struct pc87108 *self;
-	int iobase;
-	__u8 bank;
-
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-	
-	ASSERT(dev != NULL, return -1;);
-	self = (struct pc87108 *) dev->priv;
-	
-	ASSERT(self != NULL, return 0;);
-
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	/* Stop and remove instance of IrLAP */
-	if (self->irlap)
-		irlap_close(self->irlap);
-	self->irlap = NULL;
-	
-	iobase = self->io.iobase;
-
-	disable_dma(self->io.dma);
-
-	/* Save current bank */
-	bank = inb(iobase+BSR);
-
-	/* Disable interrupts */
-	switch_bank(iobase, BANK0);
-	outb(0, iobase+IER); 
-       
-	free_irq(self->io.irq, dev);
-	free_dma(self->io.dma);
-
-	/* Restore bank register */
-	outb(bank, iobase+BSR);
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function pc87108_net_ioctl (dev, rq, cmd)
- *
- *    Process IOCTL commands for this device
- *
- */
-static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct if_irda_req *irq = (struct if_irda_req *) rq;
-	struct pc87108 *self;
-	unsigned long flags;
-	int ret = 0;
-
-	ASSERT(dev != NULL, return -1;);
-
-	self = dev->priv;
-
-	ASSERT(self != NULL, return -1;);
-
-	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
-	
-	/* Disable interrupts & save flags */
-	save_flags(flags);
-	cli();
-	
-	switch (cmd) {
-	case SIOCSBANDWIDTH: /* Set bandwidth */
-		pc87108_change_speed(self, irq->ifr_baudrate);
-		break;
-	case SIOCSMEDIABUSY: /* Set media busy */
-		irda_device_set_media_busy(self->netdev, TRUE);
-		break;
-	case SIOCGRECEIVING: /* Check if we are receiving right now */
-		irq->ifr_receiving = pc87108_is_receiving(self);
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-	}
-	
-	restore_flags(flags);
-	
-	return ret;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
-
-MODULE_PARM(qos_mtt_bits, "i");
-MODULE_PARM(io, "1-4i");
-MODULE_PARM(io2, "1-4i");
-MODULE_PARM(irq, "1-4i");
-
-/*
- * Function init_module (void)
- *
- *    
- *
- */
-int init_module(void)
-{
-	return pc87108_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
-void cleanup_module(void)
-{
-	pc87108_cleanup();
-}
-#endif /* MODULE */
-
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.37/linux/drivers/net/irda/smc-ircc.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/smc-ircc.c	Thu Jan  6 14:46:18 2000
@@ -1,26 +1,35 @@
 /*********************************************************************
  *                
  * Filename:      smc-ircc.c
- * Version:       0.1
- * Description:   Driver for the SMC Infrared Communications Controller (SMC)
+ * Version:       0.3
+ * Description:   Driver for the SMC Infrared Communications Controller
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  * Created at:    
- * Modified at:   Sat Dec 11 14:38:26 1999
+ * Modified at:   Wed Jan  5 12:38:06 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli
+ *     Copyright (c) 1998-1999 Thomas Davis, 
+ *     All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, admit no liability nor provide warranty for any
- *     of this software. This material is provided "AS-IS" and at no charge.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *
- *     Applicable Models : Fujitsu Lifebook 635t
- *			   Sony PCG-505TX (gets DMA wrong.)
+ *     SIO's: SMC FDC37N869, FDC37C669
+ *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
  *
  ********************************************************************/
 
@@ -53,8 +62,8 @@
 
 #define CHIP_IO_EXTENT 8
 
-static unsigned int io[]  = { 0x2e8, 0x140, 0x118, ~0 }; 
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0};
+static unsigned int io[]  = { 0x2e8, 0x140, 0x118, 0x240 }; 
+static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0x3e8 };
 
 static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
 
@@ -64,10 +73,11 @@
 static int  ircc_close(struct ircc_cb *self);
 #endif /* MODULE */
 static int  ircc_probe(int iobase, int board_addr);
+static int  ircc_probe_smc(int *ioaddr, int *ioaddr2);
 static int  ircc_dma_receive(struct ircc_cb *self); 
 static int  ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ircc_dma_write(struct ircc_cb *self, int iobase);
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase);
 static void ircc_change_speed(void *priv, __u32 speed);
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int  ircc_is_receiving(struct ircc_cb *self);
@@ -75,24 +85,13 @@
 static int  ircc_net_open(struct net_device *dev);
 static int  ircc_net_close(struct net_device *dev);
 
-static int ircc_debug=3;
 static int ircc_irq=255;
 static int ircc_dma=255;
 
-static inline void register_bank(int port, int bank)
-{
-        outb(((inb(port+UART_MASTER) & 0xF0) | (bank & 0x07)),
-             port+UART_MASTER);
-}
-
-static inline unsigned int serial_in(int port, int offset)
+static inline void register_bank(int iobase, int bank)
 {
-        return inb(port+offset);
-}
-
-static inline void serial_out(int port, int offset, int value)
-{
-        outb(value, port+offset);
+        outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+               iobase+IRCC_MASTER);
 }
 
 /*
@@ -103,9 +102,10 @@
  */
 int __init ircc_init(void)
 {
+	int ioaddr, ioaddr2;
 	int i;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 	for (i=0; (io[i] < 2000) && (i < 4); i++) {
 		int ioaddr = io[i];
 		if (check_region(ioaddr, CHIP_IO_EXTENT))
@@ -113,7 +113,13 @@
 		if (ircc_open(i, io[i], io2[i]) == 0)
 			return 0;
 	}
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+
+	/* last chance saloon, see what the controller says */
+	if (ircc_probe_smc(&ioaddr, &ioaddr2) == 0) {
+                  if (check_region(ioaddr, CHIP_IO_EXTENT) == 0)
+                          if (ircc_open(0, ioaddr, ioaddr2) == 0)
+                                  return 0; 
+	}
 
 	return -ENODEV;
 }
@@ -129,13 +135,12 @@
 {
 	int i;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
 			ircc_close(dev_self[i]);
 	}
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 }
 #endif /* MODULE */
 
@@ -152,11 +157,11 @@
 	int config;
 	int ret;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
 	if ((config = ircc_probe(iobase, iobase2)) == -1) {
-	        IRDA_DEBUG(ircc_debug, 
-		      __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), addr 0x%04x - no device found!\n", iobase);
 		return -1;
 	}
 	
@@ -165,11 +170,12 @@
 	 */
 	self = kmalloc(sizeof(struct ircc_cb), GFP_KERNEL);
 	if (self == NULL) {
-		printk(KERN_ERR "IrDA: Can't allocate memory for "
-			"IrDA control block!\n");
+		ERROR("%s, Can't allocate memory for control block!\n",
+                      driver_name);
 		return -ENOMEM;
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
+	spin_lock_init(&self->lock);
    
 	/* Need to store self somewhere */
 	dev_self[i] = self;
@@ -188,16 +194,16 @@
         self->io.iobase2   = iobase2; /* Used by irport */
         self->io.irq       = config >> 4 & 0x0f;
 	if (ircc_irq < 255) {
-	        MESSAGE("smc_ircc: Overriding IRQ - chip says %d, using %d\n",
-			self->io.irq, ircc_irq);
+	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+			driver_name, self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
         self->io.io_ext    = CHIP_IO_EXTENT;
         self->io.io_ext2   = 8;       /* Used by irport */
         self->io.dma       = config & 0x0f;
 	if (ircc_dma < 255) {
-	        MESSAGE("smc: Overriding DMA - chip says %d, using %d\n",
-			self->io.dma, ircc_dma);
+	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+			driver_name, self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
         self->io.fifo_size = 16;
@@ -206,7 +212,7 @@
 	ret = check_region(self->io.iobase, self->io.io_ext);
 	if (ret < 0) { 
 		IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
-		       self->io.iobase);
+			   self->io.iobase);
 		/* ircc_cleanup(self->self);  */
 		return -ENODEV;
 	}
@@ -214,17 +220,11 @@
 	request_region(self->io.iobase, self->io.io_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&self->qos);
+	irda_init_max_qos_capabilies(&irport->qos);
 	
-#if 1
 	/* The only value we must override it the baudrate */
-	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	irport->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-#else
-	/* The only value we must override it the baudrate */
-	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-		IR_115200;
-#endif
 
 	irport->qos.min_turn_time.bits = 0x07;
 	irda_qos_bits_to_value(&irport->qos);
@@ -235,23 +235,19 @@
 	self->rx_buff.truesize = 4000; 
 	self->tx_buff.truesize = 4000;
 
-	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-						      GFP_KERNEL|GFP_DMA);
-		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
-	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-						      GFP_KERNEL|GFP_DMA);
-		if (self->tx_buff.head == NULL) {
-			kfree(self->rx_buff.head);
-			return -ENOMEM;
-		}
-		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
 	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -260,12 +256,11 @@
 	
 	/* Override the speed change function, since we must control it now */
 	irport->change_speed = &ircc_change_speed;
-	self->netdev->open  = &ircc_net_open;
-	self->netdev->stop = &ircc_net_close;
+	self->netdev->open   = &ircc_net_open;
+	self->netdev->stop   = &ircc_net_close;
 
 	irport_start(self->irport);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -280,7 +275,7 @@
 {
 	int iobase;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return -1;);
 
@@ -289,18 +284,16 @@
 	irport_close(self->irport);
 
 	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, 0);
-	serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+	outb(0, iobase+IRCC_IER);
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
 
 	register_bank(iobase, 1);
 
-        serial_out(iobase, UART_SCE_CFGA, 
-		   UART_CFGA_IRDA_SIR_A | UART_CFGA_TX_POLARITY);
-        serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
+        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
+        outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
  
 	/* Release the PORT that this driver is using */
-	IRDA_DEBUG(ircc_debug, 
-	       __FUNCTION__ ": releasing 0x%03x\n", self->io.iobase);
+	IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", self->io.iobase);
 
 	release_region(self->io.iobase, self->io.io_ext);
 
@@ -312,13 +305,67 @@
 
 	kfree(self);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-
 	return 0;
 }
 #endif /* MODULE */
 
 /*
+ * Function ircc_probe_smc (ioaddr, ioaddr2)
+ *
+ *    Probe the SMC Chip for an IrDA port
+ *
+ */
+static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
+{
+        static int smcreg[] = { 0x3f0, 0x370 };
+	__u8 devid, mode;
+	__u8 conf_reg;
+	int ret = -1;
+	int fir_io;
+        int i;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+        for (i = 0; i < 2 && ret == -1; i++) {
+		conf_reg = smcreg[i];
+        
+		/* Enter configuration */
+                outb(0x55, conf_reg);
+                outb(0x55, conf_reg);
+    
+		outb(0x0d, conf_reg);
+		devid = inb(conf_reg+1);
+		IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+		
+		/* Check for expected device ID; are there others? */
+		if (devid == 0x29) {    
+			outb(0x0c, conf_reg);
+			mode = inb(conf_reg+1);
+			mode = (mode & 0x38) >> 3;
+
+			/* Value for IR port */
+			if (mode && mode < 4) {
+				/* SIR iobase */
+				outb(0x25, conf_reg);
+				*ioaddr2 = inb(conf_reg+1) << 2;
+
+				/* FIR iobase */
+				outb(0x2b, conf_reg);
+				fir_io = inb(conf_reg+1) << 3;
+				if (fir_io) {
+					ret = 0;
+					*ioaddr = fir_io;
+				}
+			}
+		}
+
+		/* Exit configuration */
+		outb(0xaa, conf_reg);
+        }
+	return ret;
+}
+
+/*
  * Function ircc_probe (iobase, board_addr, irq, dma)
  *
  *    Returns non-negative on success.
@@ -329,14 +376,18 @@
 	int version = 1;
 	int low, high, chip, config, dma, irq;
 	
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
+
+	/* Power on device */
+	outb(inb(iobase+IRCC_MASTER) & ~IRCC_MASTER_POWERDOWN, 
+	     iobase+IRCC_MASTER);
 
 	register_bank(iobase, 3);
-	high = serial_in(iobase, UART_ID_HIGH);
-	low = serial_in(iobase, UART_ID_LOW);
-	chip = serial_in(iobase, UART_CHIP_ID);
-	version = serial_in(iobase, UART_VERSION);
-	config = serial_in(iobase, UART_INTERFACE);
+	high = inb(iobase+IRCC_ID_HIGH);
+	low = inb(iobase+IRCC_ID_LOW);
+	chip = inb(iobase+IRCC_CHIP_ID);
+	version = inb(iobase+IRCC_VERSION);
+	config = inb(iobase+IRCC_INTERFACE);
 	irq = config >> 4 & 0x0f;
 	dma = config & 0x0f;
 
@@ -344,13 +395,10 @@
                 IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
 		      "port 0x%04x, dma %d, interrupt %d\n",
                       chip & 0x0f, version, iobase, dma, irq);
-	} else {
+	} else
 		return -1;
-	}
-
-	serial_out(iobase, UART_MASTER, 0);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+	outb(0, iobase+IRCC_MASTER);
 
 	return config;
 }
@@ -367,7 +415,7 @@
 	struct ircc_cb *self = (struct ircc_cb *) priv;
 	struct net_device *dev;
 
-	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return;);
 
@@ -380,16 +428,16 @@
 	switch (speed) {
 	case 9600:
 	case 19200:
-	case 37600:
+	case 38400:
 	case 57600:
 	case 115200:
-	        IRDA_DEBUG(ircc_debug+1, 
-		      __FUNCTION__ ": using irport to change speed to %d\n",
-		      speed);
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), using irport to change speed to %d\n", speed);
+
 		register_bank(iobase, 0);
-		serial_out(iobase, UART_IER, 0);
-		serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
-		serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+		outb(0, iobase+IRCC_IER);
+		outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+		outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
 
 		dev->hard_start_xmit = &irport_hard_xmit;
 
@@ -400,27 +448,23 @@
 		irport_change_speed(self->irport, speed);
 		return;
 		break;
-
 	case 576000:		
-		ir_mode = UART_CFGA_IRDA_HDLC;
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
 		select = 0;
 		fast = 0;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
-			   "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
-		ir_mode = UART_CFGA_IRDA_HDLC;
-		select = UART_1152;
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
+		select = IRCC_1152;
 		fast = 0;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
-			   "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
-		ir_mode = UART_CFGA_IRDA_4PPM;
+		ir_mode = IRCC_CFGA_IRDA_4PPM;
 		select = 0;
-		fast = UART_LCR_A_FAST;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
-			   "(), handling baud of 4000000\n");
+		fast = IRCC_LCR_A_FAST;
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
@@ -428,14 +472,10 @@
 		return;
 	}
 
-#if 0
-	serial_out(self->io.iobase2, 4, 0x08);
-#endif
-
-	serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
 
 	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, 0);
+	outb(0, iobase+IRCC_IER);
 	
        	irport_stop(self->irport);	
 
@@ -448,27 +488,23 @@
 	dev->tbusy = 0;
 	
 	register_bank(iobase, 1);
+	outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode), 
+	     iobase+IRCC_SCE_CFGA);
+	
+	outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_IR), 
+	     iobase+IRCC_SCE_CFGB);
 
-	serial_out(iobase, UART_SCE_CFGA, 
-		   ((serial_in(iobase, UART_SCE_CFGA) & 0x87) | ir_mode));
-
-	serial_out(iobase, UART_SCE_CFGB,
-		   ((serial_in(iobase, UART_SCE_CFGB) & 0x3f) | UART_CFGB_IR));
-
-	(void) serial_in(iobase, UART_FIFO_THRESHOLD);
-	serial_out(iobase, UART_FIFO_THRESHOLD, 64);
+	(void) inb(iobase+IRCC_FIFO_THRESHOLD);
+	outb(64, iobase+IRCC_FIFO_THRESHOLD);
 
 	register_bank(iobase, 4);
 
-	serial_out(iobase, UART_CONTROL,
-		   (serial_in(iobase, UART_CONTROL) & 0x30) 
-		   | select | UART_CRC );
+	outb((inb(iobase+IRCC_CONTROL) & 0x30) | select | IRCC_CRC, 
+	     iobase+IRCC_CONTROL);
 
 	register_bank(iobase, 0);
 
-	serial_out(iobase, UART_LCR_A, fast);
-
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+	outb(fast, iobase+IRCC_LCR_A);
 }
 
 /*
@@ -485,7 +521,6 @@
 	int mtt;
 	__u32 speed;
 
-	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
 	irport = (struct irport_cb *) dev->priv;
 	self = (struct ircc_cb *) irport->priv;
 
@@ -493,15 +528,13 @@
 
 	iobase = self->io.iobase;
 
-	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
+	IRDA_DEBUG(2, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
 		   (int) skb->len);
 
 	/* Check if we need to change the speed */
 	if ((speed = irda_get_speed(skb)) != self->io.speed)
 		self->new_speed = speed;
 	
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
-
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
@@ -514,21 +547,15 @@
 
 	self->tx_buff.len = skb->len;
 	self->tx_buff.data = self->tx_buff.head;
-#if 0
-	self->tx_buff.offset = 0;
-#endif
-	
-	mtt = irda_get_mtt(skb);
 	
-	/* Use udelay for delays less than 50 us. */
+	mtt = irda_get_mtt(skb);	
 	if (mtt)
 		udelay(mtt);
 	
-	ircc_dma_write(self, iobase);
+	ircc_dma_xmit(self, iobase);
 	
 	dev_kfree_skb(skb);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -538,48 +565,44 @@
  *    Transmit data using DMA
  *
  */
-static void ircc_dma_write(struct ircc_cb *self, int iobase)
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
 {
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return;);
 
 	iobase = self->io.iobase;
 
 	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
-		   DMA_MODE_WRITE);
+		  DMA_TX_MODE);
 	
 	self->io.direction = IO_XMIT;
 
-	serial_out(self->io.iobase2, 4, 0x08);
-
+	outb(0x08, self->io.iobase2+4);
+	
 	register_bank(iobase, 4);
-	serial_out(iobase, UART_CONTROL, 
-		   (serial_in(iobase, UART_CONTROL) & 0xF0));
-
-	serial_out(iobase, UART_BOF_COUNT_LO, 2);
-	serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
+	outb((inb(iobase+IRCC_CONTROL) & 0xf0), iobase+IRCC_CONTROL);
+	
+	outb(2, iobase+IRCC_BOF_COUNT_LO);
+	outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
 #if 1
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, self->tx_buff.len >> 8);
-	serial_out(iobase, UART_TX_SIZE_LO, self->tx_buff.len & 0xff);
+	outb(self->tx_buff.len >> 8, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+	outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
 #else
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
-	serial_out(iobase, UART_TX_SIZE_LO, 0);
+	outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+	outb(0, iobase+IRCC_TX_SIZE_LO);
 #endif
 
 	register_bank(iobase, 1);
-	serial_out(iobase, UART_SCE_CFGB,
-		   serial_in(iobase, UART_SCE_CFGB) | UART_CFGB_DMA_ENABLE);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE,
+	     iobase+IRCC_SCE_CFGB);
 
 	register_bank(iobase, 0);
 
-	serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME | UART_IER_EOM);
-	serial_out(iobase, UART_LCR_B,
-		   UART_LCR_B_SCE_TRANSMIT|UART_LCR_B_SIP_ENABLE);
+	outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
+	outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
 
-	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
-
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
 }
 
 /*
@@ -593,20 +616,20 @@
 {
 	int iobase, d;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return;);
 
 	register_bank(self->io.iobase, 1);
 
-	serial_out(self->io.iobase, UART_SCE_CFGB,
-		   serial_in(self->io.iobase, UART_SCE_CFGB) &
-		   ~UART_CFGB_DMA_ENABLE);
+	outb(inb(self->io.iobase+IRCC_SCE_CFGB) & IRCC_CFGB_DMA_ENABLE,
+	     self->io.iobase+IRCC_SCE_CFGB);
 
 	d = get_dma_residue(self->io.dma);
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", 
-	      d, self->tx_buff.len, self->tx_buff.len - d);
+	IRDA_DEBUG(0, __FUNCTION__ 
+		   ": dma residue = %d, len=%d, sent=%d\n", 
+		   d, self->tx_buff.len, self->tx_buff.len - d);
 
 	iobase = self->io.iobase;
 
@@ -630,8 +653,6 @@
 	
 	/* Tell the network layer, that we can accept more frames */
 	mark_bh(NET_BH);
-
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -645,14 +666,14 @@
 {
 	int iobase;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return -1;);
 
 	iobase= self->io.iobase;
 
 	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
-		   DMA_MODE_READ);
+		   DMA_RX_MODE);
 	
 	/* driver->media_busy = FALSE; */
 	self->io.direction = IO_RECV;
@@ -662,25 +683,22 @@
 #endif
 
 	register_bank(iobase, 4);
-	serial_out(iobase, UART_CONTROL, 
-		   (serial_in(iobase, UART_CONTROL) &0xF0));
-	serial_out(iobase, UART_BOF_COUNT_LO, 2);
-	serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
-	serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
-	serial_out(iobase, UART_TX_SIZE_LO, 0);
-	serial_out(iobase, UART_RX_SIZE_HI, 0);
-	serial_out(iobase, UART_RX_SIZE_LO, 0);
+	outb(inb(iobase+IRCC_CONTROL) & 0xf0, iobase+IRCC_CONTROL);
+	outb(2, iobase+IRCC_BOF_COUNT_LO);
+	outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
+	outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+	outb(0, iobase+IRCC_TX_SIZE_LO);
+	outb(0, iobase+IRCC_RX_SIZE_HI);
+	outb(0, iobase+IRCC_RX_SIZE_LO);
 
 	register_bank(iobase, 0);
-	serial_out(iobase, 
-		   UART_LCR_B, UART_LCR_B_SCE_RECEIVE | UART_LCR_B_SIP_ENABLE);
+	outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, 
+	     iobase+IRCC_LCR_B);
 	
 	register_bank(iobase, 1);
-	serial_out(iobase, UART_SCE_CFGB,
-		   serial_in(iobase, UART_SCE_CFGB) | 
-		   UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | 
+	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -696,22 +714,20 @@
 	struct sk_buff *skb;
 	int len, msgcnt;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(2, __FUNCTION__ "\n");
 
-	msgcnt = serial_in(self->io.iobase, UART_LCR_B) & 0x08;
+	msgcnt = inb(self->io.iobase+IRCC_LCR_B) & 0x08;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
-	      get_dma_residue(self->io.dma));
+	IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+		   get_dma_residue(self->io.dma));
 
 	len = self->rx_buff.truesize - get_dma_residue(self->io.dma) - 4;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+	IRDA_DEBUG(0, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
 
 	skb = dev_alloc_skb(len+1);
-
-	if (skb == NULL)  {
-		printk(KERN_INFO __FUNCTION__ 
-			": memory squeeze, dropping frame.\n");
+	if (!skb)  {
+		WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
 		return FALSE;
 	}
 			
@@ -728,11 +744,9 @@
 	netif_rx(skb);
 
 	register_bank(self->io.iobase, 1);
-	serial_out(self->io.iobase, UART_SCE_CFGB,
-		   serial_in(self->io.iobase, UART_SCE_CFGB) &
-		   ~UART_CFGB_DMA_ENABLE);
+	outb(inb(self->io.iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	     self->io.iobase+IRCC_SCE_CFGB);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return TRUE;
 }
 
@@ -748,11 +762,9 @@
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct ircc_cb *self;
 
-	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
-
 	if (dev == NULL) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
-			driver_name, irq);
+		       driver_name, irq);
 		return;
 	}
 	
@@ -762,45 +774,42 @@
 
 	dev->interrupt = 1;
 
-	serial_out(iobase, UART_MASTER, 0);
+	outb(0, iobase+IRCC_MASTER);
 
 	register_bank(iobase, 0);
+	iir = inb(iobase+IRCC_IIR);
 
-	iir = serial_in(iobase, UART_IIR);
+	/* Disable interrupts */
+	outb(0, iobase+IRCC_IER);
 
-	serial_out(iobase, UART_IER, 0);
+	IRDA_DEBUG(0, __FUNCTION__ "(), iir = 0x%02x\n", iir);
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+	if (iir & IRCC_IIR_EOM) {
+	        IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_EOM\n");
 
-	if (iir & UART_IIR_EOM) {
-	        IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
-		if (self->io.direction == IO_RECV) {
+		if (self->io.direction == IO_RECV)
 			ircc_dma_receive_complete(self, iobase);
-		} else {
+		else
 			ircc_dma_xmit_complete(self, iobase);
-		}
+		
 		ircc_dma_receive(self);
 	}
-
-	if (iir & UART_IIR_ACTIVE_FRAME) {
-	        IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
+	if (iir & IRCC_IIR_ACTIVE_FRAME) {
+	        IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_ACTIVE_FRAME\n");
 		self->rx_buff.state = INSIDE_FRAME;
 #if 0
 		ircc_dma_receive(self);
 #endif
 	}
-
-	if (iir & UART_IIR_RAW_MODE) {
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+	if (iir & IRCC_IIR_RAW_MODE) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), IIR RAW mode interrupt.\n");
 	}
 
-	dev->interrupt = 0;
-
 	register_bank(iobase, 0);
-	serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
-	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+	outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+	dev->interrupt = 0;
 }
 
 /*
@@ -814,17 +823,15 @@
 	int status = FALSE;
 	/* int iobase; */
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
 	ASSERT(self != NULL, return FALSE;);
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
-	      get_dma_residue(self->io.dma));
+	IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+		   get_dma_residue(self->io.dma));
 
 	status = (self->rx_buff.state != OUTSIDE_FRAME);
 	
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-
 	return status;
 }
 
@@ -840,7 +847,7 @@
 	struct ircc_cb *self;
 	int iobase;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 	
 	ASSERT(dev != NULL, return -1;);
 	irport = (struct irport_cb *) dev->priv;
@@ -850,20 +857,20 @@
 	
 	iobase = self->io.iobase;
 
-	irport_net_open(dev);
+	irport_net_open(dev); /* irport allocates the irq */
 
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
 	 */
 	if (request_dma(self->io.dma, dev->name)) {
-		free_irq(self->io.irq, dev);
+		irport_net_close(dev);
+
 		return -EAGAIN;
 	}
 	
 	MOD_INC_USE_COUNT;
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -879,7 +886,7 @@
 	struct ircc_cb *self;
 	int iobase;
 
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(0, __FUNCTION__ "\n");
 	
 	ASSERT(dev != NULL, return -1;);
 	irport = (struct irport_cb *) dev->priv;
@@ -897,15 +904,12 @@
 
 	MOD_DEC_USE_COUNT;
 
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
 MODULE_DESCRIPTION("SMC IrCC controller driver");
-MODULE_PARM(ircc_debug,"1i");
 MODULE_PARM(ircc_dma, "1i");
 MODULE_PARM(ircc_irq, "1i");
 
@@ -919,4 +923,4 @@
 	ircc_cleanup();
 }
 
-#endif
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.37/linux/drivers/net/irda/tekram.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/irda/tekram.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Fri Dec 17 09:17:45 1999
+ * Modified at:   Fri Dec 17 09:13:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.37/linux/drivers/net/irda/toshoboe.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/irda/toshoboe.c	Fri Jan  7 11:51:56 2000
@@ -10,7 +10,7 @@
  * Modified:      Paul Bristow <paul.bristow@technologist.com>
  * Modified:      Mon Nov 11 19:10:05 1999
  * 
- *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ *     Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
diff -u --recursive --new-file v2.3.37/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.37/linux/drivers/net/irda/w83977af_ir.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/irda/w83977af_ir.c	Fri Jan  7 11:51:56 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Tue Dec 21 21:53:09 1999
+ * Modified at:   Wed Jan  5 15:11:21 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998-1999 Rebel.com
  *      
  *     This program is free software; you can redistribute it and/or 
@@ -62,9 +62,9 @@
 #include <net/irda/w83977af.h>
 #include <net/irda/w83977af_ir.h>
 
-#ifdef  CONFIG_ARCH_VNC            /* Adjust to NetWinder differences */
-#undef  CONFIG_VNC_TX_DMA_PROBLEMS /* Not needed */
-#define CONFIG_VNC_RX_DMA_PROBLEMS /* Must have this one! */
+#ifdef  CONFIG_ARCH_NETWINDER            /* Adjust to NetWinder differences */
+#undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
 #endif
 #undef  CONFIG_USE_INTERNAL_TIMER  /* Just cannot make that timer work */
 #define CONFIG_USE_W977_PNP        /* Currently needed */
@@ -76,7 +76,7 @@
 #define CHIP_IO_EXTENT 8
 
 static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
-#ifdef CONFIG_ARCH_VNC             /* Adjust to NetWinder differences */
+#ifdef CONFIG_ARCH_NETWINDER             /* Adjust to NetWinder differences */
 static unsigned int irq[] = { 6, 0, 0, 0 };
 #else
 static unsigned int irq[] = { 11, 0, 0, 0 };
@@ -105,6 +105,7 @@
 static int  w83977af_net_open(struct net_device *dev);
 static int  w83977af_net_close(struct net_device *dev);
 static int  w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev);
 
 /*
  * Function w83977af_init ()
@@ -218,22 +219,20 @@
 	self->tx_buff.truesize = 4000;
 	
 	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-						      GFP_KERNEL|GFP_DMA);
-		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
-	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-						      GFP_KERNEL|GFP_DMA);
-		if (self->tx_buff.head == NULL) {
-			kfree(self->rx_buff.head);
-			return -ENOMEM;
-		}
-		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL)
+		return -ENOMEM;
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		kfree(self->rx_buff.head);
+		return -ENOMEM;
 	}
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -244,6 +243,9 @@
 		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
 		return -ENOMEM;
 	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
 	dev->priv = (void *) self;
 	self->netdev = dev;
 
@@ -253,6 +255,7 @@
 	dev->open            = w83977af_net_open;
 	dev->stop            = w83977af_net_close;
 	dev->do_ioctl        = w83977af_net_ioctl;
+	dev->get_stats	     = w83977af_net_get_stats;
 
 	rtnl_lock();
 	err = register_netdev(dev);
@@ -298,6 +301,8 @@
 		rtnl_lock();
 		unregister_netdevice(self->netdev);
 		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
 	}
 
 	/* Release the PORT that this driver is using */
@@ -334,12 +339,12 @@
  		w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
   
  		w977_write_reg(0x70, irq, efbase[i]);
-#ifdef CONFIG_ARCH_VNC
+#ifdef CONFIG_ARCH_NETWINDER
 		/* Netwinder uses 1 higher than Linux */
  		w977_write_reg(0x74, dma+1, efbase[i]);
 #else
  		w977_write_reg(0x74, dma, efbase[i]);   
-#endif /*CONFIG_ARCH_VNC */
+#endif /*CONFIG_ARCH_NETWINDER */
  		w977_write_reg(0x75, 0x04, efbase[i]);  /* Disable Tx DMA */
   	
  		/* Set append hardware CRC, enable IR bank selection */	
@@ -440,7 +445,7 @@
 	switch (speed) {
 	case 9600:   outb(0x0c, iobase+ABLL); break;
 	case 19200:  outb(0x06, iobase+ABLL); break;
-	case 37600:  outb(0x03, iobase+ABLL); break;
+	case 38400:  outb(0x03, iobase+ABLL); break;
 	case 57600:  outb(0x02, iobase+ABLL); break;
 	case 115200: outb(0x01, iobase+ABLL); break;
 	case 576000:
@@ -471,7 +476,6 @@
 	
 	/* set FIFO threshold to TX17, RX16 */
 	switch_bank(iobase, SET0);
-
 	outb(0x00, iobase+UFR);        /* Reset */
 	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
 	outb(0xa7, iobase+UFR);
@@ -508,7 +512,8 @@
 
 	iobase = self->io.iobase;
 
-	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, 
+		   (int) skb->len);
 	
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -584,7 +589,7 @@
 static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
 {
 	__u8 set;
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
@@ -600,7 +605,7 @@
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, SET2);
 	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
@@ -617,7 +622,7 @@
 	
 	/* Enable DMA */
  	switch_bank(iobase, SET0);
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
 	enable_dma(self->io.dma);
@@ -648,10 +653,12 @@
 
 	switch_bank(iobase, SET0);
 	if (!(inb_p(iobase+USR) & USR_TSRE)) {
-		IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", 
+			   fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -733,11 +740,10 @@
 {
 	int iobase;
 	__u8 set;
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
-
 	ASSERT(self != NULL, return -1;);
 
 	IRDA_DEBUG(4, __FUNCTION__ "\n");
@@ -759,7 +765,7 @@
 	self->io.direction = IO_RECV;
 	self->rx_buff.data = self->rx_buff.head;
 
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
@@ -783,7 +789,7 @@
 	
 	/* Enable DMA */
 	switch_bank(iobase, SET0);
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
 	enable_dma(self->io.dma);
@@ -993,14 +999,6 @@
 			self->netdev->tbusy = 0; /* Unlock */
 			self->stats.tx_packets++;
 
-			/* Check if we need to change the speed? */
-			if (self->new_speed) {
-				IRDA_DEBUG(2, __FUNCTION__ 
-					   "(), Changing speed!\n");
-				w83977af_change_speed(self, self->new_speed);
-				self->new_speed = 0;
-			}
-
 			/* Schedule network layer */
 		        mark_bh(NET_BH);	
 
@@ -1112,7 +1110,7 @@
 }
 
 /*
- * Function pc87108_interrupt (irq, dev_id, regs)
+ * Function w83977af_interrupt (irq, dev_id, regs)
  *
  *    An interrupt from the chip has arrived. Time to do some work
  *
@@ -1367,12 +1365,22 @@
 	return ret;
 }
 
+static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev)
+{
+	struct w83977af_ir *self = (struct w83977af_ir *) dev->priv;
+	
+	return &self->stats;
+}
+
 #ifdef MODULE
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
 
 MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
 
 /*
  * Function init_module (void)
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/Config.in linux/drivers/net/tokenring/Config.in
--- v2.3.37/linux/drivers/net/tokenring/Config.in	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/tokenring/Config.in	Thu Jan  6 15:01:56 2000
@@ -10,6 +10,7 @@
    tristate '  IBM Tropic chipset based adapter support' CONFIG_IBMTR
    tristate '  IBM Olympic chipset PCI adapter support' CONFIG_IBMOL
    tristate '  Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR
+   tristate '  SMC ISA adapter support' CONFIG_SMCTR
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/Makefile linux/drivers/net/tokenring/Makefile
--- v2.3.37/linux/drivers/net/tokenring/Makefile	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/tokenring/Makefile	Thu Jan  6 15:01:56 2000
@@ -47,5 +47,13 @@
   endif
 endif
 
+ifeq ($(CONFIG_SMCTR),y)
+  L_OBJS += smctr.o
+else
+  ifeq ($(CONFIG_SMCTR),m)
+    M_OBJS += smctr.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- v2.3.37/linux/drivers/net/tokenring/smctr.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/tokenring/smctr.c	Fri Jan  7 11:51:56 2000
@@ -0,0 +1,5712 @@
+/*
+ *  smctr.c: A network driver for the SMC Token Ring Adapters.
+ *
+ *  Written by Jay Schulist <jschlst@turbolinux.com>
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ *
+ *  This device driver works with the following SMC adapters:
+ *      - SMC TokenCard Elite   (8115T)
+ *      - SMC TokenCard Elite/A MCA (8115T/A)
+ *
+ *  Source(s):
+ *  	- SMC TokenCard SDK.
+ *
+ *  Maintainer(s):
+ *    JS        Jay Schulist <jschlst@turbolinux.com>
+ *
+ *  To do:
+ *    1. MCA SMC TokenCard Support. (Some support is already done).
+ *    4. Multicast support.
+ */
+
+static const char *version = "smctr.c: v1.0 1/1/00 by jschlst@turbolinux.com\n";
+static const char *cardname = "smctr";
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/trdevice.h>
+
+#include "smctr.h"               /* Our Stuff */
+#include "smctr_firmware.h"      /* SMC adapter firmware */
+
+#define SMCTR_IO_EXTENT   20
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int smctr_portlist[] __initdata = {
+        0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+        0x320, 0x340, 0x360, 0x380,
+        0
+};
+
+static int ringspeed = 0;
+
+/* SMC Name of the Adapter. */
+static char *smctr_name = "SMC TokenCard";
+char *smctr_model = "Unknown";
+
+/* Use 0 for production, 1 for verification, 2 for debug, and
+ * 3 for very verbose debug.
+ */
+#ifndef SMCTR_DEBUG
+#define SMCTR_DEBUG 1
+#endif
+static unsigned int smctr_debug = SMCTR_DEBUG;
+
+/* smctr.c prototypes and functions are arranged alphabeticly 
+ * for clearity, maintainability and pure old fashion fun. 
+ */
+/* A */
+static int smctr_alloc_shared_memory(struct net_device *dev);
+
+/* B */
+static int smctr_bypass_state(struct net_device *dev);
+
+/* C */
+static int smctr_checksum_firmware(struct net_device *dev);
+static int smctr_chg_rx_mask(struct net_device *dev);
+static int smctr_clear_int(struct net_device *dev);
+static int smctr_clear_trc_reset(int ioaddr);
+static int smctr_close(struct net_device *dev);
+
+/* D */
+static int smctr_decode_firmware(struct net_device *dev);
+static int smctr_disable_16bit(struct net_device *dev);
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_disable_adapter_ram(struct net_device *dev);
+static int smctr_disable_bic_int(struct net_device *dev);
+
+/* E */
+static int smctr_enable_16bit(struct net_device *dev);
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_enable_adapter_ram(struct net_device *dev);
+static int smctr_enable_bic_int(struct net_device *dev);
+
+/* F */
+static int __init smctr_find_adapter(struct net_device *dev);
+
+/* G */
+static int __init smctr_get_boardid(struct net_device *dev);
+static int smctr_get_group_address(struct net_device *dev);
+static int smctr_get_functional_address(struct net_device *dev);
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev);
+static int smctr_get_physical_drop_number(struct net_device *dev);
+static __u8 *smctr_get_rx_pointer(struct net_device *dev, short queue);
+static int smctr_get_station_id(struct net_device *dev);
+static struct enet_statistics *smctr_get_stats(struct net_device *dev);
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+        __u16 bytes_count);
+static int smctr_get_upstream_neighbor_addr(struct net_device *dev);
+
+/* H */
+static int smctr_hardware_send_packet(struct net_device *dev,
+        struct net_local *tp);
+
+/* I */
+static int smctr_init_acbs(struct net_device *dev);
+static int smctr_init_adapter(struct net_device *dev);
+static int __init smctr_init_card(struct net_device *dev);
+static int smctr_init_card_real(struct net_device *dev);
+static int smctr_init_rx_bdbs(struct net_device *dev);
+static int smctr_init_rx_fcbs(struct net_device *dev);
+static int smctr_init_shared_memory(struct net_device *dev);
+static int smctr_init_tx_bdbs(struct net_device *dev);
+static int smctr_init_tx_fcbs(struct net_device *dev);
+static int smctr_internal_self_test(struct net_device *dev);
+static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+        __u16 interrupt_enable_mask);
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
+        __u16 ibits);
+static int smctr_issue_init_timers_cmd(struct net_device *dev);
+static int smctr_issue_init_txrx_cmd(struct net_device *dev);
+static int smctr_issue_insert_cmd(struct net_device *dev);
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev);
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt);
+static int smctr_issue_remove_cmd(struct net_device *dev);
+static int smctr_issue_resume_acb_cmd(struct net_device *dev);
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev);
+static int smctr_issue_test_hic_cmd(struct net_device *dev);
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev);
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev);
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev);
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+        short aword_cnt, void *byte);
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+        short aword_cnt, void *word);
+
+/* J */
+static int smctr_join_complete_state(struct net_device *dev);
+
+/* L */
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev);
+static int smctr_load_firmware(struct net_device *dev);
+static int smctr_load_node_addr(struct net_device *dev);
+static int smctr_lobe_media_test(struct net_device *dev);
+static int smctr_lobe_media_test_cmd(struct net_device *dev);
+static int smctr_lobe_media_test_state(struct net_device *dev);
+
+/* M */
+static int smctr_make_8025_hdr(struct net_device *dev,
+        MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc);
+static int smctr_make_access_pri(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_auth_funct_class(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_corr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv, __u16 correlator);
+static int smctr_make_funct_addr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_group_addr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_phy_drop_num(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_status(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_version(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_tx_status_code(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv, __u16 tx_fstatus);
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+static int smctr_make_wrap_data(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv);
+
+/* O */
+static int smctr_open(struct net_device *dev);
+static int smctr_open_tr(struct net_device *dev);
+
+/* P */
+int __init smctr_probe (struct net_device *dev);
+static int __init smctr_probe1(struct net_device *dev, int ioaddr);
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+        struct net_device *dev, __u16 rx_status);
+
+/* R */
+static int smctr_ram_conflict_test(struct net_device *dev);
+static int smctr_ram_memory_test(struct net_device *dev);
+static unsigned int __init smctr_read_584_chksum(int ioaddr);
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator);
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator);
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf);
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+        MAC_HEADER *rmf, __u16 *correlator);
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator);
+static int smctr_reset_adapter(struct net_device *dev);
+static int smctr_restart_tx_chain(struct net_device *dev, short queue);
+static int smctr_ring_status_chg(struct net_device *dev);
+static int smctr_rom_conflict_test(struct net_device *dev);
+static int smctr_rx_frame(struct net_device *dev);
+
+/* S */
+static int smctr_send_dat(struct net_device *dev);
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int smctr_send_lobe_media_test(struct net_device *dev);
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator);
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator);
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator);
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+        MAC_HEADER *rmf, __u16 tx_fstatus);
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 rcode, __u16 correlator);
+static int smctr_send_rq_init(struct net_device *dev);
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *tx_fstatus);
+static int smctr_set_auth_access_pri(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv);
+static int smctr_set_auth_funct_class(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv);
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+	__u16 *correlator);
+static int smctr_set_error_timer_value(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv);
+static int smctr_set_frame_forward(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv, __u8 dc_sc);
+static int smctr_set_local_ring_num(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv);
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev);
+static void smctr_set_multicast_list(struct net_device *dev);
+static int smctr_set_page(struct net_device *dev, __u8 *buf);
+static int smctr_set_phy_drop(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv);
+static int smctr_set_ring_speed(struct net_device *dev);
+static int smctr_set_rx_look_ahead(struct net_device *dev);
+static int smctr_set_trc_reset(int ioaddr);
+static int smctr_setup_single_cmd(struct net_device *dev,
+        __u16 command, __u16 subcommand);
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+        __u16 command, __u16 subcommand);
+static char *smctr_malloc(struct net_device *dev, __u16 size);
+static int smctr_status_chg(struct net_device *dev);
+
+/* T */
+static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
+        __u16 queue);
+static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue);
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+        struct sk_buff *skb, __u8 *pbuff, unsigned int bytes);
+
+/* U */
+static int smctr_update_err_stats(struct net_device *dev);
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue);
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+        __u16 queue);
+
+/* W */
+static int smctr_wait_cmd(struct net_device *dev);
+static int smctr_wait_while_cbusy(struct net_device *dev);
+
+#define TO_256_BYTE_BOUNDRY(X)  (((X + 0xff) & 0xff00) - X)
+#define TO_PARAGRAPH_BOUNDRY(X) (((X + 0x0f) & 0xfff0) - X)
+#define PARAGRAPH_BOUNDRY(X)    smctr_malloc(dev, TO_PARAGRAPH_BOUNDRY(X))
+
+/* Allocate Adapter Shared Memory.
+ * IMPORTANT NOTE: Any changes to this function MUST be mirrored in the
+ * function "get_num_rx_bdbs" below!!!
+ *
+ * Order of memory allocation:
+ *
+ *       0. Initial System Configuration Block Pointer
+ *       1. System Configuration Block
+ *       2. System Control Block
+ *       3. Action Command Block
+ *       4. Interrupt Status Block
+ *
+ *       5. MAC TX FCB'S
+ *       6. NON-MAC TX FCB'S
+ *       7. MAC TX BDB'S
+ *       8. NON-MAC TX BDB'S
+ *       9. MAC RX FCB'S
+ *      10. NON-MAC RX FCB'S
+ *      11. MAC RX BDB'S
+ *      12. NON-MAC RX BDB'S
+ *      13. MAC TX Data Buffer( 1, 256 byte buffer)
+ *      14. MAC RX Data Buffer( 1, 256 byte buffer)
+ *
+ *      15. NON-MAC TX Data Buffer
+ *      16. NON-MAC RX Data Buffer
+ */
+static int smctr_alloc_shared_memory(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_alloc_shared_memory\n", dev->name);
+
+        /* Allocate initial System Control Block pointer.
+         * This pointer is located in the last page, last offset - 4.
+         */
+        tp->iscpb_ptr = (ISCPBlock *)(tp->ram_access + ((__u32)64 * 0x400)
+                - (long)ISCP_BLOCK_SIZE);
+
+        /* Allocate System Control Blocks. */
+        tp->scgb_ptr = (SCGBlock *)smctr_malloc(dev, sizeof(SCGBlock));
+        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+        tp->sclb_ptr = (SCLBlock *)smctr_malloc(dev, sizeof(SCLBlock));
+        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+        tp->acb_head = (ACBlock *)smctr_malloc(dev,
+                sizeof(ACBlock)*tp->num_acbs);
+        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+        tp->isb_ptr = (ISBlock *)smctr_malloc(dev, sizeof(ISBlock));
+        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+        tp->misc_command_data = (__u16 *)smctr_malloc(dev, MISC_DATA_SIZE);
+        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+        /* Allocate transmit FCBs. */
+        tp->tx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+                sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE]);
+
+        tp->tx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+                sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE]);
+
+        tp->tx_fcb_head[BUG_QUEUE] = (FCBlock *)smctr_malloc(dev,
+                sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE]);
+
+        /* Allocate transmit BDBs. */
+        tp->tx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+                sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE]);
+
+        tp->tx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+                sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE]);
+
+        tp->tx_bdb_head[BUG_QUEUE] = (BDBlock *)smctr_malloc(dev,
+                sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE]);
+
+        /* Allocate receive FCBs. */
+        tp->rx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+                sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE]);
+
+        tp->rx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+                sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE]);
+
+        /* Allocate receive BDBs. */
+        tp->rx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+                sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE]);
+
+        tp->rx_bdb_end[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+        tp->rx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+                sizeof(BDBlock) * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+
+        tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+        /* Allocate MAC transmit buffers.
+         * MAC Tx Buffers doen't have to be on an ODD Boundry.
+         */
+        tp->tx_buff_head[MAC_QUEUE]
+                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]);
+        tp->tx_buff_curr[MAC_QUEUE] = tp->tx_buff_head[MAC_QUEUE];
+        tp->tx_buff_end [MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+        /* Allocate BUG transmit buffers. */
+        tp->tx_buff_head[BUG_QUEUE]
+                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[BUG_QUEUE]);
+        tp->tx_buff_curr[BUG_QUEUE] = tp->tx_buff_head[BUG_QUEUE];
+        tp->tx_buff_end[BUG_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+        /* Allocate MAC receive data buffers.
+         * MAC Rx buffer doesn't have to be on a 256 byte boundry.
+         */
+        tp->rx_buff_head[MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+                RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE]);
+        tp->rx_buff_end[MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+        /* Allocate Non-MAC transmit buffers.
+         * ?? For maximum Netware performance, put Tx Buffers on
+         * ODD Boundry and then restore malloc to Even Boundrys.
+         */
+        smctr_malloc(dev, 1L);
+        tp->tx_buff_head[NON_MAC_QUEUE]
+                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[NON_MAC_QUEUE]);
+        tp->tx_buff_curr[NON_MAC_QUEUE] = tp->tx_buff_head[NON_MAC_QUEUE];
+        tp->tx_buff_end [NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+        smctr_malloc(dev, 1L);
+
+        /* Allocate Non-MAC receive data buffers.
+         * To guarantee a minimum of 256 contigous memory to
+         * UM_Receive_Packet's lookahead pointer, before a page
+         * change or ring end is encountered, place each rx buffer on
+         * a 256 byte boundry.
+         */
+        smctr_malloc(dev, TO_256_BYTE_BOUNDRY(tp->sh_mem_used));
+        tp->rx_buff_head[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+                RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+        tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+        return (0);
+}
+
+/* Enter Bypass state. */
+static int smctr_bypass_state(struct net_device *dev)
+{
+        int err;
+
+	if(smctr_debug > 10)
+        	printk("%s: smctr_bypass_state\n", dev->name);
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+                JS_BYPASS_STATE);
+
+        return (err);
+}
+
+static int smctr_checksum_firmware(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 i, checksum = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_checksum_firmware\n", dev->name);
+
+        smctr_enable_adapter_ctrl_store(dev);
+
+        for(i = 0; i < CS_RAM_SIZE; i += 2)
+                checksum += *((__u16 *)(tp->ram_access + i));
+
+        tp->microcode_version = *(__u16 *)(tp->ram_access
+                + CS_RAM_VERSION_OFFSET);
+        tp->microcode_version >>= 8;
+
+        smctr_disable_adapter_ctrl_store(dev);
+
+        if(checksum)
+                return (checksum);
+
+        return (0);
+}
+
+static int smctr_chg_rx_mask(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_chg_rx_mask\n", dev->name);
+
+        smctr_enable_16bit(dev);
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        if(tp->mode_bits & LOOPING_MODE_MASK)
+                tp->config_word0 |= RX_OWN_BIT;
+        else
+                tp->config_word0 &= ~RX_OWN_BIT;
+
+        if(tp->receive_mask & PROMISCUOUS_MODE)
+                tp->config_word0 |= PROMISCUOUS_BIT;
+        else
+                tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+        if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+                tp->config_word0 |= SAVBAD_BIT;
+        else
+                tp->config_word0 &= ~SAVBAD_BIT;
+
+        if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+                tp->config_word0 |= RXATMAC;
+        else
+                tp->config_word0 &= ~RXATMAC;
+
+        if(tp->receive_mask & ACCEPT_MULTI_PROM)
+                tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+        else
+                tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+        if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+                tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+        else
+        {
+                if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+                        tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+                else
+                        tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+        }
+
+        if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
+                &tp->config_word0)))
+        {
+                return (err);
+        }
+
+        if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
+                &tp->config_word1)))
+        {
+                return (err);
+        }
+
+        smctr_disable_16bit(dev);
+
+        return (0);
+}
+
+static int smctr_clear_int(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
+
+        return (0);
+}
+
+static int smctr_clear_trc_reset(int ioaddr)
+{
+        __u8 r;
+
+        r = inb(ioaddr + MSR);
+        outb(~MSR_RST & r, ioaddr + MSR);
+
+        return (0);
+}
+
+/*
+ * The inverse routine to smctr_open().
+ */
+static int smctr_close(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        struct sk_buff *skb;
+        int err;
+
+        dev->tbusy = 1;
+        dev->start = 0;
+
+#ifdef MODULE
+        MOD_DEC_USE_COUNT;
+#endif
+
+	tp->cleanup = 1;
+
+        /* Check to see if adapter is already in a closed state. */
+        if(tp->status != OPEN)
+                return (0);
+
+        smctr_enable_16bit(dev);
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        if((err = smctr_issue_remove_cmd(dev)))
+        {
+                smctr_disable_16bit(dev);
+                return (err);
+        }
+
+        for(;;)
+        {
+                skb = skb_dequeue(&tp->SendSkbQueue);
+                if(skb == NULL)
+                        break;
+                tp->QueueSkb++;
+                dev_kfree_skb(skb);
+        }
+
+
+        return (0);
+}
+
+static int smctr_decode_firmware(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        short bit = 0x80, shift = 12;
+        DECODE_TREE_NODE *tree;
+        short branch, tsize;
+        __u16 buff = 0;
+        long weight;
+        __u8 *ucode;
+        __u16 *mem;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_decode_firmware\n", dev->name);
+
+        weight  = *(long *)(tp->ptr_ucode + WEIGHT_OFFSET);
+        tsize   = *(__u8 *)(tp->ptr_ucode + TREE_SIZE_OFFSET);
+        tree    = (DECODE_TREE_NODE *)(tp->ptr_ucode + TREE_OFFSET);
+        ucode   = (__u8 *)(tp->ptr_ucode + TREE_OFFSET
+                        + (tsize * sizeof(DECODE_TREE_NODE)));
+        mem     = (__u16 *)(tp->ram_access);
+
+        while(weight)
+        {
+                branch = ROOT;
+                while((tree + branch)->tag != LEAF && weight)
+                {
+                        branch = *ucode & bit ? (tree + branch)->llink
+                                : (tree + branch)->rlink;
+
+                        bit >>= 1;
+                        weight--;
+
+                        if(bit == 0)
+                        {
+                                bit = 0x80;
+                                ucode++;
+                        }
+                }
+
+                buff |= (tree + branch)->info << shift;
+                shift -= 4;
+
+                if(shift < 0)
+                {
+                        *(mem++) = SWAP_BYTES(buff);
+                        buff    = 0;
+                        shift   = 12;
+                }
+        }
+
+        /* The following assumes the Control Store Memory has
+         * been initialized to zero. If the last partial word
+         * is zero, it will not be written.
+         */
+        if(buff)
+                *(mem++) = SWAP_BYTES(buff);
+
+        return (0);
+}
+
+static int smctr_disable_16bit(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u8 r;
+
+        if(tp->adapter_bus == BUS_ISA16_TYPE
+                && ((tp->adapter_flags & FORCED_16BIT_MODE) == 0))
+        {
+                r = inb(dev->base_addr + LAAR);
+                outb((r & ~LAAR_MEM16ENB), dev->base_addr + LAAR);
+        }
+
+        return (0);
+}
+
+/*
+ * On Exit, Adapter is:
+ * 1. TRC is in a reset state and un-initialized.
+ * 2. Adapter memory is enabled.
+ * 3. Control Store memory is out of context (-WCSS is 1).
+ */
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_disable_adapter_ctrl_store\n", dev->name);
+
+        tp->trc_mask |= CSR_WCSS;
+        outb(tp->trc_mask, ioaddr + CSR);
+
+        return (0);
+}
+
+static int smctr_disable_adapter_ram(struct net_device *dev)
+{
+        int ioaddr = dev->base_addr;
+        __u8 r;
+
+        /* First disable memory enable bit. */
+        r = inb(ioaddr + MSR);
+        outb(~MSR_MEMB & r, ioaddr + MSR);
+
+        /* Now disable 16 bit memory enable bit. */
+        r = inb(ioaddr + LAAR);
+        outb(~LAAR_MEM16ENB & r, ioaddr + LAAR);
+
+        return (0);
+}
+
+static int smctr_disable_bic_int(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        tp->trc_mask = CSR_MSK_ALL | CSR_MSKCBUSY
+	        | CSR_MSKTINT | CSR_WCSS;
+        outb(tp->trc_mask, ioaddr + CSR);
+
+        return (0);
+}
+
+static int smctr_enable_16bit(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u8    r;
+
+        if(tp->adapter_bus == BUS_ISA16_TYPE)
+        {
+                r = inb(dev->base_addr + LAAR);
+                outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
+        }
+
+        return (0);
+}
+
+/*
+ * To enable the adapter control store memory:
+ * 1. Adapter must be in a RESET state.
+ * 2. Adapter memory must be enabled.
+ * 3. Control Store Memory is in context (-WCSS is 0).
+ */
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_enable_adapter_ctrl_store\n", dev->name);
+
+        smctr_set_trc_reset(ioaddr);
+        smctr_enable_adapter_ram(dev);
+
+        tp->trc_mask &= ~CSR_WCSS;
+        outb(tp->trc_mask, ioaddr + CSR);
+
+        return (0);
+}
+
+static int smctr_enable_adapter_ram(struct net_device *dev)
+{
+        int ioaddr = dev->base_addr;
+        __u8 r;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_enable_adapter_ram\n", dev->name);
+
+        r = inb(ioaddr + MSR);
+        outb(MSR_MEMB | r, ioaddr + MSR);
+
+        return (0);
+}
+
+static int smctr_enable_bic_int(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+        __u8 r;
+
+        switch(tp->bic_type)
+        {
+                case (BIC_584_CHIP):
+                        tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+                        outb(tp->trc_mask, ioaddr + CSR);
+                        r = inb(ioaddr + IRR);
+                        outb(r | IRR_IEN, ioaddr + IRR);
+                        break;
+
+                case (BIC_594_CHIP):
+                        tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+                        outb(tp->trc_mask, ioaddr + CSR);
+                        r = inb(ioaddr + IMCCR);
+                        outb(r | IMCCR_EIL, ioaddr + IMCCR);
+                        break;
+        }
+
+        return (0);
+}
+
+static int __init smctr_find_adapter(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+        __u8 r1, r2, b, chksum = 0;
+        __u16 r;
+	int i;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_find_adapter %#4x\n", dev->name, ioaddr);
+
+        /* Checksum SMC node address */
+        for(i = 0; i < 8; i++)
+        {
+                b = inb(ioaddr + LAR0 + i);
+                chksum += b;
+        }
+
+        if(chksum != NODE_ADDR_CKSUM)
+                return (-1);            /* Adapter Not Found */
+
+        /* Grab the region so that no one else tries to probe our ioports. */
+        request_region(ioaddr, SMCTR_IO_EXTENT, smctr_name);
+
+        b = inb(ioaddr + BDID);
+
+        /* Check for 8115T Board ID */
+        r2 = 0;
+        for(r = 0; r < 8; r++)
+        {
+            r1 = inb(ioaddr + 0x8 + r);
+            r2 += r1;
+        }
+
+        /* value of RegF adds up the sum to 0xFF */
+        if((r2 != 0xFF) && (r2 != 0xEE))
+                return (-1);
+
+        /* Get adapter ID */
+        tp->board_id = smctr_get_boardid(dev);
+        switch(tp->board_id & 0xffff)
+        {
+                case WD8115TA:
+                        smctr_model = "8115T/A";
+                        break;
+
+                case WD8115T:
+                        smctr_model = "8115T";
+                        break;
+
+                default:
+                        smctr_model = "Unknown";
+                        break;
+        }
+
+        /* Store BIC type. */
+        tp->bic_type = BIC_584_CHIP;
+        tp->nic_type = NIC_825_CHIP;
+
+        /* Copy Ram Size */
+        tp->ram_usable  = CNFG_SIZE_16KB;
+        tp->ram_size    = CNFG_SIZE_64KB;
+
+        /* Get 58x Ram Base */
+        r1 = inb(ioaddr);
+        r1 &= 0x3F;
+
+        r2 = inb(ioaddr + CNFG_LAAR_584);
+        r2 &= CNFG_LAAR_MASK;
+        r2 <<= 3;
+        r2 |= ((r1 & 0x38) >> 3);
+
+        tp->ram_base = ((__u32)r2 << 16) + (((__u32)(r1 & 0x7)) << 13);
+
+        /* Get 584 Irq */
+        r1 = 0;
+        r1 = inb(ioaddr + CNFG_ICR_583);
+        r1 &= CNFG_ICR_IR2_584;
+
+        r2 = inb(ioaddr + CNFG_IRR_583);
+        r2 &= CNFG_IRR_IRQS;     /* 0x60 */
+        r2 >>= 5;
+
+        switch(r2)
+        {
+                case 0:
+                        if(r1 == 0)
+                                dev->irq = 2;
+                        else
+                                dev->irq = 10;
+                        break;
+
+                case 1:
+                        if(r1 == 0)
+                                dev->irq = 3;
+                        else
+                                dev->irq = 11;
+                        break;
+
+                case 2:
+                        if(r1 == 0)
+                        {
+                                if(tp->extra_info & ALTERNATE_IRQ_BIT)
+                                        dev->irq = 5;
+                                else
+                                        dev->irq = 4;
+                        }
+                        else
+                                dev->irq = 15;
+                        break;
+
+                case 3:
+                        if(r1 == 0)
+                                dev->irq = 7;
+                        else
+                                dev->irq = 4;
+                        break;
+
+                default:
+                        printk("%s: No IRQ found aborting\n", dev->name);
+                        return(-1);
+         }
+
+        if(request_irq(dev->irq, smctr_interrupt, SA_SHIRQ, smctr_name, dev))
+                return (-ENODEV);
+
+        /* Get 58x Rom Base */
+        r1 = inb(ioaddr + CNFG_BIO_583);
+        r1 &= 0x3E;
+        r1 |= 0x40;
+
+        tp->rom_base = (__u32)r1 << 13;
+
+        /* Get 58x Rom Size */
+        r1 = inb(ioaddr + CNFG_BIO_583);
+        r1 &= 0xC0;
+        if(r1 == 0)
+                tp->rom_size = ROM_DISABLE;
+        else
+        {
+                r1 >>= 6;
+                tp->rom_size = (__u16)CNFG_SIZE_8KB << r1;
+        }
+
+        /* Get 58x Boot Status */
+        r1 = inb(ioaddr + CNFG_GP2);
+
+        tp->mode_bits &= (~BOOT_STATUS_MASK);
+
+        if(r1 & CNFG_GP2_BOOT_NIBBLE)
+                tp->mode_bits |= BOOT_TYPE_1;
+
+        /* Get 58x Zero Wait State */
+        tp->mode_bits &= (~ZERO_WAIT_STATE_MASK);
+
+        r1 = inb(ioaddr + CNFG_IRR_583);
+
+        if(r1 & CNFG_IRR_ZWS)
+                 tp->mode_bits |= ZERO_WAIT_STATE_8_BIT;
+
+        if(tp->board_id & BOARD_16BIT)
+        {
+                r1 = inb(ioaddr + CNFG_LAAR_584);
+
+                if(r1 & CNFG_LAAR_ZWS)
+                        tp->mode_bits |= ZERO_WAIT_STATE_16_BIT;
+        }
+
+        /* Get 584 Media Menu */
+        tp->media_menu = 14;
+        r1 = inb(ioaddr + CNFG_IRR_583);
+
+        tp->mode_bits &= 0xf8ff;       /* (~CNFG_INTERFACE_TYPE_MASK) */
+        if((tp->board_id & TOKEN_MEDIA) == TOKEN_MEDIA)
+        {
+                /* Get Advanced Features */
+                if(((r1 & 0x6) >> 1) == 0x3)
+                        tp->media_type |= MEDIA_UTP_16;
+                else
+                {
+                        if(((r1 & 0x6) >> 1) == 0x2)
+                                tp->media_type |= MEDIA_STP_16;
+                        else
+                        {
+                                if(((r1 & 0x6) >> 1) == 0x1)
+                                        tp->media_type |= MEDIA_UTP_4;
+
+                                else
+                                        tp->media_type |= MEDIA_STP_4;
+                        }
+                }
+
+                r1 = inb(ioaddr + CNFG_GP2);
+                if(!(r1 & 0x2) )           /* GP2_ETRD */
+                        tp->mode_bits |= EARLY_TOKEN_REL;
+
+                /* see if the chip is corrupted */
+                if(smctr_read_584_chksum(ioaddr))
+                {
+                        printk("%s: EEPROM Checksum Failure\n", dev->name);
+                        return(-1);
+                }
+        }
+
+        return (0);
+}
+
+static int __init smctr_get_boardid(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+        __u8 r, r1, IdByte;
+        __u16 BoardIdMask;
+
+        tp->board_id = BoardIdMask = 0;
+
+        BoardIdMask |= (INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
+        tp->extra_info |= (INTERFACE_584_CHIP + RAM_SIZE_64K
+                + NIC_825_BIT + ALTERNATE_IRQ_BIT);
+
+        r = inb(ioaddr + BID_REG_1);
+        r &= 0x0c;
+        outb(r, ioaddr + BID_REG_1);
+        r = inb(ioaddr + BID_REG_1);
+
+        if(r & BID_SIXTEEN_BIT_BIT)
+        {
+                tp->extra_info |= SLOT_16BIT;
+                tp->adapter_bus = BUS_ISA16_TYPE;
+        }
+        else
+                tp->adapter_bus = BUS_ISA8_TYPE;
+
+        /* Get Board Id Byte */
+        IdByte = inb(ioaddr + BID_BOARD_ID_BYTE);
+
+        /* if Major version > 1.0 then
+         *      return;
+         */
+        if(IdByte & 0xF8)
+                return (-1);
+
+        r1 = inb(ioaddr + BID_REG_1);
+        r1 &= BID_ICR_MASK;
+        r1 |= BID_OTHER_BIT;
+
+        outb(r1, ioaddr + BID_REG_1);
+        r1 = inb(ioaddr + BID_REG_3);
+
+        r1 &= BID_EAR_MASK;
+        r1 |= BID_ENGR_PAGE;
+
+        outb(r1, ioaddr + BID_REG_3);
+        r1 = inb(ioaddr + BID_REG_1);
+        r1 &= BID_ICR_MASK;
+        r1 |= (BID_RLA | BID_OTHER_BIT);
+
+        outb(r1, ioaddr + BID_REG_1);
+
+        r1 = inb(ioaddr + BID_REG_1);
+        while(r1 & BID_RECALL_DONE_MASK)
+                r1 = inb(ioaddr + BID_REG_1);
+
+        r = inb(ioaddr + BID_LAR_0 + BID_REG_6);
+
+        /* clear chip rev bits */
+        tp->extra_info &= ~CHIP_REV_MASK;
+        tp->extra_info |= ((r & BID_EEPROM_CHIP_REV_MASK) << 6);
+
+        r1 = inb(ioaddr + BID_REG_1);
+        r1 &= BID_ICR_MASK;
+        r1 |= BID_OTHER_BIT;
+
+        outb(r1, ioaddr + BID_REG_1);
+        r1 = inb(ioaddr + BID_REG_3);
+
+        r1 &= BID_EAR_MASK;
+        r1 |= BID_EA6;
+
+        outb(r1, ioaddr + BID_REG_3);
+        r1 = inb(ioaddr + BID_REG_1);
+
+        r1 &= BID_ICR_MASK;
+        r1 |= BID_RLA;
+
+        outb(r1, ioaddr + BID_REG_1);
+        r1 = inb(ioaddr + BID_REG_1);
+
+        while(r1 & BID_RECALL_DONE_MASK)
+                r1 = inb(ioaddr + BID_REG_1);
+
+        return (BoardIdMask);
+}
+
+static int smctr_get_group_address(struct net_device *dev)
+{
+        smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
+
+        return(smctr_wait_cmd(dev));
+}
+
+static int smctr_get_functional_address(struct net_device *dev)
+{
+        smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
+
+        return(smctr_wait_cmd(dev));
+}
+
+/* Calculate number of Non-MAC receive BDB's and data buffers.
+ * This function must simulate allocateing shared memory exactly
+ * as the allocate_shared_memory function above.
+ */
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int mem_used = 0;
+
+        /* Allocate System Control Blocks. */
+        mem_used += sizeof(SCGBlock);
+
+        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+        mem_used += sizeof(SCLBlock);
+
+        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+        mem_used += sizeof(ACBlock) * tp->num_acbs;
+
+        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+        mem_used += sizeof(ISBlock);
+
+        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+        mem_used += MISC_DATA_SIZE;
+
+        /* Allocate transmit FCB's. */
+        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+
+        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE];
+        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE];
+        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE];
+
+        /* Allocate transmit BDBs. */
+        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE];
+        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE];
+        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE];
+
+        /* Allocate receive FCBs. */
+        mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE];
+        mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE];
+
+        /* Allocate receive BDBs. */
+        mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE];
+
+        /* Allocate MAC transmit buffers.
+         * MAC transmit buffers don't have to be on an ODD Boundry.
+         */
+        mem_used += tp->tx_buff_size[MAC_QUEUE];
+
+        /* Allocate BUG transmit buffers. */
+        mem_used += tp->tx_buff_size[BUG_QUEUE];
+
+        /* Allocate MAC receive data buffers.
+         * MAC receive buffers don't have to be on a 256 byte boundry.
+         */
+        mem_used += RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE];
+
+        /* Allocate Non-MAC transmit buffers.
+         * For maximum Netware performance, put Tx Buffers on
+         * ODD Boundry,and then restore malloc to Even Boundrys.
+         */
+        mem_used += 1L;
+        mem_used += tp->tx_buff_size[NON_MAC_QUEUE];
+        mem_used += 1L;
+
+        /* CALCULATE NUMBER OF NON-MAC RX BDB'S
+         * AND NON-MAC RX DATA BUFFERS
+         *
+         * Make sure the mem_used offset at this point is the
+         * same as in allocate_shared memory or the following
+         * boundry adjustment will be incorrect (i.e. not allocating
+         * the non-mac recieve buffers above cannot change the 256
+         * byte offset).
+         *
+         * Since this cannot be guaranteed, adding the full 256 bytes
+         * to the amount of shared memory used at this point will guaranteed
+         * that the rx data buffers do not overflow shared memory.
+         */
+        mem_used += 0x100;
+
+        return((0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock)));
+}
+
+static int smctr_get_physical_drop_number(struct net_device *dev)
+{
+        smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
+
+        return(smctr_wait_cmd(dev));
+}
+
+static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        BDBlock *bdb;
+
+        bdb = (BDBlock *)((__u32)tp->ram_access
+                + (__u32)(tp->rx_fcb_curr[queue]->trc_bdb_ptr));
+
+        tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
+
+        return ((__u8 *)bdb->data_block_ptr);
+}
+
+static int smctr_get_station_id(struct net_device *dev)
+{
+        smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
+
+        return(smctr_wait_cmd(dev));
+}
+
+/*
+ * Get the current statistics. This may be called with the card open
+ * or closed.
+ */
+static struct enet_statistics *smctr_get_stats(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        return ((struct enet_statistics *)&tp->MacStat);
+}
+
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+        __u16 bytes_count)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        FCBlock *pFCB;
+        BDBlock *pbdb;
+        unsigned short alloc_size;
+        unsigned short *temp;
+
+        if(smctr_debug > 20)
+                printk("smctr_get_tx_fcb\n");
+
+        /* check if there is enough FCB blocks */
+        if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
+                return ((FCBlock *)(-1L));
+
+        /* round off the input pkt size to the nearest even number */
+        alloc_size = (bytes_count + 1) & 0xfffe;
+
+        /* check if enough mem */
+        if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
+                return ((FCBlock *)(-1L));
+
+        /* check if past the end ;
+         * if exactly enough mem to end of ring, alloc from front.
+         * this avoids update of curr when curr = end
+         */
+        if(((unsigned long)(tp->tx_buff_curr[queue]) + alloc_size)
+                >= (unsigned long)(tp->tx_buff_end[queue]))
+        {
+                /* check if enough memory from ring head */
+                alloc_size = alloc_size +
+                        (__u16)((__u32)tp->tx_buff_end[queue]
+                        - (__u32)tp->tx_buff_curr[queue]);
+
+                if((tp->tx_buff_used[queue] + alloc_size)
+                        > tp->tx_buff_size[queue])
+                {
+                        return ((FCBlock *)(-1L));
+                }
+
+                /* ring wrap */
+                tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+        }
+
+        tp->tx_buff_used[queue] += alloc_size;
+        tp->num_tx_fcbs_used[queue]++;
+        tp->tx_fcb_curr[queue]->frame_length = bytes_count;
+        tp->tx_fcb_curr[queue]->memory_alloc = alloc_size;
+        temp = tp->tx_buff_curr[queue];
+        tp->tx_buff_curr[queue]
+                = (__u16 *)((__u32)temp + (__u32)((bytes_count + 1) & 0xfffe));
+
+        pbdb = tp->tx_fcb_curr[queue]->bdb_ptr;
+        pbdb->buffer_length = bytes_count;
+        pbdb->data_block_ptr = temp;
+        pbdb->trc_data_block_ptr = TRC_POINTER(temp);
+
+        pFCB = tp->tx_fcb_curr[queue];
+        tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
+
+        return (pFCB);
+}
+
+static int smctr_get_upstream_neighbor_addr(struct net_device *dev)
+{
+        smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
+
+        return(smctr_wait_cmd(dev));
+}
+
+static int smctr_hardware_send_packet(struct net_device *dev,
+        struct net_local *tp)
+{
+        struct tr_statistics *tstat = &tp->MacStat;
+        struct sk_buff *skb;
+        FCBlock *fcb;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_hardware_send_packet\n", dev->name);
+
+        if(tp->status != OPEN)
+                return (-1);
+
+        if(tp->monitor_state_ready != 1)
+                return (-1);
+
+        for(;;)
+        {
+                /* Send first buffer from queue */
+                skb = skb_dequeue(&tp->SendSkbQueue);
+                if(skb == NULL)
+                        return (-1);
+
+                tp->QueueSkb++;
+
+                if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size)                        return (-1);
+
+                smctr_enable_16bit(dev);
+                smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+                if((fcb = smctr_get_tx_fcb(dev, NON_MAC_QUEUE, skb->len))
+                        == (FCBlock *)(-1L))
+                {
+                        smctr_disable_16bit(dev);
+                        return (-1);
+                }
+
+                smctr_tx_move_frame(dev, skb,
+                        (__u8 *)fcb->bdb_ptr->data_block_ptr, skb->len);
+
+                smctr_set_page(dev, (__u8 *)fcb);
+
+                smctr_trc_send_packet(dev, fcb, NON_MAC_QUEUE);
+                dev_kfree_skb(skb);
+
+                tstat->tx_packets++;
+
+                smctr_disable_16bit(dev);
+        }
+
+        return (0);
+}
+
+static int smctr_init_acbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+        ACBlock *acb;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_acbs\n", dev->name);
+
+        acb                     = tp->acb_head;
+        acb->cmd_done_status    = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+        acb->cmd_info           = ACB_CHAIN_END;
+        acb->cmd                = 0;
+        acb->subcmd             = 0;
+        acb->data_offset_lo     = 0;
+        acb->data_offset_hi     = 0;
+        acb->next_ptr
+                = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+        acb->trc_next_ptr       = TRC_POINTER(acb->next_ptr);
+
+        for(i = 1; i < tp->num_acbs; i++)
+        {
+                acb             = acb->next_ptr;
+                acb->cmd_done_status
+                        = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+                acb->cmd_info = ACB_CHAIN_END;
+                acb->cmd        = 0;
+                acb->subcmd     = 0;
+                acb->data_offset_lo = 0;
+                acb->data_offset_hi = 0;
+                acb->next_ptr
+                        = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+                acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
+        }
+
+        acb->next_ptr           = tp->acb_head;
+        acb->trc_next_ptr       = TRC_POINTER(tp->acb_head);
+        tp->acb_next            = tp->acb_head->next_ptr;
+        tp->acb_curr            = tp->acb_head->next_ptr;
+        tp->num_acbs_used       = 0;
+
+        return (0);
+}
+
+static int smctr_init_adapter(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_adapter\n", dev->name);
+
+        tp->status              = CLOSED;
+        tp->page_offset_mask    = (tp->ram_usable * 1024) - 1;
+        skb_queue_head_init(&tp->SendSkbQueue);
+        tp->QueueSkb = MAX_TX_QUEUE;
+
+        if(!(tp->group_address_0 & 0x0080))
+                tp->group_address_0 |= 0x00C0;
+
+        if(!(tp->functional_address_0 & 0x00C0))
+                tp->functional_address_0 |= 0x00C0;
+
+        tp->functional_address[0] &= 0xFF7F;
+
+        if(tp->authorized_function_classes == 0)
+                tp->authorized_function_classes = 0x7FFF;
+
+        if(tp->authorized_access_priority == 0)
+                tp->authorized_access_priority = 0x06;
+
+        smctr_disable_bic_int(dev);
+        smctr_set_trc_reset(dev->base_addr);
+
+        /* By default the adapter will operate in 16-bit mode only. If
+         * there are two or more adapters in a box, switching between
+         * 16-bit and 8-bit mode may cause problems. In short the adapters
+         * will interfere with each other. XXX - smc.
+         */
+        smctr_disable_adapter_ram(dev);
+        if((err = smctr_rom_conflict_test(dev)))
+                return (err);
+
+        if((err = smctr_ram_conflict_test(dev)))
+                return (err);
+
+        smctr_enable_adapter_ram(dev);
+        smctr_enable_16bit(dev);
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        if(smctr_checksum_firmware(dev))
+                return (UCODE_NOT_PRESENT);
+
+        if((err = smctr_ram_memory_test(dev)))
+                return (err);
+
+        smctr_enable_16bit(dev);
+        if(smctr_checksum_firmware(dev))
+                return (-1);
+
+        if((err = smctr_ram_memory_test(dev)))
+                return (-1);
+
+        smctr_set_rx_look_ahead(dev);
+        smctr_load_node_addr(dev);
+
+        /* Initialize adapter for Internal Self Test. */
+        smctr_reset_adapter(dev);
+
+        if((err = smctr_init_card_real(dev)))
+                return (err);
+
+        /* This routine clobbers the TRC's internal registers. */
+        if((err = smctr_internal_self_test(dev)))
+                return (err);
+
+        /* Re-Initialize adapter's internal registers */
+        smctr_reset_adapter(dev);
+
+        if((err = smctr_init_card_real(dev)))
+                return (err);
+
+        smctr_enable_bic_int(dev);
+
+        if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+                return (err);
+
+        smctr_disable_16bit(dev);
+
+        return (0);
+}
+
+/* Dummy function */
+static int __init smctr_init_card(struct net_device *dev)
+{
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_card\n", dev->name);
+
+        return (0);
+}
+
+static int smctr_init_card_real(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_card_real\n", dev->name);
+
+        tp->sh_mem_used = 0;
+        tp->num_acbs    = NUM_OF_ACBS;
+
+        /* Range Check Max Packet Size */
+        if(tp->max_packet_size < 256)
+                tp->max_packet_size = 256;
+        else
+        {
+                if(tp->max_packet_size > NON_MAC_TX_BUFFER_MEMORY)
+                        tp->max_packet_size = NON_MAC_TX_BUFFER_MEMORY;
+        }
+
+        tp->num_of_tx_buffs = (NON_MAC_TX_BUFFER_MEMORY
+                / tp->max_packet_size) - 1;
+
+        if(tp->num_of_tx_buffs > NUM_NON_MAC_TX_FCBS)
+                tp->num_of_tx_buffs = NUM_NON_MAC_TX_FCBS;
+        else
+        {
+                if(tp->num_of_tx_buffs == 0)
+                        tp->num_of_tx_buffs = 1;
+        }
+
+        /* Tx queue constants */
+        tp->num_tx_fcbs        [BUG_QUEUE]     = NUM_BUG_TX_FCBS;
+        tp->num_tx_bdbs        [BUG_QUEUE]     = NUM_BUG_TX_BDBS;
+        tp->tx_buff_size       [BUG_QUEUE]     = BUG_TX_BUFFER_MEMORY;
+        tp->tx_buff_used       [BUG_QUEUE]     = 0;
+        tp->tx_queue_status    [BUG_QUEUE]     = NOT_TRANSMITING;
+
+        tp->num_tx_fcbs        [MAC_QUEUE]     = NUM_MAC_TX_FCBS;
+        tp->num_tx_bdbs        [MAC_QUEUE]     = NUM_MAC_TX_BDBS;
+        tp->tx_buff_size       [MAC_QUEUE]     = MAC_TX_BUFFER_MEMORY;
+        tp->tx_buff_used       [MAC_QUEUE]     = 0;
+        tp->tx_queue_status    [MAC_QUEUE]     = NOT_TRANSMITING;
+
+        tp->num_tx_fcbs        [NON_MAC_QUEUE] = NUM_NON_MAC_TX_FCBS;
+        tp->num_tx_bdbs        [NON_MAC_QUEUE] = NUM_NON_MAC_TX_BDBS;
+        tp->tx_buff_size       [NON_MAC_QUEUE] = NON_MAC_TX_BUFFER_MEMORY;
+        tp->tx_buff_used       [NON_MAC_QUEUE] = 0;
+        tp->tx_queue_status    [NON_MAC_QUEUE] = NOT_TRANSMITING;
+
+        /* Receive Queue Constants */
+        tp->num_rx_fcbs[MAC_QUEUE] = NUM_MAC_RX_FCBS;
+        tp->num_rx_bdbs[MAC_QUEUE] = NUM_MAC_RX_BDBS;
+
+        if(tp->extra_info & CHIP_REV_MASK)
+                tp->num_rx_fcbs[NON_MAC_QUEUE] = 78;    /* 825 Rev. XE */
+        else
+                tp->num_rx_fcbs[NON_MAC_QUEUE] = 7;     /* 825 Rev. XD */
+
+        tp->num_rx_bdbs[NON_MAC_QUEUE] = smctr_get_num_rx_bdbs(dev);
+
+        smctr_alloc_shared_memory(dev);
+        smctr_init_shared_memory(dev);
+
+        if((err = smctr_issue_init_timers_cmd(dev)))
+                return (err);
+
+        if((err = smctr_issue_init_txrx_cmd(dev)))
+                return (err);
+
+        return (0);
+}
+
+static int smctr_init_rx_bdbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, j;
+        BDBlock *bdb;
+        __u16 *buf;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_rx_bdbs\n", dev->name);
+
+        for(i = 0; i < NUM_RX_QS_USED; i++)
+        {
+                bdb = tp->rx_bdb_head[i];
+                buf = tp->rx_buff_head[i];
+                bdb->info = (BDB_CHAIN_END | BDB_NO_WARNING);
+                bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+                bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+                bdb->data_block_ptr = buf;
+                bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+                if(i == NON_MAC_QUEUE)
+                        bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+                else
+                        bdb->trc_data_block_ptr = TRC_POINTER(buf);
+
+                for(j = 1; j < tp->num_rx_bdbs[i]; j++)
+                {
+                        bdb->next_ptr->back_ptr = bdb;
+                        bdb = bdb->next_ptr;
+                        buf = (__u16 *)((char *)buf + RX_DATA_BUFFER_SIZE);
+                        bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+                        bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+                        bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+                        bdb->data_block_ptr = buf;
+                        bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+                        if(i == NON_MAC_QUEUE)
+                                bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+                        else
+                                bdb->trc_data_block_ptr = TRC_POINTER(buf);
+                }
+
+                bdb->next_ptr           = tp->rx_bdb_head[i];
+                bdb->trc_next_ptr       = TRC_POINTER(tp->rx_bdb_head[i]);
+
+                tp->rx_bdb_head[i]->back_ptr    = bdb;
+                tp->rx_bdb_curr[i]              = tp->rx_bdb_head[i]->next_ptr;
+        }
+
+        return (0);
+}
+
+static int smctr_init_rx_fcbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, j;
+        FCBlock *fcb;
+
+        for(i = 0; i < NUM_RX_QS_USED; i++)
+        {
+                fcb               = tp->rx_fcb_head[i];
+                fcb->frame_status = 0;
+                fcb->frame_length = 0;
+                fcb->info         = FCB_CHAIN_END;
+                fcb->next_ptr     = (FCBlock *)(((char*)fcb) + sizeof(FCBlock));
+                if(i == NON_MAC_QUEUE)
+                        fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+                else
+                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+                for(j = 1; j < tp->num_rx_fcbs[i]; j++)
+                {
+                        fcb->next_ptr->back_ptr = fcb;
+                        fcb                     = fcb->next_ptr;
+                        fcb->frame_status       = 0;
+                        fcb->frame_length       = 0;
+                        fcb->info               = FCB_WARNING;
+                        fcb->next_ptr
+                                = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+
+                        if(i == NON_MAC_QUEUE)
+                                fcb->trc_next_ptr
+                                        = RX_FCB_TRC_POINTER(fcb->next_ptr);
+                        else
+                                fcb->trc_next_ptr
+                                        = TRC_POINTER(fcb->next_ptr);
+                }
+
+                fcb->next_ptr = tp->rx_fcb_head[i];
+
+                if(i == NON_MAC_QUEUE)
+                        fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+                else
+                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+                tp->rx_fcb_head[i]->back_ptr    = fcb;
+                tp->rx_fcb_curr[i]              = tp->rx_fcb_head[i]->next_ptr;
+        }
+
+        return(0);
+}
+
+static int smctr_init_shared_memory(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+        __u32 *iscpb;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_init_shared_memory\n", dev->name);
+
+        smctr_set_page(dev, (__u8 *)(unsigned int)tp->iscpb_ptr);
+
+        /* Initialize Initial System Configuration Point. (ISCP) */
+        iscpb = (__u32 *)PAGE_POINTER(&tp->iscpb_ptr->trc_scgb_ptr);
+        *iscpb = (__u32)(SWAP_WORDS(TRC_POINTER(tp->scgb_ptr)));
+
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        /* Initialize System Configuration Pointers. (SCP) */
+        tp->scgb_ptr->config = (SCGB_ADDRESS_POINTER_FORMAT
+                | SCGB_MULTI_WORD_CONTROL | SCGB_DATA_FORMAT
+                | SCGB_BURST_LENGTH);
+
+        tp->scgb_ptr->trc_sclb_ptr      = TRC_POINTER(tp->sclb_ptr);
+        tp->scgb_ptr->trc_acb_ptr       = TRC_POINTER(tp->acb_head);
+        tp->scgb_ptr->trc_isb_ptr       = TRC_POINTER(tp->isb_ptr);
+        tp->scgb_ptr->isbsiz            = (sizeof(ISBlock)) - 2;
+
+        /* Initialize System Control Block. (SCB) */
+        tp->sclb_ptr->valid_command    = SCLB_VALID | SCLB_CMD_NOP;
+        tp->sclb_ptr->iack_code        = 0;
+        tp->sclb_ptr->resume_control   = 0;
+        tp->sclb_ptr->int_mask_control = 0;
+        tp->sclb_ptr->int_mask_state   = 0;
+
+        /* Initialize Interrupt Status Block. (ISB) */
+        for(i = 0; i < NUM_OF_INTERRUPTS; i++)
+        {
+                tp->isb_ptr->IStatus[i].IType = 0xf0;
+                tp->isb_ptr->IStatus[i].ISubtype = 0;
+        }
+
+        tp->current_isb_index = 0;
+
+        /* Initialize Action Command Block. (ACB) */
+        smctr_init_acbs(dev);
+
+        /* Initialize transmit FCB's and BDB's. */
+        smctr_link_tx_fcbs_to_bdbs(dev);
+        smctr_init_tx_bdbs(dev);
+        smctr_init_tx_fcbs(dev);
+
+        /* Initialize receive FCB's and BDB's. */
+        smctr_init_rx_bdbs(dev);
+        smctr_init_rx_fcbs(dev);
+
+        return (0);
+}
+
+static int smctr_init_tx_bdbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, j;
+        BDBlock *bdb;
+
+        for(i = 0; i < NUM_TX_QS_USED; i++)
+        {
+                bdb = tp->tx_bdb_head[i];
+                bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+                bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+                bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+                for(j = 1; j < tp->num_tx_bdbs[i]; j++)
+                {
+                        bdb->next_ptr->back_ptr = bdb;
+                        bdb = bdb->next_ptr;
+                        bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+                        bdb->next_ptr
+                                = (BDBlock *)(((char *)bdb) + sizeof( BDBlock));                        bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+                }
+
+                bdb->next_ptr = tp->tx_bdb_head[i];
+                bdb->trc_next_ptr = TRC_POINTER(tp->tx_bdb_head[i]);
+                tp->tx_bdb_head[i]->back_ptr = bdb;
+        }
+
+        return (0);
+}
+
+static int smctr_init_tx_fcbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, j;
+        FCBlock *fcb;
+
+        for(i = 0; i < NUM_TX_QS_USED; i++)
+        {
+                fcb               = tp->tx_fcb_head[i];
+                fcb->frame_status = 0;
+                fcb->frame_length = 0;
+                fcb->info         = FCB_CHAIN_END;
+                fcb->next_ptr = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+                fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+                for(j = 1; j < tp->num_tx_fcbs[i]; j++)
+                {
+                        fcb->next_ptr->back_ptr = fcb;
+                        fcb                     = fcb->next_ptr;
+                        fcb->frame_status       = 0;
+                        fcb->frame_length       = 0;
+                        fcb->info               = FCB_CHAIN_END;
+                        fcb->next_ptr
+                                = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+                }
+
+                fcb->next_ptr           = tp->tx_fcb_head[i];
+                fcb->trc_next_ptr       = TRC_POINTER(tp->tx_fcb_head[i]);
+
+                tp->tx_fcb_head[i]->back_ptr    = fcb;
+                tp->tx_fcb_end[i]               = tp->tx_fcb_head[i]->next_ptr;
+                tp->tx_fcb_curr[i]              = tp->tx_fcb_head[i]->next_ptr;
+                tp->num_tx_fcbs_used[i]         = 0;
+        }
+
+        return (0);
+}
+
+static int smctr_internal_self_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if((err = smctr_issue_test_internal_rom_cmd(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        if(tp->acb_head->cmd_done_status & 0xff)
+                return (-1);
+
+        if((err = smctr_issue_test_hic_cmd(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        if(tp->acb_head->cmd_done_status & 0xff)
+                return (-1);
+
+        if((err = smctr_issue_test_mac_reg_cmd(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        if(tp->acb_head->cmd_done_status & 0xff)
+                return (-1);
+
+        return (0);
+}
+
+/*
+ * The typical workload of the driver: Handle the network interface interrupts.
+ */
+static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        struct net_device *dev = dev_id;
+        struct net_local *tp;
+        int ioaddr;
+        __u16 interrupt_unmask_bits = 0, interrupt_ack_code = 0xff00;
+        __u16 err1, err = NOT_MY_INTERRUPT;
+        __u8 isb_type, isb_subtype;
+        __u16 isb_index;
+
+        if(dev == NULL)
+        {
+                printk("%s: irq %d for unknown device.\n", dev->name, irq);
+                return;
+        }
+
+        dev->interrupt = 1;
+
+        ioaddr = dev->base_addr;
+        tp = (struct net_local *)dev->priv;
+
+        dev->interrupt = 0;
+
+        if(tp->status == NOT_INITIALIZED)
+                return;
+
+        smctr_disable_bic_int(dev);
+        smctr_enable_16bit(dev);
+
+        smctr_clear_int(dev);
+
+        /* First read the LSB */
+        while((tp->isb_ptr->IStatus[tp->current_isb_index].IType & 0xf0) == 0)
+        {
+                isb_index       = tp->current_isb_index;
+                isb_type        = tp->isb_ptr->IStatus[isb_index].IType;
+                isb_subtype     = tp->isb_ptr->IStatus[isb_index].ISubtype;
+
+                (tp->current_isb_index)++;
+                if(tp->current_isb_index == NUM_OF_INTERRUPTS)
+                        tp->current_isb_index = 0;
+
+                if(isb_type >= 0x10)
+                {
+                        smctr_disable_16bit(dev);
+                        return;
+                }
+
+                err = HARDWARE_FAILED;
+                interrupt_ack_code = isb_index;
+                tp->isb_ptr->IStatus[isb_index].IType |= 0xf0;
+
+                interrupt_unmask_bits |= (1 << (__u16)isb_type);
+
+                switch(isb_type)
+                {
+                        case ISB_IMC_MAC_TYPE_3:
+                                smctr_disable_16bit(dev);
+
+                                switch(isb_subtype)
+                                {
+                                        case 0:
+                                                tp->monitor_state
+                                                = MS_MONITOR_FSM_INACTIVE;
+                                                break;
+
+                                        case 1:
+                                                tp->monitor_state
+                                                = MS_REPEAT_BEACON_STATE;
+                                                break;
+
+                                        case 2:
+                                                tp->monitor_state
+                                                = MS_REPEAT_CLAIM_TOKEN_STATE;
+                                                break;
+
+                                        case 3:
+                                                tp->monitor_state
+                                                = MS_TRANSMIT_CLAIM_TOKEN_STATE;                                                break;
+
+                                        case 4:
+                                                tp->monitor_state
+                                                = MS_STANDBY_MONITOR_STATE;
+                                                break;
+
+                                        case 5:
+                                                tp->monitor_state
+                                                = MS_TRANSMIT_BEACON_STATE;
+                                                break;
+
+                                        case 6:
+                                                tp->monitor_state
+                                                = MS_ACTIVE_MONITOR_STATE;
+                                                break;
+
+                                        case 7:
+                                                tp->monitor_state
+                                                = MS_TRANSMIT_RING_PURGE_STATE;
+                                                break;
+
+                                        case 8:   /* diagnostic state */
+                                                break;
+
+                                        case 9:
+                                                tp->monitor_state
+                                                = MS_BEACON_TEST_STATE;
+                                                if(smctr_lobe_media_test(dev))
+                                                {
+                                                        tp->ring_status_flags
+                                                        = RING_STATUS_CHANGED;
+                                                        tp->ring_status
+                                                        = AUTO_REMOVAL_ERROR;
+                                                        smctr_ring_status_chg(dev);
+                                                        smctr_bypass_state(dev);
+                                                }
+                                                else
+                                                        smctr_issue_insert_cmd(dev);
+                                                break;
+
+                                        /* case 0x0a-0xff, illegal states */
+                                        default:
+                                                break;
+                                }
+
+                                tp->ring_status_flags = MONITOR_STATE_CHANGED;
+                                err = smctr_ring_status_chg(dev);
+
+                                smctr_enable_16bit(dev);
+                                break;
+
+                        /* Type 0x02 - MAC Error Counters Interrupt
+                         * One or more MAC Error Counter is half full
+                         *      MAC Error Counters
+                         *      Lost_FR_Error_Counter
+                         *      RCV_Congestion_Counter
+                         *      FR_copied_Error_Counter
+                         *      FREQ_Error_Counter
+                         *      Token_Error_Counter
+                         *      Line_Error_Counter
+                         *      Internal_Error_Count
+                         */
+                        case ISB_IMC_MAC_ERROR_COUNTERS:
+                                /* Read 802.5 Error Counters */
+                                err = smctr_issue_read_ring_status_cmd(dev);
+                                break;
+
+                        /* Type 0x04 - MAC Type 2 Interrupt
+                         * HOST needs to enqueue MAC Frame for transmission
+                         * SubType Bit 15 - RQ_INIT_PDU( Request Initialization)                         * Changed from RQ_INIT_PDU to
+                         * TRC_Status_Changed_Indicate
+                         */
+                        case ISB_IMC_MAC_TYPE_2:
+                                err = smctr_issue_read_ring_status_cmd(dev);
+                                break;
+
+
+                        /* Type 0x05 - TX Frame Interrupt (FI). */
+                        case ISB_IMC_TX_FRAME:
+                                /* BUG QUEUE for TRC stuck receive BUG */
+                                if(isb_subtype & TX_PENDING_PRIORITY_2)
+                                {
+                                        if((err = smctr_tx_complete(dev,
+                                                BUG_QUEUE)) != SUCCESS)
+                                                break;
+                                }
+
+                                /* NON-MAC frames only */
+                                if(isb_subtype & TX_PENDING_PRIORITY_1)
+                                {
+                                        if((err = smctr_tx_complete(dev,
+                                                NON_MAC_QUEUE)) != SUCCESS)
+                                                break;
+                                }
+
+                                /* MAC frames only */
+                                if(isb_subtype & TX_PENDING_PRIORITY_0)
+                                        err = smctr_tx_complete(dev, MAC_QUEUE);                                break;
+
+                        /* Type 0x06 - TX END OF QUEUE (FE) */
+                        case ISB_IMC_END_OF_TX_QUEUE:
+                                /* BUG queue */
+                                if(isb_subtype & TX_PENDING_PRIORITY_2)
+                                {
+                                        /* ok to clear Receive FIFO overrun
+                                         * imask send_BUG now completes.
+                                         */
+                                        interrupt_unmask_bits |= 0x800;
+
+                                        tp->tx_queue_status[BUG_QUEUE]
+                                                = NOT_TRANSMITING;
+                                        if((err = smctr_tx_complete(dev,
+                                                BUG_QUEUE)) != SUCCESS)
+                                                break;
+                                        if((err = smctr_restart_tx_chain(dev,
+                                                BUG_QUEUE)) != SUCCESS)
+                                                break;
+                                }
+
+                                /* NON-MAC queue only */
+                                if(isb_subtype & TX_PENDING_PRIORITY_1)
+                                {
+                                        tp->tx_queue_status[NON_MAC_QUEUE]
+                                                = NOT_TRANSMITING;
+                                        if((err = smctr_tx_complete(dev,
+                                                NON_MAC_QUEUE)) != SUCCESS)
+                                                break;
+                                        if((err = smctr_restart_tx_chain(dev,
+                                                NON_MAC_QUEUE)) != SUCCESS)
+                                                break;
+                                }
+
+                                /* MAC queue only */
+                                if(isb_subtype & TX_PENDING_PRIORITY_0)
+                                {
+                                        tp->tx_queue_status[MAC_QUEUE]
+                                                = NOT_TRANSMITING;
+                                        if((err = smctr_tx_complete(dev,
+                                                MAC_QUEUE)) != SUCCESS)
+                                                break;
+
+                                        err = smctr_restart_tx_chain(dev,
+                                                MAC_QUEUE);
+                                }
+                                break;
+
+                        /* Type 0x07 - NON-MAC RX Resource Interrupt
+                         *   Subtype bit 12 - (BW) BDB warning
+                         *   Subtype bit 13 - (FW) FCB warning
+                         *   Subtype bit 14 - (BE) BDB End of chain
+                         *   Subtype bit 15 - (FE) FCB End of chain
+                         */
+                        case ISB_IMC_NON_MAC_RX_RESOURCE:
+                                tp->rx_fifo_overrun_count = 0;
+                                tp->receive_queue_number = NON_MAC_QUEUE;
+                                err1 = smctr_rx_frame(dev);
+
+                                if(isb_subtype & NON_MAC_RX_RESOURCE_FE)
+                                {
+                                        if((err = smctr_issue_resume_rx_fcb_cmd(                                                dev, NON_MAC_QUEUE)) != SUCCESS)                                                break;
+
+                                        if(tp->ptr_rx_fcb_overruns)
+                                                (*tp->ptr_rx_fcb_overruns)++;
+                                }
+
+                                if(isb_subtype & NON_MAC_RX_RESOURCE_BE)
+                                {
+                                        if((err = smctr_issue_resume_rx_bdb_cmd(                                                dev, NON_MAC_QUEUE)) != SUCCESS)                                                break;
+
+                                        if(tp->ptr_rx_bdb_overruns)
+                                                (*tp->ptr_rx_bdb_overruns)++;
+                                }
+                                err = err1;
+                                break;
+
+                        /* Type 0x08 - MAC RX Resource Interrupt
+                         *   Subtype bit 12 - (BW) BDB warning
+                         *   Subtype bit 13 - (FW) FCB warning
+                         *   Subtype bit 14 - (BE) BDB End of chain
+                         *   Subtype bit 15 - (FE) FCB End of chain
+                         */
+                        case ISB_IMC_MAC_RX_RESOURCE:
+                                tp->receive_queue_number = MAC_QUEUE;
+                                err1 = smctr_rx_frame(dev);
+
+                                if(isb_subtype & MAC_RX_RESOURCE_FE)
+                                {
+                                        if((err = smctr_issue_resume_rx_fcb_cmd(                                                dev, MAC_QUEUE)) != SUCCESS)
+                                                break;
+
+                                        if(tp->ptr_rx_fcb_overruns)
+                                                (*tp->ptr_rx_fcb_overruns)++;
+                                }
+
+                                if(isb_subtype & MAC_RX_RESOURCE_BE)
+                                {
+                                        if((err = smctr_issue_resume_rx_bdb_cmd(                                                dev, MAC_QUEUE)) != SUCCESS)
+                                                break;
+
+                                        if(tp->ptr_rx_bdb_overruns)
+                                                (*tp->ptr_rx_bdb_overruns)++;
+                                }
+                                err = err1;
+                                break;
+
+                        /* Type 0x09 - NON_MAC RX Frame Interrupt */
+                        case ISB_IMC_NON_MAC_RX_FRAME:
+                                tp->rx_fifo_overrun_count = 0;
+                                tp->receive_queue_number = NON_MAC_QUEUE;
+                                err = smctr_rx_frame(dev);
+                                break;
+
+                        /* Type 0x0A - MAC RX Frame Interrupt */
+                        case ISB_IMC_MAC_RX_FRAME:
+                                tp->receive_queue_number = MAC_QUEUE;
+                                err = smctr_rx_frame(dev);
+                                break;
+
+                        /* Type 0x0B - TRC status
+                         * TRC has encountered an error condition
+                         * subtype bit 14 - transmit FIFO underrun
+                         * subtype bit 15 - receive FIFO overrun
+                         */
+                        case ISB_IMC_TRC_FIFO_STATUS:
+                                if(isb_subtype & TRC_FIFO_STATUS_TX_UNDERRUN)
+                                {
+                                        if(tp->ptr_tx_fifo_underruns)
+                                                (*tp->ptr_tx_fifo_underruns)++;
+                                }
+
+                                if(isb_subtype & TRC_FIFO_STATUS_RX_OVERRUN)
+                                {
+                                        /* update overrun stuck receive counter
+                                         * if >= 3, has to clear it by sending
+                                         * back to back frames. We pick
+                                         * DAT(duplicate address MAC frame)
+                                         */
+                                        tp->rx_fifo_overrun_count++;
+
+                                        if(tp->rx_fifo_overrun_count >= 3)
+                                        {
+                                                tp->rx_fifo_overrun_count = 0;
+
+                                                /* delay clearing fifo overrun
+                                                 * imask till send_BUG tx
+                                                 * complete posted
+                                                 */
+                                                interrupt_unmask_bits &= (~0x800);
+                                                printk("Jay please send bug\n");//                                              smctr_send_bug(dev);
+                                        }
+
+                                        if(tp->ptr_rx_fifo_overruns)
+                                                (*tp->ptr_rx_fifo_overruns)++;
+                                }
+
+                                err = SUCCESS;
+                                break;
+
+                        /* Type 0x0C - Action Command Status Interrupt
+                         * Subtype bit 14 - CB end of command chain (CE)
+                         * Subtype bit 15 - CB command interrupt (CI)
+                         */
+                        case ISB_IMC_COMMAND_STATUS:
+                                err = SUCCESS;
+                                if(tp->acb_head->cmd == ACB_CMD_HIC_NOP)
+                                {
+                                        printk("i1\n");
+                                        smctr_disable_16bit(dev);
+
+                                        /* XXXXXXXXXXXXXXXXX */
+                                /*      err = UM_Interrupt(dev); */
+
+                                        smctr_enable_16bit(dev);
+                                }
+                                else
+                                {
+                                        if((tp->acb_head->cmd
+                                                == ACB_CMD_READ_TRC_STATUS)
+                                                && (tp->acb_head->subcmd
+                                                == RW_TRC_STATUS_BLOCK))
+                                        {
+                                                if(tp->ptr_bcn_type != 0)
+                                                {
+                                                        *(tp->ptr_bcn_type)
+                                                                = (__u32)((SBlock *)tp->misc_command_data)->BCN_Type;
+                                                }
+
+                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & ERROR_COUNTERS_CHANGED)
+                                                {
+                                                        smctr_update_err_stats(dev);
+                                                }
+
+                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & TI_NDIS_RING_STATUS_CHANGED)
+                                                {
+                                                        tp->ring_status
+                                                                = ((SBlock*)tp->misc_command_data)->TI_NDIS_Ring_Status;
+                                                        smctr_disable_16bit(dev);
+                                                        err = smctr_ring_status_chg(dev);
+                                                        smctr_enable_16bit(dev);
+                                                        if((tp->ring_status & REMOVE_RECEIVED)
+                                                                && (tp->config_word0 & NO_AUTOREMOVE))
+                                                        {
+                                                                smctr_issue_remove_cmd(dev);
+                                                        }
+
+                                                        if(err != SUCCESS)
+                                                        {
+                                                                tp->acb_pending
+= 0;
+                                                                break;
+                                                        }
+                                                }
+
+                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & UNA_CHANGED)
+                                                {
+                                                        if(tp->ptr_una)
+                                                        {
+                                                                tp->ptr_una[0]
+                                                                        = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[0]);
+                                                                tp->ptr_una[1]
+                                                                        = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[1]);
+                                                                tp->ptr_una[2]
+                                                                        = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[2]);
+                                                        }
+
+                                                }
+
+                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate
+                                                        & READY_TO_SEND_RQ_INIT)                                                {
+                                                        err = smctr_send_rq_init(dev);
+                                                }
+                                        }
+                                }
+
+                                tp->acb_pending = 0;
+                                break;
+
+                        /* Type 0x0D - MAC Type 1 interrupt
+                         * Subtype -- 00 FR_BCN received at S12
+                         *            01 FR_BCN received at S21
+                         *            02 FR_DAT(DA=MA, A<>0) received at S21
+                         *            03 TSM_EXP at S21
+                         *            04 FR_REMOVE received at S42
+                         *            05 TBR_EXP, BR_FLAG_SET at S42
+                         *            06 TBT_EXP at S53
+                         */
+                        case ISB_IMC_MAC_TYPE_1:
+                                if(isb_subtype > 8)
+                                {
+                                        err = HARDWARE_FAILED;
+                                        break;
+                                }
+
+                                err = SUCCESS;
+                                switch(isb_subtype)
+                                {
+                                        case 0:
+                                                tp->join_state = JS_BYPASS_STATE;
+                                                if(tp->status != CLOSED)
+                                                {
+                                                        tp->status = CLOSED;
+                                                        err = smctr_status_chg(dev);
+                                                }
+                                                break;
+
+                                        case 1:
+                                                tp->join_state
+                                                        = JS_LOBE_TEST_STATE;
+                                                break;
+
+                                        case 2:
+                                                tp->join_state
+                                                        = JS_DETECT_MONITOR_PRESENT_STATE;
+                                                break;
+
+                                        case 3:
+                                                tp->join_state
+                                                        = JS_AWAIT_NEW_MONITOR_STATE;
+                                                break;
+
+                                        case 4:
+                                                tp->join_state
+                                                        = JS_DUPLICATE_ADDRESS_TEST_STATE;
+                                                break;
+
+                                        case 5:
+                                                tp->join_state
+                                                        = JS_NEIGHBOR_NOTIFICATION_STATE;
+                                                break;
+
+                                        case 6:
+                                                tp->join_state
+                                                        = JS_REQUEST_INITIALIZATION_STATE;
+                                                break;
+
+                                        case 7:
+                                                tp->join_state
+                                                        = JS_JOIN_COMPLETE_STATE;
+                                                tp->status = OPEN;
+                                                err = smctr_status_chg(dev);
+                                                break;
+
+                                        case 8:
+                                                tp->join_state
+                                                        = JS_BYPASS_WAIT_STATE;
+                                                break;
+                                }
+                                break ;
+
+                        /* Type 0x0E - TRC Initialization Sequence Interrupt
+                         * Subtype -- 00-FF Initializatin sequence complete
+                         */
+                        case ISB_IMC_TRC_INTRNL_TST_STATUS:
+                                tp->status = INITIALIZED;
+                                smctr_disable_16bit(dev);
+                                err = smctr_status_chg(dev);
+                                smctr_enable_16bit(dev);
+                                break;
+
+                        /* other interrupt types, illegal */
+                        default:
+                                break;
+                }
+
+                if(err != SUCCESS)
+                        break;
+        }
+
+        /* Checking the ack code instead of the unmask bits here is because :
+         * while fixing the stuck receive, DAT frame are sent and mask off
+         * FIFO overrun interrupt temporarily (interrupt_unmask_bits = 0)
+         * but we still want to issue ack to ISB
+         */
+        if(!(interrupt_ack_code & 0xff00))
+                smctr_issue_int_ack(dev, interrupt_ack_code,
+                        interrupt_unmask_bits);
+
+        smctr_disable_16bit(dev);
+        smctr_enable_bic_int(dev);
+
+        return;
+}
+
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+        __u16 interrupt_enable_mask)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        tp->sclb_ptr->int_mask_control  = interrupt_enable_mask;
+        tp->sclb_ptr->valid_command     = SCLB_VALID
+                | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
+        __u16 ibits)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_wait_while_cbusy(dev))
+                return (-1);
+
+        tp->sclb_ptr->int_mask_control = ibits;
+        tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */        tp->sclb_ptr->resume_control = 0;
+        tp->sclb_ptr->valid_command =
+                SCLB_VALID | SCLB_IACK_CODE_VALID
+                | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_init_timers_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+        int err;
+        __u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
+        tp->config_word1 = 0;
+
+        if((tp->media_type == MEDIA_STP_16)
+                || (tp->media_type == MEDIA_UTP_16)
+                || (tp->media_type == MEDIA_STP_16_UTP_16))
+        {
+                tp->config_word0 |= FREQ_16MB_BIT;
+        }
+
+        if(tp->mode_bits & EARLY_TOKEN_REL)
+                tp->config_word0 |= ETREN;
+
+        if(tp->mode_bits & LOOPING_MODE_MASK)
+                tp->config_word0 |= RX_OWN_BIT;
+        else
+                tp->config_word0 &= ~RX_OWN_BIT;
+
+        if(tp->receive_mask & PROMISCUOUS_MODE)
+                tp->config_word0 |= PROMISCUOUS_BIT;
+        else
+                tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+        if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+                tp->config_word0 |= SAVBAD_BIT;
+        else
+                tp->config_word0 &= ~SAVBAD_BIT;
+
+        if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+                tp->config_word0 |= RXATMAC;
+        else
+                tp->config_word0 &= ~RXATMAC;
+
+        if(tp->receive_mask & ACCEPT_MULTI_PROM)
+                tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+        else
+                tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+        if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+                tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+        else
+        {
+                if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+                        tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+                else
+                        tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+        }
+
+        if((tp->media_type == MEDIA_STP_16)
+                || (tp->media_type == MEDIA_UTP_16)
+                || (tp->media_type == MEDIA_STP_16_UTP_16))
+        {
+                tp->config_word1 |= INTERFRAME_SPACING_16;
+        }
+        else
+                tp->config_word1 |= INTERFRAME_SPACING_4;
+
+        *pTimer_Struc++ = tp->config_word0;
+        *pTimer_Struc++ = tp->config_word1;
+
+        if((tp->media_type == MEDIA_STP_4)
+                || (tp->media_type == MEDIA_UTP_4)
+                || (tp->media_type == MEDIA_STP_4_UTP_4))
+        {
+                *pTimer_Struc++ = 0x00FA;       /* prescale */
+                *pTimer_Struc++ = 0x2710;       /* TPT_limit */
+                *pTimer_Struc++ = 0x2710;       /* TQP_limit */
+                *pTimer_Struc++ = 0x0A28;       /* TNT_limit */
+                *pTimer_Struc++ = 0x3E80;       /* TBT_limit */
+                *pTimer_Struc++ = 0x3A98;       /* TSM_limit */
+                *pTimer_Struc++ = 0x1B58;       /* TAM_limit */
+                *pTimer_Struc++ = 0x00C8;       /* TBR_limit */
+                *pTimer_Struc++ = 0x07D0;       /* TER_limit */
+                *pTimer_Struc++ = 0x000A;       /* TGT_limit */
+                *pTimer_Struc++ = 0x1162;       /* THT_limit */
+                *pTimer_Struc++ = 0x07D0;       /* TRR_limit */
+                *pTimer_Struc++ = 0x1388;       /* TVX_limit */
+                *pTimer_Struc++ = 0x0000;       /* reserved */
+        }
+        else
+        {
+                *pTimer_Struc++ = 0x03E8;       /* prescale */
+                *pTimer_Struc++ = 0x9C40;       /* TPT_limit */
+                *pTimer_Struc++ = 0x9C40;       /* TQP_limit */
+                *pTimer_Struc++ = 0x0A28;       /* TNT_limit */
+                *pTimer_Struc++ = 0x3E80;       /* TBT_limit */
+                *pTimer_Struc++ = 0x3A98;       /* TSM_limit */
+                *pTimer_Struc++ = 0x1B58;       /* TAM_limit */
+                *pTimer_Struc++ = 0x00C8;       /* TBR_limit */
+                *pTimer_Struc++ = 0x07D0;       /* TER_limit */
+                *pTimer_Struc++ = 0x000A;       /* TGT_limit */
+                *pTimer_Struc++ = 0x4588;       /* THT_limit */
+                *pTimer_Struc++ = 0x1F40;       /* TRR_limit */
+                *pTimer_Struc++ = 0x4E20;       /* TVX_limit */
+                *pTimer_Struc++ = 0x0000;       /* reserved */
+        }
+
+        /* Set node address. */
+        *pTimer_Struc++ = dev->dev_addr[0] << 8
+                | (dev->dev_addr[1] & 0xFF);
+        *pTimer_Struc++ = dev->dev_addr[2] << 8
+                | (dev->dev_addr[3] & 0xFF);
+        *pTimer_Struc++ = dev->dev_addr[4] << 8
+                | (dev->dev_addr[5] & 0xFF);
+
+        /* Set group address. */
+        *pTimer_Struc++ = tp->group_address_0 << 8
+                | tp->group_address_0 >> 8;
+        *pTimer_Struc++ = tp->group_address[0] << 8
+                | tp->group_address[0] >> 8;
+        *pTimer_Struc++ = tp->group_address[1] << 8
+                | tp->group_address[1] >> 8;
+
+        /* Set functional address. */
+        *pTimer_Struc++ = tp->functional_address_0 << 8
+                | tp->functional_address_0 >> 8;
+        *pTimer_Struc++ = tp->functional_address[0] << 8
+                | tp->functional_address[0] >> 8;
+        *pTimer_Struc++ = tp->functional_address[1] << 8
+                | tp->functional_address[1] >> 8;
+
+        /* Set Bit-Wise group address. */
+        *pTimer_Struc++ = tp->bitwise_group_address[0] << 8
+                | tp->bitwise_group_address[0] >> 8;
+        *pTimer_Struc++ = tp->bitwise_group_address[1] << 8
+                | tp->bitwise_group_address[1] >> 8;
+
+        /* Set ring number address. */
+        *pTimer_Struc++ = tp->source_ring_number;
+        *pTimer_Struc++ = tp->target_ring_number;
+
+        /* Physical drop number. */
+        *pTimer_Struc++ = (unsigned short)0;
+        *pTimer_Struc++ = (unsigned short)0;
+
+        /* Product instance ID. */
+        for(i = 0; i < 9; i++)
+                *pTimer_Struc++ = (unsigned short)0;
+
+        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
+
+        return (err);
+}
+
+static int smctr_issue_init_txrx_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+        int err;
+        void **txrx_ptrs = (void *)tp->misc_command_data;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        /* Initialize Transmit Queue Pointers that are used, to point to
+         * a single FCB.
+         */
+        for(i = 0; i < NUM_TX_QS_USED; i++)
+                *txrx_ptrs++ = (void *)TRC_POINTER(tp->tx_fcb_head[i]);
+
+        /* Initialize Transmit Queue Pointers that are NOT used to ZERO. */
+        for(; i < MAX_TX_QS; i++)
+                *txrx_ptrs++ = (void *)0;
+
+        /* Initialize Receive Queue Pointers (MAC and Non-MAC) that are
+         * used, to point to a single FCB and a BDB chain of buffers.
+         */
+        for(i = 0; i < NUM_RX_QS_USED; i++)
+        {
+                *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_fcb_head[i]);
+                *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_bdb_head[i]);
+        }
+
+        /* Initialize Receive Queue Pointers that are NOT used to ZERO. */
+        for(; i < MAX_RX_QS; i++)
+        {
+                *txrx_ptrs++ = (void *)0;
+                *txrx_ptrs++ = (void *)0;
+        }
+
+        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
+
+        return (err);
+}
+
+static int smctr_issue_insert_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
+
+        return (err);
+}
+
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
+{
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
+                RW_TRC_STATUS_BLOCK);
+
+        return (err);
+}
+
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
+{
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
+                aword_cnt);
+
+        return (err);
+}
+
+static int smctr_issue_remove_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        tp->sclb_ptr->resume_control    = 0;
+        tp->sclb_ptr->valid_command     = SCLB_VALID | SCLB_CMD_REMOVE;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_resume_acb_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        tp->sclb_ptr->resume_control = SCLB_RC_ACB;
+        tp->sclb_ptr->valid_command  = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+        tp->acb_pending = 1;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if(queue == MAC_QUEUE)
+                tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
+        else
+                tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_BDB;
+
+        tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
+
+        if(smctr_wait_while_cbusy(dev))
+                return (-1);
+
+        if(queue == MAC_QUEUE)
+                tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
+        else
+                tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_FCB;
+
+        tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
+
+        if(smctr_wait_while_cbusy(dev))
+                return (-1);
+
+        tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
+        tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
+
+        smctr_set_ctrl_attention(dev);
+
+        return (0);
+}
+
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+                TRC_INTERNAL_ROM_TEST);
+
+        return (err);
+}
+
+static int smctr_issue_test_hic_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
+                TRC_HOST_INTERFACE_REG_TEST);
+
+        return (err);
+}
+
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+                TRC_MAC_REGISTERS_TEST);
+
+        return (err);
+}
+
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+                TRC_INTERNAL_LOOPBACK);
+
+        return (err);
+}
+
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+                TRC_TRI_LOOPBACK);
+
+        return (err);
+}
+
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+        short aword_cnt, void *byte)
+{
+	struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int iword, ibyte;
+	int err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
+        	iword++, ibyte += 2)
+        {
+                tp->misc_command_data[iword] = (*((__u8 *)byte + ibyte) << 8)
+			| (*((__u8 *)byte + ibyte + 1));
+        }
+
+        return (smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE, 
+		aword_cnt));
+}
+
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+        short aword_cnt, void *word)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, err;
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
+                tp->misc_command_data[i] = *((__u16 *)word + i);
+
+        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+                aword_cnt);
+
+        return (err);
+}
+
+static int smctr_join_complete_state(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+                JS_JOIN_COMPLETE_STATE);
+
+        return (err);
+}
+
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, j;
+        FCBlock *fcb;
+        BDBlock *bdb;
+
+        for(i = 0; i < NUM_TX_QS_USED; i++)
+        {
+                fcb = tp->tx_fcb_head[i];
+                bdb = tp->tx_bdb_head[i];
+
+                for(j = 0; j < tp->num_tx_fcbs[i]; j++)
+                {
+                        fcb->bdb_ptr            = bdb;
+                        fcb->trc_bdb_ptr        = TRC_POINTER(bdb);
+                        fcb = (FCBlock *)((char *)fcb + sizeof(FCBlock));
+                        bdb = (BDBlock *)((char *)bdb + sizeof(BDBlock));
+                }
+        }
+
+        return (0);
+}
+
+static int smctr_load_firmware(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 i, checksum = 0;
+        int err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_load_firmware\n", dev->name);
+
+        tp->ptr_ucode           = smctr_code;
+        tp->num_of_tx_buffs     = 4;
+        tp->mode_bits          |= UMAC;
+        tp->receive_mask        = 0;
+        tp->max_packet_size     = 4177;
+
+        /* Can only upload the firmware once per adapter reset. */
+        if(tp->microcode_version != 0)
+                return (UCODE_PRESENT);
+
+        /* Verify the firmware exists and is there in the right amount. */
+        if((tp->ptr_ucode == 0L)
+                || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET) < UCODE_VERSION))
+        {
+                return (UCODE_NOT_PRESENT);
+        }
+
+        /* UCODE_SIZE is not included in Checksum. */
+        for(i = 0; i < *((__u16 *)(tp->ptr_ucode + UCODE_SIZE_OFFSET)); i += 2)
+                checksum += *((__u16 *)(tp->ptr_ucode + 2 + i));
+        if(checksum)
+                return (UCODE_NOT_PRESENT);
+
+        /* At this point we have a valid firmware image, lets kick it on up. */
+        smctr_enable_adapter_ram(dev);
+        smctr_enable_16bit(dev);
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        if((smctr_checksum_firmware(dev))
+                || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET)
+                > tp->microcode_version))
+        {
+                smctr_enable_adapter_ctrl_store(dev);
+
+                /* Zero out ram space for firmware. */
+                for(i = 0; i < CS_RAM_SIZE; i += 2)
+                        *((__u16 *)(tp->ram_access + i)) = 0;
+
+                smctr_decode_firmware(dev);
+
+                tp->microcode_version = *(tp->ptr_ucode + UCODE_VERSION_OFFSET);                *((__u16 *)(tp->ram_access + CS_RAM_VERSION_OFFSET))
+                        = (tp->microcode_version << 8);
+                *((__u16 *)(tp->ram_access + CS_RAM_CHECKSUM_OFFSET))
+                        = ~(tp->microcode_version << 8) + 1;
+
+                smctr_disable_adapter_ctrl_store(dev);
+
+                if(smctr_checksum_firmware(dev))
+                        err = HARDWARE_FAILED;
+        }
+        else
+                err = UCODE_PRESENT;
+
+        smctr_disable_16bit(dev);
+
+        return (err);
+}
+
+static int smctr_load_node_addr(struct net_device *dev)
+{
+        int ioaddr = dev->base_addr;
+        unsigned int i;
+        __u8 r;
+
+        /* Check if node address has been specified by user. (non-0) */
+        for(i = 0; ((i < 6) && (dev->dev_addr[i] == 0)); i++);
+        {
+                if(i != 6)
+                {
+                        for(i = 0; i < 6; i++)
+                        {
+                                r = inb(ioaddr + LAR0 + i);
+                                dev->dev_addr[i] = (char)r;
+                        }
+                        dev->addr_len = 6;
+                }
+                else    /* Node addr. not given by user, read it from board. */
+                {
+                        for(i = 0; i < 6; i++)
+                        {
+                                r = inb(ioaddr + LAR0 + i);
+                                dev->dev_addr[i] = (char)r;
+                        }
+                        dev->addr_len = 6;
+                }
+        }
+
+        return (0);
+}
+
+/* Lobe Media Test.
+ * During the transmission of the initial 1500 lobe media MAC frames,
+ * the phase lock loop in the 805 chip may lock, and then un-lock, causing
+ * the 825 to go into a PURGE state. When performing a PURGE, the MCT
+ * microcode will not transmit any frames given to it by the host, and
+ * will consequently cause a timeout.
+ *
+ * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit
+ * queues other then the one used for the lobe_media_test should be
+ * disabled.!?
+ *
+ * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
+ * has any multi-cast or promiscous bits set, the receive_mask needs to
+ * be changed to clear the multi-cast or promiscous mode bits, the lobe_test
+ * run, and then the receive mask set back to its original value if the test
+ * is successful.
+ */
+static int smctr_lobe_media_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, perror = 0;
+        unsigned short saved_rcv_mask;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_lobe_media_test\n", dev->name);
+
+        /* Clear receive mask for lobe test. */
+        saved_rcv_mask          = tp->receive_mask;
+        tp->receive_mask        = 0;
+
+        smctr_chg_rx_mask(dev);
+
+        /* Setup the lobe media test. */
+        smctr_lobe_media_test_cmd(dev);
+        if(smctr_wait_cmd(dev))
+        {
+                smctr_reset_adapter(dev);
+                tp->status = CLOSED;
+                return (LOBE_MEDIA_TEST_FAILED);
+        }
+
+        /* Tx lobe media test frames. */
+        for(i = 0; i < 1500; ++i)
+        {
+                if(smctr_send_lobe_media_test(dev))
+                {
+                        if(perror)
+                        {
+                                smctr_reset_adapter(dev);
+                                tp->state = CLOSED;
+                                return (LOBE_MEDIA_TEST_FAILED);
+                        }
+                        else
+                        {
+                                perror = 1;
+                                if(smctr_lobe_media_test_cmd(dev))
+                                {
+                                        smctr_reset_adapter(dev);
+                                        tp->state = CLOSED;
+                                        return (LOBE_MEDIA_TEST_FAILED);
+                                }
+                        }
+                }
+        }
+
+        if(smctr_send_dat(dev))
+        {
+                if(smctr_send_dat(dev))
+                {
+                        smctr_reset_adapter(dev);
+                        tp->state = CLOSED;
+                        return (LOBE_MEDIA_TEST_FAILED);
+                }
+        }
+
+        /* Check if any frames received during test. */
+        if((tp->rx_fcb_curr[MAC_QUEUE]->frame_status)
+                || (tp->rx_fcb_curr[NON_MAC_QUEUE]->frame_status))
+        {
+                smctr_reset_adapter(dev);
+                tp->state = CLOSED;
+                return (LOBE_MEDIA_TEST_FAILED);
+        }
+
+        /* Set receive mask to "Promisc" mode. */
+        tp->receive_mask = saved_rcv_mask;
+
+        smctr_chg_rx_mask(dev);
+
+        return (0);
+}
+
+static int smctr_lobe_media_test_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_lobe_media_test_cmd\n", dev->name);
+
+        /* Change to lobe media test state. */
+        if(tp->monitor_state != MS_BEACON_TEST_STATE)
+        {
+                smctr_lobe_media_test_state(dev);
+                if(smctr_wait_cmd(dev))
+                {
+                        printk("Lobe Failed test state\n");
+                        return (LOBE_MEDIA_TEST_FAILED);
+                }
+        }
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+                TRC_LOBE_MEDIA_TEST);
+
+        return (err);
+}
+
+static int smctr_lobe_media_test_state(struct net_device *dev)
+{
+        int err;
+
+        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+                JS_LOBE_TEST_STATE);
+
+        return (err);
+}
+
+static int smctr_make_8025_hdr(struct net_device *dev,
+        MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc)
+{
+        tmf->ac = MSB(ac_fc);                 /* msb is access control */
+        tmf->fc = LSB(ac_fc);                 /* lsb is frame control */
+
+        tmf->sa[0] = dev->dev_addr[0];
+        tmf->sa[1] = dev->dev_addr[1];
+        tmf->sa[2] = dev->dev_addr[2];
+        tmf->sa[3] = dev->dev_addr[3];
+        tmf->sa[4] = dev->dev_addr[4];
+        tmf->sa[5] = dev->dev_addr[5];
+
+        switch(tmf->vc)
+        {
+		/* Send RQ_INIT to RPS */
+                case RQ_INIT:
+                        tmf->da[0] = 0xc0;
+                        tmf->da[1] = 0x00;
+                        tmf->da[2] = 0x00;
+                        tmf->da[3] = 0x00;
+                        tmf->da[4] = 0x00;
+                        tmf->da[5] = 0x02;
+                        break;
+
+		/* Send RPT_TX_FORWARD to CRS */
+                case RPT_TX_FORWARD:
+                        tmf->da[0] = 0xc0;
+                        tmf->da[1] = 0x00;
+                        tmf->da[2] = 0x00;
+                        tmf->da[3] = 0x00;
+                        tmf->da[4] = 0x00;
+                        tmf->da[5] = 0x10;
+                        break;
+
+		/* Everything else goes to sender */
+                default:
+                        tmf->da[0] = rmf->sa[0];
+                        tmf->da[1] = rmf->sa[1];
+                        tmf->da[2] = rmf->sa[2];
+                        tmf->da[3] = rmf->sa[3];
+                        tmf->da[4] = rmf->sa[4];
+                        tmf->da[5] = rmf->sa[5];
+                        break;
+        }
+
+        return (0);
+}
+
+static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        tsv->svi = AUTHORIZED_ACCESS_PRIORITY;
+        tsv->svl = S_AUTHORIZED_ACCESS_PRIORITY;
+
+        tsv->svv[0] = MSB(tp->authorized_access_priority);
+        tsv->svv[1] = LSB(tp->authorized_access_priority);
+
+	return (0);
+}
+
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        tsv->svi = ADDRESS_MODIFER;
+        tsv->svl = S_ADDRESS_MODIFER;
+
+        tsv->svv[0] = 0;
+        tsv->svv[1] = 0;
+
+        return (0);
+}
+
+static int smctr_make_auth_funct_class(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        tsv->svi = AUTHORIZED_FUNCTION_CLASS;
+        tsv->svl = S_AUTHORIZED_FUNCTION_CLASS;
+
+        tsv->svv[0] = MSB(tp->authorized_function_classes);
+        tsv->svv[1] = LSB(tp->authorized_function_classes);
+
+        return (0);
+}
+
+static int smctr_make_corr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv, __u16 correlator)
+{
+        tsv->svi = CORRELATOR;
+        tsv->svl = S_CORRELATOR;
+
+        tsv->svv[0] = MSB(correlator);
+        tsv->svv[1] = LSB(correlator);
+
+        return (0);
+}
+
+static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        smctr_get_functional_address(dev);
+
+        tsv->svi = FUNCTIONAL_ADDRESS;
+        tsv->svl = S_FUNCTIONAL_ADDRESS;
+
+        tsv->svv[0] = MSB(tp->misc_command_data[0]);
+        tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+        tsv->svv[2] = MSB(tp->misc_command_data[1]);
+        tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+        return (0);
+}
+
+static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        smctr_get_group_address(dev);
+
+        tsv->svi = GROUP_ADDRESS;
+        tsv->svl = S_GROUP_ADDRESS;
+
+        tsv->svv[0] = MSB(tp->misc_command_data[0]);
+        tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+        tsv->svv[2] = MSB(tp->misc_command_data[1]);
+        tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+        /* Set Group Address Sub-vector to all zeros if only the
+         * Group Address/Functional Address Indicator is set.
+         */
+        if(tsv->svv[0] == 0x80 && tsv->svv[1] == 0x00
+        	&& tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
+                tsv->svv[0] = 0x00;
+
+        return (0);
+}
+
+static int smctr_make_phy_drop_num(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        smctr_get_physical_drop_number(dev);
+
+        tsv->svi = PHYSICAL_DROP;
+        tsv->svl = S_PHYSICAL_DROP;
+
+        tsv->svv[0] = MSB(tp->misc_command_data[0]);
+        tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+        tsv->svv[2] = MSB(tp->misc_command_data[1]);
+        tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+        return (0);
+}
+
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        int i;
+
+        tsv->svi = PRODUCT_INSTANCE_ID;
+        tsv->svl = S_PRODUCT_INSTANCE_ID;
+
+        for(i = 0; i < 18; i++)
+                tsv->svv[i] = 0xF0;
+
+        return (0);
+}
+
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        smctr_get_station_id(dev);
+
+        tsv->svi = STATION_IDENTIFER;
+        tsv->svl = S_STATION_IDENTIFER;
+
+        tsv->svv[0] = MSB(tp->misc_command_data[0]);
+        tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+        tsv->svv[2] = MSB(tp->misc_command_data[1]);
+        tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+        tsv->svv[4] = MSB(tp->misc_command_data[2]);
+        tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+        return (0);
+}
+
+static int smctr_make_ring_station_status(struct net_device *dev,
+        MAC_SUB_VECTOR * tsv)
+{
+        tsv->svi = RING_STATION_STATUS;
+        tsv->svl = S_RING_STATION_STATUS;
+
+        tsv->svv[0] = 0;
+        tsv->svv[1] = 0;
+        tsv->svv[2] = 0;
+        tsv->svv[3] = 0;
+        tsv->svv[4] = 0;
+        tsv->svv[5] = 0;
+
+        return (0);
+}
+
+static int smctr_make_ring_station_version(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        tsv->svi = RING_STATION_VERSION_NUMBER;
+        tsv->svl = S_RING_STATION_VERSION_NUMBER;
+
+        tsv->svv[0] = 0xe2;            /* EBCDIC - S */
+        tsv->svv[1] = 0xd4;            /* EBCDIC - M */
+        tsv->svv[2] = 0xc3;            /* EBCDIC - C */
+        tsv->svv[3] = 0x40;            /* EBCDIC -   */
+        tsv->svv[4] = 0xe5;            /* EBCDIC - V */
+        tsv->svv[5] = 0xF0 + (tp->microcode_version >> 4);
+        tsv->svv[6] = 0xF0 + (tp->microcode_version & 0x0f);
+        tsv->svv[7] = 0x40;            /* EBCDIC -   */
+        tsv->svv[8] = 0xe7;            /* EBCDIC - X */
+
+        if(tp->extra_info & CHIP_REV_MASK)
+                tsv->svv[9] = 0xc5;    /* EBCDIC - E */
+        else
+                tsv->svv[9] = 0xc4;    /* EBCDIC - D */
+
+        return (0);
+}
+
+static int smctr_make_tx_status_code(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv, __u16 tx_fstatus)
+{
+        tsv->svi = TRANSMIT_STATUS_CODE;
+        tsv->svl = S_TRANSMIT_STATUS_CODE;
+
+        tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) || IBM_PASS_SOURCE_ADDR);
+
+        /* Stripped frame status of Transmitted Frame */
+        tsv->svv[1] = tx_fstatus & 0xff;
+
+        return (0);
+}
+
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+        MAC_SUB_VECTOR *tsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        smctr_get_upstream_neighbor_addr(dev);
+
+        tsv->svi = UPSTREAM_NEIGHBOR_ADDRESS;
+        tsv->svl = S_UPSTREAM_NEIGHBOR_ADDRESS;
+
+        tsv->svv[0] = MSB(tp->misc_command_data[0]);
+        tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+        tsv->svv[2] = MSB(tp->misc_command_data[1]);
+        tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+        tsv->svv[4] = MSB(tp->misc_command_data[2]);
+        tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+        return (0);
+}
+
+static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+        tsv->svi = WRAP_DATA;
+        tsv->svl = S_WRAP_DATA;
+
+        return (0);
+}
+
+/*
+ * Open/initialize the board. This is called sometime after
+ * booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
+static int smctr_open(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_open\n", dev->name);
+
+        tp->status = NOT_INITIALIZED;
+
+        err = smctr_load_firmware(dev);
+        if(err < 0)
+                return (err);
+
+        err = smctr_init_adapter(dev);
+        if(err < 0)
+                return (err);
+
+#ifdef MODULE
+        MOD_INC_USE_COUNT;
+#endif
+
+        return (err);
+}
+
+/* Interrupt driven open of Token card. */
+static int smctr_open_tr(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned long flags;
+        int err;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_open_tr\n", dev->name);
+
+        /* Now we can actually open the adapter. */
+        if(tp->status == OPEN)
+                return (0);
+        if(tp->status != INITIALIZED)
+                return (-1);
+
+        save_flags(flags);
+        cli();
+
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
+                return (err);
+
+        if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
+                return (err);
+
+        if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
+                return (err);
+
+        if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
+                return (err);
+
+        tp->status = CLOSED;
+
+        /* Insert into the Ring or Enter Loopback Mode. */
+        if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_1)
+        {
+                tp->status = CLOSED;
+
+                if(!(err = smctr_issue_trc_loopback_cmd(dev)))
+                {
+                        if(!(err = smctr_wait_cmd(dev)))
+                                tp->status = OPEN;
+                }
+
+                smctr_status_chg(dev);
+        }
+        else
+        {
+                if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_2)
+                {
+                        tp->status = CLOSED;
+                        if(!(err = smctr_issue_tri_loopback_cmd(dev)))
+                        {
+                                if(!(err = smctr_wait_cmd(dev)))
+                                        tp->status = OPEN;
+                        }
+
+                        smctr_status_chg(dev);
+                }
+                else
+                {
+                        if((tp->mode_bits & LOOPING_MODE_MASK)
+                                == LOOPBACK_MODE_3)
+                        {
+                                tp->status = CLOSED;
+                                if(!(err = smctr_lobe_media_test_cmd(dev)))
+                                {
+                                        if(!(err = smctr_wait_cmd(dev)))
+                                                tp->status = OPEN;
+                                }
+                                smctr_status_chg(dev);
+                        }
+                        else
+                        {
+                                if(!(err = smctr_lobe_media_test(dev)))
+                                        err = smctr_issue_insert_cmd(dev);
+                        }
+                }
+        }
+
+        restore_flags(flags);
+
+        return (err);
+}
+
+/* Check for a network adapter of this type, and return '0 if one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ */
+int __init smctr_probe (struct net_device *dev)
+{
+        int i;
+        int base_addr = dev ? dev->base_addr : 0;
+
+        if(base_addr > 0x1ff)    /* Check a single specified location. */
+                return (smctr_probe1(dev, base_addr));
+        else if(base_addr != 0)  /* Don't probe at all. */
+                return (-ENXIO);
+
+        for(i = 0; smctr_portlist[i]; i++)
+        {
+                int ioaddr = smctr_portlist[i];
+                if(check_region(ioaddr, SMCTR_IO_EXTENT))
+                        continue;
+                if(smctr_probe1(dev, ioaddr))
+                {
+#ifndef MODULE
+                        tr_freedev(dev);
+#endif
+                }
+                else
+                        return (0);
+        }
+
+        return (-ENODEV);
+}
+
+static int __init smctr_probe1(struct net_device *dev, int ioaddr)
+{
+        static unsigned version_printed = 0;
+        struct net_local *tp;
+        int err;
+        __u32 *ram;
+
+        if(smctr_debug && version_printed++ == 0)
+                printk("%s", version);
+
+#ifndef MODULE
+        dev = init_trdev(dev, 0);
+        if(dev == NULL)
+                return (-ENOMEM);
+#endif
+
+        /* See if we have a SMCTR card floating around. */
+        if((ioaddr & 0x1F) != 0)
+                return (-ENODEV);            /* No Adapter */
+
+        /* Setup this devices private information structure */
+        tp = (struct net_local *)kmalloc(sizeof(struct net_local),
+                GFP_KERNEL);
+        if(tp == NULL)
+                return (-ENOMEM);
+        memset(tp, 0, sizeof(struct net_local));
+        dev->priv = tp;
+        dev->base_addr = ioaddr;
+
+        err = smctr_find_adapter(dev);
+        if(err < 0)
+        {
+                kfree_s(tp, sizeof(struct net_local));
+                return (-ENODEV);
+        }
+
+        tp = (struct net_local *)dev->priv;
+        dev->rmem_start = dev->mem_start = tp->ram_base;
+        dev->rmem_end = dev->mem_end = dev->mem_start + 0x10000;
+        ram = (__u32 *)phys_to_virt(dev->mem_start);
+        tp->ram_access = *(__u32 *)&ram;
+
+	/* Allow user to specify ring speed on module insert. */
+	if(ringspeed == 4)
+		tp->media_type = MEDIA_UTP_4;
+	else
+		tp->media_type = MEDIA_UTP_16;
+
+        printk("%s: %s %s at Io %#4x, Irq %d, Rom %#4x, Ram %#4x.\n",
+                dev->name, smctr_name, smctr_model,
+                (unsigned int)dev->base_addr,
+                dev->irq, tp->rom_base, tp->ram_base);
+
+        dev->init               = smctr_init_card;
+        dev->open               = smctr_open;
+        dev->stop               = smctr_close;
+        dev->hard_start_xmit    = smctr_send_packet;
+        dev->get_stats          = smctr_get_stats;
+        dev->set_multicast_list = &smctr_set_multicast_list;
+
+        return (0);
+}
+
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+        struct net_device *dev, __u16 rx_status)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        struct sk_buff *skb;
+        __u16 rcode, correlator;
+        int err = 0;
+        __u8 xframe = 1;
+        __u16 tx_fstatus;
+
+        rmf->vl = SWAP_BYTES(rmf->vl);
+        if(rx_status & FCB_RX_STATUS_DA_MATCHED)
+        {
+                switch(rmf->vc)
+                {
+                        /* Received MAC Frames Processed by RS. */
+                        case INIT:
+                                if((rcode = smctr_rcv_init(dev, rmf,
+                                        &correlator)) == HARDWARE_FAILED)
+                                {
+                                        return (rcode);
+                                }
+
+                                if((err = smctr_send_rsp(dev, rmf, rcode,
+                                        correlator)))
+                                {
+                                        return (err);
+                                }
+                                break;
+
+                        case CHG_PARM:
+                                if((rcode = smctr_rcv_chg_param(dev, rmf,
+                                        &correlator)) ==HARDWARE_FAILED)
+                                {
+                                        return (rcode);
+                                }
+
+                                if((err = smctr_send_rsp(dev, rmf, rcode,
+                                        correlator)))
+                                {
+                                        return (err);
+                                }
+                                break;
+
+                        case RQ_ADDR:
+                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+                                        rmf, &correlator)) != POSITIVE_ACK)
+                                {
+                                        if(rcode == HARDWARE_FAILED)
+                                                return (rcode);
+                                        else
+                                                return (smctr_send_rsp(dev, rmf,
+                                                        rcode, correlator));
+                                }
+
+                                if((err = smctr_send_rpt_addr(dev, rmf,
+                                        correlator)))
+                                {
+                                        return (err);
+                                }
+                                break;
+
+                        case RQ_ATTCH:
+                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+                                        rmf, &correlator)) != POSITIVE_ACK)
+                                {
+                                        if(rcode == HARDWARE_FAILED)
+                                                return (rcode);
+                                        else
+                                                return (smctr_send_rsp(dev, rmf,
+                                                        rcode,
+                                                        correlator));
+                                }
+
+                                if((err = smctr_send_rpt_attch(dev, rmf,
+                                        correlator)))
+                                {
+                                        return (err);
+                                }
+                                break;
+
+                        case RQ_STATE:
+                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+                                        rmf, &correlator)) != POSITIVE_ACK)
+                                {
+                                        if(rcode == HARDWARE_FAILED)
+                                                return (rcode);
+                                        else
+                                                return (smctr_send_rsp(dev, rmf,
+                                                        rcode,
+                                                        correlator));
+                                }
+
+                                if((err = smctr_send_rpt_state(dev, rmf,
+                                        correlator)))
+                                {
+                                        return (err);
+                                }
+                                break;
+
+                        case TX_FORWARD:
+                                if((rcode = smctr_rcv_tx_forward(dev, rmf))
+                                        != POSITIVE_ACK)
+                                {
+                                        if(rcode == HARDWARE_FAILED)
+                                                return (rcode);
+                                        else
+                                                return (smctr_send_rsp(dev, rmf,
+                                                        rcode,
+                                                        correlator));
+                                }
+
+                                if((err = smctr_send_tx_forward(dev, rmf,
+                                        &tx_fstatus)) == HARDWARE_FAILED)
+                                {
+                                        return (err);
+                                }
+
+                                if(err == A_FRAME_WAS_FORWARDED)
+                                {
+                                        if((err = smctr_send_rpt_tx_forward(dev,
+						rmf, tx_fstatus))
+                                                == HARDWARE_FAILED)
+                                        {
+                                                return (err);
+                                        }
+                                }
+                                break;
+
+                        /* Received MAC Frames Processed by CRS/REM/RPS. */
+                        case RSP:
+                        case RQ_INIT:
+                        case RPT_NEW_MON:
+                        case RPT_SUA_CHG:
+                        case RPT_ACTIVE_ERR:
+                        case RPT_NN_INCMP:
+                        case RPT_ERROR:
+                        case RPT_ATTCH:
+                        case RPT_STATE:
+                        case RPT_ADDR:
+                                break;
+
+                        /* Rcvd Att. MAC Frame (if RXATMAC set) or UNKNOWN */
+                        default:
+                                xframe = 0;
+                                if(!(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES))
+                                {
+                                        rcode = smctr_rcv_unknown(dev, rmf,
+                                                &correlator);
+                                        if((err = smctr_send_rsp(dev, rmf,rcode,
+                                                correlator)))
+                                        {
+                                                return (err);
+                                        }
+                                }
+
+                                break;
+                }
+        }
+        else
+        {
+                /* 1. DA doesn't match (Promiscuous Mode).
+                 * 2. Parse for Extended MAC Frame Type.
+                 */
+                switch(rmf->vc)
+                {
+                        case RSP:
+                        case INIT:
+                        case RQ_INIT:
+                        case RQ_ADDR:
+                        case RQ_ATTCH:
+                        case RQ_STATE:
+                        case CHG_PARM:
+                        case RPT_ADDR:
+                        case RPT_ERROR:
+                        case RPT_ATTCH:
+                        case RPT_STATE:
+                        case RPT_NEW_MON:
+                        case RPT_SUA_CHG:
+                        case RPT_NN_INCMP:
+                        case RPT_ACTIVE_ERR:
+                                break;
+
+                        default:
+                                xframe = 0;
+                                break;
+                }
+        }
+
+        /* NOTE: UNKNOWN MAC frames will NOT be passed up unless
+         * ACCEPT_ATT_MAC_FRAMES is set.
+         */
+        if(((tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+                && (xframe == (__u8)0))
+                || ((tp->receive_mask & ACCEPT_EXT_MAC_FRAMES)
+                && (xframe == (__u8)1)))
+        {
+                rmf->vl = SWAP_BYTES(rmf->vl);
+
+                skb = dev_alloc_skb(size);
+                skb->len = size;
+
+                /* Slide data into a sleek skb. */
+                skb_put(skb, skb->len);
+                memcpy(skb->data, rmf, skb->len);
+
+                /* Update Counters */
+                tp->MacStat.rx_packets++;
+                tp->MacStat.rx_bytes += skb->len;
+
+                /* Kick the packet on up. */
+                skb->dev = dev;
+                skb->protocol = tr_type_trans(skb, dev);
+                netif_rx(skb);
+                err = 0;
+        }
+
+        return (err);
+}
+
+/* Test for RAM in adapter RAM space. */
+static int smctr_ram_conflict_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+        __u16 sword;
+
+        for(i = 0; i < (unsigned int)(tp->ram_usable * 1024); i += 1024)
+        {
+                sword = *(__u16 *)(tp->ram_access + i);
+                *(__u16 *)(tp->ram_access + i) = 0x1234;
+                if(*(__u16 *)(tp->ram_access + i) == 0x1234)
+                {
+                        *(__u16 *)(tp->ram_access + i) = sword;
+                        return (-1);
+                }
+        }
+
+        return (0);
+}
+
+/* Adapter RAM test. Incremental word ODD boundry data test. */
+static int smctr_ram_memory_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 page, pages_of_ram, start_pattern = 0, word_pattern = 0,
+                word_read = 0, err_word = 0, err_pattern = 0;
+        unsigned int err_offset;
+        __u32 j, pword;
+        __u8 err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_ram_memory_test\n", dev->name);
+
+        start_pattern   = 0x0001;
+        pages_of_ram    = tp->ram_size / tp->ram_usable;
+        pword           = tp->ram_access;
+
+        /* Incremental word ODD boundry test. */
+        for(page = 0; (page < pages_of_ram) && (~err);
+                page++, start_pattern += 0x8000)
+        {
+                smctr_set_page(dev, (__u8 *)(tp->ram_access
+                        + (page * tp->ram_usable * 1024) + 1));
+                word_pattern = start_pattern;
+
+                for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1; j += 2)
+                        *(__u16 *)(pword + j) = word_pattern++;
+
+                word_pattern = start_pattern;
+
+                for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1
+                        && (~err); j += 2, word_pattern++)
+                {
+                        word_read = *(__u16 *)(pword + j);
+                        if(word_read != word_pattern)
+                        {
+                                err             = (__u8)1;
+                                err_offset      = j;
+                                err_word        = word_read;
+                                err_pattern     = word_pattern;
+                                return (-1);
+                        }
+                }
+        }
+
+        /* Zero out memory. */
+        for(page = 0; page < pages_of_ram && (~err); page++)
+        {
+                smctr_set_page(dev, (__u8 *)(tp->ram_access
+                        + (page * tp->ram_usable * 1024)));
+                word_pattern = 0;
+
+                for(j = 0; j < (__u32)tp->ram_usable * 1024; j +=2)
+                        *(__u16 *)(pword + j) = word_pattern;
+
+                for(j =0; j < (__u32)tp->ram_usable * 1024
+                        && (~err); j += 2)
+                {
+                        word_read = *(__u16 *)(pword + j);
+                        if(word_read != word_pattern)
+                        {
+                                err             = (__u8)1;
+                                err_offset      = j;
+                                err_word        = word_read;
+                                err_pattern     = word_pattern;
+                                return (-1);
+                        }
+                }
+        }
+
+        smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+        return (0);
+}
+
+static unsigned int __init smctr_read_584_chksum(int ioaddr)
+{
+        __u8 pg_no, r1, r2;
+        __u16 byte_no, csum_val = 0;
+
+        for(pg_no = 0; pg_no < 16; pg_no++)
+        {
+                r1 = inb(ioaddr + 0x01);
+                r1 &= 0x04;
+                r1 |= 0x02;
+
+                outb(r1, ioaddr + 0x01);
+
+                r1 = inb(ioaddr + 0x03);
+                r1 &= 0x0f;
+                r1 |= (pg_no << 4);
+
+                outb(r1, ioaddr + 0x03);
+
+                r1 = inb(ioaddr + 0x01);
+                r1 &= 0x04;
+                r1 |= 0x12;
+
+                outb(r1, ioaddr + 0x01);
+
+                do {
+                        r1 = inb(ioaddr + 0x01);
+                } while(r1 & 0x10);
+
+                r2 = 0;
+                for(byte_no = 0x08; byte_no < 0x10; byte_no++)
+                {
+                        r1 = inb(ioaddr + byte_no);
+                        r2 += r1;
+                }
+
+                csum_val += r2;
+        }
+
+        r1 = inb(ioaddr + 0x01);
+        r1 &= 0x04;
+        r1 |= 0x10;
+        outb(r1, ioaddr + 0x01);
+
+        csum_val &= 0xff;
+        if(csum_val == 0xff)
+                return (0);
+        else
+                return (-1);
+}
+
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator)
+{
+        MAC_SUB_VECTOR *rsv;
+        signed short vlen;
+        __u16 rcode = POSITIVE_ACK;
+        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+        /* This Frame can only come from a CRS */
+        if((rmf->dc_sc & SC_MASK) != SC_CRS)
+                return(E_INAPPROPRIATE_SOURCE_CLASS);
+
+        /* Remove MVID Length from total length. */
+        vlen = (signed short)rmf->vl - 4;
+
+        /* Point to First SVID */
+        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+        /* Search for Appropriate SVID's. */
+        while((vlen > 0) && (rcode == POSITIVE_ACK))
+        {
+                switch(rsv->svi)
+                {
+                        case CORRELATOR:
+                                svectors |= F_CORRELATOR;
+                                rcode = smctr_set_corr(dev, rsv, correlator);
+                                break;
+
+                        case LOCAL_RING_NUMBER:
+                                svectors |= F_LOCAL_RING_NUMBER;
+                                rcode = smctr_set_local_ring_num(dev, rsv);
+                                break;
+
+                        case ASSIGN_PHYSICAL_DROP:
+                                svectors |= F_ASSIGN_PHYSICAL_DROP;
+                                rcode = smctr_set_phy_drop(dev, rsv);
+                                break;
+
+                        case ERROR_TIMER_VALUE:
+                                svectors |= F_ERROR_TIMER_VALUE;
+                                rcode = smctr_set_error_timer_value(dev, rsv);
+                                break;
+
+                        case AUTHORIZED_FUNCTION_CLASS:
+                                svectors |= F_AUTHORIZED_FUNCTION_CLASS;
+                                rcode = smctr_set_auth_funct_class(dev, rsv);
+                                break;
+
+                        case AUTHORIZED_ACCESS_PRIORITY:
+                                svectors |= F_AUTHORIZED_ACCESS_PRIORITY;
+                                rcode = smctr_set_auth_access_pri(dev, rsv);
+                                break;
+
+                        default:
+                                rcode = E_SUB_VECTOR_UNKNOWN;
+                                break;
+                }
+
+                /* Let Sender Know if SUM of SV length's is
+                 * larger then length in MVID length field
+                 */
+                if((vlen -= rsv->svl) < 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+
+                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+        }
+
+        if(rcode == POSITIVE_ACK)
+        {
+                /* Let Sender Know if MVID length field
+                 * is larger then SUM of SV length's
+                 */
+                if(vlen != 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+                else
+		{
+                	/* Let Sender Know if Expected SVID Missing */
+                	if((svectors & R_CHG_PARM) ^ R_CHG_PARM)
+                        	rcode = E_MISSING_SUB_VECTOR;
+		}
+        }
+
+        return (rcode);
+}
+
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator)
+{
+        MAC_SUB_VECTOR *rsv;
+        signed short vlen;
+        __u16 rcode = POSITIVE_ACK;
+        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+        /* This Frame can only come from a RPS */
+        if((rmf->dc_sc & SC_MASK) != SC_RPS)
+                return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+        /* Remove MVID Length from total length. */
+        vlen = (signed short)rmf->vl - 4;
+
+        /* Point to First SVID */
+        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+        /* Search for Appropriate SVID's */
+        while((vlen > 0) && (rcode == POSITIVE_ACK))
+        {
+                switch(rsv->svi)
+                {
+                        case CORRELATOR:
+                                svectors |= F_CORRELATOR;
+                                rcode = smctr_set_corr(dev, rsv, correlator);
+                                break;
+
+                        case LOCAL_RING_NUMBER:
+                                svectors |= F_LOCAL_RING_NUMBER;
+                                rcode = smctr_set_local_ring_num(dev, rsv);
+                                break;
+
+                        case ASSIGN_PHYSICAL_DROP:
+                                svectors |= F_ASSIGN_PHYSICAL_DROP;
+                                rcode = smctr_set_phy_drop(dev, rsv);
+                                break;
+
+                        case ERROR_TIMER_VALUE:
+                                svectors |= F_ERROR_TIMER_VALUE;
+                                rcode = smctr_set_error_timer_value(dev, rsv);
+                                break;
+
+                        default:
+                                rcode = E_SUB_VECTOR_UNKNOWN;
+                                break;
+                }
+
+                /* Let Sender Know if SUM of SV length's is
+                 * larger then length in MVID length field
+		 */
+                if((vlen -= rsv->svl) < 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+
+                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+        }
+
+        if(rcode == POSITIVE_ACK)
+        {
+                /* Let Sender Know if MVID length field
+                 * is larger then SUM of SV length's
+                 */
+                if(vlen != 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+                else
+		{
+                	/* Let Sender Know if Expected SV Missing */
+                	if((svectors & R_INIT) ^ R_INIT)
+                        	rcode = E_MISSING_SUB_VECTOR;
+		}
+        }
+
+        return (rcode);
+}
+
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
+{
+        MAC_SUB_VECTOR *rsv;
+        signed short vlen;
+        __u16 rcode = POSITIVE_ACK;
+        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+        /* This Frame can only come from a CRS */
+        if((rmf->dc_sc & SC_MASK) != SC_CRS)
+                return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+        /* Remove MVID Length from total length */
+        vlen = (signed short)rmf->vl - 4;
+
+        /* Point to First SVID */
+        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+        /* Search for Appropriate SVID's */
+        while((vlen > 0) && (rcode == POSITIVE_ACK))
+        {
+                switch(rsv->svi)
+                {
+                        case FRAME_FORWARD:
+                                svectors |= F_FRAME_FORWARD;
+                                rcode = smctr_set_frame_forward(dev, rsv, 
+					rmf->dc_sc);
+                                break;
+
+                        default:
+                                rcode = E_SUB_VECTOR_UNKNOWN;
+                                break;
+                }
+
+                /* Let Sender Know if SUM of SV length's is
+                 * larger then length in MVID length field
+		 */
+                if((vlen -= rsv->svl) < 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+
+                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+        }
+
+        if(rcode == POSITIVE_ACK)
+        {
+                /* Let Sender Know if MVID length field
+                 * is larger then SUM of SV length's
+                 */
+                if(vlen != 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+                else
+		{
+                	/* Let Sender Know if Expected SV Missing */
+                	if((svectors & R_TX_FORWARD) ^ R_TX_FORWARD)
+                        	rcode = E_MISSING_SUB_VECTOR;
+		}
+        }
+
+        return (rcode);
+}
+
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+        MAC_HEADER *rmf, __u16 *correlator)
+{
+        MAC_SUB_VECTOR *rsv;
+        signed short vlen;
+        __u16 rcode = POSITIVE_ACK;
+        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+        /* Remove MVID Length from total length */
+        vlen = (signed short)rmf->vl - 4;
+
+        /* Point to First SVID */
+        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+        /* Search for Appropriate SVID's */
+        while((vlen > 0) && (rcode == POSITIVE_ACK))
+        {
+                switch(rsv->svi)
+                {
+                        case CORRELATOR:
+                                svectors |= F_CORRELATOR;
+                                rcode = smctr_set_corr(dev, rsv, correlator);
+                                break;
+
+                        default:
+                                rcode = E_SUB_VECTOR_UNKNOWN;
+                                break;
+                }
+
+                /* Let Sender Know if SUM of SV length's is
+                 * larger then length in MVID length field
+                 */
+                if((vlen -= rsv->svl) < 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+
+                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+        }
+
+        if(rcode == POSITIVE_ACK)
+        {
+                /* Let Sender Know if MVID length field
+                 * is larger then SUM of SV length's
+                 */
+                if(vlen != 0)
+                        rcode = E_VECTOR_LENGTH_ERROR;
+                else
+		{
+                	/* Let Sender Know if Expected SVID Missing */
+                	if((svectors & R_RQ_ATTCH_STATE_ADDR) 
+				^ R_RQ_ATTCH_STATE_ADDR)
+                        	rcode = E_MISSING_SUB_VECTOR;
+			}
+        }
+
+        return (rcode);
+}
+
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *correlator)
+{
+        MAC_SUB_VECTOR *rsv;
+        signed short vlen;
+
+        *correlator = 0;
+
+        /* Remove MVID Length from total length */
+        vlen = (signed short)rmf->vl - 4;
+
+        /* Point to First SVID */
+        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+        /* Search for CORRELATOR for RSP to UNKNOWN */
+        while((vlen > 0) && (*correlator == 0))
+        {
+                switch(rsv->svi)
+                {
+                        case CORRELATOR:
+                                smctr_set_corr(dev, rsv, correlator);
+                                break;
+
+                        default:
+                                break;
+                }
+
+                vlen -= rsv->svl;
+                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+        }
+
+        return (E_UNRECOGNIZED_VECTOR_ID);
+}
+
+/*
+ * Reset the 825 NIC and exit w:
+ * 1. The NIC reset cleared (non-reset state), halted and un-initialized.
+ * 2. TINT masked.
+ * 3. CBUSY masked.
+ * 4. TINT clear.
+ * 5. CBUSY clear.
+ */
+static int smctr_reset_adapter(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        /* Reseting the NIC will put it in a halted and un-initialized state. */        smctr_set_trc_reset(ioaddr);
+        udelay(200000); /* ~2 ms */
+
+        smctr_clear_trc_reset(ioaddr);
+        udelay(200000); /* ~2 ms */
+
+        /* Remove any latched interrupts that occured prior to reseting the
+         * adapter or possibily caused by line glitches due to the reset.
+         */
+        outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
+
+        return (0);
+}
+
+static int smctr_restart_tx_chain(struct net_device *dev, short queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_restart_tx_chain\n", dev->name);
+
+        if(tp->num_tx_fcbs_used[queue] != 0
+                && tp->tx_queue_status[queue] == NOT_TRANSMITING)
+        {
+                tp->tx_queue_status[queue] = TRANSMITING;
+                err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+        }
+
+        return (err);
+}
+
+static int smctr_ring_status_chg(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_ring_status_chg\n", dev->name);
+
+        /* Check for ring_status_flag: whenever MONITOR_STATE_BIT
+         * Bit is set, check value of monitor_state, only then we
+         * enable and start transmit/receive timeout (if and only
+         * if it is MS_ACTIVE_MONITOR_STATE or MS_STANDBY_MONITOR_STATE)
+         */
+        if(tp->ring_status_flags == MONITOR_STATE_CHANGED)
+        {
+                if((tp->monitor_state == MS_ACTIVE_MONITOR_STATE)
+                        || (tp->monitor_state == MS_STANDBY_MONITOR_STATE))
+                {
+                        tp->monitor_state_ready = 1;
+                }
+                else
+                {
+                        /* if adapter is NOT in either active monitor
+                         * or standby monitor state => Disable
+                         * transmit/receive timeout.
+                         */
+                        tp->monitor_state_ready = 0;
+
+			/* Ring speed problem, switching to auto mode. */
+			if(tp->monitor_state == MS_MONITOR_FSM_INACTIVE
+				&& !tp->cleanup)
+			{
+				printk(KERN_INFO "%s: Incorrect ring speed switching.\n",
+					dev->name);
+				smctr_set_ring_speed(dev);
+			}
+                }
+        }
+
+        if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
+                return (0);
+
+        switch(tp->ring_status)
+        {
+                case RING_RECOVERY:
+                        printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+                        tp->current_ring_status |= RING_RECOVERY;
+                        break;
+
+                case SINGLE_STATION:
+                        printk(KERN_INFO "%s: Single Statinon\n", dev->name);
+                        tp->current_ring_status |= SINGLE_STATION;
+                        break;
+
+                case COUNTER_OVERFLOW:
+                        printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+                        tp->current_ring_status |= COUNTER_OVERFLOW;
+                        break;
+
+                case REMOVE_RECEIVED:
+                        printk(KERN_INFO "%s: Remove Received\n", dev->name);
+                        tp->current_ring_status |= REMOVE_RECEIVED;
+                        break;
+
+                case AUTO_REMOVAL_ERROR:
+                        printk(KERN_INFO "%s: Auto Remove Error\n", dev->name);
+                        tp->current_ring_status |= AUTO_REMOVAL_ERROR;
+                        break;
+
+                case LOBE_WIRE_FAULT:
+                        printk(KERN_INFO "%s: Lobe Wire Fault\n", dev->name);
+                        tp->current_ring_status |= LOBE_WIRE_FAULT;
+                        break;
+
+                case TRANSMIT_BEACON:
+                        printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+                        tp->current_ring_status |= TRANSMIT_BEACON;
+                        break;
+
+                case SOFT_ERROR:
+                        printk(KERN_INFO "%s: Soft Error\n", dev->name);
+                        tp->current_ring_status |= SOFT_ERROR;
+                        break;
+
+                case HARD_ERROR:
+                        printk(KERN_INFO "%s: Hard Error\n", dev->name);
+                        tp->current_ring_status |= HARD_ERROR;
+                        break;
+
+                case SIGNAL_LOSS:
+                        printk(KERN_INFO "%s: Singal Loss\n", dev->name);
+                        tp->current_ring_status |= SIGNAL_LOSS;
+                        break;
+
+                default:
+			printk(KERN_INFO "%s: Unknown ring status change\n",
+				dev->name);
+                        break;
+        }
+
+        return (0);
+}
+
+/* Test for ROM signature within adapter RAM space. */
+static int smctr_rom_conflict_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i;
+
+        for(i = 0; i < (unsigned int)tp->ram_usable * 1024; i += 4096)
+        {
+                if(*(__u16 *)(tp->ram_access + i) == 0xaa55)
+                        return (-1);
+        }
+
+        return (0);
+}
+
+static int smctr_rx_frame(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 queue, status, rx_size, err = 0;
+        __u8 *pbuff;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_rx_frame\n", dev->name);
+
+        cli();
+        queue = tp->receive_queue_number;
+
+        while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
+        {
+                err = HARDWARE_FAILED;
+
+                if(((status & 0x007f) == 0)
+                        || ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
+                {
+                        /* frame length less the CRC (4 bytes) + FS (1 byte) */
+                        rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;
+
+                        pbuff = smctr_get_rx_pointer(dev, queue);
+
+                        smctr_set_page(dev, pbuff);
+                        smctr_disable_16bit(dev);
+
+                        /* pbuff points to addr within one page */
+                        pbuff = (__u8 *)PAGE_POINTER(pbuff);
+
+                        if(queue == NON_MAC_QUEUE)
+                        {
+                                struct sk_buff *skb;
+
+                                skb = dev_alloc_skb(rx_size);
+                                skb_put(skb, rx_size);
+
+                                memcpy(skb->data, pbuff, rx_size);
+                                sti();
+
+                                /* Update Counters */
+                                tp->MacStat.rx_packets++;
+                                tp->MacStat.rx_bytes += skb->len;
+
+                                /* Kick the packet on up. */
+                                skb->dev = dev;
+                                skb->protocol = tr_type_trans(skb, dev);
+                                netif_rx(skb);
+                        }
+                        else
+                                smctr_process_rx_packet((MAC_HEADER *)pbuff,
+                                        rx_size, dev, status);
+                }
+
+                smctr_enable_16bit(dev);
+                smctr_set_page(dev, (__u8 *)tp->ram_access);
+                smctr_update_rx_chain(dev, queue);
+
+                if(err != SUCCESS)
+                        break;
+        }
+
+        return (err);
+}
+
+static int smctr_send_dat(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int i, err;
+        MAC_HEADER *tmf;
+        FCBlock *fcb;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_send_dat\n", dev->name);
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
+                sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
+        {
+                return (OUT_OF_RESOURCES);
+        }
+
+        /* Initialize DAT Data Fields. */
+        tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->ac = MSB(AC_FC_DAT);
+        tmf->fc = LSB(AC_FC_DAT);
+
+        for(i = 0; i < 6; i++)
+        {
+                tmf->sa[i] = dev->dev_addr[i];
+                tmf->da[i] = dev->dev_addr[i];
+
+        }
+
+        tmf->vc        = DAT;
+        tmf->dc_sc     = DC_RS | SC_RS;
+        tmf->vl        = 4;
+        tmf->vl        = SWAP_BYTES(tmf->vl);
+
+        /* Start Transmit. */
+        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+                return (err);
+
+        /* Wait for Transmit to Complete */
+        for(i = 0; i < 10000; i++)
+        {
+                if(fcb->frame_status & FCB_COMMAND_DONE)
+                        break;
+                udelay(1000);
+        }
+
+        /* Check if GOOD frame Tx'ed. */
+        if(!(fcb->frame_status &  FCB_COMMAND_DONE)
+                || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+        {
+                return (INITIALIZE_FAILED);
+        }
+
+        /* De-allocated Tx FCB and Frame Buffer
+         * The FCB must be de-allocated manually if executing with
+         * interrupts disabled, other wise the ISR (LM_Service_Events)
+         * will de-allocate it when the interrupt occurs.
+         */
+        tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+        smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+        return (0);
+}
+
+/*
+ * Gets skb from system, queues it and checks if it can be sent
+ */
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_send_packet\n", dev->name);
+
+        if(dev->tbusy)
+        {
+                /*
+                 * If we get here, some higher level has decided we are broken.
+                 * There should really be a "kick me" function call instead.
+                 *
+                 * Resetting the token ring adapter takes a long time so just
+                 * fake transmission time and go on trying. Our own timeout
+                 * routine is in sktr_timer_chk()
+                 */
+                dev->tbusy       = 0;
+                dev->trans_start = jiffies;
+                return (1);
+        }
+
+        /*
+         * If some higher layer thinks we've missed an tx-done interrupt we
+         * are passed NULL.
+         */
+        if(skb == NULL)
+                return (0);
+
+        /*
+         * Block a timer-based transmit from overlapping. This could better be
+         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+         */
+        if(test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+        {
+                printk("%s: Transmitter access conflict.\n", dev->name);
+                return (1);
+        }
+
+        if(tp->QueueSkb == 0)
+                return (1);     /* Return with tbusy set: queue full */
+
+        tp->QueueSkb--;
+        skb_queue_tail(&tp->SendSkbQueue, skb);
+        smctr_hardware_send_packet(dev, tp);
+        if(tp->QueueSkb > 0)
+                dev->tbusy = 0;
+
+        return (0);
+}
+
+static int smctr_send_lobe_media_test(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+	MAC_SUB_VECTOR *tsv;
+	MAC_HEADER *tmf;
+        FCBlock *fcb;
+	__u32 i;
+	int err;
+
+        if(smctr_debug > 15)
+                printk("%s: smctr_send_lobe_media_test\n", dev->name);
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
+                + S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
+        {
+                return (OUT_OF_RESOURCES);
+        }
+
+        /* Initialize DAT Data Fields. */
+        tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->ac = MSB(AC_FC_LOBE_MEDIA_TEST);
+        tmf->fc = LSB(AC_FC_LOBE_MEDIA_TEST);
+
+        for(i = 0; i < 6; i++)
+        {
+                tmf->da[i] = 0;
+                tmf->sa[i] = dev->dev_addr[i];
+        }
+
+        tmf->vc        = LOBE_MEDIA_TEST;
+        tmf->dc_sc     = DC_RS | SC_RS;
+        tmf->vl        = 4;
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_wrap_data(dev, tsv);
+        tmf->vl += tsv->svl;
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_wrap_data(dev, tsv);
+        tmf->vl += tsv->svl;
+
+        /* Start Transmit. */
+        tmf->vl = SWAP_BYTES(tmf->vl);
+        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+                return (err);
+
+        /* Wait for Transmit to Complete. (10 ms). */
+        for(i=0; i < 10000; i++)
+        {
+                if(fcb->frame_status & FCB_COMMAND_DONE)
+                        break;
+                udelay(1000);
+        }
+
+        /* Check if GOOD frame Tx'ed */
+        if(!(fcb->frame_status & FCB_COMMAND_DONE)
+                || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+        {
+                return (LOBE_MEDIA_TEST_FAILED);
+        }
+
+        /* De-allocated Tx FCB and Frame Buffer
+         * The FCB must be de-allocated manually if executing with
+         * interrupts disabled, other wise the ISR (LM_Service_Events)
+         * will de-allocate it when the interrupt occurs.
+         */
+        tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+        smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+        return (0);
+}
+
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator)
+{
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+		+ S_CORRELATOR + S_PHYSICAL_DROP + S_UPSTREAM_NEIGHBOR_ADDRESS
+		+ S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
+		== (FCBlock *)(-1L))
+        {
+                return (0);
+        }
+
+        tmf 		= (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->vc    	= RPT_ADDR;
+        tmf->dc_sc 	= (rmf->dc_sc & SC_MASK) << 4;
+        tmf->vl    	= 4;
+
+        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ADDR);
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_corr(dev, tsv, correlator);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_phy_drop_num(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_upstream_neighbor_addr(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_addr_mod(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_group_addr(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_funct_addr(dev, tsv);
+
+        tmf->vl += tsv->svl;
+
+        /* Subtract out MVID and MVL which is
+         * include in both vl and MAC_HEADER
+         */
+/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
+        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+        tmf->vl = SWAP_BYTES(tmf->vl);
+
+        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator)
+{
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+		+ S_CORRELATOR + S_PRODUCT_INSTANCE_ID + S_FUNCTIONAL_ADDRESS
+		+ S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
+		== (FCBlock *)(-1L))
+        {
+                return (0);
+        }
+
+        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->vc    = RPT_ATTCH;
+        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+        tmf->vl    = 4;
+
+        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ATTCH);
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_corr(dev, tsv, correlator);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_product_id(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_funct_addr(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_auth_funct_class(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_access_pri(dev, tsv);
+
+        tmf->vl += tsv->svl;
+
+        /* Subtract out MVID and MVL which is
+         * include in both vl and MAC_HEADER
+         */
+/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
+        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+        tmf->vl = SWAP_BYTES(tmf->vl);
+
+        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 correlator)
+{
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+		+ S_CORRELATOR + S_RING_STATION_VERSION_NUMBER
+		+ S_RING_STATION_STATUS + S_STATION_IDENTIFER))
+		== (FCBlock *)(-1L))
+        {
+                return (0);
+        }
+
+        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->vc    = RPT_STATE;
+        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+        tmf->vl    = 4;
+
+        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_STATE);
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_corr(dev, tsv, correlator);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_ring_station_version(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_ring_station_status(dev, tsv);
+
+        tmf->vl += tsv->svl;
+        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+        smctr_make_station_id(dev, tsv);
+
+        tmf->vl += tsv->svl;
+
+        /* Subtract out MVID and MVL which is
+         * include in both vl and MAC_HEADER
+         */
+/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
+        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+        tmf->vl = SWAP_BYTES(tmf->vl);
+
+        return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+        MAC_HEADER *rmf, __u16 tx_fstatus)
+{
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+		+ S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
+        {
+                return (0);
+        }
+
+        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->vc    = RPT_TX_FORWARD;
+        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+        tmf->vl    = 4;
+
+        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_TX_FORWARD);
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_tx_status_code(dev, tsv, tx_fstatus);
+
+        tmf->vl += tsv->svl;
+
+        /* Subtract out MVID and MVL which is
+         * include in both vl and MAC_HEADER
+         */
+/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
+        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+        tmf->vl = SWAP_BYTES(tmf->vl);
+
+        return(smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 rcode, __u16 correlator)
+{
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+		+ S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
+        {
+                return (0);
+        }
+
+        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+        tmf->vc    = RSP;
+        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+        tmf->vl    = 4;
+
+        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RSP);
+
+        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+        smctr_make_corr(dev, tsv, correlator);
+
+        return (0);
+}
+
+static int smctr_send_rq_init(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        MAC_HEADER *tmf;
+        MAC_SUB_VECTOR *tsv;
+        FCBlock *fcb;
+	unsigned int i, count = 0;
+	__u16 fstatus;
+	int err;
+
+        do {
+        	if(((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+			+ S_PRODUCT_INSTANCE_ID + S_UPSTREAM_NEIGHBOR_ADDRESS
+			+ S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
+			== (FCBlock *)(-1L)))
+                {
+                        return (0);
+                }
+
+                tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+                tmf->vc    = RQ_INIT;
+                tmf->dc_sc = DC_RPS | SC_RS;
+                tmf->vl    = 4;
+
+                smctr_make_8025_hdr(dev, 0L, tmf, AC_FC_RQ_INIT);
+
+                tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+                smctr_make_product_id(dev, tsv);
+
+                tmf->vl += tsv->svl;
+                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+                smctr_make_upstream_neighbor_addr(dev, tsv);
+
+                tmf->vl += tsv->svl;
+                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+                smctr_make_ring_station_version(dev, tsv);
+
+                tmf->vl += tsv->svl;
+                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+                smctr_make_addr_mod(dev, tsv);
+
+                tmf->vl += tsv->svl;
+
+                /* Subtract out MVID and MVL which is
+                 * include in both vl and MAC_HEADER
+                 */
+/*              fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
+                fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+                tmf->vl = SWAP_BYTES(tmf->vl);
+
+                if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+                        return (err);
+
+                /* Wait for Transmit to Complete */
+      		for(i = 0; i < 10000; i++) 
+		{
+          		if(fcb->frame_status & FCB_COMMAND_DONE)
+              			break;
+          		udelay(1000);
+      		}
+
+                /* Check if GOOD frame Tx'ed */
+                fstatus = fcb->frame_status;
+
+                if(!(fstatus & FCB_COMMAND_DONE))
+                        return (HARDWARE_FAILED);
+
+                if(!(fstatus & FCB_TX_STATUS_E))
+                        count++;
+
+                /* De-allocated Tx FCB and Frame Buffer
+                 * The FCB must be de-allocated manually if executing with
+                 * interrupts disabled, other wise the ISR (LM_Service_Events)
+                 * will de-allocate it when the interrupt occurs.
+                 */
+                tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+                smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+        } while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
+
+	return (smctr_join_complete_state(dev));
+}
+
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+        __u16 *tx_fstatus)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        FCBlock *fcb;
+        unsigned int i;
+	int err;
+
+        /* Check if this is the END POINT of the Transmit Forward Chain. */
+        if(rmf->vl <= 18)
+                return (0);
+
+        /* Allocate Transmit FCB only by requesting 0 bytes
+         * of data buffer.
+         */
+        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
+                return (0);
+
+        /* Set pointer to Transmit Frame Buffer to the data
+         * portion of the received TX Forward frame, making
+         * sure to skip over the Vector Code (vc) and Vector
+         * length (vl).
+         */
+        fcb->bdb_ptr->trc_data_block_ptr = TRC_POINTER((__u32)rmf 
+		+ sizeof(MAC_HEADER) + 2);
+        fcb->bdb_ptr->data_block_ptr     = (__u16 *)((__u32)rmf 
+		+ sizeof(MAC_HEADER) + 2);
+
+        fcb->frame_length                = rmf->vl - 4 - 2;
+        fcb->bdb_ptr->buffer_length      = rmf->vl - 4 - 2;
+
+        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+                return (err);
+
+        /* Wait for Transmit to Complete */
+   	for(i = 0; i < 10000; i++) 
+	{
+       		if(fcb->frame_status & FCB_COMMAND_DONE)
+           		break;
+        	udelay(1000);
+   	}
+
+        /* Check if GOOD frame Tx'ed */
+        if(!(fcb->frame_status & FCB_COMMAND_DONE))
+        {
+                if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
+                        return (err);
+
+      		for(i = 0; i < 10000; i++) 
+		{
+          		if(fcb->frame_status & FCB_COMMAND_DONE)
+              			break;
+        		udelay(1000);
+      		}
+
+                if(!(fcb->frame_status & FCB_COMMAND_DONE))
+                        return (HARDWARE_FAILED);
+        }
+
+        *tx_fstatus = fcb->frame_status;
+
+        return (A_FRAME_WAS_FORWARDED);
+}
+
+static int smctr_set_auth_access_pri(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+        return (POSITIVE_ACK);
+}
+
+static int smctr_set_auth_funct_class(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+        return (POSITIVE_ACK);
+}
+
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+        __u16 *correlator)
+{
+        if(rsv->svl != S_CORRELATOR)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        *correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+        return (POSITIVE_ACK);
+}
+
+static int smctr_set_error_timer_value(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv)
+{
+	__u16 err_tval;
+	int err;
+
+        if(rsv->svl != S_ERROR_TIMER_VALUE)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
+
+        smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
+
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        return (POSITIVE_ACK);
+}
+
+static int smctr_set_frame_forward(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv, __u8 dc_sc)
+{
+        if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        if((dc_sc & DC_MASK) != DC_CRS)
+        {
+                if(rsv->svl >= 2 && rsv->svl < 20)
+                	return (E_TRANSMIT_FORWARD_INVALID);
+
+                if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
+                        return (E_TRANSMIT_FORWARD_INVALID);
+        }
+
+        return (POSITIVE_ACK);
+}
+
+static int smctr_set_local_ring_num(struct net_device *dev,
+        MAC_SUB_VECTOR *rsv)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(rsv->svl != S_LOCAL_RING_NUMBER)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        if(tp->ptr_local_ring_num)
+                *(__u16 *)(tp->ptr_local_ring_num) 
+			= (rsv->svv[0] << 8 | rsv->svv[1]);
+
+        return (POSITIVE_ACK);
+}
+
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int ioaddr = dev->base_addr;
+
+        if(tp->bic_type == BIC_585_CHIP)
+                outb((tp->trc_mask | HWR_CA), ioaddr + HWR);
+        else
+        {
+                outb((tp->trc_mask | CSR_CA), ioaddr + CSR);
+                outb(tp->trc_mask, ioaddr + CSR);
+        }
+
+        return (0);
+}
+
+static void smctr_set_multicast_list(struct net_device *dev)
+{
+        if(smctr_debug > 10)
+                printk("%s: smctr_set_multicast_list\n", dev->name);
+
+        return;
+}
+
+static int smctr_set_page(struct net_device *dev, __u8 *buf)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u8 amask;
+        __u32 tptr;
+
+        tptr = (__u32)buf - (__u32)tp->ram_access;
+        amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
+        outb(amask, dev->base_addr + PR);
+
+        return (0);
+}
+
+static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
+{
+	int err;
+
+        if(rsv->svl != S_PHYSICAL_DROP)
+                return (E_SUB_VECTOR_LENGTH_ERROR);
+
+        smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
+        if((err = smctr_wait_cmd(dev)))
+                return (err);
+
+        return (POSITIVE_ACK);
+}
+
+/* Reset the ring speed to the oposite of what it was. This auto-pilot
+ * mode requires a complete reset and re-init of the adapter.
+ */
+static int smctr_set_ring_speed(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+	int err;
+
+        if(tp->media_type == MEDIA_UTP_16)
+                tp->media_type = MEDIA_UTP_4;
+        else
+                tp->media_type = MEDIA_UTP_16;
+
+        smctr_enable_16bit(dev);
+
+        /* Re-Initialize adapter's internal registers */
+        smctr_reset_adapter(dev);
+
+        if((err = smctr_init_card_real(dev)))
+                return (err);
+
+        smctr_enable_bic_int(dev);
+
+        if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+                return (err);
+
+        smctr_disable_16bit(dev);
+
+	return (0);
+}
+
+static int smctr_set_rx_look_ahead(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 sword, rword;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_set_rx_look_ahead_flag\n", dev->name);
+
+        tp->adapter_flags &= ~(FORCED_16BIT_MODE);
+        tp->adapter_flags |= RX_VALID_LOOKAHEAD;
+
+        if(tp->adapter_bus == BUS_ISA16_TYPE)
+        {
+                sword = *((__u16 *)(tp->ram_access));
+                *((__u16 *)(tp->ram_access)) = 0x1234;
+
+                smctr_disable_16bit(dev);
+                rword = *((__u16 *)(tp->ram_access));
+                smctr_enable_16bit(dev);
+
+                if(rword != 0x1234)
+                        tp->adapter_flags |= FORCED_16BIT_MODE;
+
+                *((__u16 *)(tp->ram_access)) = sword;
+        }
+
+        return (0);
+}
+
+static int smctr_set_trc_reset(int ioaddr)
+{
+        __u8 r;
+
+        r = inb(ioaddr + MSR);
+        outb(MSR_RST | r, ioaddr + MSR);
+
+        return (0);
+}
+
+/*
+ * This function can be called if the adapter is busy or not.
+ */
+static int smctr_setup_single_cmd(struct net_device *dev,
+        __u16 command, __u16 subcommand)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int err;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_setup_single_cmd\n", dev->name);
+
+        if((err = smctr_wait_while_cbusy(dev)))
+                return (err);
+
+        if((err = (unsigned int)smctr_wait_cmd(dev)))
+                return (err);
+
+        tp->acb_head->cmd_done_status   = 0;
+        tp->acb_head->cmd               = command;
+        tp->acb_head->subcmd            = subcommand;
+
+        err = smctr_issue_resume_acb_cmd(dev);
+
+        return (err);
+}
+
+/*
+ * This function can not be called with the adapter busy.
+ */
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+        __u16 command, __u16 subcommand)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        tp->acb_head->cmd_done_status   = 0;
+        tp->acb_head->cmd               = command;
+        tp->acb_head->subcmd            = subcommand;
+        tp->acb_head->data_offset_lo
+                = (__u16)TRC_POINTER(tp->misc_command_data);
+
+        return(smctr_issue_resume_acb_cmd(dev));
+}
+
+static char *smctr_malloc(struct net_device *dev, __u16 size)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        char *m;
+
+        m = (char *)(tp->ram_access + tp->sh_mem_used);
+        tp->sh_mem_used += (__u32)size;
+
+        return (m);
+}
+
+static int smctr_status_chg(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_status_chg\n", dev->name);
+
+        switch(tp->status)
+        {
+                case OPEN:
+                        break;
+
+                case CLOSED:
+                        break;
+
+                /* Interrupt driven open() completion. XXX */
+                case INITIALIZED:
+                        tp->group_address_0 = 0;
+                        tp->group_address[0] = 0;
+                        tp->group_address[1] = 0;
+                        tp->functional_address_0 = 0;
+                        tp->functional_address[0] = 0;
+                        tp->functional_address[1] = 0;
+                        smctr_open_tr(dev);
+                        break;
+
+                default:
+                        printk(KERN_INFO "%s: status change unknown %x\n",
+                                dev->name, tp->status);
+                        break;
+        }
+
+        return (0);
+}
+
+static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
+        __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        int err = 0;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_trc_send_packet\n", dev->name);
+
+        fcb->info = FCB_CHAIN_END | FCB_ENABLE_TFS;
+        if(tp->num_tx_fcbs[queue] != 1)
+                fcb->back_ptr->info = FCB_INTERRUPT_ENABLE | FCB_ENABLE_TFS;
+
+        if(tp->tx_queue_status[queue] == NOT_TRANSMITING)
+        {
+                tp->tx_queue_status[queue] = TRANSMITING;
+                err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+        }
+
+        return (err);
+}
+
+static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        __u16 status, err = 0;
+        int cstatus;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_tx_complete\n", dev->name);
+
+        while((status = tp->tx_fcb_end[queue]->frame_status) != SUCCESS)
+        {
+                if(status & 0x7e00 )
+                {
+                        err = HARDWARE_FAILED;
+                        break;
+                }
+
+                if((err = smctr_update_tx_chain(dev, tp->tx_fcb_end[queue],
+                        queue)) != SUCCESS)
+                        break;
+
+                smctr_disable_16bit(dev);
+
+                if(tp->mode_bits & UMAC)
+                {
+                        if(!(status & (FCB_TX_STATUS_AR1 | FCB_TX_STATUS_AR2)))
+                                cstatus = NO_SUCH_DESTINATION;
+                        else
+                        {
+                                if(!(status & (FCB_TX_STATUS_CR1 | FCB_TX_STATUS_CR2)))
+                                        cstatus = DEST_OUT_OF_RESOURCES;
+                                else
+                                {
+                                        if(status & FCB_TX_STATUS_E)
+                                                cstatus = MAX_COLLISIONS;
+                                        else
+                                                cstatus = SUCCESS;
+                                }
+                        }
+                }
+                else
+                        cstatus = SUCCESS;
+
+                if(queue == BUG_QUEUE)
+                        err = SUCCESS;
+
+                smctr_enable_16bit(dev);
+                if(err != SUCCESS)
+                        break;
+        }
+
+        return (err);
+}
+
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+        struct sk_buff *skb, __u8 *pbuff, unsigned int bytes)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int ram_usable;
+        __u32 flen, len, offset = 0;
+        __u8 *frag, *page;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_tx_move_frame\n", dev->name);
+
+        ram_usable = ((unsigned int)tp->ram_usable) << 10;
+        frag       = skb->data;
+        flen       = skb->len;
+
+        while(flen > 0 && bytes > 0)
+        {
+                smctr_set_page(dev, pbuff);
+
+                offset = SMC_PAGE_OFFSET(pbuff);
+
+                if(offset + flen > ram_usable)
+                        len = ram_usable - offset;
+                else
+                        len = flen;
+
+                if(len > bytes)
+                        len = bytes;
+
+                page = (char *) (offset + tp->ram_access);
+                memcpy(page, frag, len);
+
+                flen -=len;
+                bytes -= len;
+                frag += len;
+                pbuff += len;
+        }
+
+        return (0);
+}
+
+/* Update the error statistic counters for this adapter. */
+static int smctr_update_err_stats(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        struct tr_statistics *tstat = &tp->MacStat;
+
+        if(tstat->internal_errors)
+                tstat->internal_errors
+                        += *(tp->misc_command_data + 0) & 0x00ff;
+
+        if(tstat->line_errors)
+                tstat->line_errors += *(tp->misc_command_data + 0) >> 8;
+
+        if(tstat->A_C_errors)
+                tstat->A_C_errors += *(tp->misc_command_data + 1) & 0x00ff;
+
+        if(tstat->burst_errors)
+                tstat->burst_errors += *(tp->misc_command_data + 1) >> 8;
+
+        if(tstat->abort_delimiters)
+                tstat->abort_delimiters += *(tp->misc_command_data + 2) >> 8;
+
+        if(tstat->recv_congest_count)
+                tstat->recv_congest_count
+                        += *(tp->misc_command_data + 3) & 0x00ff;
+
+        if(tstat->lost_frames)
+                tstat->lost_frames
+                        += *(tp->misc_command_data + 3) >> 8;
+
+        if(tstat->frequency_errors)
+                tstat->frequency_errors += *(tp->misc_command_data + 4) & 0x00ff;
+
+        if(tstat->frame_copied_errors)
+                 tstat->frame_copied_errors
+                        += *(tp->misc_command_data + 4) >> 8;
+
+        if(tstat->token_errors)
+                tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
+
+        return (0);
+}
+
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        FCBlock *fcb;
+        BDBlock *bdb;
+        __u16 size, len;
+
+        fcb = tp->rx_fcb_curr[queue];
+        len = fcb->frame_length;
+
+        fcb->frame_status = 0;
+        fcb->info = FCB_CHAIN_END;
+        fcb->back_ptr->info = FCB_WARNING;
+
+        tp->rx_fcb_curr[queue] = tp->rx_fcb_curr[queue]->next_ptr;
+
+        /* update RX BDBs */
+        size = (len >> RX_BDB_SIZE_SHIFT);
+        if(len & RX_DATA_BUFFER_SIZE_MASK)
+                size += sizeof(BDBlock);
+        size &= (~RX_BDB_SIZE_MASK);
+
+        /* check if wrap around */
+        bdb = (BDBlock *)((__u32)(tp->rx_bdb_curr[queue]) + (__u32)(size));
+        if((__u32)bdb >= (__u32)tp->rx_bdb_end[queue])
+        {
+                bdb = (BDBlock *)((__u32)(tp->rx_bdb_head[queue])
+                        + (__u32)(bdb) - (__u32)(tp->rx_bdb_end[queue]));
+        }
+
+        bdb->back_ptr->info = BDB_CHAIN_END;
+        tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
+        tp->rx_bdb_curr[queue] = bdb;
+
+        return (0);
+}
+
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+        __u16 queue)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+
+        if(smctr_debug > 20)
+                printk("smctr_update_tx_chain\n");
+
+        if(tp->num_tx_fcbs_used[queue] <= 0)
+                return (HARDWARE_FAILED);
+        else
+        {
+                if(tp->tx_buff_used[queue] < fcb->memory_alloc)
+                {
+                        tp->tx_buff_used[queue] = 0;
+                        return (HARDWARE_FAILED);
+                }
+
+                tp->tx_buff_used[queue] -= fcb->memory_alloc;
+
+                /* if all transmit buffer are cleared
+                 * need to set the tx_buff_curr[] to tx_buff_head[]
+                 * otherwise, tx buffer will be segregate and cannot
+                 * accomodate and buffer greater than (curr - head) and
+                 * (end - curr) since we do not allow wrap around allocation.
+                 */
+                if(tp->tx_buff_used[queue] == 0)
+                        tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+
+                tp->num_tx_fcbs_used[queue]--;
+                fcb->frame_status = 0;
+                tp->tx_fcb_end[queue] = fcb->next_ptr;
+
+                return (0);
+        }
+}
+
+static int smctr_wait_cmd(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int loop_count = 0x20000;
+
+        if(smctr_debug > 10)
+                printk("%s: smctr_wait_cmd\n", dev->name);
+
+        while(loop_count)
+        {
+                if(tp->acb_head->cmd_done_status & ACB_COMMAND_DONE)
+                        break;
+                loop_count--;
+        }
+
+        if(loop_count == 0)
+                return(-1);
+
+        if(tp->acb_head->cmd_done_status & 0xff)
+                return(-1);
+
+        return (0);
+}
+
+static int smctr_wait_while_cbusy(struct net_device *dev)
+{
+        struct net_local *tp = (struct net_local *)dev->priv;
+        unsigned int timeout = 0x20000;
+        int ioaddr = dev->base_addr;
+        __u8 r;
+
+        if(tp->bic_type == BIC_585_CHIP)
+        {
+                while(timeout)
+                {
+                        r = inb(ioaddr + HWR);
+                        if((r & HWR_CBUSY) == 0)
+                                break;
+                        timeout--;
+                }
+        }
+        else
+        {
+                while(timeout)
+                {
+                        r = inb(ioaddr + CSR);
+                        if((r & CSR_CBUSY) == 0)
+                                break;
+                        timeout--;
+                }
+        }
+
+        if(timeout)
+                return (0);
+        else
+                return (-1);
+}
+
+#ifdef MODULE
+
+static struct net_device* dev_smctr[SMCTR_MAX_ADAPTERS];
+static int io[SMCTR_MAX_ADAPTERS]        = { 0, 0 };
+static int irq[SMCTR_MAX_ADAPTERS]       = { 0, 0 };
+static int mem[SMCTR_MAX_ADAPTERS]       = { 0, 0 };
+
+MODULE_PARM(io,  "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(mem, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(ringspeed, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+
+int init_module(void)
+{
+        int i;
+
+        for(i = 0; i < SMCTR_MAX_ADAPTERS; i++)
+        {
+                irq[i] = 0;
+                mem[i] = 0;
+                dev_smctr[i] = NULL;
+                dev_smctr[i] = init_trdev(dev_smctr[i], 0);
+                if(dev_smctr[i] == NULL)
+                        return (-ENOMEM);
+
+                dev_smctr[i]->base_addr = io[i];
+                dev_smctr[i]->irq       = irq[i];
+                dev_smctr[i]->mem_start = mem[i];
+                dev_smctr[i]->init      = &smctr_probe;
+
+                if(register_trdev(dev_smctr[i]) != 0)
+                {
+                        kfree_s(dev_smctr[i], sizeof(struct net_device));
+                        dev_smctr[i] = NULL;
+                        if(i == 0)
+                        {
+                                printk("%s: register_trdev() returned (<0).\n",
+                                        cardname);
+                                return (-EIO);
+                        }
+                        else
+                                return (0);
+                }
+        }
+
+        return (0);
+}
+
+void cleanup_module(void)
+{
+        int i;
+
+        for(i = 0; i < SMCTR_MAX_ADAPTERS; i++)
+        {
+                if(dev_smctr[i])
+                {
+                        unregister_trdev(dev_smctr[i]);
+                        release_region(dev_smctr[i]->base_addr,
+                                SMCTR_IO_EXTENT);
+                        if(dev_smctr[i]->irq)
+                                free_irq(dev_smctr[i]->irq, dev_smctr[i]);
+                        if(dev_smctr[i]->priv)
+                                kfree_s(dev_smctr[i]->priv,
+                                        sizeof(struct net_local));
+                        kfree_s(dev_smctr[i], sizeof(struct net_device));
+                        dev_smctr[i] = NULL;
+                }
+        }
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/smctr.h linux/drivers/net/tokenring/smctr.h
--- v2.3.37/linux/drivers/net/tokenring/smctr.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/tokenring/smctr.h	Thu Jan  6 15:01:56 2000
@@ -0,0 +1,1583 @@
+/* smctr.h: SMC Token Ring driver header for Linux
+ *
+ * Authors:
+ *  - Jay Schulist <jschlst@turbolinux.com>
+ */
+
+#ifndef __LINUX_SMCTR_H
+#define __LINUX_SMCTR_H
+
+#ifdef __KERNEL__
+
+#define MAX_TX_QUEUE 10
+
+#define SMC_HEADER_SIZE 14
+
+#define SMC_PAGE_OFFSET(X)          (((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask)
+
+#define INIT            0x0D
+#define RQ_ATTCH        0x10
+#define RQ_STATE        0x0F
+#define RQ_ADDR         0x0E
+#define CHG_PARM        0x0C
+#define RSP             0x00
+#define TX_FORWARD      0x09
+
+#define AC_FC_DAT	((3<<13) | 1)
+#define      DAT             0x07
+
+#define RPT_NEW_MON     0x25
+#define RPT_SUA_CHG     0x26
+#define RPT_ACTIVE_ERR  0x28
+#define RPT_NN_INCMP    0x27
+#define RPT_ERROR       0x29
+
+#define RQ_INIT         0x20
+#define RPT_ATTCH       0x24
+#define RPT_STATE       0x23
+#define RPT_ADDR        0x22
+
+#define POSITIVE_ACK                    0x0001
+#define A_FRAME_WAS_FORWARDED           0x8888
+
+#define      GROUP_ADDRESS                   0x2B
+#define      PHYSICAL_DROP                   0x0B
+#define      AUTHORIZED_ACCESS_PRIORITY      0x07
+#define      AUTHORIZED_FUNCTION_CLASS       0x06
+#define      FUNCTIONAL_ADDRESS              0x2C
+#define      RING_STATION_STATUS             0x29
+#define      TRANSMIT_STATUS_CODE            0x2A
+#define      IBM_PASS_SOURCE_ADDR    0x01
+#define      AC_FC_RPT_TX_FORWARD            ((0<<13) | 0)
+#define      AC_FC_RPT_STATE                 ((0<<13) | 0)
+#define      AC_FC_RPT_ADDR                  ((0<<13) | 0)
+#define      CORRELATOR                      0x09
+
+#define POSITIVE_ACK                    0x0001          /*             */
+#define E_MAC_DATA_INCOMPLETE           0x8001          /* not used    */
+#define E_VECTOR_LENGTH_ERROR           0x8002          /*             */
+#define E_UNRECOGNIZED_VECTOR_ID        0x8003          /*             */
+#define E_INAPPROPRIATE_SOURCE_CLASS    0x8004          /*             */
+#define E_SUB_VECTOR_LENGTH_ERROR       0x8005          /*             */
+#define E_TRANSMIT_FORWARD_INVALID      0x8006          /* def. by IBM */
+#define E_MISSING_SUB_VECTOR            0x8007          /*             */
+#define E_SUB_VECTOR_UNKNOWN            0x8008          /*             */
+#define E_MAC_HEADER_TOO_LONG           0x8009          /*             */
+#define E_FUNCTION_DISABLED             0x800A          /* not used    */
+
+#define A_FRAME_WAS_FORWARDED           0x8888          /* used by send_TX_FORWARD */
+
+#define UPSTREAM_NEIGHBOR_ADDRESS       0x02
+#define LOCAL_RING_NUMBER               0x03
+#define ASSIGN_PHYSICAL_DROP            0x04
+#define ERROR_TIMER_VALUE               0x05
+#define AUTHORIZED_FUNCTION_CLASS       0x06
+#define AUTHORIZED_ACCESS_PRIORITY      0x07
+#define CORRELATOR                      0x09
+#define PHYSICAL_DROP                   0x0B
+#define RESPONSE_CODE                   0x20
+#define ADDRESS_MODIFER                 0x21
+#define PRODUCT_INSTANCE_ID             0x22
+#define RING_STATION_VERSION_NUMBER     0x23
+#define WRAP_DATA                       0x26
+#define FRAME_FORWARD                   0x27
+#define STATION_IDENTIFER               0x28
+#define RING_STATION_STATUS             0x29
+#define TRANSMIT_STATUS_CODE            0x2A
+#define GROUP_ADDRESS                   0x2B
+#define FUNCTIONAL_ADDRESS              0x2C
+
+#define F_NO_SUB_VECTORS_FOUND                  0x0000
+#define F_UPSTREAM_NEIGHBOR_ADDRESS             0x0001
+#define F_LOCAL_RING_NUMBER                     0x0002
+#define F_ASSIGN_PHYSICAL_DROP                  0x0004
+#define F_ERROR_TIMER_VALUE                     0x0008
+#define F_AUTHORIZED_FUNCTION_CLASS             0x0010
+#define F_AUTHORIZED_ACCESS_PRIORITY            0x0020
+#define F_CORRELATOR                            0x0040
+#define F_PHYSICAL_DROP                         0x0080
+#define F_RESPONSE_CODE                         0x0100
+#define F_PRODUCT_INSTANCE_ID                   0x0200
+#define F_RING_STATION_VERSION_NUMBER           0x0400
+#define F_STATION_IDENTIFER                     0x0800
+#define F_RING_STATION_STATUS                   0x1000
+#define F_GROUP_ADDRESS                         0x2000
+#define F_FUNCTIONAL_ADDRESS                    0x4000
+#define F_FRAME_FORWARD                         0x8000
+
+#define R_INIT                                  0x00
+#define R_RQ_ATTCH_STATE_ADDR                   0x00
+#define R_CHG_PARM                              0x00
+#define R_TX_FORWARD                            F_FRAME_FORWARD
+
+
+#define      UPSTREAM_NEIGHBOR_ADDRESS       0x02
+#define      ADDRESS_MODIFER                 0x21
+#define      RING_STATION_VERSION_NUMBER     0x23
+#define      PRODUCT_INSTANCE_ID             0x22
+
+#define      RPT_TX_FORWARD  0x2A
+
+#define AC_FC_INIT                      (3<<13) | 0 /*                     */
+#define AC_FC_RQ_INIT                   ((3<<13) | 0) /*                     */
+#define AC_FC_RQ_ATTCH                  (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_STATE                  (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_ADDR                   (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_CHG_PARM                  (3<<13) | 0 /*                     */
+#define AC_FC_RSP                       (0<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RPT_ATTCH                 (0<<13) | 0
+
+#define S_UPSTREAM_NEIGHBOR_ADDRESS               6 + 2
+#define S_LOCAL_RING_NUMBER                       2 + 2
+#define S_ASSIGN_PHYSICAL_DROP                    4 + 2
+#define S_ERROR_TIMER_VALUE                       2 + 2
+#define S_AUTHORIZED_FUNCTION_CLASS               2 + 2
+#define S_AUTHORIZED_ACCESS_PRIORITY              2 + 2
+#define S_CORRELATOR                              2 + 2
+#define S_PHYSICAL_DROP                           4 + 2
+#define S_RESPONSE_CODE                           4 + 2
+#define S_ADDRESS_MODIFER                         2 + 2
+#define S_PRODUCT_INSTANCE_ID                    18 + 2
+#define S_RING_STATION_VERSION_NUMBER            10 + 2
+#define S_STATION_IDENTIFER                       6 + 2
+#define S_RING_STATION_STATUS                     6 + 2
+#define S_GROUP_ADDRESS                           4 + 2
+#define S_FUNCTIONAL_ADDRESS                      4 + 2
+#define S_FRAME_FORWARD                         252 + 2
+#define S_TRANSMIT_STATUS_CODE                    2 + 2
+
+#define ISB_IMC_RES0                    0x0000  /* */
+#define ISB_IMC_MAC_TYPE_3              0x0001  /* MAC_ARC_INDICATE */
+#define ISB_IMC_MAC_ERROR_COUNTERS      0x0002  /* */
+#define ISB_IMC_RES1                    0x0003  /* */
+#define ISB_IMC_MAC_TYPE_2              0x0004  /* QUE_MAC_INDICATE */
+#define ISB_IMC_TX_FRAME                0x0005  /* */
+#define ISB_IMC_END_OF_TX_QUEUE         0x0006  /* */
+#define ISB_IMC_NON_MAC_RX_RESOURCE     0x0007  /* */
+#define ISB_IMC_MAC_RX_RESOURCE         0x0008  /* */
+#define ISB_IMC_NON_MAC_RX_FRAME        0x0009  /* */
+#define ISB_IMC_MAC_RX_FRAME            0x000A  /* */
+#define ISB_IMC_TRC_FIFO_STATUS         0x000B  /* */
+#define ISB_IMC_COMMAND_STATUS          0x000C  /* */
+#define ISB_IMC_MAC_TYPE_1              0x000D  /* Self Removed */
+#define ISB_IMC_TRC_INTRNL_TST_STATUS   0x000E  /* */
+#define ISB_IMC_RES2                    0x000F  /* */
+
+#define NON_MAC_RX_RESOURCE_BW          0x10    /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FW          0x20    /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_BE          0x40    /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FE          0x80    /* shifted right 8 bits */
+#define RAW_NON_MAC_RX_RESOURCE_BW      0x1000  /* */
+#define RAW_NON_MAC_RX_RESOURCE_FW      0x2000  /* */
+#define RAW_NON_MAC_RX_RESOURCE_BE      0x4000  /* */
+#define RAW_NON_MAC_RX_RESOURCE_FE      0x8000  /* */
+
+#define MAC_RX_RESOURCE_BW              0x10    /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FW              0x20    /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_BE              0x40    /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FE              0x80    /* shifted right 8 bits */
+#define RAW_MAC_RX_RESOURCE_BW          0x1000  /* */
+#define RAW_MAC_RX_RESOURCE_FW          0x2000  /* */
+#define RAW_MAC_RX_RESOURCE_BE          0x4000  /* */
+#define RAW_MAC_RX_RESOURCE_FE          0x8000  /* */
+
+#define TRC_FIFO_STATUS_TX_UNDERRUN     0x40    /* shifted right 8 bits */
+#define TRC_FIFO_STATUS_RX_OVERRUN      0x80    /* shifted right 8 bits */
+#define RAW_TRC_FIFO_STATUS_TX_UNDERRUN 0x4000  /* */
+#define RAW_TRC_FIFO_STATUS_RX_OVERRUN  0x8000  /* */
+
+#define       CSR_CLRTINT             0x08
+
+#define MSB(X)                  ((__u8)((__u16) X >> 8))
+#define LSB(X)                  ((__u8)((__u16) X &  0xff))
+
+#define AC_FC_LOBE_MEDIA_TEST           ((3<<13) | 0)
+#define S_WRAP_DATA                             248 + 2 /* 500 + 2 */
+#define      WRAP_DATA                       0x26
+#define LOBE_MEDIA_TEST 0x08
+
+/* Destination Class (dc) */
+
+#define DC_MASK         0xF0
+#define DC_RS           0x00
+#define DC_CRS          0x40
+#define DC_RPS          0x50
+#define DC_REM          0x60
+
+/* Source Classes (sc) */
+
+#define SC_MASK         0x0F
+#define SC_RS           0x00
+#define SC_CRS          0x04
+#define SC_RPS          0x05
+#define SC_REM          0x06
+
+#define PR		0x11
+#define PR_PAGE_MASK	0x0C000
+
+#define MICROCHANNEL	0x0008
+#define INTERFACE_CHIP	0x0010
+#define BOARD_16BIT	0x0040
+#define PAGED_RAM	0x0080
+#define WD8115TA	(TOKEN_MEDIA | MICROCHANNEL | INTERFACE_CHIP | PAGED_RAM)
+#define WD8115T		(TOKEN_MEDIA | INTERFACE_CHIP | BOARD_16BIT | PAGED_RAM)
+
+#define BRD_ID_8316	0x50
+
+#define r587_SER	0x001
+#define SER_DIN		0x80
+#define SER_DOUT	0x40
+#define SER_CLK		0x20
+#define SER_ECS		0x10
+#define SER_E806	0x08
+#define SER_PNP		0x04
+#define SER_BIO		0x02
+#define SER_16B		0x01
+
+#define r587_IDR	0x004
+#define IDR_IRQ_MASK	0x0F0
+#define IDR_DCS_MASK	0x007
+#define IDR_RWS		0x008
+
+
+#define r587_BIO	0x003
+#define BIO_ENB		0x080
+#define BIO_MASK	0x03F
+
+#define r587_PCR	0x005
+#define PCR_RAMS	0x040
+
+
+
+#define NUM_ADDR_BITS	8
+
+#define ISA_MAX_ADDRESS		0x00ffffff
+
+#define SMCTR_MAX_ADAPTERS	7
+
+#define MC_TABLE_ENTRIES      16
+
+#define MAXFRAGMENTS          32
+
+#define CHIP_REV_MASK         0x3000
+
+#define MAX_TX_QS             8
+#define NUM_TX_QS_USED        3
+
+#define MAX_RX_QS             2
+#define NUM_RX_QS_USED        2
+
+#define INTEL_DATA_FORMAT	0x4000
+#define INTEL_ADDRESS_POINTER_FORMAT	0x8000
+#define PAGE_POINTER(X)		((((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask) + tp->ram_access)
+#define SWAP_WORDS(X)		(((X & 0xFFFF) << 16) | (X >> 16))
+
+#define INTERFACE_CHIP          0x0010          /* Soft Config Adapter */
+#define ADVANCED_FEATURES       0x0020          /* Adv. netw. interface features */
+#define BOARD_16BIT             0x0040          /* 16 bit capability */
+#define PAGED_RAM               0x0080          /* Adapter has paged RAM */
+
+#define PAGED_ROM               0x0100          /* Adapter has paged ROM */
+
+#define RAM_SIZE_UNKNOWN        0x0000          /* Unknown RAM size */
+#define RAM_SIZE_0K             0x0001          /* 0K  RAM */
+#define RAM_SIZE_8K             0x0002          /* 8k  RAM */
+#define RAM_SIZE_16K            0x0003          /* 16k RAM */
+#define RAM_SIZE_32K            0x0004          /* 32k RAM */
+#define RAM_SIZE_64K            0x0005          /* 64k RAM */
+#define RAM_SIZE_RESERVED_6     0x0006          /* Reserved RAM size */
+#define RAM_SIZE_RESERVED_7     0x0007          /* Reserved RAM size */
+#define RAM_SIZE_MASK           0x0007          /* Isolates RAM Size */
+
+#define TOKEN_MEDIA           0x0005
+
+#define BID_REG_0       0x00
+#define BID_REG_1       0x01
+#define BID_REG_2       0x02
+#define BID_REG_3       0x03
+#define BID_REG_4       0x04
+#define BID_REG_5       0x05
+#define BID_REG_6       0x06
+#define BID_REG_7       0x07
+#define BID_LAR_0       0x08
+#define BID_LAR_1       0x09
+#define BID_LAR_2       0x0A
+#define BID_LAR_3       0x0B
+#define BID_LAR_4       0x0C
+#define BID_LAR_5       0x0D
+
+#define BID_BOARD_ID_BYTE       0x0E
+#define BID_CHCKSM_BYTE         0x0F
+#define BID_LAR_OFFSET          0x08  
+
+#define BID_MSZ_583_BIT         0x08
+#define BID_SIXTEEN_BIT_BIT     0x01
+
+#define BID_BOARD_REV_MASK      0x1E
+
+#define BID_MEDIA_TYPE_BIT      0x01
+#define BID_SOFT_CONFIG_BIT     0x20
+#define BID_RAM_SIZE_BIT        0x40
+#define BID_BUS_TYPE_BIT        0x80
+
+#define BID_CR          0x10
+
+#define BID_TXP         0x04            /* Transmit Packet Command */
+
+#define BID_TCR_DIFF    0x0D    /* Transmit Configuration Register */
+
+#define BID_TCR_VAL     0x18            /* Value to Test 8390 or 690 */
+#define BID_PS0         0x00            /* Register Page Select 0 */
+#define BID_PS1         0x40            /* Register Page Select 1 */
+#define BID_PS2         0x80            /* Register Page Select 2 */
+#define BID_PS_MASK     0x3F            /* For Masking Off Page Select Bits */
+
+#define BID_EEPROM_0                    0x08
+#define BID_EEPROM_1                    0x09
+#define BID_EEPROM_2                    0x0A
+#define BID_EEPROM_3                    0x0B
+#define BID_EEPROM_4                    0x0C
+#define BID_EEPROM_5                    0x0D
+#define BID_EEPROM_6                    0x0E
+#define BID_EEPROM_7                    0x0F
+
+#define BID_OTHER_BIT                   0x02
+#define BID_ICR_MASK                    0x0C
+#define BID_EAR_MASK                    0x0F
+#define BID_ENGR_PAGE                   0x0A0
+#define BID_RLA                         0x10
+#define BID_EA6                         0x80
+#define BID_RECALL_DONE_MASK            0x10
+#define BID_BID_EEPROM_OVERRIDE         0xFFB0
+#define BID_EXTRA_EEPROM_OVERRIDE       0xFFD0
+#define BID_EEPROM_MEDIA_MASK           0x07
+#define BID_STARLAN_TYPE                0x00
+#define BID_ETHERNET_TYPE               0x01
+#define BID_TP_TYPE                     0x02
+#define BID_EW_TYPE                     0x03
+#define BID_TOKEN_RING_TYPE             0x04
+#define BID_UTP2_TYPE                   0x05
+#define BID_EEPROM_IRQ_MASK             0x18
+#define BID_PRIMARY_IRQ                 0x00
+#define BID_ALTERNATE_IRQ_1             0x08
+#define BID_ALTERNATE_IRQ_2             0x10
+#define BID_ALTERNATE_IRQ_3             0x18
+#define BID_EEPROM_RAM_SIZE_MASK        0xE0
+#define BID_EEPROM_RAM_SIZE_RES1        0x00
+#define BID_EEPROM_RAM_SIZE_RES2        0x20
+#define BID_EEPROM_RAM_SIZE_8K          0x40
+#define BID_EEPROM_RAM_SIZE_16K         0x60
+#define BID_EEPROM_RAM_SIZE_32K         0x80
+#define BID_EEPROM_RAM_SIZE_64K         0xA0
+#define BID_EEPROM_RAM_SIZE_RES3        0xC0
+#define BID_EEPROM_RAM_SIZE_RES4        0xE0
+#define BID_EEPROM_BUS_TYPE_MASK        0x07
+#define BID_EEPROM_BUS_TYPE_AT          0x00
+#define BID_EEPROM_BUS_TYPE_MCA         0x01
+#define BID_EEPROM_BUS_TYPE_EISA        0x02
+#define BID_EEPROM_BUS_TYPE_NEC         0x03
+#define BID_EEPROM_BUS_SIZE_MASK        0x18
+#define BID_EEPROM_BUS_SIZE_8BIT        0x00
+#define BID_EEPROM_BUS_SIZE_16BIT       0x08
+#define BID_EEPROM_BUS_SIZE_32BIT       0x10
+#define BID_EEPROM_BUS_SIZE_64BIT       0x18
+#define BID_EEPROM_BUS_MASTER           0x20
+#define BID_EEPROM_RAM_PAGING           0x40
+#define BID_EEPROM_ROM_PAGING           0x80
+#define BID_EEPROM_PAGING_MASK          0xC0
+#define BID_EEPROM_LOW_COST             0x08
+#define BID_EEPROM_IO_MAPPED            0x10
+#define BID_EEPROM_HMI                  0x01
+#define BID_EEPROM_AUTO_MEDIA_DETECT    0x01
+#define BID_EEPROM_CHIP_REV_MASK        0x0C
+
+#define BID_EEPROM_LAN_ADDR             0x30
+
+#define BID_EEPROM_MEDIA_OPTION         0x54
+#define BID_EEPROM_MEDIA_UTP            0x01
+#define BID_EEPROM_4MB_RING             0x08
+#define BID_EEPROM_16MB_RING            0x10
+#define BID_EEPROM_MEDIA_STP            0x40
+
+#define BID_EEPROM_MISC_DATA            0x56
+#define BID_EEPROM_EARLY_TOKEN_RELEASE  0x02
+
+#define CNFG_ID_8003E           0x6fc0
+#define CNFG_ID_8003S           0x6fc1
+#define CNFG_ID_8003W           0x6fc2
+#define CNFG_ID_8115TRA         0x6ec6
+#define CNFG_ID_8013E           0x61C8
+#define CNFG_ID_8013W           0x61C9
+#define CNFG_ID_BISTRO03E       0xEFE5
+#define CNFG_ID_BISTRO13E       0xEFD5
+#define CNFG_ID_BISTRO13W       0xEFD4
+#define CNFG_MSR_583    0x0
+#define CNFG_ICR_583    0x1
+#define CNFG_IAR_583    0x2
+#define CNFG_BIO_583    0x3
+#define CNFG_EAR_583    0x3
+#define CNFG_IRR_583    0x4
+#define CNFG_LAAR_584   0x5
+#define CNFG_GP2                0x7
+#define CNFG_LAAR_MASK          0x1F
+#define CNFG_LAAR_ZWS           0x20
+#define CNFG_LAAR_L16E          0x40
+#define CNFG_ICR_IR2_584        0x04
+#define CNFG_ICR_MASK       0x08
+#define CNFG_ICR_MSZ        0x08
+#define CNFG_ICR_RLA        0x10
+#define CNFG_ICR_STO        0x80
+#define CNFG_IRR_IRQS           0x60
+#define CNFG_IRR_IEN            0x80
+#define CNFG_IRR_ZWS            0x01
+#define CNFG_GP2_BOOT_NIBBLE    0x0F
+#define CNFG_IRR_OUT2       0x04
+#define CNFG_IRR_OUT1       0x02
+
+#define CNFG_SIZE_8KB           8
+#define CNFG_SIZE_16KB          16
+#define CNFG_SIZE_32KB          32
+#define CNFG_SIZE_64KB          64
+#define CNFG_SIZE_128KB     128
+#define CNFG_SIZE_256KB     256
+#define ROM_DISABLE             0x0
+
+#define CNFG_SLOT_ENABLE_BIT    0x08
+
+#define CNFG_POS_CONTROL_REG    0x096
+#define CNFG_POS_REG0           0x100
+#define CNFG_POS_REG1           0x101
+#define CNFG_POS_REG2           0x102
+#define CNFG_POS_REG3           0x103
+#define CNFG_POS_REG4           0x104
+#define CNFG_POS_REG5           0x105
+
+#define CNFG_ADAPTER_TYPE_MASK  0x0e
+
+#define SLOT_16BIT              0x0008
+#define INTERFACE_5X3_CHIP      0x0000          /* 0000 = 583 or 593 chips */
+#define NIC_690_BIT                     0x0010          /* NIC is 690 */
+#define ALTERNATE_IRQ_BIT       0x0020          /* Alternate IRQ is used */
+#define INTERFACE_584_CHIP      0x0040          /* 0001 = 584 chip */
+#define INTERFACE_594_CHIP      0x0080          /* 0010 = 594 chip */
+#define INTERFACE_585_CHIP      0x0100          /* 0100 = 585/790 chip */
+#define INTERFACE_CHIP_MASK     0x03C0          /* Isolates Intfc Chip Type */
+
+#define BOARD_16BIT             0x0040
+#define NODE_ADDR_CKSUM 	0xEE
+#define BRD_ID_8115T    	0x04
+
+#define NIC_825_BIT             0x0400          /* TRC 83C825 NIC */
+#define NIC_790_BIT             0x0800          /* NIC is 83C790 Ethernet */
+
+#define CHIP_REV_MASK           0x3000
+
+#define HWR_CBUSY			0x02
+#define HWR_CA				0x01
+
+#define MAC_QUEUE                       0
+#define NON_MAC_QUEUE                   1
+#define BUG_QUEUE                       2       /* NO RECEIVE QUEUE, ONLY TX */
+
+#define NUM_MAC_TX_FCBS                 8
+#define NUM_MAC_TX_BDBS                 NUM_MAC_TX_FCBS
+#define NUM_MAC_RX_FCBS                 7
+#define NUM_MAC_RX_BDBS                 8
+
+#define NUM_NON_MAC_TX_FCBS             6
+#define NUM_NON_MAC_TX_BDBS             NUM_NON_MAC_TX_FCBS
+
+#define NUM_NON_MAC_RX_BDBS             0       /* CALCULATED DYNAMICALLY */
+
+#define NUM_BUG_TX_FCBS                 8
+#define NUM_BUG_TX_BDBS                 NUM_BUG_TX_FCBS
+
+#define MAC_TX_BUFFER_MEMORY            1024
+#define NON_MAC_TX_BUFFER_MEMORY        (20 * 1024)
+#define BUG_TX_BUFFER_MEMORY            (NUM_BUG_TX_FCBS * 32)
+
+#define RX_BUFFER_MEMORY                0       /* CALCULATED DYNAMICALLY */
+#define RX_DATA_BUFFER_SIZE             256
+#define RX_BDB_SIZE_SHIFT               3       /* log2(RX_DATA_BUFFER_SIZE)-log2(sizeof(BDBlock)) */
+#define RX_BDB_SIZE_MASK                (sizeof(BDBlock) - 1)
+#define RX_DATA_BUFFER_SIZE_MASK        (RX_DATA_BUFFER_SIZE-1)
+
+#define NUM_OF_INTERRUPTS               0x20
+
+#define NOT_TRANSMITING                 0
+#define TRANSMITING			1
+
+#define TRC_INTERRUPT_ENABLE_MASK       0x7FF6
+
+#define UCODE_VERSION                   0x58
+
+#define UCODE_SIZE_OFFSET               0x0000  /* WORD */
+#define UCODE_CHECKSUM_OFFSET           0x0002  /* WORD */
+#define UCODE_VERSION_OFFSET            0x0004  /* BYTE */
+
+#define CS_RAM_SIZE                     0X2000
+#define CS_RAM_CHECKSUM_OFFSET          0x1FFE  /* WORD 1FFE(MSB)-1FFF(LSB)*/
+#define CS_RAM_VERSION_OFFSET           0x1FFC  /* WORD 1FFC(MSB)-1FFD(LSB)*/
+
+#define MISC_DATA_SIZE                  128
+#define NUM_OF_ACBS                     1
+
+#define ACB_COMMAND_NOT_DONE            0x0000  /* Init, command not done */
+#define ACB_COMMAND_DONE                0x8000  /* TRC says command done */
+#define ACB_COMMAND_STATUS_MASK         0x00FF  /* low byte is status */
+#define ACB_COMMAND_SUCCESSFUL          0x0000  /* means cmd was successful */
+#define ACB_NOT_CHAIN_END               0x0000  /* tell TRC more CBs in chain */
+#define ACB_CHAIN_END                   0x8000  /* tell TRC last CB in chain */
+#define ACB_COMMAND_NO_INTERRUPT        0x0000  /* tell TRC no INT after CB */
+#define ACB_COMMAND_INTERRUPT           0x2000  /* tell TRC to INT after CB */
+#define ACB_SUB_CMD_NOP                 0x0000
+#define ACB_CMD_HIC_NOP                 0x0080
+#define ACB_CMD_MCT_NOP                 0x0000
+#define ACB_CMD_MCT_TEST                0x0001
+#define ACB_CMD_HIC_TEST                0x0081
+#define ACB_CMD_INSERT                  0x0002
+#define ACB_CMD_REMOVE                  0x0003
+#define ACB_CMD_MCT_WRITE_VALUE         0x0004
+#define ACB_CMD_HIC_WRITE_VALUE         0x0084
+#define ACB_CMD_MCT_READ_VALUE          0x0005
+#define ACB_CMD_HIC_READ_VALUE          0x0085
+#define ACB_CMD_INIT_TX_RX              0x0086
+#define ACB_CMD_INIT_TRC_TIMERS         0x0006
+#define ACB_CMD_READ_TRC_STATUS         0x0007
+#define ACB_CMD_CHANGE_JOIN_STATE       0x0008
+#define ACB_CMD_RESERVED_9              0x0009
+#define ACB_CMD_RESERVED_A              0x000A
+#define ACB_CMD_RESERVED_B              0x000B
+#define ACB_CMD_RESERVED_C              0x000C
+#define ACB_CMD_RESERVED_D              0x000D
+#define ACB_CMD_RESERVED_E              0x000E
+#define ACB_CMD_RESERVED_F              0x000F
+
+#define TRC_MAC_REGISTERS_TEST          0x0000
+#define TRC_INTERNAL_LOOPBACK           0x0001
+#define TRC_TRI_LOOPBACK                0x0002
+#define TRC_INTERNAL_ROM_TEST           0x0003
+#define TRC_LOBE_MEDIA_TEST             0x0004
+#define TRC_ANALOG_TEST                 0x0005
+#define TRC_HOST_INTERFACE_REG_TEST     0x0003
+
+#define TEST_DMA_1                      0x0000
+#define TEST_DMA_2                      0x0001
+#define TEST_MCT_ROM                    0x0002
+#define HIC_INTERNAL_DIAG               0x0003
+
+#define ABORT_TRANSMIT_PRIORITY_0       0x0001
+#define ABORT_TRANSMIT_PRIORITY_1       0x0002
+#define ABORT_TRANSMIT_PRIORITY_2       0x0004
+#define ABORT_TRANSMIT_PRIORITY_3       0x0008
+#define ABORT_TRANSMIT_PRIORITY_4       0x0010
+#define ABORT_TRANSMIT_PRIORITY_5       0x0020
+#define ABORT_TRANSMIT_PRIORITY_6       0x0040
+#define ABORT_TRANSMIT_PRIORITY_7       0x0080
+
+#define TX_PENDING_PRIORITY_0           0x0001
+#define TX_PENDING_PRIORITY_1           0x0002
+#define TX_PENDING_PRIORITY_2           0x0004
+#define TX_PENDING_PRIORITY_3           0x0008
+#define TX_PENDING_PRIORITY_4           0x0010
+#define TX_PENDING_PRIORITY_5           0x0020
+#define TX_PENDING_PRIORITY_6           0x0040
+#define TX_PENDING_PRIORITY_7           0x0080
+
+#define FCB_FRAME_LENGTH                0x100
+#define FCB_COMMAND_DONE                0x8000  /* FCB Word 0 */
+#define FCB_NOT_CHAIN_END               0x0000  /* FCB Word 1 */
+#define FCB_CHAIN_END                   0x8000
+#define FCB_NO_WARNING                  0x0000
+#define FCB_WARNING                     0x4000
+#define FCB_INTERRUPT_DISABLE           0x0000
+#define FCB_INTERRUPT_ENABLE            0x2000
+
+#define FCB_ENABLE_IMA                  0x0008
+#define FCB_ENABLE_TES                  0x0004  /* Guarantee Tx before Int */
+#define FCB_ENABLE_TFS                  0x0002  /* Post Tx Frame Status */
+#define FCB_ENABLE_NTC                  0x0001  /* No Tx CRC */
+
+#define FCB_TX_STATUS_CR2               0x0004
+#define FCB_TX_STATUS_AR2               0x0008
+#define FCB_TX_STATUS_CR1               0x0040
+#define FCB_TX_STATUS_AR1               0x0080
+#define FCB_TX_AC_BITS                  (FCB_TX_STATUS_AR1+FCB_TX_STATUS_AR2+FCB_TX_STATUS_CR1+FCB_TX_STATUS_CR2)
+#define FCB_TX_STATUS_E                 0x0100
+
+#define FCB_RX_STATUS_ANY_ERROR         0x0001
+#define FCB_RX_STATUS_FCS_ERROR         0x0002
+
+#define FCB_RX_STATUS_IA_MATCHED        0x0400
+#define FCB_RX_STATUS_IGA_BSGA_MATCHED  0x0500
+#define FCB_RX_STATUS_FA_MATCHED        0x0600
+#define FCB_RX_STATUS_BA_MATCHED        0x0700
+#define FCB_RX_STATUS_DA_MATCHED        0x0400
+#define FCB_RX_STATUS_SOURCE_ROUTING    0x0800
+
+#define BDB_BUFFER_SIZE                 0x100
+#define BDB_NOT_CHAIN_END               0x0000
+#define BDB_CHAIN_END                   0x8000
+#define BDB_NO_WARNING                  0x0000
+#define BDB_WARNING                     0x4000
+
+#define ERROR_COUNTERS_CHANGED          0x0001
+#define TI_NDIS_RING_STATUS_CHANGED     0x0002
+#define UNA_CHANGED                     0x0004
+#define READY_TO_SEND_RQ_INIT           0x0008
+
+#define SCGB_ADDRESS_POINTER_FORMAT     INTEL_ADDRESS_POINTER_FORMAT
+#define SCGB_DATA_FORMAT                INTEL_DATA_FORMAT
+#define SCGB_MULTI_WORD_CONTROL         0
+#define SCGB_BURST_LENGTH               0x000E  /* DMA Burst Length */
+
+#define SCGB_CONFIG                     (INTEL_ADDRESS_POINTER_FORMAT+INTEL_DATA_FORMAT+SCGB_BURST_LENGTH)
+
+#define ISCP_BLOCK_SIZE                 0x0A
+#define RAM_SIZE                        0x10000
+#define INIT_SYS_CONFIG_PTR_OFFSET      (RAM_SIZE-ISCP_BLOCK_SIZE)
+#define SCGP_BLOCK_OFFSET               0
+
+#define SCLB_NOT_VALID                  0x0000  /* Initially, SCLB not valid */
+#define SCLB_VALID                      0x8000  /* Host tells TRC SCLB valid */
+#define SCLB_PROCESSED                  0x0000  /* TRC says SCLB processed */
+#define SCLB_RESUME_CONTROL_NOT_VALID   0x0000  /* Initially, RC not valid */
+#define SCLB_RESUME_CONTROL_VALID       0x4000  /* Host tells TRC RC valid */
+#define SCLB_IACK_CODE_NOT_VALID        0x0000  /* Initially, IACK not valid */
+#define SCLB_IACK_CODE_VALID            0x2000  /* Host tells TRC IACK valid */
+#define SCLB_CMD_NOP                    0x0000
+#define SCLB_CMD_REMOVE                 0x0001
+#define SCLB_CMD_SUSPEND_ACB_CHAIN      0x0002
+#define SCLB_CMD_SET_INTERRUPT_MASK     0x0003
+#define SCLB_CMD_CLEAR_INTERRUPT_MASK   0x0004
+#define SCLB_CMD_RESERVED_5             0x0005
+#define SCLB_CMD_RESERVED_6             0x0006
+#define SCLB_CMD_RESERVED_7             0x0007
+#define SCLB_CMD_RESERVED_8             0x0008
+#define SCLB_CMD_RESERVED_9             0x0009
+#define SCLB_CMD_RESERVED_A             0x000A
+#define SCLB_CMD_RESERVED_B             0x000B
+#define SCLB_CMD_RESERVED_C             0x000C
+#define SCLB_CMD_RESERVED_D             0x000D
+#define SCLB_CMD_RESERVED_E             0x000E
+#define SCLB_CMD_RESERVED_F             0x000F
+
+#define SCLB_RC_ACB                     0x0001  /* Action Command Block Chain */
+#define SCLB_RC_RES0                    0x0002  /* Always Zero */
+#define SCLB_RC_RES1                    0x0004  /* Always Zero */
+#define SCLB_RC_RES2                    0x0008  /* Always Zero */
+#define SCLB_RC_RX_MAC_FCB              0x0010  /* RX_MAC_FCB Chain */
+#define SCLB_RC_RX_MAC_BDB              0x0020  /* RX_MAC_BDB Chain */
+#define SCLB_RC_RX_NON_MAC_FCB          0x0040  /* RX_NON_MAC_FCB Chain */
+#define SCLB_RC_RX_NON_MAC_BDB          0x0080  /* RX_NON_MAC_BDB Chain */
+#define SCLB_RC_TFCB0                   0x0100  /* TX Priority 0 FCB Chain */
+#define SCLB_RC_TFCB1                   0x0200  /* TX Priority 1 FCB Chain */
+#define SCLB_RC_TFCB2                   0x0400  /* TX Priority 2 FCB Chain */
+#define SCLB_RC_TFCB3                   0x0800  /* TX Priority 3 FCB Chain */
+#define SCLB_RC_TFCB4                   0x1000  /* TX Priority 4 FCB Chain */
+#define SCLB_RC_TFCB5                   0x2000  /* TX Priority 5 FCB Chain */
+#define SCLB_RC_TFCB6                   0x4000  /* TX Priority 6 FCB Chain */
+#define SCLB_RC_TFCB7                   0x8000  /* TX Priority 7 FCB Chain */
+
+#define SCLB_IMC_RES0                   0x0001  /* */
+#define SCLB_IMC_MAC_TYPE_3             0x0002  /* MAC_ARC_INDICATE */
+#define SCLB_IMC_MAC_ERROR_COUNTERS     0x0004  /* */
+#define SCLB_IMC_RES1                   0x0008  /* */
+#define SCLB_IMC_MAC_TYPE_2             0x0010  /* QUE_MAC_INDICATE */
+#define SCLB_IMC_TX_FRAME               0x0020  /* */
+#define SCLB_IMC_END_OF_TX_QUEUE        0x0040  /* */
+#define SCLB_IMC_NON_MAC_RX_RESOURCE    0x0080  /* */
+#define SCLB_IMC_MAC_RX_RESOURCE        0x0100  /* */
+#define SCLB_IMC_NON_MAC_RX_FRAME       0x0200  /* */
+#define SCLB_IMC_MAC_RX_FRAME           0x0400  /* */
+#define SCLB_IMC_TRC_FIFO_STATUS        0x0800  /* */
+#define SCLB_IMC_COMMAND_STATUS         0x1000  /* */
+#define SCLB_IMC_MAC_TYPE_1             0x2000  /* Self Removed */
+#define SCLB_IMC_TRC_INTRNL_TST_STATUS  0x4000  /* */
+#define SCLB_IMC_RES2                   0x8000  /* */
+
+#define DMA_TRIGGER                     0x0004
+#define FREQ_16MB_BIT                   0x0010
+#define THDREN                          0x0020
+#define CFG0_RSV1                       0x0040
+#define CFG0_RSV2                       0x0080
+#define ETREN                           0x0100
+#define RX_OWN_BIT                      0x0200
+#define RXATMAC                         0x0400
+#define PROMISCUOUS_BIT                 0x0800
+#define USETPT                          0x1000
+#define SAVBAD_BIT                      0x2000
+#define ONEQUE                          0x4000
+#define NO_AUTOREMOVE                   0x8000
+
+#define RX_FCB_AREA_8316        0x00000000
+#define RX_BUFF_AREA_8316       0x00000000
+
+#define TRC_POINTER(X)          ((unsigned long)(X) - tp->ram_access)
+#define RX_FCB_TRC_POINTER(X)   ((unsigned long)(X) - tp->ram_access + RX_FCB_AREA_8316)
+#define RX_BUFF_TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access + RX_BUFF_AREA_8316)
+
+// Offset 0: MSR - Memory Select Register
+//
+#define r587_MSR        0x000   // Register Offset
+//#define       MSR_RST         0x080   // LAN Controller Reset
+#define MSR_MENB        0x040   // Shared Memory Enable
+#define MSR_RA18        0x020   // Ram Address bit 18   (583, 584, 587)
+#define MSR_RA17        0x010   // Ram Address bit 17   (583, 584, 585/790)
+#define MSR_RA16        0x008   // Ram Address bit 16   (583, 584, 585/790)
+#define MSR_RA15        0x004   // Ram Address bit 15   (583, 584, 585/790)
+#define MSR_RA14        0x002   // Ram Address bit 14   (583, 584, 585/790)
+#define MSR_RA13        0x001   // Ram Address bit 13   (583, 584, 585/790)
+
+#define MSR_MASK        0x03F   // Mask for Address bits RA18-RA13 (583, 584, 587)
+
+#define MSR                     0x00
+#define IRR                     0x04
+#define HWR                     0x04
+#define LAAR                    0x05
+#define IMCCR                   0x05
+#define LAR0                    0x08
+#define BDID                    0x0E    // Adapter ID byte register offset
+#define CSR                     0x10
+#define PR                      0x11
+
+#define MSR_RST                 0x80
+#define MSR_MEMB                0x40
+#define MSR_0WS                 0x20
+
+#define FORCED_16BIT_MODE       0x0002
+
+#define INTERFRAME_SPACING_16           0x0003  /* 6 bytes */
+#define INTERFRAME_SPACING_4            0x0001  /* 2 bytes */
+#define MULTICAST_ADDRESS_BIT           0x0010
+#define NON_SRC_ROUTING_BIT             0x0020
+
+#define LOOPING_MODE_MASK       0x0007
+
+/*
+ * Decode firmware defines.
+ */
+#define SWAP_BYTES(X)		((X & 0xff) << 8) | (X >> 8)
+#define WEIGHT_OFFSET		5
+#define TREE_SIZE_OFFSET	9
+#define TREE_OFFSET		11
+
+/* The Huffman Encoding Tree is constructed of these nodes. */
+typedef struct {
+	__u8	llink;	/* Short version of above node. */
+	__u8	tag;
+	__u8	info;	/* This node is used on decodes. */
+	__u8	rlink;
+} DECODE_TREE_NODE;
+
+#define ROOT	0	/* Branch value. */
+#define LEAF	0	/* Tag field value. */
+#define BRANCH	1	/* Tag field value. */
+
+/*
+ * Multicast Table Structure
+ */
+typedef struct {
+        __u8    address[6];
+        __u8    instance_count;
+} McTable;
+
+/*
+ * Fragment Descriptor Definition
+ */
+typedef struct {
+        __u8  *fragment_ptr;
+        __u32   fragment_length;
+} FragmentStructure;
+
+/*
+ * Data Buffer Structure Definition
+ */
+typedef struct {
+        __u32 fragment_count;
+        FragmentStructure       fragment_list[MAXFRAGMENTS];
+} DataBufferStructure;
+
+#pragma pack(1)
+typedef struct {
+                __u8    IType;
+                __u8    ISubtype;
+} Interrupt_Status_Word;
+
+#pragma pack(1)
+typedef struct BDBlockType {
+                __u16                   info;                   /* 02 */
+                __u32                   trc_next_ptr;           /* 06 */
+                __u32                   trc_data_block_ptr;     /* 10 */
+                __u16                   buffer_length;          /* 12 */
+
+                __u16                   *data_block_ptr;        /* 16 */
+                struct  BDBlockType     *next_ptr;              /* 20 */
+                struct  BDBlockType     *back_ptr;              /* 24 */
+                __u8                    filler[8];              /* 32 */
+} BDBlock;
+
+#pragma pack(1)
+typedef struct FCBlockType {
+                __u16                   frame_status;           /* 02 */
+                __u16                   info;                   /* 04 */
+                __u32                   trc_next_ptr;           /* 08 */
+                __u32                   trc_bdb_ptr;            /* 12 */
+                __u16                   frame_length;           /* 14 */
+
+                BDBlock                 *bdb_ptr;               /* 18 */
+                struct  FCBlockType     *next_ptr;              /* 22 */
+                struct  FCBlockType     *back_ptr;              /* 26 */
+                __u16                   memory_alloc;           /* 28 */
+                __u8                    filler[4];              /* 32 */
+
+} FCBlock;
+
+#pragma pack(1)
+typedef struct SBlockType{
+                __u8                           Internal_Error_Count;
+                __u8                           Line_Error_Count;
+                __u8                           AC_Error_Count;
+                __u8                           Burst_Error_Count;
+                __u8                            RESERVED_COUNTER_0;
+                __u8                            AD_TRANS_Count;
+                __u8                            RCV_Congestion_Count;
+                __u8                            Lost_FR_Error_Count;
+                __u8                            FREQ_Error_Count;
+                __u8                            FR_Copied_Error_Count;
+                __u8                            RESERVED_COUNTER_1;
+                __u8                            Token_Error_Count;
+
+                __u16                           TI_NDIS_Ring_Status;
+                __u16                           BCN_Type;
+                __u16                           Error_Code;
+                __u16                           SA_of_Last_AMP_SMP[3];
+                __u16                           UNA[3];
+                __u16                           Ucode_Version_Number;
+                __u16                           Status_CHG_Indicate;
+                __u16                           RESERVED_STATUS_0;
+} SBlock;
+
+#pragma pack(1)
+typedef struct ACBlockType {
+                __u16                   cmd_done_status;    /* 02 */
+                __u16                   cmd_info;           /* 04 */
+                __u32                   trc_next_ptr;           /* 08 */
+                __u16                   cmd;                /* 10 */
+                __u16                   subcmd;             /* 12 */
+                __u16                   data_offset_lo;         /* 14 */
+                __u16                   data_offset_hi;         /* 16 */
+
+                struct  ACBlockType     *next_ptr;              /* 20 */
+
+                __u8                    filler[12];             /* 32 */
+} ACBlock;
+
+#define NUM_OF_INTERRUPTS               0x20
+
+#pragma pack(1)
+typedef struct {
+                Interrupt_Status_Word   IStatus[NUM_OF_INTERRUPTS];
+} ISBlock;
+
+#pragma pack(1)
+typedef struct {
+                __u16                   valid_command;          /* 02 */
+                __u16                   iack_code;              /* 04 */
+                __u16                   resume_control;         /* 06 */
+                __u16                   int_mask_control;       /* 08 */
+                __u16                   int_mask_state;         /* 10 */
+
+                __u8                    filler[6];              /* 16 */
+} SCLBlock;
+
+#pragma pack(1)
+typedef struct
+{
+                __u16                   config;                 /* 02 */
+                __u32                   trc_sclb_ptr;           /* 06 */
+                __u32                   trc_acb_ptr;            /* 10 */
+                __u32                   trc_isb_ptr;            /* 14 */
+                __u16                   isbsiz;                 /* 16 */
+
+                SCLBlock                *sclb_ptr;              /* 20 */
+                ACBlock                 *acb_ptr;               /* 24 */
+                ISBlock                 *isb_ptr;               /* 28 */
+
+                __u16                   Non_Mac_Rx_Bdbs;        /* 30 DEBUG */
+                __u8                    filler[2];              /* 32 */
+
+} SCGBlock;
+
+#pragma pack(1)
+typedef struct
+{
+	__u32		trc_scgb_ptr;
+	SCGBlock	*scgb_ptr;
+} ISCPBlock;
+#pragma pack()
+
+typedef struct net_local {
+	ISCPBlock       *iscpb_ptr;
+        SCGBlock        *scgb_ptr;
+        SCLBlock        *sclb_ptr;
+        ISBlock         *isb_ptr;
+
+	ACBlock         *acb_head;
+        ACBlock         *acb_curr;
+        ACBlock         *acb_next;
+
+	__u8		adapter_name[12];
+
+	__u16		num_rx_bdbs	[NUM_RX_QS_USED];
+	__u16		num_rx_fcbs	[NUM_RX_QS_USED];
+
+	__u16		num_tx_bdbs	[NUM_TX_QS_USED];
+	__u16		num_tx_fcbs	[NUM_TX_QS_USED];
+
+	__u16		num_of_tx_buffs;
+
+	__u16		tx_buff_size	[NUM_TX_QS_USED];
+	__u16		tx_buff_used	[NUM_TX_QS_USED];
+	__u16		tx_queue_status	[NUM_TX_QS_USED];
+
+	FCBlock		*tx_fcb_head[NUM_TX_QS_USED];
+	FCBlock		*tx_fcb_curr[NUM_TX_QS_USED];
+	FCBlock		*tx_fcb_end[NUM_TX_QS_USED];
+	BDBlock		*tx_bdb_head[NUM_TX_QS_USED];
+	__u16		*tx_buff_head[NUM_TX_QS_USED];
+	__u16		*tx_buff_end[NUM_TX_QS_USED];
+	__u16		*tx_buff_curr[NUM_TX_QS_USED];
+	__u16		num_tx_fcbs_used[NUM_TX_QS_USED];
+
+	FCBlock		*rx_fcb_head[NUM_RX_QS_USED];
+	FCBlock		*rx_fcb_curr[NUM_RX_QS_USED];
+	BDBlock		*rx_bdb_head[NUM_RX_QS_USED];
+	BDBlock		*rx_bdb_curr[NUM_RX_QS_USED];
+	BDBlock		*rx_bdb_end[NUM_RX_QS_USED];
+	__u16		*rx_buff_head[NUM_RX_QS_USED];
+	__u16		*rx_buff_end[NUM_RX_QS_USED];
+
+	__u32		*ptr_local_ring_num;
+
+	__u32		sh_mem_used;
+
+	__u16		page_offset_mask;
+
+	__u16		authorized_function_classes;
+	__u16		authorized_access_priority;
+
+        __u16            num_acbs;
+        __u16            num_acbs_used;
+        __u16            acb_pending;
+
+	__u16		current_isb_index;
+
+	__u8            monitor_state;
+	__u8		monitor_state_ready;
+	__u16		ring_status;
+	__u8		ring_status_flags;
+	__u8		current_ring_status;
+	__u8		state;
+
+	__u8		join_state;
+
+	__u32		*ptr_una;
+	__u32		*ptr_bcn_type;
+	__u32		*ptr_tx_fifo_underruns;
+	__u32		*ptr_rx_fifo_underruns;
+	__u32		*ptr_rx_fifo_overruns;
+	__u32		*ptr_tx_fifo_overruns;
+	__u32		*ptr_tx_fcb_overruns;
+	__u32		*ptr_rx_fcb_overruns;
+	__u32		*ptr_tx_bdb_overruns;
+	__u32		*ptr_rx_bdb_overruns;
+
+	__u16		receive_queue_number;
+
+	__u8		rx_fifo_overrun_count;
+	__u8		tx_fifo_overrun_count;
+
+	__u16            adapter_flags;
+	__u16		adapter_flags1;
+	__u16            *misc_command_data;
+	__u16            max_packet_size;
+
+	__u16            config_word0;
+        __u16            config_word1;
+
+	__u8            trc_mask;
+
+	__u16            source_ring_number;
+        __u16            target_ring_number;
+
+	__u16		microcode_version;
+
+	__u16            bic_type;
+        __u16            nic_type;
+        __u16            board_id;
+
+	__u16            rom_size;
+	__u32		rom_base;
+        __u16            ram_size;
+        __u16            ram_usable;
+	__u32		ram_base;
+	__u32		ram_access;
+
+	__u16            extra_info;
+        __u16            mode_bits;
+	__u16		media_menu;
+	__u16		media_type;
+	__u16		adapter_bus;
+
+	__u16		status;
+	__u16            receive_mask;
+
+	__u16            group_address_0;
+        __u16            group_address[2];
+        __u16            functional_address_0;
+        __u16            functional_address[2];
+        __u16            bitwise_group_address[2];
+
+	__u8            *ptr_ucode;
+
+	__u8		cleanup;
+
+	struct sk_buff_head SendSkbQueue;
+        __u16 QueueSkb;
+
+	struct tr_statistics MacStat;   /* MAC statistics structure */
+} NET_LOCAL;
+
+/************************************
+ * SNMP-ON-BOARD Agent Link Structure
+ ************************************/
+
+typedef struct {
+        __u8           LnkSigStr[12]; /* signature string "SmcLinkTable" */
+        __u8           LnkDrvTyp;     /* 1=Redbox ODI, 2=ODI DOS, 3=ODI OS/2, 4=NDIS DOS */
+        __u8           LnkFlg;        /* 0 if no agent linked, 1 if agent linked */
+        void           *LnkNfo;       /* routine which returns pointer to NIC info */
+        void           *LnkAgtRcv;    /* pointer to agent receive trap entry */
+        void           *LnkAgtXmt;            /* pointer to agent transmit trap
+entry  */
+void           *LnkGet;                  /* pointer to NIC receive data
+copy routine */
+        void           *LnkSnd;                  /* pointer to NIC send routine
+*/
+        void           *LnkRst;                  /* pointer to NIC driver reset
+routine */
+        void           *LnkMib;                  /* pointer to MIB data base */
+        void           *LnkMibAct;            /* pointer to MIB action routine list */
+        __u16           LnkCntOffset;  /* offset to error counters */
+        __u16           LnkCntNum;     /* number of error counters */
+        __u16           LnkCntSize;    /* size of error counters i.e. 32 = 32 bits */
+        void           *LnkISR;       /* pointer to interrupt vector */
+        __u8           LnkFrmTyp;     /* 1=Ethernet, 2=Token Ring */
+        __u8           LnkDrvVer1 ;   /* driver major version */
+        __u8           LnkDrvVer2 ;   /* driver minor version */
+} AgentLink;
+
+/*
+ * Definitions for pcm_card_flags(bit_mapped)
+ */
+#define REG_COMPLETE   0x0001
+#define INSERTED       0x0002
+#define PCC_INSERTED   0x0004         /* 1=currently inserted, 0=cur removed */
+
+/*
+ * Adapter RAM test patterns
+ */
+#define RAM_PATTERN_1  0x55AA
+#define RAM_PATTERN_2  0x9249
+#define RAM_PATTERN_3  0xDB6D
+
+/*
+ * definitions for RAM test
+ */
+#define ROM_SIGNATURE  0xAA55
+#define MIN_ROM_SIZE   0x2000
+
+/*
+ * Return Codes
+ */
+#define SUCCESS                 0x0000
+#define ADAPTER_AND_CONFIG      0x0001
+#define ADAPTER_NO_CONFIG       0x0002
+#define NOT_MY_INTERRUPT        0x0003
+#define FRAME_REJECTED          0x0004
+#define EVENTS_DISABLED         0x0005
+#define OUT_OF_RESOURCES        0x0006
+#define INVALID_PARAMETER       0x0007
+#define INVALID_FUNCTION        0x0008
+#define INITIALIZE_FAILED       0x0009
+#define CLOSE_FAILED            0x000A
+#define MAX_COLLISIONS          0x000B
+#define NO_SUCH_DESTINATION     0x000C
+#define BUFFER_TOO_SMALL_ERROR  0x000D
+#define ADAPTER_CLOSED          0x000E
+#define UCODE_NOT_PRESENT       0x000F
+#define FIFO_UNDERRUN           0x0010
+#define DEST_OUT_OF_RESOURCES   0x0011
+#define ADAPTER_NOT_INITIALIZED 0x0012
+#define PENDING                 0x0013
+#define UCODE_PRESENT           0x0014
+#define NOT_INIT_BY_BRIDGE      0x0015
+
+#define OPEN_FAILED             0x0080
+#define HARDWARE_FAILED         0x0081
+#define SELF_TEST_FAILED        0x0082
+#define RAM_TEST_FAILED         0x0083
+#define RAM_CONFLICT            0x0084
+#define ROM_CONFLICT            0x0085
+#define UNKNOWN_ADAPTER         0x0086
+#define CONFIG_ERROR            0x0087
+#define CONFIG_WARNING          0x0088
+#define NO_FIXED_CNFG           0x0089
+#define EEROM_CKSUM_ERROR       0x008A
+#define ROM_SIGNATURE_ERROR     0x008B
+#define ROM_CHECKSUM_ERROR      0x008C
+#define ROM_SIZE_ERROR          0x008D
+#define UNSUPPORTED_NIC_CHIP    0x008E
+#define NIC_REG_ERROR           0x008F
+#define BIC_REG_ERROR           0x0090
+#define MICROCODE_TEST_ERROR    0x0091
+#define LOBE_MEDIA_TEST_FAILED  0x0092
+
+#define ADAPTER_FOUND_LAN_CORRUPT 0x009B
+
+#define ADAPTER_NOT_FOUND       0xFFFF
+
+#define ILLEGAL_FUNCTION        INVALID_FUNCTION
+
+/* Errors */
+#define IO_BASE_INVALID         0x0001
+#define IO_BASE_RANGE           0x0002
+#define IRQ_INVALID             0x0004
+#define IRQ_RANGE               0x0008
+#define RAM_BASE_INVALID        0x0010
+#define RAM_BASE_RANGE          0x0020
+#define RAM_SIZE_RANGE          0x0040
+#define MEDIA_INVALID           0x0800
+
+/* Warnings */
+#define IRQ_MISMATCH            0x0080
+#define RAM_BASE_MISMATCH       0x0100
+#define RAM_SIZE_MISMATCH       0x0200
+#define BUS_MODE_MISMATCH       0x0400
+
+#define RX_CRC_ERROR                            0x01
+#define RX_ALIGNMENT_ERROR              0x02
+#define RX_HW_FAILED                            0x80
+
+/*
+ * Definitions for the field RING_STATUS_FLAGS
+ */
+#define RING_STATUS_CHANGED                     0X01
+#define MONITOR_STATE_CHANGED                   0X02
+#define JOIN_STATE_CHANGED                      0X04
+
+/*
+ * Definitions for the field JOIN_STATE
+ */
+#define JS_BYPASS_STATE                         0x00
+#define JS_LOBE_TEST_STATE                      0x01
+#define JS_DETECT_MONITOR_PRESENT_STATE         0x02
+#define JS_AWAIT_NEW_MONITOR_STATE              0x03
+#define JS_DUPLICATE_ADDRESS_TEST_STATE         0x04
+#define JS_NEIGHBOR_NOTIFICATION_STATE          0x05
+#define JS_REQUEST_INITIALIZATION_STATE         0x06
+#define JS_JOIN_COMPLETE_STATE                  0x07
+#define JS_BYPASS_WAIT_STATE                    0x08
+
+/*
+ * Definitions for the field MONITOR_STATE
+ */
+#define MS_MONITOR_FSM_INACTIVE                 0x00
+#define MS_REPEAT_BEACON_STATE                  0x01
+#define MS_REPEAT_CLAIM_TOKEN_STATE             0x02
+#define MS_TRANSMIT_CLAIM_TOKEN_STATE           0x03
+#define MS_STANDBY_MONITOR_STATE                0x04
+#define MS_TRANSMIT_BEACON_STATE                0x05
+#define MS_ACTIVE_MONITOR_STATE                 0x06
+#define MS_TRANSMIT_RING_PURGE_STATE            0x07
+#define MS_BEACON_TEST_STATE                    0x09
+
+/*
+ * Definitions for the bit-field RING_STATUS
+ */
+#define SIGNAL_LOSS                             0x8000
+#define HARD_ERROR                              0x4000
+#define SOFT_ERROR                              0x2000
+#define TRANSMIT_BEACON                         0x1000
+#define LOBE_WIRE_FAULT                         0x0800
+#define AUTO_REMOVAL_ERROR                      0x0400
+#define REMOVE_RECEIVED                         0x0100
+#define COUNTER_OVERFLOW                        0x0080
+#define SINGLE_STATION                          0x0040
+#define RING_RECOVERY                           0x0020
+
+/*
+ * Definitions for the field BUS_TYPE
+ */
+#define AT_BUS                  0x00
+#define MCA_BUS                 0x01
+#define EISA_BUS                0x02
+#define PCI_BUS                 0x03
+#define PCMCIA_BUS              0x04
+
+/*
+ * Definitions for adapter_flags
+ */
+#define RX_VALID_LOOKAHEAD      0x0001
+#define FORCED_16BIT_MODE       0x0002
+#define ADAPTER_DISABLED        0x0004
+#define TRANSMIT_CHAIN_INT      0x0008
+#define EARLY_RX_FRAME          0x0010
+#define EARLY_TX                0x0020
+#define EARLY_RX_COPY           0x0040
+#define USES_PHYSICAL_ADDR      0x0080		/* Rsvd for DEC PCI and 9232 */
+#define NEEDS_PHYSICAL_ADDR  	0x0100       	/* Reserved*/
+#define RX_STATUS_PENDING       0x0200
+#define ERX_DISABLED         	0x0400       	/* EARLY_RX_ENABLE rcv_mask */
+#define ENABLE_TX_PENDING       0x0800
+#define ENABLE_RX_PENDING       0x1000
+#define PERM_CLOSE              0x2000  
+#define IO_MAPPED               0x4000  	/* IOmapped bus interface 795 */
+#define ETX_DISABLED            0x8000
+
+
+/*
+ * Definitions for adapter_flags1
+ */
+#define TX_PHY_RX_VIRT          0x0001 
+#define NEEDS_HOST_RAM          0x0002
+#define NEEDS_MEDIA_TYPE        0x0004
+#define EARLY_RX_DONE           0x0008
+#define PNP_BOOT_BIT            0x0010  /* activates PnP & config on power-up */
+                                        /* clear => regular PnP operation */
+#define PNP_ENABLE              0x0020  /* regular PnP operation clear => */
+                                        /* no PnP, overrides PNP_BOOT_BIT */
+#define SATURN_ENABLE           0x0040
+
+#define ADAPTER_REMOVABLE       0x0080 	/* adapter is hot swappable */
+#define TX_PHY                  0x0100  /* Uses physical address for tx bufs */
+#define RX_PHY                  0x0200  /* Uses physical address for rx bufs */
+#define TX_VIRT                 0x0400  /* Uses virtual addr for tx bufs */
+#define RX_VIRT                 0x0800 
+#define NEEDS_SERVICE           0x1000 
+
+/*
+ * Adapter Status Codes
+ */
+#define OPEN                    0x0001
+#define INITIALIZED             0x0002
+#define CLOSED                  0x0003
+#define FAILED                  0x0005
+#define NOT_INITIALIZED         0x0006
+#define IO_CONFLICT             0x0007
+#define CARD_REMOVED            0x0008
+#define CARD_INSERTED           0x0009
+
+/*
+ * Mode Bit Definitions
+ */
+#define INTERRUPT_STATUS_BIT    0x8000  /* PC Interrupt Line: 0 = Not Enabled */
+#define BOOT_STATUS_MASK        0x6000  /* Mask to isolate BOOT_STATUS */
+#define BOOT_INHIBIT            0x0000  /* BOOT_STATUS is 'inhibited' */
+#define BOOT_TYPE_1             0x2000  /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_2             0x4000  /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_3             0x6000  /* Unused BOOT_STATUS value */
+#define ZERO_WAIT_STATE_MASK    0x1800  /* Mask to isolate Wait State flags */
+#define ZERO_WAIT_STATE_8_BIT   0x1000  /* 0 = Disabled (Inserts Wait States) */
+#define ZERO_WAIT_STATE_16_BIT  0x0800  /* 0 = Disabled (Inserts Wait States) */
+#define LOOPING_MODE_MASK       0x0007
+#define LOOPBACK_MODE_0         0x0000
+#define LOOPBACK_MODE_1         0x0001
+#define LOOPBACK_MODE_2         0x0002
+#define LOOPBACK_MODE_3         0x0003
+#define LOOPBACK_MODE_4         0x0004
+#define LOOPBACK_MODE_5         0x0005
+#define LOOPBACK_MODE_6         0x0006
+#define LOOPBACK_MODE_7         0x0007
+#define AUTO_MEDIA_DETECT       0x0008
+#define MANUAL_CRC              0x0010
+#define EARLY_TOKEN_REL         0x0020  /* Early Token Release for Token Ring */
+#define UMAC               0x0040 
+#define UTP2_PORT               0x0080  /* For 8216T2, 0=port A, 1=Port B. */
+#define BNC_10BT_INTERFACE      0x0600  /* BNC and UTP current media set */
+#define UTP_INTERFACE           0x0500  /* Ethernet UTP Only. */
+#define BNC_INTERFACE           0x0400
+#define AUI_INTERFACE           0x0300
+#define AUI_10BT_INTERFACE      0x0200
+#define STARLAN_10_INTERFACE    0x0100
+#define INTERFACE_TYPE_MASK     0x0700
+
+/*
+ * Media Type Bit Definitions
+ *
+ * legend:      TP = Twisted Pair
+ *              STP = Shielded twisted pair
+ *              UTP = Unshielded twisted pair
+ */
+
+#define CNFG_MEDIA_TYPE_MASK    0x001e  /* POS Register 3 Mask         */
+
+#define MEDIA_S10               0x0000  /* Ethernet adapter, TP.        */
+#define MEDIA_AUI_UTP           0x0001  /* Ethernet adapter, AUI/UTP media */
+#define MEDIA_BNC               0x0002  /* Ethernet adapter, BNC media. */
+#define MEDIA_AUI               0x0003  /* Ethernet Adapter, AUI media. */
+#define MEDIA_STP_16            0x0004  /* TokenRing adap, 16Mbit STP.  */
+#define MEDIA_STP_4             0x0005  /* TokenRing adap, 4Mbit STP.   */
+#define MEDIA_UTP_16            0x0006  /* TokenRing adap, 16Mbit UTP.  */
+#define MEDIA_UTP_4             0x0007  /* TokenRing adap, 4Mbit UTP.   */
+#define MEDIA_UTP               0x0008  /* Ethernet adapter, UTP media (no AUI)
+*/
+#define MEDIA_BNC_UTP           0x0010  /* Ethernet adapter, BNC/UTP media */
+#define MEDIA_UTPFD             0x0011  /* Ethernet adapter, TP full duplex */
+#define MEDIA_UTPNL             0x0012  /* Ethernet adapter, TP with link integrity test disabled */
+#define MEDIA_AUI_BNC           0x0013  /* Ethernet adapter, AUI/BNC media */
+#define MEDIA_AUI_BNC_UTP       0x0014  /* Ethernet adapter, AUI_BNC/UTP */
+#define MEDIA_UTPA              0x0015  /* Ethernet UTP-10Mbps Ports A */
+#define MEDIA_UTPB              0x0016  /* Ethernet UTP-10Mbps Ports B */
+#define MEDIA_STP_16_UTP_16     0x0017  /* Token Ring STP-16Mbps/UTP-16Mbps */
+#define MEDIA_STP_4_UTP_4       0x0018  /* Token Ring STP-4Mbps/UTP-4Mbps */
+
+#define MEDIA_STP100_UTP100     0x0020  /* Ethernet STP-100Mbps/UTP-100Mbps */
+#define MEDIA_UTP100FD          0x0021  /* Ethernet UTP-100Mbps, full duplex */
+#define MEDIA_UTP100            0x0022  /* Ethernet UTP-100Mbps */
+
+
+#define MEDIA_UNKNOWN           0xFFFF  /* Unknown adapter/media type   */
+
+/*
+ * Definitions for the field:
+ * media_type2
+ */
+#define MEDIA_TYPE_MII              0x0001
+#define MEDIA_TYPE_UTP              0x0002
+#define MEDIA_TYPE_BNC              0x0004
+#define MEDIA_TYPE_AUI              0x0008
+#define MEDIA_TYPE_S10              0x0010
+#define MEDIA_TYPE_AUTO_SENSE       0x1000
+#define MEDIA_TYPE_AUTO_DETECT      0x4000
+#define MEDIA_TYPE_AUTO_NEGOTIATE   0x8000
+
+/*
+ * Definitions for the field:
+ * line_speed
+ */
+#define LINE_SPEED_UNKNOWN          0x0000
+#define LINE_SPEED_4                0x0001
+#define LINE_SPEED_10               0x0002
+#define LINE_SPEED_16               0x0004
+#define LINE_SPEED_100              0x0008
+#define LINE_SPEED_T4               0x0008  /* 100BaseT4 aliased for 9332BVT */
+#define LINE_SPEED_FULL_DUPLEX      0x8000
+
+/*
+ * Definitions for the field:
+ * bic_type (Bus interface chip type)
+ */
+#define BIC_NO_CHIP             0x0000  /* Bus interface chip not implemented */#define BIC_583_CHIP            0x0001  /* 83C583 bus interface chip */
+#define BIC_584_CHIP            0x0002  /* 83C584 bus interface chip */
+#define BIC_585_CHIP            0x0003  /* 83C585 bus interface chip */
+#define BIC_593_CHIP            0x0004  /* 83C593 bus interface chip */
+#define BIC_594_CHIP            0x0005  /* 83C594 bus interface chip */
+#define BIC_564_CHIP            0x0006  /* PCMCIA Bus interface chip */
+#define BIC_790_CHIP            0x0007  /* 83C790 bus i-face/Ethernet NIC chip */
+#define BIC_571_CHIP            0x0008  /* 83C571 EISA bus master i-face */
+#define BIC_587_CHIP            0x0009  /* Token Ring AT bus master i-face */
+#define BIC_574_CHIP            0x0010  /* FEAST bus interface chip */
+#define BIC_8432_CHIP           0x0011  /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define BIC_9332_CHIP           0x0012  /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define BIC_8432E_CHIP          0x0013  /* 8432 Enhanced bus iface/Ethernet NIC(DEC) */
+#define BIC_EPIC100_CHIP        0x0014  /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define BIC_C94_CHIP            0x0015  /* 91C94 bus i-face in PCMCIA mode */
+#define BIC_X8020_CHIP          0x0016  /* Xilinx PCMCIA multi-func i-face */
+
+/*
+ * Definitions for the field:
+ * nic_type (Bus interface chip type)
+ */
+#define NIC_UNK_CHIP            0x0000  /* Unknown NIC chip      */
+#define NIC_8390_CHIP           0x0001  /* DP8390 Ethernet NIC   */
+#define NIC_690_CHIP            0x0002  /* 83C690 Ethernet NIC   */
+#define NIC_825_CHIP            0x0003  /* 83C825 Token Ring NIC */
+/*      #define NIC_???_CHIP    0x0004  */ /* Not used           */
+/*      #define NIC_???_CHIP    0x0005  */ /* Not used           */
+/*      #define NIC_???_CHIP    0x0006  */ /* Not used           */
+#define NIC_790_CHIP            0x0007  /* 83C790 bus i-face/Ethernet NIC chip */
+#define NIC_C100_CHIP           0x0010  /* FEAST 100Mbps Ethernet NIC */
+#define NIC_8432_CHIP           0x0011  /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define NIC_9332_CHIP           0x0012  /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define NIC_8432E_CHIP          0x0013  /* 8432 enhanced bus iface/Ethernet NIC(DEC) */
+#define NIC_EPIC100_CHIP        0x0014   /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define NIC_C94_CHIP            0x0015  /* 91C94 PC Card with multi func */
+
+/*
+ * Definitions for the field:
+ * adapter_type The adapter_type field describes the adapter/bus
+ *              configuration.
+ */
+#define BUS_UNK_TYPE            0x0000  /*  */
+#define BUS_ISA16_TYPE          0x0001  /* 16 bit adap in 16 bit (E)ISA slot  */
+#define BUS_ISA8_TYPE           0x0002  /* 8/16b adap in 8 bit XT/(E)ISA slot */
+#define BUS_MCA_TYPE            0x0003  /* Micro Channel adapter              */#define BUS_EISA32M_TYPE        0x0004  /* EISA 32 bit bus master adapter     */#define BUS_EISA32S_TYPE        0x0005  /* EISA 32 bit bus slave adapter      */#define BUS_PCMCIA_TYPE         0x0006  /* PCMCIA adapter */
+#define BUS_PCI_TYPE            0x0007  /* PCI bus */
+
+/*
+ * Receive Mask definitions
+ */
+#define ACCEPT_MULTICAST                0x0001
+#define ACCEPT_BROADCAST                0x0002
+#define PROMISCUOUS_MODE                0x0004
+#define ACCEPT_SOURCE_ROUTING           0x0008
+#define ACCEPT_ERR_PACKETS              0x0010
+#define ACCEPT_ATT_MAC_FRAMES           0x0020
+#define ACCEPT_MULTI_PROM               0x0040
+#define TRANSMIT_ONLY                   0x0080
+#define ACCEPT_EXT_MAC_FRAMES           0x0100
+#define EARLY_RX_ENABLE                 0x0200
+#define PKT_SIZE_NOT_NEEDED             0x0400
+#define ACCEPT_SOURCE_ROUTING_SPANNING  0x0808
+
+#define ACCEPT_ALL_MAC_FRAMES           0x0120
+
+/*
+ * config_mode defs
+ */
+#define STORE_EEROM             0x0001  /* Store config in EEROM. */
+#define STORE_REGS              0x0002  /* Store config in register set. */
+
+/*
+ * equates for lmac_flags in adapter structure (Ethernet)
+ */
+#define         MEM_DISABLE     0x0001
+#define         RX_STATUS_POLL  0x0002
+#define         USE_RE_BIT      0x0004
+/*#define       RESERVED        0x0008 */
+/*#define       RESERVED        0x0010 */
+/*#define       RESERVED        0x0020 */
+/*#define       RESERVED        0x0040 */
+/*#define       RESERVED        0x0080 */
+/*#define       RESERVED        0x0100 */
+/*#define       RESERVED        0x0200 */
+/*#define       RESERVED        0x0400 */
+/*#define       RESERVED        0x0800 */
+/*#define       RESERVED        0x1000 */
+/*#define       RESERVED        0x2000 */
+/*#define       RESERVED        0x4000 */
+/*#define       RESERVED        0x8000 */
+
+/* media_opts & media_set Fields bit defs for Ethernet ... */
+#define         MED_OPT_BNC     0x01
+#define         MED_OPT_UTP     0x02
+#define         MED_OPT_AUI     0x04
+#define         MED_OPT_10MB    0x08
+#define         MED_OPT_100MB   0x10
+#define         MED_OPT_S10     0x20
+
+/* media_opts & media_set Fields bit defs for Token Ring ... */
+#define         MED_OPT_4MB     0x08
+#define         MED_OPT_16MB    0x10
+#define         MED_OPT_STP     0x40
+
+#define MAX_8023_SIZE           1500    /* Max 802.3 size of frame. */
+#define DEFAULT_ERX_VALUE       4       /* Number of 16-byte blocks for 790B early Rx. */
+#define DEFAULT_ETX_VALUE       32      /* Number of bytes for 790B early Tx. */#define DEFAULT_TX_RETRIES      3       /* Number of transmit retries */
+#define LPBK_FRAME_SIZE         1024    /* Default loopback frame for Rx calibration test. */
+#define MAX_LOOKAHEAD_SIZE      252     /* Max lookahead size for ethernet. */
+
+#define RW_MAC_STATE                    0x1101
+#define RW_SA_OF_LAST_AMP_OR_SMP        0x2803
+#define RW_PHYSICAL_DROP_NUMBER         0x3B02
+#define RW_UPSTREAM_NEIGHBOR_ADDRESS    0x3E03
+#define RW_PRODUCT_INSTANCE_ID          0x4B09
+
+#define RW_TRC_STATUS_BLOCK             0x5412
+
+#define RW_MAC_ERROR_COUNTERS_NO_CLEAR  0x8006
+#define RW_MAC_ERROR_COUNTER_CLEAR      0x7A06
+#define RW_CONFIG_REGISTER_0            0xA001
+#define RW_CONFIG_REGISTER_1            0xA101
+#define RW_PRESCALE_TIMER_THRESHOLD     0xA201
+#define RW_TPT_THRESHOLD                0xA301
+#define RW_TQP_THRESHOLD                0xA401
+#define RW_TNT_THRESHOLD                0xA501
+#define RW_TBT_THRESHOLD                0xA601
+#define RW_TSM_THRESHOLD                0xA701
+#define RW_TAM_THRESHOLD                0xA801
+#define RW_TBR_THRESHOLD                0xA901
+#define RW_TER_THRESHOLD                0xAA01
+#define RW_TGT_THRESHOLD                0xAB01
+#define RW_THT_THRESHOLD                0xAC01
+#define RW_TRR_THRESHOLD                0xAD01
+#define RW_TVX_THRESHOLD                0xAE01
+#define RW_INDIVIDUAL_MAC_ADDRESS       0xB003
+
+#define RW_INDIVIDUAL_GROUP_ADDRESS     0xB303  /* all of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR_WORD_0 0xB301  /* 1st word of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR        0xB402  /* 2nd-3rd word of group addr */
+#define RW_FUNCTIONAL_ADDRESS           0xB603  /* all of functional addr */
+#define RW_FUNCTIONAL_ADDR_WORD_0       0xB601  /* 1st word of func  addr */
+#define RW_FUNCTIONAL_ADDR              0xB702  /* 2nd-3rd word func addr */
+
+#define RW_BIT_SIGNIFICANT_GROUP_ADDR   0xB902
+#define RW_SOURCE_RING_BRIDGE_NUMBER    0xBB01
+#define RW_TARGET_RING_NUMBER           0xBC01
+
+#define RW_HIC_INTERRUPT_MASK           0xC601
+
+#define SOURCE_ROUTING_SPANNING_BITS    0x00C0  /* Spanning Tree Frames */
+#define SOURCE_ROUTING_EXPLORER_BIT     0x0040  /* Explorer and Single Route */
+
+        /* write */
+
+#define CSR_MSK_ALL             0x80    // Bic 587 Only
+#define CSR_MSKTINT             0x20
+#define CSR_MSKCBUSY            0x10
+#define CSR_CLRTINT             0x08
+#define CSR_CLRCBUSY            0x04
+#define CSR_WCSS                0x02
+#define CSR_CA                  0x01
+
+        /* read */
+
+#define CSR_TINT                0x20
+#define CSR_CINT                0x10
+#define CSR_TSTAT               0x08
+#define CSR_CSTAT               0x04
+#define CSR_FAULT               0x02
+#define CSR_CBUSY               0x01
+
+#define LAAR_MEM16ENB           0x80
+#define Zws16                   0x20
+
+#define IRR_IEN                 0x80
+#define Zws8                    0x01
+
+#define IMCCR_EIL               0x04
+
+typedef struct {
+        __u8            ac;                             /* Access Control */
+        __u8            fc;                             /* Frame Control */
+        __u8            da[6];                          /* Dest Addr */
+        __u8            sa[6];                          /* Source Addr */
+
+        __u16            vl;                             /* Vector Length */
+        __u8            dc_sc;                          /* Dest/Source Class */
+        __u8            vc;                             /* Vector Code */
+        } MAC_HEADER;
+
+#define MAX_SUB_VECTOR_INFO     (RX_DATA_BUFFER_SIZE - sizeof(MAC_HEADER) - 2)
+
+typedef struct
+        {
+        __u8            svl;                            /* Sub-vector Length */
+        __u8            svi;                            /* Sub-vector Code */
+        __u8            svv[MAX_SUB_VECTOR_INFO];       /* Sub-vector Info */
+        } MAC_SUB_VECTOR;
+
+#endif	/* __KERNEL__ */
+#endif	/* __LINUX_SMCTR_H */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/smctr_firmware.h linux/drivers/net/tokenring/smctr_firmware.h
--- v2.3.37/linux/drivers/net/tokenring/smctr_firmware.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/tokenring/smctr_firmware.h	Thu Jan  6 15:01:56 2000
@@ -0,0 +1,979 @@
+/*
+ * The firmware this driver downloads into the tokenring card is a
+ * seperate 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 SMC TokenRing adapters. There is no waranty
+ * expressed or implied about its fitness for any purpose.
+ */
+
+/* smctr_firmware.h: SMC TokenRing driver firmware dump for Linux.
+ *
+ * Notes:
+ *  - This is an 8K binary image. (MCT.BIN v6.3C1 03/01/95)
+ *
+ * Authors:
+ *  - Jay Schulist <jschlst@turbolinux.com>
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE)
+
+unsigned char smctr_code[] = {
+	0x0BC, 0x01D, 0x012, 0x03B, 0x063, 0x0B4, 0x0E9, 0x000,
+	0x000, 0x01F, 0x000, 0x001, 0x001, 0x000, 0x002, 0x005,
+	0x001, 0x000, 0x006, 0x003, 0x001, 0x000, 0x004, 0x009,
+	0x001, 0x000, 0x00A, 0x007, 0x001, 0x000, 0x008, 0x00B,
+	0x001, 0x000, 0x00C, 0x000, 0x000, 0x000, 0x000, 0x00F,
+	0x001, 0x000, 0x010, 0x00D, 0x001, 0x000, 0x00E, 0x013,
+	0x001, 0x000, 0x014, 0x011, 0x001, 0x000, 0x012, 0x000,
+	0x000, 0x005, 0x000, 0x015, 0x001, 0x000, 0x016, 0x019,
+	0x001, 0x000, 0x01A, 0x017, 0x001, 0x000, 0x018, 0x000,
+	0x000, 0x00E, 0x000, 0x000, 0x000, 0x001, 0x000, 0x000,
+	0x000, 0x004, 0x000, 0x01B, 0x001, 0x000, 0x01C, 0x000,
+	0x000, 0x007, 0x000, 0x000, 0x000, 0x00F, 0x000, 0x000,
+	0x000, 0x00B, 0x000, 0x01D, 0x001, 0x000, 0x01E, 0x000,
+	0x000, 0x008, 0x000, 0x000, 0x000, 0x002, 0x000, 0x000,
+	0x000, 0x00C, 0x000, 0x000, 0x000, 0x006, 0x000, 0x000,
+	0x000, 0x00D, 0x000, 0x000, 0x000, 0x003, 0x000, 0x000,
+	0x000, 0x00A, 0x000, 0x000, 0x000, 0x009, 0x000, 0x004,
+	0x078, 0x0C6, 0x0BC, 0x001, 0x094, 0x004, 0x093, 0x080,
+	0x0C8, 0x040, 0x062, 0x0E9, 0x0DA, 0x01C, 0x02C, 0x015,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x058,
+	0x00B, 0x0E9, 0x0E5, 0x0D5, 0x095, 0x0C1, 0x09D, 0x077,
+	0x0CE, 0x0BB, 0x0A0, 0x06E, 0x01C, 0x005, 0x0F6, 0x077,
+	0x0C6, 0x002, 0x0FA, 0x096, 0x070, 0x0E8, 0x01D, 0x0C0,
+	0x017, 0x00E, 0x002, 0x0FA, 0x058, 0x07D, 0x0C0, 0x05F,
+	0x072, 0x0CE, 0x0EC, 0x0A4, 0x0C3, 0x084, 0x090, 0x07A,
+	0x030, 0x0CD, 0x08D, 0x079, 0x019, 0x0E7, 0x06C, 0x024,
+	0x027, 0x09C, 0x008, 0x039, 0x007, 0x038, 0x0A8, 0x04A,
+	0x04C, 0x0EA, 0x04D, 0x098, 0x09B, 0x024, 0x04C, 0x0C0,
+	0x026, 0x0D3, 0x0E7, 0x054, 0x05A, 0x04D, 0x0F2, 0x04C,
+	0x00C, 0x013, 0x023, 0x049, 0x090, 0x032, 0x06E, 0x0A4,
+	0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1, 0x026,
+	0x0F8, 0x026, 0x00C, 0x04C, 0x012, 0x026, 0x008, 0x009,
+	0x082, 0x082, 0x060, 0x0A9, 0x030, 0x079, 0x036, 0x0B0,
+	0x0B2, 0x0A8, 0x0A7, 0x072, 0x064, 0x08F, 0x09B, 0x033,
+	0x033, 0x0F9, 0x0B8, 0x039, 0x0D5, 0x011, 0x073, 0x0AA,
+	0x075, 0x026, 0x05D, 0x026, 0x051, 0x093, 0x02A, 0x049,
+	0x094, 0x0C9, 0x095, 0x089, 0x0BC, 0x04D, 0x0C8, 0x09B,
+	0x080, 0x09B, 0x0A0, 0x099, 0x006, 0x04C, 0x086, 0x026,
+	0x058, 0x09B, 0x0A4, 0x09B, 0x099, 0x037, 0x062, 0x06C,
+	0x067, 0x09B, 0x033, 0x030, 0x0BF, 0x036, 0x066, 0x061,
+	0x0BF, 0x036, 0x0EC, 0x0C5, 0x0BD, 0x066, 0x082, 0x05A,
+	0x050, 0x031, 0x0D5, 0x09D, 0x098, 0x018, 0x029, 0x03C,
+	0x098, 0x086, 0x04C, 0x017, 0x026, 0x03E, 0x02C, 0x0B8,
+	0x069, 0x03B, 0x049, 0x02E, 0x0B4, 0x008, 0x043, 0x01A,
+	0x0A4, 0x0F9, 0x0B3, 0x051, 0x0F1, 0x010, 0x0F3, 0x043,
+	0x0CD, 0x008, 0x06F, 0x063, 0x079, 0x0B3, 0x033, 0x00E,
+	0x013, 0x098, 0x049, 0x098, 0x004, 0x0DA, 0x07C, 0x0E0,
+	0x052, 0x079, 0x031, 0x00C, 0x098, 0x02E, 0x04D, 0x0AC,
+	0x02C, 0x084, 0x014, 0x0EE, 0x04C, 0x0FE, 0x067, 0x05E,
+	0x0E4, 0x09A, 0x075, 0x029, 0x0D7, 0x0A9, 0x035, 0x03A,
+	0x094, 0x05B, 0x0D5, 0x09B, 0x058, 0x0B4, 0x0AF, 0x075,
+	0x066, 0x0AF, 0x014, 0x0A9, 0x0EF, 0x040, 0x095, 0x025,
+	0x008, 0x0B9, 0x0AD, 0x042, 0x0FC, 0x0D8, 0x0D9, 0x08C,
+	0x033, 0x00E, 0x013, 0x098, 0x066, 0x01E, 0x045, 0x0AC,
+	0x0B0, 0x00C, 0x042, 0x0D3, 0x0CC, 0x0A6, 0x012, 0x062,
+	0x0DE, 0x0B4, 0x0B1, 0x080, 0x049, 0x07D, 0x0A2, 0x0DE,
+	0x0B4, 0x018, 0x0C0, 0x024, 0x084, 0x0E6, 0x054, 0x0F5,
+	0x083, 0x046, 0x001, 0x068, 0x01A, 0x063, 0x00C, 0x0C6,
+	0x012, 0x064, 0x0FA, 0x04C, 0x035, 0x01C, 0x02C, 0x00E,
+	0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+	0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AD, 0x0D7, 0x002,
+	0x070, 0x0E0, 0x04C, 0x0F3, 0x0A1, 0x0C1, 0x0D5, 0x0C0,
+	0x03C, 0x0B9, 0x069, 0x039, 0x060, 0x04E, 0x058, 0x077,
+	0x002, 0x067, 0x093, 0x03C, 0x099, 0x0E4, 0x0CF, 0x038,
+	0x01C, 0x097, 0x02E, 0x040, 0x01B, 0x090, 0x031, 0x046,
+	0x0A3, 0x05E, 0x00E, 0x088, 0x034, 0x06A, 0x035, 0x0E0,
+	0x0E8, 0x0AA, 0x035, 0x01A, 0x0A9, 0x0F5, 0x015, 0x046,
+	0x0A3, 0x0EA, 0x07D, 0x04A, 0x0A3, 0x051, 0x0AA, 0x09F,
+	0x070, 0x054, 0x0A6, 0x057, 0x02E, 0x0B4, 0x0CD, 0x0C8,
+	0x0A3, 0x00C, 0x0C1, 0x0DA, 0x0C6, 0x0E1, 0x0CB, 0x07A,
+	0x0D4, 0x01C, 0x068, 0x0FF, 0x0CF, 0x055, 0x0A8, 0x0C0,
+	0x02D, 0x085, 0x011, 0x017, 0x044, 0x02A, 0x030, 0x00B,
+	0x04A, 0x088, 0x0C2, 0x04D, 0x0B5, 0x020, 0x0D5, 0x026,
+	0x001, 0x069, 0x051, 0x069, 0x052, 0x019, 0x052, 0x060,
+	0x016, 0x095, 0x016, 0x082, 0x096, 0x054, 0x098, 0x005,
+	0x0A5, 0x045, 0x0F3, 0x0DD, 0x06A, 0x0F9, 0x028, 0x018,
+	0x0EF, 0x000, 0x030, 0x030, 0x051, 0x04E, 0x044, 0x05D,
+	0x012, 0x0D1, 0x043, 0x0E6, 0x012, 0x06F, 0x09E, 0x0BA,
+	0x0CC, 0x0DF, 0x025, 0x003, 0x01D, 0x0E0, 0x006, 0x006,
+	0x00A, 0x030, 0x0CC, 0x0A9, 0x0EB, 0x02D, 0x000, 0x086,
+	0x0A6, 0x012, 0x065, 0x04F, 0x056, 0x0D6, 0x065, 0x049,
+	0x05F, 0x03D, 0x0E8, 0x037, 0x0C9, 0x040, 0x0C7, 0x078,
+	0x001, 0x081, 0x082, 0x08C, 0x033, 0x018, 0x049, 0x080,
+	0x0AE, 0x040, 0x0C5, 0x018, 0x005, 0x09C, 0x06D, 0x018,
+	0x066, 0x00E, 0x0F3, 0x0A0, 0x0C6, 0x012, 0x062, 0x0DE,
+	0x0F5, 0x004, 0x0B4, 0x0AC, 0x06B, 0x0C6, 0x019, 0x091,
+	0x073, 0x005, 0x048, 0x02E, 0x072, 0x094, 0x080, 0x073,
+	0x0A1, 0x0C8, 0x047, 0x036, 0x066, 0x064, 0x02F, 0x036,
+	0x066, 0x064, 0x007, 0x099, 0x002, 0x091, 0x08E, 0x072,
+	0x0D1, 0x00F, 0x09D, 0x006, 0x031, 0x073, 0x0A0, 0x0C3,
+	0x051, 0x06A, 0x01A, 0x020, 0x0BF, 0x03A, 0x00C, 0x02C,
+	0x073, 0x087, 0x043, 0x05E, 0x060, 0x002, 0x023, 0x0FC,
+	0x0E0, 0x0D6, 0x035, 0x0EF, 0x09E, 0x0F5, 0x0EF, 0x092,
+	0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+	0x045, 0x0CC, 0x00B, 0x048, 0x02E, 0x070, 0x00A, 0x040,
+	0x039, 0x0D0, 0x0E4, 0x023, 0x09B, 0x033, 0x032, 0x017,
+	0x09B, 0x033, 0x032, 0x003, 0x0CC, 0x085, 0x048, 0x0C7,
+	0x038, 0x014, 0x0A5, 0x0CE, 0x029, 0x07E, 0x0D2, 0x080,
+	0x0A1, 0x0A8, 0x0B4, 0x048, 0x088, 0x02F, 0x0CE, 0x083,
+	0x00B, 0x01C, 0x0E1, 0x0D0, 0x0D7, 0x098, 0x004, 0x088,
+	0x087, 0x0CE, 0x096, 0x031, 0x073, 0x0A5, 0x08F, 0x0F3,
+	0x083, 0x058, 0x0D7, 0x0BE, 0x07B, 0x082, 0x0AF, 0x092,
+	0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+	0x045, 0x0CC, 0x015, 0x020, 0x0B9, 0x0C8, 0x029, 0x000,
+	0x0E7, 0x043, 0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E,
+	0x06C, 0x0CC, 0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C,
+	0x0E4, 0x050, 0x0D4, 0x05A, 0x017, 0x088, 0x02F, 0x0CE,
+	0x083, 0x010, 0x0F9, 0x0D0, 0x023, 0x017, 0x03A, 0x004,
+	0x035, 0x0E6, 0x000, 0x022, 0x016, 0x039, 0x0C3, 0x0A3,
+	0x0FC, 0x0E0, 0x0D6, 0x035, 0x0E0, 0x0BF, 0x0F4, 0x018,
+	0x0F2, 0x02D, 0x04D, 0x043, 0x051, 0x06E, 0x05A, 0x022,
+	0x01F, 0x030, 0x0D4, 0x017, 0x0E7, 0x041, 0x091, 0x073,
+	0x005, 0x048, 0x02E, 0x077, 0x069, 0x000, 0x0E7, 0x043,
+	0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E, 0x06C, 0x0CC,
+	0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C, 0x0EF, 0x04C,
+	0x04E, 0x006, 0x004, 0x0C9, 0x09E, 0x00B, 0x0FF, 0x041,
+	0x08F, 0x022, 0x0D4, 0x0D4, 0x035, 0x016, 0x0E5, 0x0A2,
+	0x021, 0x0F3, 0x05A, 0x082, 0x0FC, 0x0E8, 0x032, 0x02E,
+	0x060, 0x0A9, 0x005, 0x0CE, 0x013, 0x048, 0x007, 0x03A,
+	0x01C, 0x084, 0x073, 0x066, 0x066, 0x042, 0x0F3, 0x066,
+	0x066, 0x040, 0x079, 0x090, 0x029, 0x018, 0x0E7, 0x00A,
+	0x098, 0x09C, 0x00A, 0x09E, 0x0B5, 0x012, 0x05C, 0x07C,
+	0x0C3, 0x031, 0x08B, 0x098, 0x02A, 0x07C, 0x0D3, 0x0ED,
+	0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED, 0x049, 0x09E,
+	0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4, 0x0D4, 0x035,
+	0x016, 0x0E5, 0x0A2, 0x02D, 0x0EB, 0x045, 0x033, 0x08F,
+	0x0FC, 0x0F7, 0x0A0, 0x05F, 0x025, 0x003, 0x01D, 0x0E4,
+	0x00E, 0x006, 0x00A, 0x030, 0x0CC, 0x00C, 0x0F3, 0x0EB,
+	0x040, 0x0DE, 0x061, 0x0A8, 0x070, 0x092, 0x00A, 0x000,
+	0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+	0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+	0x0E1, 0x024, 0x01E, 0x001, 0x00F, 0x098, 0x02A, 0x00B,
+	0x0F3, 0x0A0, 0x0C8, 0x0B9, 0x0A2, 0x0A4, 0x017, 0x03A,
+	0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+	0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x000, 0x052, 0x031,
+	0x0CC, 0x018, 0x014, 0x0A5, 0x0CC, 0x009, 0x082, 0x094,
+	0x073, 0x00C, 0x0A0, 0x091, 0x0F5, 0x025, 0x0CC, 0x007,
+	0x006, 0x084, 0x084, 0x09F, 0x030, 0x0A2, 0x0A4, 0x07D,
+	0x050, 0x075, 0x0A6, 0x065, 0x001, 0x04A, 0x08E, 0x0B4,
+	0x0CC, 0x0C4, 0x035, 0x054, 0x075, 0x066, 0x0A4, 0x097,
+	0x07A, 0x089, 0x050, 0x053, 0x013, 0x080, 0x019, 0x0E3,
+	0x049, 0x05C, 0x06D, 0x0CE, 0x0A9, 0x040, 0x035, 0x006,
+	0x078, 0x0D2, 0x057, 0x006, 0x0F1, 0x0B3, 0x02A, 0x08D,
+	0x097, 0x023, 0x062, 0x092, 0x05D, 0x069, 0x099, 0x01C,
+	0x06A, 0x036, 0x0E6, 0x0CD, 0x046, 0x012, 0x06F, 0x09E,
+	0x0E1, 0x0AB, 0x0E4, 0x0A3, 0x00C, 0x0C0, 0x0DE, 0x0AC,
+	0x0D4, 0x00D, 0x028, 0x01B, 0x0D0, 0x012, 0x0A5, 0x000,
+	0x0F8, 0x04B, 0x0AD, 0x033, 0x028, 0x006, 0x0A0, 0x0DE,
+	0x014, 0x097, 0x03A, 0x089, 0x05D, 0x0C0, 0x00D, 0x0E3,
+	0x006, 0x090, 0x092, 0x05D, 0x069, 0x098, 0x066, 0x0B9,
+	0x019, 0x095, 0x0E4, 0x0A8, 0x0CF, 0x09D, 0x033, 0x018,
+	0x049, 0x0BE, 0x07B, 0x086, 0x0AF, 0x092, 0x08C, 0x033,
+	0x024, 0x014, 0x00C, 0x0F4, 0x083, 0x024, 0x021, 0x0C2,
+	0x070, 0x0BF, 0x0F4, 0x018, 0x0F2, 0x02D, 0x04D, 0x043,
+	0x051, 0x06E, 0x05A, 0x022, 0x01F, 0x032, 0x0A8, 0x02F,
+	0x0CE, 0x083, 0x022, 0x0E6, 0x005, 0x0A4, 0x017, 0x03A,
+	0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+	0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x042, 0x0A4, 0x063,
+	0x098, 0x002, 0x029, 0x04B, 0x09A, 0x029, 0x078, 0x0E9,
+	0x040, 0x053, 0x013, 0x081, 0x081, 0x032, 0x067, 0x082,
+	0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+	0x0AE, 0x050, 0x008, 0x07C, 0x0E0, 0x0D0, 0x05F, 0x09D,
+	0x006, 0x045, 0x0CC, 0x001, 0x0A4, 0x017, 0x03A, 0x069,
+	0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048, 0x05E,
+	0x070, 0x069, 0x001, 0x0E6, 0x059, 0x0A4, 0x063, 0x098,
+	0x01C, 0x052, 0x097, 0x03B, 0x030, 0x052, 0x08E, 0x07D,
+	0x02A, 0x009, 0x01F, 0x051, 0x0EB, 0x0A4, 0x0A4, 0x00A,
+	0x0B9, 0x094, 0x087, 0x0AE, 0x0C5, 0x031, 0x038, 0x002,
+	0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+	0x0AE, 0x050, 0x008, 0x07C, 0x0EA, 0x020, 0x0BF, 0x03A,
+	0x00C, 0x08B, 0x09A, 0x016, 0x090, 0x05C, 0x0E9, 0x0A4,
+	0x003, 0x09D, 0x00E, 0x042, 0x039, 0x0D5, 0x021, 0x079,
+	0x095, 0x048, 0x00F, 0x030, 0x00A, 0x091, 0x08E, 0x060,
+	0x0EB, 0x029, 0x073, 0x000, 0x009, 0x054, 0x004, 0x0CA,
+	0x082, 0x065, 0x052, 0x065, 0x0E4, 0x0CA, 0x022, 0x065,
+	0x072, 0x065, 0x009, 0x032, 0x0E0, 0x099, 0x072, 0x04C,
+	0x0C4, 0x0E0, 0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4,
+	0x0D4, 0x035, 0x016, 0x0B9, 0x040, 0x021, 0x0F3, 0x08A,
+	0x082, 0x0FC, 0x0E8, 0x032, 0x02E, 0x060, 0x0A9, 0x005,
+	0x0CE, 0x09A, 0x040, 0x039, 0x0D0, 0x0E4, 0x023, 0x09D,
+	0x052, 0x017, 0x099, 0x054, 0x061, 0x099, 0x001, 0x0E6,
+	0x040, 0x0A4, 0x063, 0x098, 0x004, 0x0B1, 0x084, 0x098,
+	0x018, 0x0EF, 0x02D, 0x003, 0x005, 0x031, 0x038, 0x002,
+	0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+	0x0B9, 0x068, 0x088, 0x07C, 0x0E0, 0x050, 0x05F, 0x09D,
+	0x006, 0x045, 0x0CC, 0x081, 0x048, 0x02E, 0x071, 0x034,
+	0x08F, 0x048, 0x001, 0x048, 0x015, 0x021, 0x005, 0x021,
+	0x0E9, 0x00A, 0x052, 0x003, 0x0CE, 0x05A, 0x046, 0x039,
+	0x0CF, 0x047, 0x08E, 0x060, 0x0AB, 0x01A, 0x0F3, 0x053,
+	0x043, 0x0EB, 0x035, 0x024, 0x0B8, 0x01B, 0x030, 0x007,
+	0x009, 0x08A, 0x074, 0x02F, 0x07E, 0x041, 0x074, 0x01E,
+	0x01D, 0x00D, 0x087, 0x046, 0x049, 0x0D5, 0x095, 0x0D1,
+	0x0D5, 0x0D5, 0x0BB, 0x0A9, 0x04E, 0x082, 0x09D, 0x005,
+	0x03A, 0x00A, 0x074, 0x014, 0x0E8, 0x029, 0x0D0, 0x042,
+	0x074, 0x05B, 0x0CE, 0x050, 0x0C4, 0x007, 0x045, 0x0BC,
+	0x0E2, 0x00C, 0x040, 0x074, 0x05B, 0x0CE, 0x083, 0x004,
+	0x0F9, 0x095, 0x04D, 0x013, 0x063, 0x05E, 0x06F, 0x031,
+	0x03B, 0x0A0, 0x08B, 0x0A2, 0x0C5, 0x039, 0x08D, 0x078,
+	0x03A, 0x022, 0x0A0, 0x000, 0x06B, 0x0C1, 0x0D1, 0x054,
+	0x060, 0x016, 0x0D9, 0x091, 0x0A2, 0x0E7, 0x043, 0x08C,
+	0x024, 0x0DC, 0x01C, 0x0E0, 0x051, 0x017, 0x039, 0x06B,
+	0x03B, 0x0CC, 0x04B, 0x042, 0x02E, 0x06B, 0x050, 0x0BF,
+	0x036, 0x036, 0x065, 0x04F, 0x07A, 0x018, 0x055, 0x025,
+	0x078, 0x098, 0x023, 0x0E7, 0x050, 0x03E, 0x0F3, 0x081,
+	0x04C, 0x002, 0x06D, 0x03E, 0x071, 0x053, 0x0AF, 0x078,
+	0x0A9, 0x0D4, 0x0A6, 0x029, 0x0B1, 0x0BC, 0x0D9, 0x099,
+	0x0B2, 0x08E, 0x062, 0x08F, 0x022, 0x02E, 0x075, 0x016,
+	0x0B0, 0x0B2, 0x0AB, 0x023, 0x028, 0x016, 0x054, 0x052,
+	0x031, 0x0BC, 0x0D9, 0x099, 0x0B2, 0x08E, 0x066, 0x019,
+	0x002, 0x02E, 0x075, 0x016, 0x050, 0x02C, 0x0A9, 0x0C8,
+	0x0C6, 0x0F5, 0x020, 0x0D3, 0x0E4, 0x07F, 0x04F, 0x09C,
+	0x00A, 0x0D6, 0x016, 0x07F, 0x090, 0x0EE, 0x04C, 0x0EB,
+	0x0CF, 0x0E2, 0x088, 0x0BA, 0x02F, 0x042, 0x086, 0x0AE,
+	0x0BD, 0x0E5, 0x0A7, 0x052, 0x09F, 0x093, 0x063, 0x079,
+	0x0EB, 0x033, 0x008, 0x0F9, 0x094, 0x052, 0x047, 0x0CD,
+	0x099, 0x025, 0x06F, 0x03A, 0x00C, 0x013, 0x0E6, 0x055,
+	0x034, 0x04C, 0x05A, 0x04D, 0x0B5, 0x023, 0x095, 0x0A5,
+	0x048, 0x011, 0x05A, 0x00A, 0x043, 0x095, 0x0AC, 0x02C,
+	0x0BA, 0x024, 0x005, 0x049, 0x0B1, 0x0BC, 0x0CA, 0x0A7,
+	0x072, 0x06C, 0x06B, 0x0C5, 0x0BD, 0x0E8, 0x031, 0x069,
+	0x052, 0x05D, 0x006, 0x012, 0x065, 0x03E, 0x0B1, 0x050,
+	0x04C, 0x07D, 0x04F, 0x0AC, 0x00A, 0x030, 0x00B, 0x036,
+	0x064, 0x011, 0x073, 0x08A, 0x083, 0x08E, 0x075, 0x012,
+	0x09F, 0x07B, 0x0D2, 0x099, 0x058, 0x0EE, 0x082, 0x02E,
+	0x077, 0x0A0, 0x0E3, 0x09D, 0x05D, 0x04F, 0x0BC, 0x02A,
+	0x053, 0x029, 0x053, 0x0DE, 0x093, 0x024, 0x0BA, 0x0B3,
+	0x036, 0x0AA, 0x04A, 0x0C6, 0x079, 0x0D4, 0x0B9, 0x0DE,
+	0x062, 0x05A, 0x011, 0x073, 0x050, 0x050, 0x0BF, 0x037,
+	0x036, 0x06F, 0x013, 0x023, 0x0BA, 0x00C, 0x024, 0x0CE,
+	0x0BD, 0x0E2, 0x0A7, 0x052, 0x0B2, 0x08E, 0x06B, 0x060,
+	0x062, 0x02E, 0x075, 0x013, 0x030, 0x0AC, 0x0A0, 0x059,
+	0x0CA, 0x064, 0x063, 0x079, 0x0B3, 0x033, 0x065, 0x01C,
+	0x0CC, 0x032, 0x004, 0x05C, 0x0EA, 0x02C, 0x0A0, 0x059,
+	0x0DF, 0x023, 0x01B, 0x0D4, 0x083, 0x052, 0x047, 0x0DD,
+	0x079, 0x096, 0x0D4, 0x09E, 0x0B3, 0x052, 0x04B, 0x0A2,
+	0x05A, 0x01A, 0x08D, 0x05D, 0x07B, 0x082, 0x0A7, 0x052,
+	0x0B2, 0x08E, 0x066, 0x019, 0x002, 0x02E, 0x075, 0x016,
+	0x050, 0x02C, 0x08C, 0x032, 0x01D, 0x07B, 0x08E, 0x0A7,
+	0x052, 0x0B1, 0x0BC, 0x0D9, 0x099, 0x098, 0x004, 0x0DA,
+	0x07C, 0x0E2, 0x0AC, 0x0FE, 0x066, 0x019, 0x002, 0x02E,
+	0x065, 0x050, 0x0BF, 0x033, 0x066, 0x064, 0x0FE, 0x074,
+	0x018, 0x086, 0x04C, 0x017, 0x026, 0x0D6, 0x016, 0x052,
+	0x039, 0x018, 0x0DE, 0x07A, 0x0CC, 0x0C2, 0x03E, 0x065,
+	0x014, 0x091, 0x0F3, 0x066, 0x049, 0x008, 0x06E, 0x083,
+	0x009, 0x033, 0x0AF, 0x031, 0x0ED, 0x00D, 0x09D, 0x006,
+	0x012, 0x062, 0x02A, 0x031, 0x08D, 0x06D, 0x0E7, 0x041,
+	0x082, 0x07C, 0x0CA, 0x0A6, 0x089, 0x087, 0x009, 0x02E,
+	0x029, 0x0B1, 0x0AF, 0x010, 0x039, 0x0D6, 0x064, 0x097,
+	0x030, 0x01D, 0x042, 0x075, 0x093, 0x044, 0x002, 0x08C,
+	0x024, 0x0D2, 0x07A, 0x0B3, 0x050, 0x0F6, 0x089, 0x005,
+	0x043, 0x05E, 0x061, 0x098, 0x0C0, 0x02C, 0x092, 0x025,
+	0x03C, 0x08B, 0x024, 0x089, 0x049, 0x005, 0x049, 0x0E7,
+	0x00C, 0x0B9, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+	0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+	0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+	0x046, 0x012, 0x062, 0x0DE, 0x0B4, 0x0CD, 0x021, 0x05C,
+	0x0B4, 0x0A3, 0x00C, 0x0C1, 0x03E, 0x072, 0x029, 0x0A2,
+	0x06C, 0x06B, 0x0C6, 0x012, 0x062, 0x047, 0x0F0, 0x0E8,
+	0x0C3, 0x032, 0x004, 0x035, 0x040, 0x092, 0x0A4, 0x082,
+	0x088, 0x010, 0x092, 0x07C, 0x0CB, 0x0D4, 0x02F, 0x0A4,
+	0x002, 0x011, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+	0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+	0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+	0x044, 0x008, 0x049, 0x03E, 0x065, 0x0EA, 0x017, 0x0D2,
+	0x001, 0x008, 0x0C2, 0x04C, 0x05B, 0x0D6, 0x099, 0x0A4,
+	0x02B, 0x096, 0x094, 0x061, 0x098, 0x027, 0x0CE, 0x045,
+	0x034, 0x04D, 0x08D, 0x078, 0x081, 0x009, 0x027, 0x0CC,
+	0x0BD, 0x012, 0x028, 0x06C, 0x058, 0x0AF, 0x0B6, 0x0F3,
+	0x0A0, 0x0C1, 0x03E, 0x065, 0x053, 0x044, 0x0D8, 0x0D7,
+	0x092, 0x08E, 0x07D, 0x04B, 0x0C2, 0x0FA, 0x061, 0x026,
+	0x006, 0x03A, 0x0B3, 0x06B, 0x003, 0x005, 0x049, 0x0E7,
+	0x00C, 0x0B9, 0x06F, 0x05A, 0x066, 0x095, 0x05C, 0x0B4,
+	0x0A3, 0x00C, 0x0C1, 0x03E, 0x070, 0x029, 0x0A2, 0x06E,
+	0x0A4, 0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1,
+	0x026, 0x0F8, 0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x0F9,
+	0x02F, 0x00B, 0x0E9, 0x084, 0x098, 0x018, 0x0EA, 0x0CC,
+	0x0EC, 0x00C, 0x015, 0x027, 0x09C, 0x032, 0x0FF, 0x03D,
+	0x056, 0x0AF, 0x092, 0x08B, 0x07A, 0x0D3, 0x035, 0x0D5,
+	0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002, 0x09A,
+	0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x041, 0x097, 0x091,
+	0x0F4, 0x083, 0x0CE, 0x004, 0x020, 0x062, 0x08B, 0x005,
+	0x016, 0x049, 0x08C, 0x024, 0x0C0, 0x0C7, 0x056, 0x090,
+	0x0C0, 0x0C1, 0x052, 0x079, 0x0C3, 0x02E, 0x05B, 0x0D5,
+	0x0A6, 0x072, 0x0D2, 0x094, 0x0FA, 0x0AD, 0x058, 0x0C8,
+	0x0FA, 0x09F, 0x054, 0x0B3, 0x032, 0x04B, 0x0B9, 0x054,
+	0x0A6, 0x051, 0x086, 0x06B, 0x079, 0x0D0, 0x060, 0x09F,
+	0x032, 0x005, 0x034, 0x04D, 0x08D, 0x07A, 0x04D, 0x01E,
+	0x07A, 0x0B3, 0x051, 0x000, 0x0A9, 0x03D, 0x059, 0x0A8,
+	0x07B, 0x044, 0x082, 0x0A1, 0x0AF, 0x04A, 0x08D, 0x052,
+	0x0A9, 0x052, 0x041, 0x049, 0x04F, 0x03A, 0x02E, 0x040,
+	0x0A4, 0x099, 0x050, 0x0BE, 0x090, 0x008, 0x052, 0x079,
+	0x0C3, 0x02E, 0x061, 0x026, 0x02D, 0x0EB, 0x04C, 0x0D0,
+	0x015, 0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002,
+	0x09A, 0x026, 0x0C6, 0x0BC, 0x048, 0x0FE, 0x01D, 0x025,
+	0x046, 0x0A9, 0x054, 0x0A9, 0x020, 0x0A4, 0x0A7, 0x09D,
+	0x017, 0x020, 0x052, 0x04C, 0x0A8, 0x05F, 0x048, 0x004,
+	0x023, 0x009, 0x031, 0x06F, 0x05A, 0x066, 0x080, 0x0AE,
+	0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x014, 0x0D1,
+	0x036, 0x035, 0x0E4, 0x0A7, 0x09D, 0x017, 0x020, 0x052,
+	0x04C, 0x0A2, 0x045, 0x00D, 0x08B, 0x015, 0x0F4, 0x091,
+	0x0DE, 0x08B, 0x0C9, 0x028, 0x0C2, 0x04C, 0x05B, 0x0D6,
+	0x099, 0x0A9, 0x05C, 0x0B4, 0x0A3, 0x00C, 0x0D6, 0x0F3,
+	0x0A0, 0x0C1, 0x03E, 0x064, 0x00A, 0x068, 0x09B, 0x01A,
+	0x0F1, 0x06D, 0x04C, 0x0AA, 0x092, 0x0E0, 0x036, 0x094,
+	0x070, 0x09B, 0x029, 0x078, 0x013, 0x0AE, 0x0B3, 0x0AA,
+	0x085, 0x0D4, 0x043, 0x075, 0x009, 0x03A, 0x0C9, 0x0EB,
+	0x035, 0x024, 0x0B8, 0x01B, 0x032, 0x08E, 0x013, 0x048,
+	0x07E, 0x04E, 0x0FD, 0x040, 0x0FD, 0x040, 0x0FD, 0x040,
+	0x0FD, 0x040, 0x0FD, 0x040, 0x0FC, 0x013, 0x0F4, 0x021,
+	0x0F9, 0x017, 0x045, 0x08A, 0x030, 0x00B, 0x033, 0x05F,
+	0x083, 0x0A2, 0x02A, 0x030, 0x00B, 0x033, 0x05F, 0x083,
+	0x0A2, 0x0A8, 0x0C0, 0x02D, 0x0B3, 0x020, 0x070, 0x092,
+	0x013, 0x09A, 0x0DE, 0x074, 0x018, 0x027, 0x0CC, 0x0AA,
+	0x068, 0x09B, 0x01A, 0x0F7, 0x007, 0x045, 0x051, 0x080,
+	0x05B, 0x066, 0x047, 0x007, 0x038, 0x0A8, 0x023, 0x0E7,
+	0x051, 0x011, 0x03F, 0x0E0, 0x0E8, 0x085, 0x046, 0x001,
+	0x06D, 0x099, 0x006, 0x012, 0x065, 0x04F, 0x07A, 0x020,
+	0x024, 0x0BA, 0x0B3, 0x032, 0x015, 0x025, 0x07B, 0x0AD,
+	0x033, 0x078, 0x0AE, 0x00E, 0x073, 0x0D0, 0x047, 0x0CE,
+	0x0A7, 0x030, 0x0CC, 0x044, 0x0FF, 0x083, 0x0A2, 0x0A8,
+	0x0C0, 0x02C, 0x0D9, 0x091, 0x0C1, 0x0D1, 0x015, 0x018,
+	0x005, 0x09B, 0x032, 0x008, 0x0BA, 0x02C, 0x051, 0x080,
+	0x059, 0x0B3, 0x020, 0x070, 0x092, 0x0E2, 0x098, 0x089,
+	0x0FD, 0x0BC, 0x0EE, 0x018, 0x090, 0x0FC, 0x08B, 0x0A2,
+	0x0C5, 0x02B, 0x00D, 0x078, 0x03A, 0x022, 0x0A5, 0x061,
+	0x0AF, 0x007, 0x045, 0x051, 0x080, 0x05B, 0x066, 0x044,
+	0x09E, 0x0B3, 0x052, 0x04B, 0x083, 0x0AD, 0x0C7, 0x009,
+	0x0BE, 0x01F, 0x09F, 0x074, 0x065, 0x05D, 0x00A, 0x017,
+	0x07C, 0x0AB, 0x0A0, 0x0C2, 0x04C, 0x038, 0x049, 0x012,
+	0x02E, 0x038, 0x049, 0x007, 0x0A3, 0x00C, 0x0C1, 0x03E,
+	0x065, 0x053, 0x044, 0x0D8, 0x0D7, 0x0AD, 0x0E7, 0x000,
+	0x032, 0x04B, 0x09B, 0x033, 0x034, 0x04A, 0x003, 0x000,
+	0x09D, 0x025, 0x0CE, 0x083, 0x024, 0x0B8, 0x019, 0x099,
+	0x08C, 0x002, 0x012, 0x04B, 0x0A1, 0x099, 0x0D8, 0x0C0,
+	0x027, 0x049, 0x073, 0x0CF, 0x0F9, 0x03C, 0x0F4, 0x07C,
+	0x0E7, 0x098, 0x004, 0x0E9, 0x02E, 0x07F, 0x039, 0x0E3,
+	0x04F, 0x046, 0x053, 0x0C0, 0x060, 0x013, 0x0A4, 0x0B9,
+	0x0E5, 0x03C, 0x003, 0x0DE, 0x08F, 0x09C, 0x0F3, 0x000,
+	0x09C, 0x06F, 0x0CF, 0x03E, 0x085, 0x0F9, 0x0A3, 0x036,
+	0x002, 0x01E, 0x060, 0x038, 0x092, 0x03E, 0x063, 0x01A,
+	0x010, 0x09F, 0x0CF, 0x018, 0x010, 0x092, 0x0BC, 0x0D0,
+	0x0A4, 0x00C, 0x0DC, 0x0C0, 0x00F, 0x09C, 0x097, 0x034,
+	0x062, 0x0B6, 0x0E7, 0x0F3, 0x0F3, 0x0A5, 0x0CF, 0x018,
+	0x042, 0x034, 0x01C, 0x0C2, 0x0CA, 0x0FA, 0x08E, 0x068,
+	0x052, 0x006, 0x0AF, 0x03C, 0x0A3, 0x00D, 0x0BF, 0x09E,
+	0x050, 0x0E1, 0x0D1, 0x073, 0x0CA, 0x0E0, 0x03A, 0x0FC,
+	0x0C1, 0x009, 0x01A, 0x01E, 0x06A, 0x05C, 0x05B, 0x08E,
+	0x063, 0x04E, 0x077, 0x073, 0x0CC, 0x061, 0x067, 0x0DD,
+	0x0E6, 0x06C, 0x048, 0x0D1, 0x0F3, 0x01B, 0x024, 0x069,
+	0x051, 0x008, 0x0D4, 0x042, 0x01B, 0x0F4, 0x067, 0x0D1,
+	0x080, 0x04E, 0x02F, 0x0D0, 0x08C, 0x0D8, 0x030, 0x009,
+	0x0C2, 0x01E, 0x080, 0x01C, 0x046, 0x001, 0x03A, 0x047,
+	0x0D0, 0x031, 0x0A1, 0x006, 0x001, 0x03A, 0x07F, 0x046,
+	0x030, 0x021, 0x018, 0x004, 0x0E9, 0x05E, 0x084, 0x029,
+	0x000, 0x0C0, 0x027, 0x0CD, 0x0D0, 0x000, 0x07C, 0x098,
+	0x004, 0x0F9, 0x02E, 0x084, 0x062, 0x08C, 0x002, 0x07D,
+	0x0BA, 0x03E, 0x07E, 0x04C, 0x002, 0x07D, 0x02E, 0x08C,
+	0x061, 0x008, 0x030, 0x009, 0x0F4, 0x01D, 0x001, 0x065,
+	0x073, 0x000, 0x09F, 0x051, 0x0D0, 0x085, 0x020, 0x018,
+	0x004, 0x0FA, 0x0BD, 0x019, 0x046, 0x018, 0x0C0, 0x027,
+	0x0DF, 0x0D1, 0x094, 0x038, 0x04C, 0x002, 0x07D, 0x017,
+	0x046, 0x057, 0x001, 0x030, 0x009, 0x0F5, 0x0FA, 0x001,
+	0x009, 0x006, 0x001, 0x03E, 0x087, 0x0A1, 0x04B, 0x088,
+	0x0C0, 0x027, 0x0DC, 0x074, 0x00D, 0x039, 0x0D3, 0x000,
+	0x09F, 0x073, 0x0D0, 0x030, 0x0B3, 0x098, 0x004, 0x0FB,
+	0x0BD, 0x006, 0x0C4, 0x083, 0x000, 0x09F, 0x047, 0x0D0,
+	0x036, 0x048, 0x0CC, 0x002, 0x071, 0x0BF, 0x03F, 0x09A,
+	0x017, 0x0E6, 0x03F, 0x008, 0x021, 0x0E6, 0x092, 0x0A4,
+	0x08F, 0x09A, 0x010, 0x031, 0x0A7, 0x0F3, 0x010, 0x0B1,
+	0x084, 0x0AF, 0x03A, 0x0AC, 0x0DC, 0x0F7, 0x073, 0x0F2,
+	0x05C, 0x0C6, 0x02A, 0x0DB, 0x09E, 0x07E, 0x07E, 0x097,
+	0x031, 0x008, 0x063, 0x0D0, 0x073, 0x07B, 0x043, 0x0A8,
+	0x0E6, 0x03D, 0x034, 0x0EA, 0x0F3, 0x0E3, 0x015, 0x0BF,
+	0x09F, 0x018, 0x05F, 0x045, 0x0CF, 0x0E8, 0x09F, 0x05F,
+	0x09A, 0x05B, 0x003, 0x0D0, 0x0F3, 0x0D3, 0x0CE, 0x037,
+	0x01C, 0x0D0, 0x00F, 0x0BB, 0x09E, 0x068, 0x078, 0x03B,
+	0x0BC, 0x0CA, 0x031, 0x0E8, 0x0F9, 0x0A2, 0x002, 0x012,
+	0x0A2, 0x073, 0x051, 0x008, 0x06F, 0x0D1, 0x0F3, 0x046,
+	0x001, 0x038, 0x0BF, 0x040, 0x0FC, 0x023, 0x000, 0x09C,
+	0x021, 0x0E8, 0x049, 0x051, 0x080, 0x04E, 0x091, 0x0F4,
+	0x021, 0x003, 0x019, 0x080, 0x04E, 0x09F, 0x0D0, 0x021,
+	0x063, 0x006, 0x001, 0x03A, 0x056, 0x08C, 0x002, 0x074,
+	0x0FE, 0x075, 0x049, 0x05E, 0x063, 0x0D3, 0x04A, 0x054,
+	0x042, 0x035, 0x013, 0x0A7, 0x0D1, 0x080, 0x04E, 0x095,
+	0x0E8, 0x01E, 0x09A, 0x04C, 0x002, 0x07C, 0x0DD, 0x01B,
+	0x0B9, 0x0E6, 0x001, 0x03E, 0x04B, 0x0A0, 0x062, 0x0A3,
+	0x000, 0x09F, 0x06E, 0x08C, 0x0FC, 0x0F3, 0x000, 0x09F,
+	0x04B, 0x0A0, 0x042, 0x018, 0x0CC, 0x002, 0x07D, 0x007,
+	0x043, 0x0DA, 0x013, 0x000, 0x09F, 0x051, 0x0D0, 0x03D,
+	0x034, 0x098, 0x004, 0x0FA, 0x0BD, 0x01C, 0x062, 0x08C,
+	0x002, 0x07D, 0x0FD, 0x01C, 0x061, 0x073, 0x000, 0x09F,
+	0x045, 0x0D1, 0x0F4, 0x04E, 0x060, 0x013, 0x0EB, 0x0F4,
+	0x025, 0x0B0, 0x033, 0x000, 0x09F, 0x043, 0x0D1, 0x0A7,
+	0x09C, 0x018, 0x004, 0x0FB, 0x08E, 0x084, 0x003, 0x0E9,
+	0x080, 0x04F, 0x0B9, 0x0E8, 0x043, 0x0C1, 0x030, 0x009,
+	0x0F7, 0x07A, 0x00A, 0x031, 0x098, 0x004, 0x0FA, 0x03E,
+	0x084, 0x040, 0x041, 0x080, 0x04E, 0x082, 0x0E7, 0x041,
+	0x087, 0x009, 0x023, 0x004, 0x023, 0x000, 0x09D, 0x005,
+	0x0CE, 0x096, 0x01C, 0x024, 0x08C, 0x010, 0x08C, 0x002,
+	0x074, 0x017, 0x03A, 0x004, 0x038, 0x049, 0x018, 0x021,
+	0x018, 0x004, 0x0E8, 0x02E, 0x074, 0x050, 0x0E1, 0x024,
+	0x060, 0x084, 0x060, 0x013, 0x0A0, 0x0B9, 0x0D4, 0x011,
+	0x0C2, 0x048, 0x0C1, 0x008, 0x0C0, 0x027, 0x041, 0x073,
+	0x0A8, 0x023, 0x084, 0x091, 0x082, 0x011, 0x080, 0x04E,
+	0x082, 0x0E7, 0x052, 0x08E, 0x012, 0x046, 0x008, 0x046,
+	0x001, 0x03A, 0x00B, 0x09D, 0x040, 0x01C, 0x024, 0x08C,
+	0x010, 0x08C, 0x002, 0x074, 0x017, 0x03A, 0x009, 0x00E,
+	0x012, 0x046, 0x008, 0x046, 0x001, 0x03A, 0x00B, 0x098,
+	0x06A, 0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0E8,
+	0x02E, 0x06B, 0x050, 0x0E1, 0x025, 0x087, 0x008, 0x0C0,
+	0x027, 0x041, 0x073, 0x005, 0x043, 0x084, 0x096, 0x01C,
+	0x023, 0x000, 0x09D, 0x005, 0x0CC, 0x0AA, 0x01C, 0x024,
+	0x0B0, 0x0E1, 0x018, 0x004, 0x0E8, 0x02E, 0x070, 0x068,
+	0x070, 0x092, 0x0C3, 0x084, 0x060, 0x013, 0x0E5, 0x044,
+	0x0F9, 0x040, 0x09D, 0x005, 0x0CE, 0x05A, 0x01C, 0x024,
+	0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1, 0x03E, 0x070,
+	0x027, 0x0CF, 0x013, 0x0E5, 0x044, 0x02C, 0x0A0, 0x042,
+	0x0CB, 0x089, 0x0F2, 0x021, 0x03A, 0x00B, 0x09C, 0x00A,
+	0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1,
+	0x00B, 0x038, 0x010, 0x0B3, 0x0C4, 0x021, 0x039, 0x036,
+	0x05C, 0x042, 0x0C8, 0x084, 0x02B, 0x079, 0x0D0, 0x061,
+	0x0C2, 0x074, 0x015, 0x024, 0x0BA, 0x0D3, 0x031, 0x0E5,
+	0x059, 0x008, 0x029, 0x008, 0x0E0, 0x066, 0x063, 0x042,
+	0x095, 0x012, 0x081, 0x000, 0x029, 0x00B, 0x0C1, 0x051,
+	0x024, 0x0B8, 0x019, 0x099, 0x090, 0x022, 0x090, 0x0B4,
+	0x018, 0x0A0, 0x091, 0x041, 0x001, 0x041, 0x041, 0x041,
+	0x052, 0x083, 0x0CA, 0x040, 0x028, 0x068, 0x029, 0x008,
+	0x0BA, 0x016, 0x010, 0x09C, 0x099, 0x00B, 0x056, 0x094,
+	0x090, 0x052, 0x015, 0x074, 0x0C0, 0x027, 0x01A, 0x02A,
+	0x0D2, 0x090, 0x025, 0x0D3, 0x000, 0x09D, 0x028, 0x0AB,
+	0x04A, 0x042, 0x017, 0x04C, 0x002, 0x070, 0x0D4, 0x084,
+	0x02E, 0x098, 0x004, 0x0E1, 0x02A, 0x042, 0x017, 0x04C,
+	0x002, 0x070, 0x082, 0x090, 0x04B, 0x0A6, 0x001, 0x038,
+	0x051, 0x048, 0x042, 0x0E9, 0x080, 0x04E, 0x015, 0x0A4,
+	0x021, 0x074, 0x0C0, 0x027, 0x00F, 0x0A4, 0x012, 0x0E9,
+	0x080, 0x04E, 0x082, 0x0AC, 0x080, 0x0AC, 0x0A0, 0x0AC,
+	0x0A9, 0x059, 0x0E5, 0x064, 0x045, 0x065, 0x0CA, 0x0C8,
+	0x04A, 0x0CE, 0x00A, 0x0CE, 0x04A, 0x0CE, 0x095, 0x091,
+	0x095, 0x094, 0x095, 0x093, 0x029, 0x025, 0x0C0, 0x0CC,
+	0x0CC, 0x088, 0x0A4, 0x097, 0x056, 0x036, 0x064, 0x072,
+	0x090, 0x054, 0x08A, 0x09C, 0x045, 0x008, 0x0B9, 0x0B7,
+	0x066, 0x012, 0x093, 0x009, 0x0C9, 0x0B2, 0x074, 0x08E,
+	0x0BA, 0x060, 0x013, 0x0E5, 0x034, 0x08E, 0x0BA, 0x060,
+	0x013, 0x0E4, 0x074, 0x08E, 0x0BA, 0x060, 0x013, 0x0E5,
+	0x069, 0x01D, 0x074, 0x0C0, 0x027, 0x0CA, 0x029, 0x01D,
+	0x074, 0x0C0, 0x027, 0x0CE, 0x0D2, 0x025, 0x0D3, 0x000,
+	0x09F, 0x038, 0x0A4, 0x04B, 0x0A6, 0x001, 0x03E, 0x05E,
+	0x091, 0x02E, 0x098, 0x004, 0x0F9, 0x015, 0x022, 0x05D,
+	0x030, 0x009, 0x0F3, 0x0E9, 0x012, 0x0E9, 0x080, 0x04F,
+	0x090, 0x052, 0x025, 0x0D3, 0x000, 0x09D, 0x0C5, 0x048,
+	0x025, 0x0D3, 0x000, 0x09C, 0x045, 0x0CE, 0x0CD, 0x009,
+	0x0C9, 0x0B2, 0x01A, 0x044, 0x0BA, 0x060, 0x013, 0x0E7,
+	0x034, 0x089, 0x074, 0x0C0, 0x027, 0x01C, 0x027, 0x0B7,
+	0x09C, 0x080, 0x0C2, 0x0D7, 0x076, 0x059, 0x09B, 0x093,
+	0x00C, 0x064, 0x0C3, 0x01D, 0x01B, 0x0F4, 0x045, 0x04B,
+	0x0C7, 0x0C6, 0x03A, 0x037, 0x0E8, 0x081, 0x04B, 0x0C7,
+	0x0C6, 0x03A, 0x037, 0x0E8, 0x091, 0x04B, 0x0C7, 0x0C6,
+	0x032, 0x061, 0x08E, 0x0B3, 0x0BC, 0x0C3, 0x04A, 0x022,
+	0x0E6, 0x0B5, 0x024, 0x097, 0x071, 0x0C9, 0x087, 0x0B4,
+	0x031, 0x0AE, 0x073, 0x0A2, 0x0CF, 0x039, 0x0D2, 0x05D,
+	0x004, 0x044, 0x042, 0x0C0, 0x0D6, 0x0DE, 0x071, 0x006,
+	0x016, 0x0BB, 0x0DB, 0x0CE, 0x083, 0x00C, 0x064, 0x0C3,
+	0x01D, 0x031, 0x013, 0x004, 0x0F9, 0x095, 0x04D, 0x013,
+	0x032, 0x093, 0x063, 0x05E, 0x066, 0x014, 0x0CC, 0x029,
+	0x02A, 0x053, 0x030, 0x0A6, 0x061, 0x04C, 0x0C2, 0x099,
+	0x085, 0x03A, 0x072, 0x0CC, 0x0C2, 0x099, 0x085, 0x006,
+	0x01B, 0x0B3, 0x00A, 0x066, 0x014, 0x014, 0x024, 0x099,
+	0x085, 0x033, 0x00A, 0x008, 0x0B1, 0x086, 0x061, 0x04C,
+	0x0C2, 0x084, 0x021, 0x068, 0x073, 0x03B, 0x030, 0x0A6,
+	0x061, 0x041, 0x04E, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+	0x059, 0x076, 0x061, 0x04C, 0x0C2, 0x0B0, 0x08D, 0x0D6,
+	0x061, 0x04C, 0x0C2, 0x0B0, 0x02C, 0x0F6, 0x061, 0x04C,
+	0x0C2, 0x0B1, 0x08C, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+	0x00F, 0x024, 0x0CC, 0x029, 0x098, 0x056, 0x00F, 0x028,
+	0x066, 0x015, 0x092, 0x01A, 0x019, 0x085, 0x033, 0x00A,
+	0x0CA, 0x085, 0x00C, 0x0C2, 0x099, 0x085, 0x065, 0x0C3,
+	0x0D9, 0x085, 0x033, 0x00A, 0x0CE, 0x070, 0x086, 0x061,
+	0x04C, 0x0C2, 0x0B3, 0x097, 0x071, 0x00C, 0x099, 0x03B,
+	0x0CC, 0x083, 0x058, 0x00B, 0x0EA, 0x077, 0x09D, 0x006,
+	0x04A, 0x0BE, 0x004, 0x074, 0x060, 0x0E0, 0x0D1, 0x04E,
+	0x038, 0x04C, 0x03E, 0x0EE, 0x03E, 0x0EE, 0x03E, 0x0EE,
+	0x03E, 0x0EE, 0x030, 0x0BB, 0x0CA, 0x0E1, 0x01F, 0x077,
+	0x01F, 0x077, 0x01F, 0x077, 0x01F, 0x077, 0x027, 0x070,
+	0x08F, 0x0BB, 0x080, 0x00E, 0x011, 0x0F7, 0x071, 0x0F7,
+	0x07C, 0x06F, 0x03C, 0x0B3, 0x036, 0x002, 0x0FB, 0x08D,
+	0x0E6, 0x055, 0x070, 0x07F, 0x02D, 0x024, 0x069, 0x055,
+	0x04F, 0x058, 0x0A9, 0x023, 0x01F, 0x054, 0x0F7, 0x08A,
+	0x095, 0x025, 0x02B, 0x075, 0x00C, 0x0CC, 0x0AC, 0x056,
+	0x051, 0x0CC, 0x051, 0x0E4, 0x045, 0x0CE, 0x0A2, 0x012,
+	0x039, 0x0C0, 0x0A0, 0x0AF, 0x056, 0x06A, 0x049, 0x07F,
+	0x002, 0x08C, 0x009, 0x0F8, 0x00B, 0x0EB, 0x0AF, 0x056,
+	0x076, 0x067, 0x052, 0x0B2, 0x08E, 0x069, 0x0A7, 0x011,
+	0x073, 0x0A8, 0x0B1, 0x0BC, 0x0CA, 0x0A0, 0x0A9, 0x036,
+	0x050, 0x02C, 0x098, 0x0E7, 0x00A, 0x0F5, 0x066, 0x0A4,
+	0x097, 0x0E2, 0x05A, 0x030, 0x027, 0x0BA, 0x0F7, 0x083,
+	0x04E, 0x0A5, 0x033, 0x00A, 0x066, 0x015, 0x08D, 0x0E6,
+	0x055, 0x039, 0x0D2, 0x0A7, 0x0AC, 0x054, 0x060, 0x016,
+	0x070, 0x01B, 0x072, 0x08E, 0x062, 0x08F, 0x022, 0x02E,
+	0x075, 0x016, 0x002, 0x0FB, 0x08D, 0x0E6, 0x00A, 0x095,
+	0x03D, 0x062, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B5, 0x053,
+	0x0DE, 0x02A, 0x054, 0x094, 0x0AD, 0x0D4, 0x033, 0x032,
+	0x0B1, 0x059, 0x047, 0x031, 0x047, 0x091, 0x017, 0x03A,
+	0x088, 0x048, 0x0E7, 0x002, 0x0B0, 0x017, 0x0DC, 0x067,
+	0x09D, 0x04B, 0x08D, 0x0E7, 0x052, 0x0AA, 0x07B, 0x0D4,
+	0x0AA, 0x092, 0x0BD, 0x0D6, 0x099, 0x0BC, 0x056, 0x002,
+	0x0FB, 0x08C, 0x0F3, 0x066, 0x066, 0x0C6, 0x0F3, 0x066,
+	0x066, 0x062, 0x099, 0x02A, 0x0F8, 0x018, 0x068, 0x070,
+	0x0B0, 0x08A, 0x00D, 0x055, 0x055, 0x055, 0x055, 0x052,
+	0x032, 0x0E1, 0x040, 0x05C, 0x038, 0x00B, 0x0EA, 0x09B,
+	0x087, 0x001, 0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0DC,
+	0x005, 0x0F5, 0x0DC, 0x09B, 0x001, 0x07D, 0x061, 0x04D,
+	0x080, 0x0BE, 0x0A7, 0x079, 0x082, 0x0A2, 0x01F, 0x050,
+	0x015, 0x02A, 0x08F, 0x08B, 0x01C, 0x0E5, 0x0A5, 0x013,
+	0x084, 0x058, 0x0E7, 0x002, 0x091, 0x054, 0x005, 0x002,
+	0x04B, 0x0BD, 0x022, 0x01A, 0x094, 0x07F, 0x09C, 0x01A,
+	0x0C0, 0x05F, 0x042, 0x01A, 0x021, 0x0D1, 0x080, 0x059,
+	0x0C0, 0x06D, 0x01C, 0x02C, 0x00A, 0x083, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x054, 0x01C, 0x0B8, 0x05C, 0x06E, 0x017, 0x09C,
+	0x02F, 0x038, 0x05E, 0x070, 0x0E7, 0x0B8, 0x05E, 0x070,
+	0x0BC, 0x0E1, 0x079, 0x0C2, 0x0F3, 0x085, 0x0E7, 0x00B,
+	0x0CE, 0x017, 0x09C, 0x029, 0x09C, 0x029, 0x09C, 0x029,
+	0x09C, 0x023, 0x00F, 0x058, 0x014, 0x0EE, 0x035, 0x077,
+	0x026, 0x021, 0x093, 0x005, 0x0C9, 0x0B0, 0x017, 0x0D2,
+	0x01D, 0x018, 0x08A, 0x021, 0x093, 0x005, 0x0C9, 0x0B0,
+	0x017, 0x0D1, 0x087, 0x0AC, 0x00A, 0x074, 0x00F, 0x0AE,
+	0x0F5, 0x05A, 0x082, 0x0A3, 0x0E4, 0x03A, 0x031, 0x014,
+	0x0BB, 0x0D7, 0x059, 0x099, 0x074, 0x0A2, 0x019, 0x030,
+	0x05C, 0x09B, 0x001, 0x07D, 0x018, 0x07A, 0x0C0, 0x0A7,
+	0x040, 0x0F8, 0x043, 0x0D4, 0x063, 0x089, 0x025, 0x0D0,
+	0x010, 0x0D6, 0x01C, 0x06A, 0x010, 0x0F5, 0x055, 0x089,
+	0x025, 0x0D1, 0x051, 0x066, 0x01F, 0x051, 0x0F5, 0x091,
+	0x049, 0x02E, 0x089, 0x015, 0x098, 0x06A, 0x0A3, 0x0E0,
+	0x08A, 0x094, 0x065, 0x064, 0x00E, 0x013, 0x017, 0x038,
+	0x0A8, 0x086, 0x04C, 0x017, 0x026, 0x0C0, 0x05F, 0x046,
+	0x01E, 0x0B0, 0x028, 0x063, 0x01F, 0x008, 0x07A, 0x08C,
+	0x071, 0x024, 0x0BA, 0x002, 0x01A, 0x0D0, 0x00D, 0x042,
+	0x01E, 0x0AA, 0x0B1, 0x024, 0x0BA, 0x02A, 0x02D, 0x031,
+	0x0F5, 0x01F, 0x058, 0x074, 0x092, 0x0E8, 0x087, 0x05A,
+	0x063, 0x052, 0x0DE, 0x0F4, 0x051, 0x069, 0x04A, 0x03E,
+	0x009, 0x069, 0x046, 0x050, 0x0F0, 0x0E1, 0x031, 0x073,
+	0x005, 0x045, 0x0BD, 0x059, 0x08D, 0x08B, 0x04A, 0x07C,
+	0x0D3, 0x0ED, 0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED,
+	0x044, 0x032, 0x060, 0x0B9, 0x036, 0x002, 0x0FA, 0x05B,
+	0x0DE, 0x08A, 0x02D, 0x029, 0x0D0, 0x0E1, 0x021, 0x0F5,
+	0x0A3, 0x092, 0x021, 0x0F2, 0x019, 0x030, 0x05C, 0x09B,
+	0x001, 0x07D, 0x021, 0x0F5, 0x0A0, 0x0C6, 0x001, 0x067,
+	0x001, 0x0B4, 0x045, 0x0CE, 0x0A5, 0x012, 0x039, 0x0D4,
+	0x01C, 0x005, 0x0F4, 0x040, 0x0A1, 0x0C2, 0x0C3, 0x050,
+	0x06A, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+	0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x081, 0x0AF,
+	0x086, 0x09F, 0x019, 0x01B, 0x0E7, 0x081, 0x0F3, 0x065,
+	0x0F2, 0x080, 0x0BE, 0x070, 0x017, 0x0DF, 0x0DF, 0x038,
+	0x00B, 0x0EB, 0x00D, 0x0C3, 0x080, 0x0BE, 0x0A7, 0x00F,
+	0x095, 0x04F, 0x05A, 0x094, 0x0C0, 0x02C, 0x0D8, 0x0B1,
+	0x0A7, 0x0CE, 0x05A, 0x011, 0x073, 0x0A8, 0x03A, 0x0C2,
+	0x0CC, 0x0B6, 0x030, 0x017, 0x0DC, 0x06F, 0x035, 0x0A9,
+	0x080, 0x04D, 0x0A7, 0x0CE, 0x02A, 0x018, 0x079, 0x0C5,
+	0x049, 0x0DE, 0x061, 0x0A8, 0x022, 0x0E7, 0x050, 0x033,
+	0x0F9, 0x098, 0x064, 0x008, 0x0B9, 0x095, 0x042, 0x0FC,
+	0x0CC, 0x0D9, 0x095, 0x03D, 0x062, 0x0A2, 0x048, 0x0D4,
+	0x048, 0x0E7, 0x002, 0x088, 0x0B9, 0x0C1, 0x0A0, 0x0E3,
+	0x09D, 0x04E, 0x062, 0x0E6, 0x0CC, 0x0C6, 0x06B, 0x0CE,
+	0x083, 0x010, 0x0C9, 0x082, 0x0E4, 0x0DA, 0x0C2, 0x0C8,
+	0x01E, 0x0C3, 0x0B9, 0x036, 0x002, 0x0FA, 0x0A9, 0x0EB,
+	0x04E, 0x030, 0x030, 0x0FA, 0x00D, 0x0F0, 0x0A9, 0x0EB,
+	0x040, 0x0B9, 0x00F, 0x0AA, 0x07A, 0x0D2, 0x0C2, 0x0C8,
+	0x0FA, 0x0A7, 0x0AD, 0x041, 0x00A, 0x047, 0x0D5, 0x03D,
+	0x068, 0x0AC, 0x0F1, 0x0F5, 0x04F, 0x05A, 0x097, 0x054,
+	0x07D, 0x04F, 0x0A8, 0x0AA, 0x055, 0x01F, 0x011, 0x073,
+	0x05A, 0x0B0, 0x017, 0x0DE, 0x05D, 0x059, 0x0A9, 0x025,
+	0x0D0, 0x055, 0x02A, 0x046, 0x0BC, 0x0B8, 0x022, 0x0AE,
+	0x045, 0x029, 0x03E, 0x014, 0x0FA, 0x0E1, 0x099, 0x094,
+	0x0CA, 0x04A, 0x0BE, 0x03D, 0x0D6, 0x099, 0x092, 0x05D,
+	0x015, 0x017, 0x0C8, 0x0D7, 0x0DC, 0x015, 0x017, 0x08A,
+	0x040, 0x01F, 0x00A, 0x09E, 0x0AC, 0x0C9, 0x065, 0x049,
+	0x05C, 0x01D, 0x010, 0x068, 0x04A, 0x03E, 0x05B, 0x0DE,
+	0x083, 0x016, 0x095, 0x080, 0x0BE, 0x091, 0x074, 0x058,
+	0x0A4, 0x000, 0x07C, 0x038, 0x0E7, 0x056, 0x030, 0x017,
+	0x0DF, 0x075, 0x0A6, 0x064, 0x097, 0x045, 0x020, 0x09D,
+	0x003, 0x05F, 0x070, 0x054, 0x05E, 0x029, 0x01D, 0x0F0,
+	0x0A9, 0x0EA, 0x0CC, 0x086, 0x054, 0x095, 0x0C1, 0x0D1,
+	0x006, 0x083, 0x00F, 0x0AA, 0x07B, 0x0D0, 0x065, 0x049,
+	0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x091, 0x0DF, 0x004,
+	0x05D, 0x016, 0x029, 0x01C, 0x07D, 0x04F, 0x0AC, 0x01A,
+	0x047, 0x01A, 0x0A9, 0x0F5, 0x067, 0x066, 0x053, 0x028,
+	0x0B7, 0x0BD, 0x02C, 0x05A, 0x052, 0x03B, 0x0E3, 0x0DD,
+	0x059, 0x0A9, 0x025, 0x0D1, 0x0A8, 0x0AC, 0x008, 0x06B,
+	0x0EE, 0x008, 0x0AB, 0x0C5, 0x020, 0x02F, 0x085, 0x04F,
+	0x056, 0x066, 0x075, 0x049, 0x05C, 0x01C, 0x018, 0x01D,
+	0x081, 0x0C2, 0x064, 0x005, 0x0F0, 0x080, 0x0BE, 0x035,
+	0x05C, 0x0D0, 0x017, 0x0C2, 0x055, 0x0F0, 0x095, 0x07C,
+	0x025, 0x05F, 0x008, 0x00B, 0x0E1, 0x001, 0x07C, 0x07B,
+	0x0AB, 0x035, 0x024, 0x0BA, 0x010, 0x055, 0x093, 0x01A,
+	0x0FB, 0x082, 0x02A, 0x0F1, 0x048, 0x0D7, 0x0C2, 0x0A7,
+	0x0AB, 0x031, 0x0B2, 0x0A4, 0x0AC, 0x063, 0x09D, 0x04A,
+	0x08D, 0x07C, 0x07B, 0x0AB, 0x035, 0x024, 0x0BA, 0x010,
+	0x054, 0x030, 0x08D, 0x07D, 0x0C1, 0x015, 0x078, 0x0AC,
+	0x06F, 0x05A, 0x094, 0x060, 0x01A, 0x0E3, 0x079, 0x0D4,
+	0x0AA, 0x04F, 0x085, 0x04F, 0x056, 0x066, 0x0D5, 0x049,
+	0x058, 0x0C7, 0x03A, 0x095, 0x049, 0x0F0, 0x045, 0x0D1,
+	0x062, 0x094, 0x086, 0x0BC, 0x01D, 0x013, 0x0D2, 0x090,
+	0x0FF, 0x0CF, 0x07A, 0x083, 0x0F2, 0x050, 0x031, 0x0DE,
+	0x000, 0x060, 0x060, 0x0A1, 0x017, 0x035, 0x0A8, 0x05F,
+	0x09B, 0x01B, 0x037, 0x007, 0x044, 0x01A, 0x030, 0x00B,
+	0x038, 0x00D, 0x0BC, 0x01C, 0x0E0, 0x0D0, 0x047, 0x0CE,
+	0x0A0, 0x0AA, 0x07A, 0x0A1, 0x098, 0x06A, 0x092, 0x095,
+	0x03D, 0x068, 0x031, 0x080, 0x05B, 0x080, 0x0DA, 0x0A9,
+	0x0EF, 0x041, 0x095, 0x025, 0x016, 0x0F7, 0x0A5, 0x08B,
+	0x04A, 0x0C6, 0x079, 0x0B3, 0x033, 0x060, 0x02F, 0x0AA,
+	0x09E, 0x0B1, 0x051, 0x080, 0x059, 0x09E, 0x0CA, 0x0A7,
+	0x0AC, 0x00A, 0x030, 0x00B, 0x067, 0x0B2, 0x0AD, 0x0D5,
+	0x0DA, 0x092, 0x05D, 0x017, 0x0A3, 0x000, 0x0B3, 0x02D,
+	0x095, 0x06E, 0x008, 0x0A9, 0x058, 0x0A1, 0x017, 0x03A,
+	0x08B, 0x001, 0x07D, 0x054, 0x0F7, 0x08E, 0x095, 0x025,
+	0x008, 0x01C, 0x0E0, 0x056, 0x002, 0x0FB, 0x0C1, 0x0D1,
+	0x015, 0x018, 0x005, 0x092, 0x06B, 0x03C, 0x01D, 0x012,
+	0x028, 0x0C0, 0x02C, 0x0A5, 0x06C, 0x011, 0x070, 0x017,
+	0x0B2, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B4,
+	0x0EC, 0x04A, 0x0ED, 0x0B3, 0x09E, 0x002, 0x0FB, 0x080,
+	0x0BE, 0x0E0, 0x02F, 0x0B1, 0x039, 0x093, 0x03E, 0x06D,
+	0x0E7, 0x010, 0x060, 0x09F, 0x032, 0x0A9, 0x0A2, 0x06C,
+	0x005, 0x0F4, 0x040, 0x0E6, 0x00A, 0x095, 0x03D, 0x06A,
+	0x023, 0x000, 0x0B3, 0x080, 0x0DA, 0x0A7, 0x0D6, 0x02A,
+	0x003, 0x00D, 0x070, 0x017, 0x0D2, 0x02E, 0x076, 0x029,
+	0x04F, 0x0BC, 0x054, 0x0A6, 0x051, 0x06F, 0x07A, 0x058,
+	0x0B4, 0x0AC, 0x005, 0x0F4, 0x08B, 0x0A2, 0x0F4, 0x00E,
+	0x035, 0x00D, 0x049, 0x02E, 0x0B4, 0x0CC, 0x018, 0x0A5,
+	0x0C8, 0x0F8, 0x04A, 0x097, 0x023, 0x0E1, 0x005, 0x02E,
+	0x047, 0x0C2, 0x08A, 0x05C, 0x08F, 0x085, 0x069, 0x072,
+	0x03E, 0x01F, 0x04A, 0x0C3, 0x055, 0x01F, 0x056, 0x043,
+	0x032, 0x08C, 0x0A3, 0x05E, 0x060, 0x0A8, 0x045, 0x0CE,
+	0x00D, 0x060, 0x02F, 0x0A3, 0x084, 0x09D, 0x0D8, 0x0F0,
+	0x017, 0x0D2, 0x02E, 0x00E, 0x01B, 0x023, 0x084, 0x0D8,
+	0x00B, 0x0EB, 0x089, 0x0F3, 0x080, 0x0BE, 0x0E0, 0x02F,
+	0x0BB, 0x039, 0x085, 0x0DF, 0x022, 0x003, 0x0E7, 0x001,
+	0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0D1, 0x017, 0x038,
+	0x014, 0x05B, 0x0D6, 0x0A2, 0x074, 0x00D, 0x04B, 0x07A,
+	0x0B3, 0x031, 0x096, 0x094, 0x06B, 0x0CC, 0x035, 0x023,
+	0x0D7, 0x049, 0x048, 0x015, 0x073, 0x029, 0x00F, 0x05D,
+	0x08A, 0x0C0, 0x05F, 0x04D, 0x079, 0x084, 0x035, 0x080,
+	0x0BE, 0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068,
+	0x0C0, 0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A,
+	0x092, 0x0BE, 0x0F3, 0x081, 0x04A, 0x07D, 0x05B, 0x059,
+	0x094, 0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x080, 0x0BE,
+	0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068, 0x0C0,
+	0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A, 0x092,
+	0x0BE, 0x0F3, 0x081, 0x043, 0x084, 0x09C, 0x07B, 0x038,
+	0x00B, 0x0EB, 0x0AF, 0x070, 0x0D4, 0x0EA, 0x053, 0x000,
+	0x09B, 0x04F, 0x09C, 0x054, 0x030, 0x0F3, 0x08A, 0x094,
+	0x0FA, 0x0B6, 0x0B3, 0x029, 0x094, 0x022, 0x0E6, 0x01A,
+	0x085, 0x0F9, 0x0B0, 0x059, 0x093, 0x0F9, 0x0D2, 0x0C4,
+	0x032, 0x060, 0x0B9, 0x036, 0x0B0, 0x0B3, 0x090, 0x0D9,
+	0x077, 0x026, 0x01C, 0x027, 0x022, 0x0E8, 0x096, 0x0B4,
+	0x023, 0x0EA, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x065,
+	0x086, 0x020, 0x073, 0x096, 0x08D, 0x079, 0x0AD, 0x058,
+	0x00B, 0x0E9, 0x017, 0x044, 0x08A, 0x04A, 0x007, 0x0D7,
+	0x07A, 0x082, 0x0A1, 0x090, 0x0FA, 0x0EF, 0x001, 0x054,
+	0x0BA, 0x050, 0x0D4, 0x059, 0x01E, 0x02C, 0x0E9, 0x0F3,
+	0x08A, 0x099, 0x085, 0x06B, 0x00B, 0x023, 0x015, 0x097,
+	0x072, 0x061, 0x017, 0x030, 0x0D4, 0x02C, 0x073, 0x087,
+	0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE, 0x091, 0x00D,
+	0x04A, 0x0C0, 0x05F, 0x07E, 0x0D2, 0x080, 0x0A5, 0x03E,
+	0x0B2, 0x0D0, 0x0C8, 0x06B, 0x080, 0x0BE, 0x088, 0x01C,
+	0x0EA, 0x009, 0x017, 0x044, 0x01A, 0x037, 0x01A, 0x091,
+	0x074, 0x058, 0x0A3, 0x071, 0x0AF, 0x007, 0x044, 0x054,
+	0x06E, 0x035, 0x0E0, 0x0E8, 0x0AA, 0x064, 0x00F, 0x090,
+	0x0FA, 0x0D0, 0x063, 0x000, 0x0B3, 0x080, 0x0DA, 0x02C,
+	0x073, 0x087, 0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE,
+	0x091, 0x00D, 0x04A, 0x0C0, 0x05F, 0x048, 0x0BA, 0x027,
+	0x0A3, 0x000, 0x0B7, 0x001, 0x0B7, 0x04F, 0x09C, 0x0B4,
+	0x06B, 0x0CC, 0x035, 0x016, 0x0F5, 0x066, 0x063, 0x02D,
+	0x029, 0x01E, 0x0BA, 0x04A, 0x040, 0x0AB, 0x099, 0x048,
+	0x07A, 0x0EC, 0x050, 0x08B, 0x09C, 0x008, 0x022, 0x0FC,
+	0x0F9, 0x0B2, 0x055, 0x03D, 0x062, 0x0A9, 0x023, 0x051,
+	0x023, 0x09C, 0x00A, 0x03C, 0x073, 0x00D, 0x044, 0x05C,
+	0x0E1, 0x050, 0x071, 0x0CE, 0x0A1, 0x01F, 0x0E7, 0x015,
+	0x06B, 0x00B, 0x025, 0x0ED, 0x00B, 0x093, 0x060, 0x02F,
+	0x0AA, 0x09E, 0x0AC, 0x036, 0x065, 0x049, 0x05F, 0x07A,
+	0x020, 0x050, 0x008, 0x07F, 0x0EF, 0x039, 0x014, 0x049,
+	0x001, 0x011, 0x081, 0x004, 0x060, 0x040, 0x0CC, 0x059,
+	0x0C0, 0x0AD, 0x023, 0x0EB, 0x041, 0x0B0, 0x081, 0x0F2,
+	0x03A, 0x041, 0x0AA, 0x050, 0x043, 0x0E4, 0x0D4, 0x086,
+	0x054, 0x0A0, 0x087, 0x0C1, 0x052, 0x0CA, 0x093, 0x001,
+	0x032, 0x054, 0x09D, 0x024, 0x002, 0x000, 0x000, 0x052,
+	0x0AF, 0x016, 0x046, 0x0A7, 0x091, 0x067, 0x008, 0x0B4,
+	0x004, 0x051, 0x0F1, 0x065, 0x019, 0x0B4, 0x06E, 0x02D,
+	0x0C0, 0x0AD, 0x049, 0x000, 0x092, 0x057, 0x01B, 0x074,
+	0x045, 0x05F, 0x023, 0x051, 0x0B7, 0x044, 0x00A, 0x010,
+	0x006, 0x0A3, 0x06E, 0x08B, 0x06B, 0x008, 0x01F, 0x019,
+	0x0D1, 0x0E6, 0x080, 0x082, 0x080, 0x054, 0x004, 0x02A,
+	0x045, 0x091, 0x0A9, 0x0E4, 0x059, 0x0C2, 0x02D, 0x001,
+	0x014, 0x004, 0x050, 0x0D3, 0x0FC, 0x055, 0x084, 0x061,
+	0x0D9, 0x080, 0x051, 0x02F, 0x0E2, 0x01F, 0x046, 0x05F,
+	0x040, 0x0E0, 0x020, 0x015, 0x04A, 0x0BC, 0x059, 0x01A,
+	0x09E, 0x045, 0x09C, 0x022, 0x0D0, 0x011, 0x048, 0x0CB,
+	0x0E8, 0x014, 0x008, 0x001, 0x054, 0x015, 0x0E2, 0x0C8,
+	0x0D4, 0x0F2, 0x02C, 0x0E1, 0x016, 0x080, 0x08A, 0x046,
+	0x05F, 0x052, 0x07C, 0x0D9, 0x0A8, 0x0F8, 0x088, 0x0D0,
+	0x05A, 0x03C, 0x0D2, 0x05C, 0x05B, 0x080, 0x0DA, 0x0A7,
+	0x0D6, 0x05A, 0x008, 0x086, 0x0A4, 0x05D, 0x017, 0x0A0,
+	0x0C3, 0x052, 0x02E, 0x088, 0x0A8, 0x022, 0x01F, 0x053,
+	0x0EA, 0x0DA, 0x0CC, 0x0A6, 0x050, 0x0E1, 0x027, 0x076,
+	0x03C, 0x005, 0x0F5, 0x04F, 0x0AB, 0x06B, 0x032, 0x099,
+	0x043, 0x084, 0x09C, 0x07B, 0x038, 0x00B, 0x0E9, 0x027,
+	0x0AC, 0x0D4, 0x092, 0x0E0, 0x00E, 0x0DA, 0x038, 0x04D,
+	0x080, 0x0BE, 0x0E6, 0x07D, 0x050, 0x0BA, 0x051, 0x0AE,
+	0x066, 0x0EF, 0x0BC, 0x0DC, 0x07B, 0x087, 0x01E, 0x002,
+	0x0FA, 0x093, 0x0E6, 0x0CD, 0x047, 0x0C4, 0x043, 0x0CD,
+	0x00F, 0x034, 0x09D, 0x0A3, 0x000, 0x0B0, 0x055, 0x001,
+	0x0AE, 0x003, 0x084, 0x004, 0x0CE, 0x001, 0x0D0, 0x0E1,
+	0x070, 0x002, 0x080, 0x00E, 0x089, 0x0E9, 0x022, 0x01F,
+	0x0E0, 0x0E8, 0x096, 0x0B0, 0x011, 0x0F4, 0x0C2, 0x0CE,
+	0x003, 0x06A, 0x044, 0x02D, 0x0C0, 0x06D, 0x048, 0x005,
+	0x0B8, 0x00D, 0x0A3, 0x000, 0x0B7, 0x076, 0x0D5, 0x0DE,
+	0x0B1, 0x050, 0x0DC, 0x07D, 0x077, 0x0BC, 0x054, 0x0BA,
+	0x052, 0x07F, 0x058, 0x014, 0x034, 0x00F, 0x09A, 0x0F3,
+	0x081, 0x058, 0x00B, 0x0EA, 0x0EF, 0x058, 0x014, 0x060,
+	0x016, 0x0A5, 0x06C, 0x02E, 0x0F7, 0x081, 0x04B, 0x0A5,
+	0x06F, 0x07D, 0x05D, 0x0EE, 0x0B5, 0x02E, 0x095, 0x080,
+	0x0BE, 0x0F0, 0x073, 0x0BD, 0x004, 0x07C, 0x0EA, 0x0FE,
+	0x0EB, 0x04C, 0x0DE, 0x029, 0x053, 0x0DD, 0x06A, 0x054,
+	0x094, 0x0A9, 0x0EA, 0x00A, 0x08C, 0x002, 0x0D6, 0x04C,
+	0x03C, 0x005, 0x0F4, 0x000, 0x0EA, 0x0CD, 0x056, 0x0AF,
+	0x0C0, 0x047, 0x0D2, 0x09C, 0x08D, 0x029, 0x0CA, 0x0E0,
+	0x02F, 0x0AE, 0x0BD, 0x075, 0x099, 0x09D, 0x04A, 0x0F9,
+	0x0EF, 0x051, 0x07C, 0x094, 0x00C, 0x077, 0x080, 0x018,
+	0x018, 0x029, 0x02A, 0x0F8, 0x0E0, 0x0E8, 0x0AA, 0x030,
+	0x00B, 0x02A, 0x098, 0x07C, 0x01D, 0x011, 0x051, 0x080,
+	0x059, 0x054, 0x0C3, 0x051, 0x0F5, 0x01B, 0x033, 0x024,
+	0x0BB, 0x082, 0x0A5, 0x019, 0x05C, 0x01D, 0x010, 0x028,
+	0x0C0, 0x02C, 0x09A, 0x0C7, 0x0C1, 0x0D1, 0x022, 0x08C,
+	0x002, 0x0C9, 0x094, 0x064, 0x05C, 0x00C, 0x0D6, 0x08E,
+	0x013, 0x060, 0x02F, 0x0B8, 0x00B, 0x0EA, 0x030, 0x0E3,
+	0x0C0, 0x05F, 0x048, 0x0DC, 0x078, 0x00B, 0x0E8, 0x000,
+	0x0E3, 0x0C0, 0x05F, 0x06C, 0x038, 0x0D5, 0x02E, 0x035,
+	0x04F, 0x05A, 0x08A, 0x061, 0x0AA, 0x09F, 0x056, 0x01B,
+	0x032, 0x099, 0x046, 0x042, 0x0C8, 0x001, 0x00C, 0x045,
+	0x0CE, 0x0A5, 0x017, 0x0E6, 0x0C6, 0x0CE, 0x0A9, 0x0EB,
+	0x015, 0x016, 0x046, 0x0A2, 0x047, 0x038, 0x014, 0x043,
+	0x026, 0x022, 0x0E7, 0x03D, 0x060, 0x02F, 0x0AA, 0x09E,
+	0x0B5, 0x012, 0x0E0, 0x07F, 0x001, 0x07D, 0x0E3, 0x0E7,
+	0x002, 0x093, 0x0F9, 0x095, 0x044, 0x05C, 0x0E5, 0x0A0,
+	0x0E3, 0x09D, 0x04A, 0x07F, 0x09C, 0x054, 0x0A9, 0x0EB,
+	0x051, 0x005, 0x046, 0x0B9, 0x0FC, 0x0C0, 0x01B, 0x022,
+	0x02E, 0x064, 0x054, 0x02F, 0x0CD, 0x046, 0x0CC, 0x0A7,
+	0x0D5, 0x086, 0x0CC, 0x0A6, 0x050, 0x055, 0x0C6, 0x045,
+	0x0CE, 0x05A, 0x00E, 0x039, 0x0D4, 0x0A7, 0x0F9, 0x0C5,
+	0x04A, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x0C0, 0x06D,
+	0x0CF, 0x0E6, 0x000, 0x0D9, 0x011, 0x073, 0x022, 0x0A1,
+	0x07E, 0x06A, 0x036, 0x065, 0x03E, 0x0AC, 0x036, 0x065,
+	0x032, 0x0B0, 0x017, 0x0DD, 0x03E, 0x072, 0x0D2, 0x079,
+	0x031, 0x00C, 0x098, 0x02E, 0x04C, 0x020, 0x073, 0x02A,
+	0x08F, 0x0F3, 0x08A, 0x0AD, 0x0E7, 0x041, 0x082, 0x07C,
+	0x0CA, 0x0A6, 0x089, 0x0B5, 0x085, 0x09F, 0x0B0, 0x0F0,
+	0x017, 0x0D5, 0x01F, 0x054, 0x054, 0x025, 0x01A, 0x0A8,
+	0x0FF, 0x02A, 0x094, 0x065, 0x011, 0x0D7, 0x049, 0x044,
+	0x0D5, 0x0CC, 0x0A0, 0x055, 0x0D8, 0x0AE, 0x00E, 0x088,
+	0x014, 0x060, 0x016, 0x04D, 0x063, 0x022, 0x0E0, 0x072,
+	0x086, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B8,
+	0x00B, 0x0EE, 0x002, 0x0FB, 0x081, 0x038, 0x0F0, 0x017,
+	0x0D7, 0x0D7, 0x01E, 0x002, 0x0FA, 0x0FA, 0x0E3, 0x0C0,
+	0x05F, 0x04C, 0x085, 0x090, 0x002, 0x018, 0x0C8, 0x05B,
+	0x080, 0x0DA, 0x030, 0x00B, 0x070, 0x01B, 0x04C, 0x022,
+	0x0D3, 0x04C, 0x033, 0x003, 0x08C, 0x02E, 0x04C, 0x043,
+	0x026, 0x0D0, 0x0F5, 0x063, 0x066, 0x0D0, 0x095, 0x0A7,
+	0x0CE, 0x045, 0x033, 0x00A, 0x0D6, 0x016, 0x042, 0x038,
+	0x06E, 0x0E4, 0x0CE, 0x0BD, 0x059, 0x02C, 0x0D2, 0x0AB,
+	0x0BA, 0x094, 0x09D, 0x0E6, 0x01A, 0x0B0, 0x017, 0x0D5,
+	0x04F, 0x05A, 0x08B, 0x009, 0x01A, 0x088, 0x0B9, 0x0C5,
+	0x042, 0x047, 0x030, 0x0D4, 0x032, 0x016, 0x072, 0x088,
+	0x065, 0x0BD, 0x059, 0x099, 0x025, 0x0A5, 0x060, 0x02F,
+	0x0B8, 0x060, 0x0F3, 0x008, 0x0B7, 0x04A, 0x01A, 0x08F,
+	0x0AB, 0x00D, 0x099, 0x046, 0x051, 0x0AF, 0x038, 0x0A8,
+	0x08E, 0x090, 0x065, 0x013, 0x052, 0x018, 0x0A0, 0x054,
+	0x0B1, 0x042, 0x02E, 0x061, 0x0A8, 0x048, 0x0E7, 0x02D,
+	0x016, 0x0F7, 0x0A8, 0x005, 0x0A5, 0x060, 0x02F, 0x0A4,
+	0x075, 0x0D2, 0x051, 0x035, 0x073, 0x028, 0x015, 0x076,
+	0x02B, 0x083, 0x0A2, 0x005, 0x018, 0x005, 0x093, 0x058,
+	0x0C8, 0x0B8, 0x006, 0x028, 0x063, 0x084, 0x0D8, 0x00B,
+	0x0EE, 0x002, 0x0FB, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0A0,
+	0x043, 0x0A7, 0x001, 0x07D, 0x04C, 0x0E3, 0x0C0, 0x05F,
+	0x070, 0x017, 0x0DC, 0x005, 0x0F4, 0x064, 0x02D, 0x0C0,
+	0x06D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A5, 0x0BD, 0x06A,
+	0x023, 0x086, 0x0AA, 0x09E, 0x0B5, 0x011, 0x0A4, 0x06A,
+	0x0A3, 0x0EA, 0x08A, 0x08D, 0x023, 0x0E1, 0x017, 0x038,
+	0x034, 0x069, 0x071, 0x098, 0x045, 0x0A6, 0x098, 0x06A,
+	0x03E, 0x0AC, 0x036, 0x065, 0x019, 0x046, 0x0BC, 0x0E2,
+	0x0A2, 0x03A, 0x041, 0x094, 0x04D, 0x048, 0x062, 0x081,
+	0x052, 0x0C5, 0x016, 0x0F7, 0x0A8, 0x08B, 0x04A, 0x054,
+	0x0F5, 0x0A8, 0x08C, 0x002, 0x0DC, 0x006, 0x0D1, 0x003,
+	0x09C, 0x0B4, 0x0A9, 0x0EE, 0x00A, 0x095, 0x025, 0x02A,
+	0x07A, 0x0AD, 0x046, 0x001, 0x067, 0x001, 0x0B5, 0x0D7,
+	0x0AC, 0x00A, 0x030, 0x00B, 0x06C, 0x049, 0x035, 0x0E6,
+	0x0B5, 0x067, 0x0F3, 0x000, 0x06C, 0x088, 0x0B9, 0x091,
+	0x050, 0x0BF, 0x031, 0x01B, 0x032, 0x0A7, 0x0B8, 0x068,
+	0x095, 0x025, 0x07B, 0x0AD, 0x033, 0x078, 0x0A7, 0x0CD,
+	0x03E, 0x0D3, 0x08E, 0x09D, 0x034, 0x0E7, 0x04E, 0x0D4,
+	0x022, 0x0E7, 0x006, 0x084, 0x08E, 0x060, 0x0A8, 0x0FF,
+	0x038, 0x0AB, 0x083, 0x09C, 0x02A, 0x008, 0x0F9, 0x0D4,
+	0x020, 0x063, 0x0BC, 0x01A, 0x006, 0x00A, 0x0C0, 0x05F,
+	0x046, 0x042, 0x0DC, 0x006, 0x0D1, 0x080, 0x05B, 0x080,
+	0x0DA, 0x022, 0x0E6, 0x01A, 0x084, 0x08E, 0x072, 0x0D1,
+	0x06F, 0x05A, 0x080, 0x087, 0x01A, 0x0AA, 0x07A, 0x0D4,
+	0x048, 0x0C8, 0x0D5, 0x047, 0x0D5, 0x015, 0x023, 0x023,
+	0x0E1, 0x017, 0x038, 0x034, 0x08C, 0x0BA, 0x04B, 0x07B,
+	0x0D4, 0x002, 0x0D2, 0x08C, 0x022, 0x0DC, 0x006, 0x0D5,
+	0x01F, 0x056, 0x01B, 0x032, 0x08C, 0x0A3, 0x05E, 0x071,
+	0x051, 0x01D, 0x020, 0x0CA, 0x026, 0x0A4, 0x031, 0x040,
+	0x0A9, 0x062, 0x0B0, 0x017, 0x0DF, 0x09E, 0x0F4, 0x0B7,
+	0x0C9, 0x040, 0x0C7, 0x078, 0x001, 0x081, 0x082, 0x0B8,
+	0x038, 0x039, 0x049, 0x01C, 0x026, 0x0C0, 0x05F, 0x070,
+	0x017, 0x0D4, 0x0AB, 0x0E1, 0x02A, 0x0F8, 0x04A, 0x0BE,
+	0x012, 0x0AF, 0x08F, 0x097, 0x04F, 0x0CB, 0x0A7, 0x001,
+	0x07D, 0x0DA, 0x080, 0x0AA, 0x091, 0x064, 0x07F, 0x04A,
+	0x081, 0x0D5, 0x022, 0x0C8, 0x0FE, 0x082, 0x080, 0x025,
+	0x048, 0x0B2, 0x03E, 0x0BB, 0x0DC, 0x035, 0x02E, 0x094,
+	0x007, 0x0E8, 0x08A, 0x09C, 0x003, 0x0E2, 0x04B, 0x0A5,
+	0x077, 0x0AB, 0x0B3, 0x032, 0x0E9, 0x04B, 0x0BD, 0x059,
+	0x086, 0x084, 0x097, 0x07A, 0x004, 0x0BA, 0x053, 0x0E1,
+	0x032, 0x0EF, 0x050, 0x0D4, 0x0E6, 0x035, 0x053, 0x0EB,
+	0x002, 0x09C, 0x0C7, 0x0D7, 0x07A, 0x0B3, 0x030, 0x0D2,
+	0x05D, 0x0EA, 0x002, 0x0E9, 0x044, 0x05D, 0x016, 0x028,
+	0x0C0, 0x02C, 0x0E0, 0x036, 0x091, 0x074, 0x045, 0x059,
+	0x018, 0x0D5, 0x04F, 0x0AC, 0x00A, 0x0C4, 0x035, 0x030,
+	0x08B, 0x038, 0x069, 0x02B, 0x0BD, 0x059, 0x098, 0x069,
+	0x02E, 0x0F5, 0x012, 0x0E9, 0x058, 0x067, 0x04A, 0x0EF,
+	0x050, 0x0D5, 0x08E, 0x03E, 0x01C, 0x0A4, 0x0B0, 0x0CE,
+	0x093, 0x021, 0x06E, 0x01A, 0x048, 0x01F, 0x0A2, 0x02A,
+	0x0C3, 0x00D, 0x057, 0x07A, 0x0B3, 0x00D, 0x009, 0x02E,
+	0x0F4, 0x043, 0x05D, 0x028, 0x08B, 0x083, 0x020, 0x092,
+	0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0AC, 0x017,
+	0x049, 0x0B3, 0x0A5, 0x082, 0x0E9, 0x03E, 0x0E9, 0x036,
+	0x074, 0x0E0, 0x02F, 0x0A6, 0x0CE, 0x09C, 0x005, 0x0F4,
+	0x0C2, 0x02C, 0x08C, 0x052, 0x057, 0x07A, 0x0D4, 0x08D,
+	0x048, 0x0FA, 0x0EF, 0x050, 0x0D5, 0x0AE, 0x035, 0x053,
+	0x0EB, 0x002, 0x086, 0x021, 0x0AA, 0x0EF, 0x056, 0x066,
+	0x01A, 0x04B, 0x0BD, 0x044, 0x0BA, 0x050, 0x0C4, 0x0E9,
+	0x053, 0x0EB, 0x002, 0x086, 0x081, 0x0F5, 0x0DE, 0x0A1,
+	0x0A8, 0x062, 0x01F, 0x05D, 0x0FE, 0x0A2, 0x05D, 0x029,
+	0x077, 0x0A8, 0x06A, 0x061, 0x08D, 0x040, 0x0FD, 0x011,
+	0x053, 0x00C, 0x06A, 0x0A7, 0x0D6, 0x005, 0x030, 0x0C7,
+	0x0D7, 0x07F, 0x0A9, 0x057, 0x04A, 0x05D, 0x0EB, 0x048,
+	0x01B, 0x00C, 0x07C, 0x08B, 0x09D, 0x08A, 0x053, 0x0EF,
+	0x066, 0x094, 0x0CA, 0x054, 0x0F5, 0x0A0, 0x0C6, 0x001,
+	0x06E, 0x003, 0x06A, 0x09F, 0x056, 0x076, 0x065, 0x032,
+	0x08B, 0x07B, 0x0D2, 0x0C5, 0x0A5, 0x060, 0x02F, 0x0AA,
+	0x07D, 0x065, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B4, 0x0C8,
+	0x05A, 0x007, 0x08F, 0x0ED, 0x001, 0x0D5, 0x027, 0x091,
+	0x067, 0x001, 0x0B4, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+	0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+	0x060, 0x0AB, 0x08C, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+	0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+	0x06C, 0x005, 0x0F5, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+	0x029, 0x05B, 0x019, 0x0FC, 0x0F6, 0x094, 0x045, 0x0CF,
+	0x015, 0x00B, 0x0F3, 0x03C, 0x0B3, 0x02A, 0x07A, 0x0C5,
+	0x046, 0x001, 0x064, 0x08A, 0x031, 0x023, 0x09C, 0x00A,
+	0x05D, 0x0EA, 0x034, 0x033, 0x02E, 0x095, 0x0C7, 0x0CE,
+	0x02A, 0x04F, 0x0E6, 0x050, 0x020, 0x0B9, 0x031, 0x00C,
+	0x09B, 0x0EF, 0x039, 0x014, 0x045, 0x0CE, 0x045, 0x007,
+	0x01C, 0x0EA, 0x046, 0x087, 0x0AB, 0x01B, 0x036, 0x084,
+	0x0A7, 0x05E, 0x0AC, 0x096, 0x067, 0x052, 0x0B0, 0x017,
+	0x0DC, 0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085,
+	0x0F9, 0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB,
+	0x0A5, 0x027, 0x0F3, 0x0A0, 0x044, 0x032, 0x060, 0x0B9,
+	0x037, 0x0DE, 0x072, 0x028, 0x08B, 0x09C, 0x08A, 0x00E,
+	0x039, 0x0D4, 0x08C, 0x005, 0x0F7, 0x0E7, 0x0B8, 0x02A,
+	0x0F9, 0x028, 0x018, 0x0EF, 0x000, 0x030, 0x030, 0x057,
+	0x007, 0x044, 0x00A, 0x050, 0x08F, 0x0F0, 0x073, 0x091,
+	0x041, 0x01F, 0x03A, 0x090, 0x045, 0x0C0, 0x0BB, 0x018,
+	0x0E1, 0x036, 0x002, 0x0FB, 0x0FB, 0x09E, 0x002, 0x0FA,
+	0x0EE, 0x0E7, 0x0F5, 0x0CF, 0x001, 0x07D, 0x010, 0x05C,
+	0x0F0, 0x017, 0x0D1, 0x005, 0x0CF, 0x001, 0x07D, 0x053,
+	0x0EB, 0x02D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A6, 0x042,
+	0x0DC, 0x006, 0x0D3, 0x017, 0x035, 0x0A8, 0x08B, 0x09C,
+	0x00A, 0x00E, 0x039, 0x0D4, 0x00C, 0x0FE, 0x07B, 0x04A,
+	0x022, 0x0E6, 0x055, 0x00B, 0x0F3, 0x031, 0x0B3, 0x060,
+	0x02F, 0x0BC, 0x07C, 0x0E2, 0x0A4, 0x0FE, 0x065, 0x051,
+	0x017, 0x038, 0x014, 0x01C, 0x073, 0x0A8, 0x019, 0x0FC,
+	0x0F6, 0x094, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x063,
+	0x066, 0x00A, 0x0B8, 0x0CC, 0x085, 0x0A1, 0x058, 0x0F6,
+	0x0A2, 0x035, 0x048, 0x048, 0x07F, 0x04A, 0x089, 0x095,
+	0x021, 0x021, 0x0FD, 0x005, 0x002, 0x054, 0x09E, 0x045,
+	0x091, 0x00E, 0x03C, 0x005, 0x0F5, 0x007, 0x040, 0x055,
+	0x048, 0x052, 0x03E, 0x086, 0x0A0, 0x075, 0x048, 0x052,
+	0x03E, 0x0B5, 0x000, 0x04A, 0x09C, 0x000, 0x06B, 0x0C7,
+	0x0CE, 0x045, 0x027, 0x0F3, 0x02A, 0x084, 0x037, 0x035,
+	0x0DE, 0x0A0, 0x0AB, 0x023, 0x01A, 0x0AE, 0x0F5, 0x083,
+	0x059, 0x018, 0x0D7, 0x043, 0x0DE, 0x02A, 0x0D0, 0x094,
+	0x0EB, 0x0DE, 0x005, 0x03A, 0x095, 0x09F, 0x0CC, 0x0C3,
+	0x020, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x066, 0x0CC,
+	0x043, 0x026, 0x04F, 0x0E7, 0x041, 0x022, 0x02E, 0x070,
+	0x068, 0x038, 0x0E7, 0x053, 0x0E0, 0x02F, 0x0AB, 0x0BC,
+	0x012, 0x0D2, 0x0E9, 0x058, 0x00B, 0x0EA, 0x0A7, 0x0AD,
+	0x045, 0x0A1, 0x01F, 0x0C0, 0x05F, 0x078, 0x039, 0x0C8,
+	0x0A0, 0x08F, 0x09D, 0x048, 0x01C, 0x024, 0x0EE, 0x0C7,
+	0x080, 0x0BE, 0x0BA, 0x0F5, 0x06D, 0x066, 0x049, 0x077,
+	0x00D, 0x04E, 0x0A5, 0x030, 0x009, 0x0B4, 0x0F9, 0x0C5,
+	0x043, 0x00F, 0x038, 0x0A9, 0x03F, 0x09D, 0x002, 0x0FB,
+	0x0CE, 0x045, 0x011, 0x073, 0x091, 0x041, 0x0C7, 0x03A,
+	0x091, 0x09F, 0x0CF, 0x069, 0x044, 0x05C, 0x0F1, 0x050,
+	0x0BF, 0x033, 0x0CB, 0x032, 0x0A7, 0x0AC, 0x054, 0x090,
+	0x08D, 0x044, 0x08E, 0x070, 0x029, 0x077, 0x0A8, 0x0D0,
+	0x0CC, 0x0BA, 0x056, 0x0B0, 0x0B2, 0x09D, 0x08C, 0x086,
+	0x04C, 0x017, 0x026, 0x077, 0x026, 0x01C, 0x027, 0x01C,
+	0x024, 0x09E, 0x023, 0x061, 0x0BE, 0x08E, 0x012, 0x04F,
+	0x011, 0x087, 0x01C, 0x0EA, 0x05C, 0x005, 0x0F5, 0x0D7,
+	0x0B8, 0x06A, 0x075, 0x029, 0x077, 0x0AB, 0x00D, 0x099,
+	0x074, 0x0A5, 0x04F, 0x072, 0x0A0, 0x0AA, 0x04A, 0x0C6,
+	0x0F3, 0x066, 0x066, 0x0C6, 0x039, 0x082, 0x0AF, 0x075,
+	0x0A6, 0x06F, 0x014, 0x06B, 0x0CE, 0x005, 0x070, 0x073,
+	0x096, 0x082, 0x03E, 0x075, 0x028, 0x0E1, 0x03A, 0x0A7,
+	0x0AD, 0x044, 0x060, 0x016, 0x052, 0x0B6, 0x01D, 0x07A,
+	0x0B6, 0x0B3, 0x024, 0x0BB, 0x086, 0x0A7, 0x052, 0x098,
+	0x004, 0x0DA, 0x07C, 0x0E2, 0x0A1, 0x087, 0x09C, 0x055,
+	0x0F7, 0x09C, 0x0B5, 0x0AC, 0x02C, 0x095, 0x033, 0x0B9,
+	0x031, 0x005, 0x0D9, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+	0x029, 0x05B, 0x002, 0x02E, 0x061, 0x05A, 0x017, 0x0E6,
+	0x09C, 0x0B3, 0x02A, 0x07A, 0x0C5, 0x040, 0x021, 0x0A8,
+	0x091, 0x0CE, 0x005, 0x027, 0x0F3, 0x0A5, 0x088, 0x064,
+	0x0C1, 0x072, 0x065, 0x04F, 0x058, 0x014, 0x00C, 0x08D,
+	0x07E, 0x0F3, 0x081, 0x044, 0x05C, 0x0EF, 0x041, 0x0C7,
+	0x03A, 0x0BE, 0x002, 0x0FA, 0x0A9, 0x0EA, 0x0CE, 0x0CC,
+	0x0A9, 0x029, 0x053, 0x0D6, 0x0A2, 0x046, 0x047, 0x0DD,
+	0x07A, 0x0C0, 0x0A3, 0x000, 0x086, 0x0E2, 0x09B, 0x029,
+	0x078, 0x08B, 0x081, 0x009, 0x098, 0x070, 0x09B, 0x029,
+	0x079, 0x05D, 0x0D9, 0x072, 0x0ED, 0x094, 0x0BC, 0x0B9,
+	0x076, 0x013, 0x03B, 0x02A, 0x05D, 0x0B2, 0x097, 0x095,
+	0x02E, 0x0D9, 0x04B, 0x0CA, 0x07D, 0x05B, 0x059, 0x094,
+	0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x094, 0x0BC, 0x0C0,
+	0x026, 0x0D3, 0x0E7, 0x015, 0x00C, 0x03C, 0x0E2, 0x0AC,
+	0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085, 0x0F9,
+	0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB, 0x0A5,
+	0x027, 0x0F3, 0x0A0, 0x041, 0x072, 0x062, 0x019, 0x037,
+	0x0DE, 0x070, 0x028, 0x08B, 0x09C, 0x08A, 0x00E, 0x039,
+	0x0D4, 0x08D, 0x00F, 0x056, 0x036, 0x06D, 0x009, 0x04E,
+	0x0BD, 0x059, 0x02C, 0x0CE, 0x0A5, 0x06B, 0x00B, 0x022,
+	0x0D9, 0x09D, 0x0C9, 0x0B2, 0x097, 0x0BE, 0x0F3, 0x081,
+	0x04A, 0x07D, 0x065, 0x0A3, 0x000, 0x093, 0x08F, 0x067,
+	0x029, 0x078, 0x0C2, 0x04D, 0x0C1, 0x0D1, 0x006, 0x082,
+	0x031, 0x0AF, 0x007, 0x038, 0x034, 0x011, 0x0F3, 0x0A8,
+	0x02A, 0x09E, 0x0A8, 0x066, 0x01A, 0x0A4, 0x0A5, 0x04F,
+	0x05A, 0x00C, 0x011, 0x08F, 0x0AA, 0x07B, 0x0D0, 0x065,
+	0x049, 0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x0B1, 0x09E,
+	0x06C, 0x0CC, 0x0C6, 0x019, 0x087, 0x009, 0x0C3, 0x08E,
+	0x075, 0x041, 0x01F, 0x03A, 0x0A5, 0x013, 0x0D5, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+	0x055, 0x055, 0x055, 0x05A, 0x0CC, 0x090
+ };
+
+#endif	/* defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE) */
diff -u --recursive --new-file v2.3.37/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- v2.3.37/linux/drivers/net/tokenring/tms380tr.c	Tue Dec  7 09:32:44 1999
+++ linux/drivers/net/tokenring/tms380tr.c	Thu Jan  6 14:46:18 2000
@@ -31,7 +31,7 @@
  *	- David Hein at Texas Instruments 
  *
  *  Maintainer(s):
- *    JS	Jay Schulist		jschlst@samba.anu.edu.au
+ *    JS	Jay Schulist		jschlst@turbolinux.com
  *    CG	Christoph Goos		cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
  *
diff -u --recursive --new-file v2.3.37/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- v2.3.37/linux/drivers/net/wan/cosa.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/net/wan/cosa.c	Fri Jan  7 11:43:09 2000
@@ -329,8 +329,6 @@
 #else
 	NULL,
 #endif
-	NULL,	/* check media change */
-	NULL,	/* revalidate */
 	NULL	/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/pci/compat.c linux/drivers/pci/compat.c
--- v2.3.37/linux/drivers/pci/compat.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pci/compat.c	Fri Jan  7 11:53:06 2000
@@ -13,7 +13,7 @@
 int
 pcibios_present(void)
 {
-	return pci_devices.next != &pci_devices;
+	return !list_empty(&pci_devices);
 }
 
 int
diff -u --recursive --new-file v2.3.37/linux/drivers/pci/setup.c linux/drivers/pci/setup.c
--- v2.3.37/linux/drivers/pci/setup.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pci/setup.c	Thu Jan  6 16:17:19 2000
@@ -157,9 +157,8 @@
 pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
 {
 	struct pbus_set_ranges_data inner;
-	struct pci_bus *child;
 	struct pci_dev *dev;
-	struct list_node *ln;
+	struct list_head *ln;
 
 	inner.found_vga = 0;
 	inner.mem_start = inner.io_start = ~0UL;
@@ -275,10 +274,10 @@
 void __init
 pci_set_bus_ranges(void)
 {
-	struct list_node *ln;
+	struct list_head *ln;
 
 	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
-		pci_set_ranges(pci_bus_b(ln), NULL);
+		pbus_set_ranges(pci_bus_b(ln), NULL);
 }
 
 static void __init
diff -u --recursive --new-file v2.3.37/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.3.37/linux/drivers/pcmcia/cardbus.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pcmcia/cardbus.c	Fri Jan  7 15:21:56 2000
@@ -99,6 +99,11 @@
 #define PCDATA_CODE_TYPE	0x0014
 #define PCDATA_INDICATOR	0x0015
 
+#ifndef CONFIG_PROC_FS
+#define pci_proc_attach_device(dev)	do { } while (0)
+#define pci_proc_detach_device(dev)	do { } while (0)
+#endif
+
 typedef struct cb_config_t {
 	struct pci_dev dev;
 } cb_config_t;
@@ -313,19 +318,11 @@
 				res->start = 0;
 				pci_assign_resource(dev, r);
 			}
-			printk("Resource %d at %08lx-%08lx (%04lx)\n",
-			       r,
-			       res->start,
-			       res->end,
-			       res->flags);
 		}
 
 		list_add_tail(&dev->bus_list, &bus->devices);
 		list_add_tail(&dev->global_list, &pci_devices);
-#ifdef CONFIG_PROC_FS
 		pci_proc_attach_device(dev);
-#endif
-
 		pci_enable_device(dev);
 	}
 
@@ -347,20 +344,20 @@
 void cb_free(socket_info_t * s)
 {
 	cb_config_t *c = s->cb_config;
-	int i;
 
 	if (c) {
+		int i;
+
+		s->cb_config = NULL;
 		for(i=0; i<s->functions; i++) {
 			struct pci_dev *dev = &c[i].dev;
+
 			list_del(&dev->bus_list);
 			list_del(&dev->global_list);
 			free_resources(dev);
-#ifdef CONFIG_PROC_FS
 			pci_proc_detach_device(dev);
-#endif
 		}
-		kfree(s->cb_config);
-		s->cb_config = NULL;
+		kfree(c);
 		printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
 	}
 }
@@ -377,59 +374,55 @@
     
 ======================================================================*/
 
+static int cb_assign_irq(u32 mask)
+{
+	int irq, try;
+
+	for (try = 0; try < 2; try++) {
+		for (irq = 1; irq < 32; irq++) {
+			if ((mask >> irq) & 1) {
+				if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0)
+					return irq;
+			}
+		}
+	}
+	return 0;
+}
+
 int cb_config(socket_info_t * s)
 {
 	cb_config_t *c = s->cb_config;
 	u_char fn = s->functions;
-	u_char i, j;
-	int irq, try, ret;
+	int i, irq;
 
 	printk(KERN_INFO "cs: cb_config(bus %d)\n", s->cap.cb_dev->subordinate->number);
 
-	/* Allocate interrupt if needed */
-	s->irq.AssignedIRQ = irq = 0;
-	ret = -1;
+	/*
+	 * If we have a PCI interrupt for the bridge,
+	 * then use that..
+	 */
+	irq = s->cap.pci_irq;
+
 	for (i = 0; i < fn; i++) {
 		struct pci_dev *dev = &c[i].dev;
-		pci_readb(dev, PCI_INTERRUPT_PIN, &j);
-		if (j == 0)
+		u8 irq_pin;
+
+		/* Does this function have an interrupt at all? */
+		pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
+		if (!irq_pin)
 			continue;
-		if (irq == 0) {
-			if (s->cap.irq_mask & (1 << s->cap.pci_irq)) {
-				irq = s->cap.pci_irq;
-				ret = 0;
-			}
-#ifdef CONFIG_ISA
-			else
-				for (try = 0; try < 2; try++) {
-					for (irq = 0; irq < 32; irq++)
-						if ((s->cap.irq_mask >> irq) & 1) {
-							ret = try_irq(IRQ_TYPE_EXCLUSIVE, irq, try);
-							if (ret == 0)
-								break;
-						}
-					if (ret == 0)
-						break;
-				}
-			if (ret != 0) {
-				printk(KERN_NOTICE "cs: could not allocate interrupt"
-				    " for CardBus socket %d\n", s->sock);
-				goto failed;
-			}
-#endif
-			s->irq.AssignedIRQ = irq;
+
+		if (!irq) {
+			irq = cb_assign_irq(s->cap.irq_mask);
+			if (!irq)
+				return CS_OUT_OF_RESOURCE;
 		}
-	}
-	for (i = 0; i < fn; i++) {
-		struct pci_dev *dev = &c[i].dev;
+
 		dev->irq = irq;
+		pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
 	}
-
+	s->irq.AssignedIRQ = irq;
 	return CS_SUCCESS;
-
-      failed:
-	cb_release(s);
-	return CS_OUT_OF_RESOURCE;
 }
 
 /*======================================================================
diff -u --recursive --new-file v2.3.37/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.3.37/linux/drivers/pcmcia/cs.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/pcmcia/cs.c	Thu Jan  6 16:19:35 2000
@@ -446,7 +446,6 @@
     s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
     init_socket(s);
     s->irq.AssignedIRQ = s->irq.Config = 0;
-    s->functions = 0;
     s->lock_count = 0;
     s->cis_used = 0;
     if (s->fake_cis) {
@@ -457,6 +456,7 @@
     cb_release_cis_mem(s);
     cb_free(s);
 #endif
+    s->functions = 0;
     if (s->config) {
 	kfree(s->config);
 	s->config = NULL;
diff -u --recursive --new-file v2.3.37/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.37/linux/drivers/pcmcia/yenta.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pcmcia/yenta.c	Fri Jan  7 17:59:43 2000
@@ -198,16 +198,15 @@
 		/* ISA interrupt control? */
 		if (bridge & CB_BRIDGE_INTR) {
 			u8 intr = exca_readb(socket, I365_INTCTL);
-			intr = (intr & ~0xf) ; // | state->io_irq;
+			intr = (intr & ~0xf) | state->io_irq;
 			exca_writeb(socket, I365_INTCTL, intr);
 		}
 	} else {
 		u8 reg;
 
-		reg = exca_readb(socket, I365_INTCTL) & I365_RING_ENA;
+		reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
 		reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
 		reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
-		reg |= I365_INTR_ENA;			/* CSC to PCI interrupt */
 		reg |= state->io_irq;
 		exca_writeb(socket, I365_INTCTL, reg);
 
@@ -444,6 +443,10 @@
 		config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
 	}
 
+	/*
+	 * Probe for usable interrupts using the force
+	 * register to generate bogus card status events.
+	 */
 	cb_writel(socket, CB_SOCKET_EVENT, -1);
 	cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
 	val = probe_irq_on();
@@ -456,7 +459,7 @@
 		cb_writel(socket, CB_SOCKET_EVENT, -1);
 	}
 	cb_writel(socket, CB_SOCKET_MASK, 0);
-	return probe_irq_mask(val);
+	return probe_irq_mask(val) & 0xffff;
 }
 
 static void yenta_clear_maps(pci_socket_t *socket)
diff -u --recursive --new-file v2.3.37/linux/drivers/pnp/Makefile linux/drivers/pnp/Makefile
--- v2.3.37/linux/drivers/pnp/Makefile	Sun Aug 15 11:50:35 1999
+++ linux/drivers/pnp/Makefile	Thu Jan  6 14:47:29 2000
@@ -19,10 +19,10 @@
 MIX_OBJS :=
 
 ifeq ($(CONFIG_ISAPNP),y)
-  LX_OBJS += isapnp.o
+  LX_OBJS += isapnp.o quirks.o
 else
   ifeq ($(CONFIG_ISAPNP),m)
-    MX_OBJS += isapnp.o
+    MX_OBJS += isapnp.o quirks.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.37/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.3.37/linux/drivers/pnp/isapnp.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pnp/isapnp.c	Fri Jan  7 14:09:34 2000
@@ -17,6 +17,9 @@
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
+ *  Changelog:
+ *  2000-01-01	Added ISAPnP quirks handling
+ *		Peter Denison <peterd@pnd-pc.demon.co.uk>
  */
 
 #include <linux/config.h>
@@ -42,6 +45,12 @@
 LIST_HEAD(isapnp_cards);
 LIST_HEAD(isapnp_devices);
 
+#define isapnp_for_each_card(card) \
+	for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next))
+#define isapnp_for_each_dev(dev) \
+	for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next))
+
+
 #ifdef CONFIG_PROC_FS
 #include "isapnp_proc.c"
 #endif
@@ -184,7 +193,7 @@
 	isapnp_write_byte(idx+3, val);
 }
 
-static void *isapnp_alloc(long size)
+void *isapnp_alloc(long size)
 {
 	void *result;
 
@@ -964,6 +973,7 @@
 	int csn;
 	unsigned char header[9], checksum;
 	struct pci_bus *card;
+	struct pci_dev *dev;
 
 	isapnp_wait();
 	isapnp_key();
@@ -993,6 +1003,9 @@
 
 		list_add_tail(&card->node, &isapnp_cards);
 	}
+	isapnp_for_each_dev(dev) {
+		isapnp_fixup_device(dev);
+	}
 	return 0;
 }
 
@@ -1147,7 +1160,7 @@
 		list = from->node.next;
 
 	while (list != &isapnp_cards) {
-		struct pci_bus *card = list_entry(list, struct pci_bus, node);
+		struct pci_bus *card = pci_bus_b(list);
 		if (card->vendor == vendor && card->device == device)
 			return card;
 		list = list->next;
@@ -1169,7 +1182,7 @@
 
 		while (list != &isapnp_devices) {
 			int idx;
-			struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+			struct pci_dev *dev = pci_dev_g(list);
 
 			if (dev->vendor == vendor && dev->device == function)
 				return dev;
@@ -1189,7 +1202,7 @@
 			return NULL;
 		while (list != &card->devices) {
 			int idx;
-			struct pci_dev *dev = list_entry(list, struct pci_dev, bus_list);
+			struct pci_dev *dev = pci_dev_b(list);
 
 			if (dev->vendor == vendor && dev->device == function)
 				return dev;
@@ -1437,7 +1450,7 @@
 {
 	int i, tmp, rport, rsize;
 	struct isapnp_port *xport;
-	struct list_head *list;
+	struct pci_dev *dev;
 
 	if (check_region(port, size))
 		return 1;
@@ -1450,8 +1463,7 @@
 			return 1;
 	}
 
-	for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
-		struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+	isapnp_for_each_dev(dev) {
 		if (dev->active) {
 			for (tmp = 0; tmp < 8; tmp++) {
 				if (dev->resource[tmp].flags) {
@@ -1540,7 +1552,7 @@
 static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
 {
 	int i;
-	struct list_head *list;
+	struct pci_dev *dev;
 
 	if (irq < 0 || irq > 15)
 		return 1;
@@ -1548,8 +1560,7 @@
 		if (isapnp_reserve_irq[i] == irq)
 			return 1;
 	}
-	for (list = isapnp_devices.next; list != &isapnp_devices; list = list->next) {
-		struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+	isapnp_for_each_dev(dev) {
 		if (dev->active) {
 			if (dev->irq_resource[0].start == irq ||
 			    dev->irq_resource[1].start == irq)
@@ -1620,7 +1631,7 @@
 static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
 {
 	int i;
-	struct list_head *list;
+	struct pci_dev *dev;
 
 	if (dma < 0 || dma == 4 || dma > 7)
 		return 1;
@@ -1628,8 +1639,7 @@
 		if (isapnp_reserve_dma[i] == dma)
 			return 1;
 	}
-	for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
-		struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+	isapnp_for_each_dev(dev) {
 		if (dev->active) {
 			if (dev->dma_resource[0].start == dma || dev->dma_resource[1].start == dma)
 				return 1;
@@ -1695,7 +1705,7 @@
 	int i, tmp;
 	unsigned int raddr, rsize;
 	struct isapnp_mem *xmem;
-	struct list_head *list;
+	struct pci_dev *dev;
 
 	for (i = 0; i < 8; i++) {
 		raddr = (unsigned int)isapnp_reserve_mem[i << 1];
@@ -1707,8 +1717,7 @@
 		if (__check_region(&iomem_resource, addr, size))
 			return 1;
 	}
-	for (list = isapnp_devices.next; list != &isapnp_devices ; list = list->next) {
-		struct pci_dev *dev = list_entry(list, struct pci_dev, global_list);
+	isapnp_for_each_dev(dev) {
 		if (dev->active) {
 			for (tmp = 0; tmp < 4; tmp++) {
 				if (dev->resource[tmp].flags) {
@@ -1988,26 +1997,22 @@
 	}
 }
 
-static void isapnp_free_device(struct pci_dev *dev)
+static void isapnp_free_card(struct pci_bus *card)
 {
-	struct pci_dev *next;
-
-	while (dev) {
-		next = dev->sibling;
+	while (!list_empty(&card->devices)) {
+		struct list_head *list = card->devices.next;
+		struct pci_dev *dev = pci_dev_b(list);
+		list_del(list);
 		isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);
 		kfree(dev);
-		dev = next;
 	}
+	kfree(card);
 }
 
 #endif /* MODULE */
 
 static void isapnp_free_all_resources(void)
 {
-#ifdef MODULE
-	struct pci_bus *card, *cardnext;
-#endif
-
 #ifdef ISAPNP_REGION_OK
 	release_resource(pidxr_res);
 #endif
@@ -2015,10 +2020,10 @@
 	if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff)
 		release_resource(isapnp_rdp_res);
 #ifdef MODULE
-	for (card = isapnp_cards; card; card = cardnext) {
-		cardnext = card->next;
-		isapnp_free_device(card->devices);
-		kfree(card);
+	while (!list_empty(&isapnp_cards)) {
+		struct list_head *list = isapnp_cards.next;
+		list_del(list);
+		isapnp_free_card(pci_bus_b(list));
 	}
 #ifdef CONFIG_PROC_FS
 	isapnp_proc_done();
@@ -2085,7 +2090,7 @@
 int __init isapnp_init(void)
 {
 	int cards;
-	struct list_head *list;
+	struct pci_bus *card;
 
 	if (isapnp_disable) {
 		isapnp_detected = 0;
@@ -2135,9 +2140,7 @@
 	isapnp_build_device_list();
 	cards = 0;
 
-	for (list = isapnp_cards.next; list != &isapnp_cards; list=list->next) {
-		struct pci_bus *card = list_entry(list, struct pci_bus, node);
-
+	isapnp_for_each_card(card) {
 		cards++;
 		if (isapnp_verbose) {
 			struct list_head *devlist;
@@ -2145,7 +2148,7 @@
 			if (isapnp_verbose < 2)
 				continue;
 			for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
-				struct pci_dev *dev = list_entry(list, struct pci_dev, bus_list);
+				struct pci_dev *dev = pci_dev_b(devlist);
 				printk("isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
 			}
 		}
diff -u --recursive --new-file v2.3.37/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.37/linux/drivers/pnp/isapnp_proc.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pnp/isapnp_proc.c	Fri Jan  7 14:08:16 2000
@@ -19,8 +19,6 @@
  *
  */
 
-static void *isapnp_alloc(long size);
-
 struct isapnp_info_buffer {
 	char *buffer;		/* pointer to begin of buffer */
 	char *curr;		/* current position in buffer */
@@ -202,8 +200,6 @@
 	isapnp_info_entry_release,	/* release */
 	NULL,				/* can't fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL,				/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/pnp/quirks.c linux/drivers/pnp/quirks.c
--- v2.3.37/linux/drivers/pnp/quirks.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pnp/quirks.c	Thu Jan  6 14:47:29 2000
@@ -0,0 +1,75 @@
+/*
+ *  This file contains quirk handling code for ISAPnP devices
+ *  Some devices do not report all their resources, and need to have extra
+ *  resources added. This is most easily accomplished at initialisation time
+ *  when building up the resource structure for the first time.
+ *
+ *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
+ *
+ *  Heavily based on PCI quirks handling which is
+ *
+ *  Copyright (c) 1999 Martin Mares <mj@suse.cz>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
+
+static void __init quirk_awe32_resources(struct pci_dev *dev)
+{
+	struct isapnp_port *port, *port2, *port3;
+	struct isapnp_resources *res = dev->sysdata;
+
+	/*
+	 * Unfortunately the isapnp_add_port_resource is too tightly bound
+	 * into the PnP discovery sequence, and cannot be used. Link in the
+	 * two extra ports (at offset 0x400 and 0x800 from the one given) by
+	 * hand.
+	 */
+	for ( ; res ; res = res->alt ) {
+		port2 = isapnp_alloc(sizeof(struct isapnp_port));
+		port3 = isapnp_alloc(sizeof(struct isapnp_port));
+		if (!port2 || !port3)
+			return;
+		port = res->port;
+		memcpy(port2, port, sizeof(struct isapnp_port));
+		memcpy(port3, port, sizeof(struct isapnp_port));
+		port->next = port2;
+		port2->next = port3;
+		port2->min += 0x400;
+		port2->max += 0x400;
+		port3->min += 0x800;
+		port3->max += 0x800;
+	}
+	printk(KERN_INFO "ISAPnP: AWE32 quirk - adding two ports\n");
+}
+
+
+/*
+ *  ISAPnP Quirks
+ *  Cards or devices that need some tweaking due to broken hardware
+ */
+
+static struct isapnp_fixup isapnp_fixups[] __initdata = {
+	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
+		quirk_awe32_resources },
+	{ 0 }
+};
+
+void isapnp_fixup_device(struct pci_dev *dev)
+{
+	int i = 0;
+
+	while (isapnp_fixups[i].vendor != 0) {
+		if ((isapnp_fixups[i].vendor == dev->vendor) &&
+		    (isapnp_fixups[i].device == dev->device)) {
+			printk(KERN_DEBUG "PnP: Calling quirk for %s\n",
+			       dev->slot_name);
+			isapnp_fixups[i].quirk_function(dev);
+		}
+		i++;
+	}
+}
+
diff -u --recursive --new-file v2.3.37/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.37/linux/drivers/sbus/char/bpp.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/bpp.c	Fri Jan  7 11:43:09 2000
@@ -846,8 +846,6 @@
 	bpp_release,
   NULL,   /* fsync */
   NULL,   /* fasync */
-  NULL,   /* check media change */
-  NULL,   /* revalidate */
   NULL,   /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.37/linux/drivers/sbus/char/pcikbd.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/pcikbd.c	Fri Jan  7 11:43:09 2000
@@ -917,10 +917,6 @@
 	NULL, 		/* ioctl */
 	NULL,		/* mmap */
 	aux_no_open,
-	NULL,		/* flush */
-	NULL,
-	NULL,
-	NULL,
 };
 
 static struct miscdevice psaux_mouse = {
diff -u --recursive --new-file v2.3.37/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.3.37/linux/drivers/sbus/char/sunkbd.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/sbus/char/sunkbd.c	Fri Jan  7 11:43:09 2000
@@ -1501,8 +1501,6 @@
 	kbd_close,		/* close */
 	NULL,			/* fsync */
 	kbd_fasync,		/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 };
 
 void __init keyboard_zsinit(void (*put_char)(unsigned char))
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.3.37/linux/drivers/scsi/hosts.h	Wed Dec 29 13:13:18 1999
+++ linux/drivers/scsi/hosts.h	Fri Jan  7 11:55:28 2000
@@ -397,6 +397,16 @@
         __attribute__ ((aligned (sizeof(unsigned long))));
 };
 
+/*
+ * These two functions are used to allocate and free a pseudo device
+ * which will connect to the host adapter itself rather than any
+ * physical device.  You must deallocate when you are done with the
+ * thing.  This physical pseudo-device isn't real and won't be available
+ * from any high-level drivers.
+ */
+extern void scsi_free_host_dev(Scsi_Device * SDpnt);
+extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt);
+
 extern struct Scsi_Host * scsi_hostlist;
 extern struct Scsi_Device_Template * scsi_devicelist;
 
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.37/linux/drivers/scsi/scsi.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/scsi/scsi.c	Fri Jan  7 11:55:28 2000
@@ -1,6 +1,6 @@
 /*
  *  scsi.c Copyright (C) 1992 Drew Eckhardt
- *         Copyright (C) 1993, 1994, 1995 Eric Youngdale
+ *         Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
  *
  *  generic mid-level SCSI driver
  *      Initial versions: Drew Eckhardt
@@ -13,7 +13,7 @@
  *      Tommy Thorn <tthorn>
  *      Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
  *
- *  Modified by Eric Youngdale eric@andante.jic.com or ericy@gnu.ai.mit.edu to
+ *  Modified by Eric Youngdale eric@andante.org or ericy@gnu.ai.mit.edu to
  *  add scatter-gather, multiple outstanding request, and other
  *  enhancements.
  *
@@ -85,7 +85,6 @@
 /*
  * Definitions and constants.
  */
-#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__))
 
 /*
  * PAGE_SIZE must be a multiple of the sector size (512).  True
@@ -153,9 +152,6 @@
  */
 unsigned int scsi_logging_level = 0;
 
-volatile struct Scsi_Host *host_active = NULL;
-
-
 const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
 {
 	"Direct-Access    ",
@@ -193,14 +189,6 @@
 extern void scsi_old_done(Scsi_Cmnd * SCpnt);
 extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
 
-#define SCSI_BLOCK(DEVICE, HOST)                                         \
-	        ((HOST->block && host_active && HOST != host_active)          \
-  		|| ((HOST)->can_queue && HOST->host_busy >= HOST->can_queue)  \
-	        || ((HOST)->host_blocked)                                     \
-	        || ((DEVICE) != NULL && (DEVICE)->device_blocked) )
-
-
-
 struct dev_info {
 	const char *vendor;
 	const char *model;
@@ -497,6 +485,7 @@
 	 * things are quiet.
 	 */
 	atomic_inc(&shpnt->host_active);
+	atomic_inc(&SDpnt->device_active);
 
 	if (hardcoded == 1) {
 		Scsi_Device *oldSDpnt = SDpnt;
@@ -578,6 +567,7 @@
 	 * so we know when everything is quiet.
 	 */
 	atomic_dec(&shpnt->host_active);
+	atomic_dec(&SDpnt->device_active);
 
       leave:
 
@@ -1079,16 +1069,10 @@
 					    || SDpnt == device) {
  						continue;
 					}
-					for (SCpnt = SDpnt->device_queue;
-					     SCpnt;
-					     SCpnt = SCpnt->next) {
-						if (SCpnt->request.rq_status != RQ_INACTIVE) {
-							break;
-						}
-					}
-					if (SCpnt) {
-						break;
-					}
+                                        if( atomic_read(&SDpnt->device_active) != 0)
+                                        {
+                                                break;
+                                        }
 				}
 				if (SDpnt) {
 					/*
@@ -1174,6 +1158,7 @@
 	SCpnt->request.sem = NULL;	/* And no one is waiting for this
 					 * to complete */
 	atomic_inc(&SCpnt->host->host_active);
+	atomic_inc(&SCpnt->device->device_active);
 
 	SCpnt->buffer  = NULL;
 	SCpnt->bufflen = 0;
@@ -1185,6 +1170,7 @@
 	SCpnt->transfersize = 0;	/* No default transfer size */
 	SCpnt->cmd_len = 0;
 
+        SCpnt->result = 0;
 	SCpnt->underflow = 0;	/* Do not flag underflow conditions */
 	SCpnt->resid = 0;
 	SCpnt->state = SCSI_STATE_INITIALIZING;
@@ -1226,10 +1212,13 @@
 
 	spin_lock_irqsave(&device_request_lock, flags);
 
+        SDpnt = SCpnt->device;
+
 	SCpnt->request.rq_status = RQ_INACTIVE;
 	SCpnt->state = SCSI_STATE_UNUSED;
 	SCpnt->owner = SCSI_OWNER_NOBODY;
 	atomic_dec(&SCpnt->host->host_active);
+	atomic_dec(&SDpnt->device_active);
 
 	SCSI_LOG_MLQUEUE(5, printk("Deactivating command for device %d (active=%d, failed=%d)\n",
 				   SCpnt->target,
@@ -1252,8 +1241,6 @@
 		up(SCpnt->host->eh_wait);
 	}
 
-        SDpnt = SCpnt->device;
-
 	spin_unlock_irqrestore(&device_request_lock, flags);
 
         /*
@@ -1368,6 +1355,7 @@
 			if (rtn != 0) {
 				scsi_delete_timer(SCpnt);
 				scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
+                                SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n"));                                
 			}
 		} else {
                         spin_lock_irqsave(&io_request_lock, flags);
@@ -1439,7 +1427,6 @@
 		 int timeout, int retries)
 {
 	struct Scsi_Host *host = SCpnt->host;
-	Scsi_Device *device = SCpnt->device;
 
 	ASSERT_LOCK(&io_request_lock, 0);
 
@@ -1694,6 +1681,8 @@
 				 * from being sent to the device, so we shouldn't end up
 				 * with tons of things being sent down that shouldn't be.
 				 */
+				SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as device queue full, put on ml queue %p\n",
+                                                              SCpnt));
 				scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
 				break;
 			default:
@@ -1758,6 +1747,13 @@
 	SCpnt->request_bufflen = SCpnt->bufflen;
 	SCpnt->use_sg = SCpnt->old_use_sg;
 	SCpnt->cmd_len = SCpnt->old_cmd_len;
+
+        /*
+         * Zero the sense information from the last time we tried
+         * this command.
+         */
+	memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer);
+
 	return scsi_dispatch_cmd(SCpnt);
 }
 
@@ -1781,6 +1777,14 @@
 	host->host_busy--;	/* Indicate that we are free */
 	device->device_busy--;	/* Decrement device usage counter. */
 
+        /*
+         * Clear the flags which say that the device/host is no longer
+         * capable of accepting new commands.  These are set in scsi_queue.c
+         * for both the queue full condition on a device, and for a
+         * host full condition on the host.
+         */
+        host->host_blocked = FALSE;
+        device->device_blocked = FALSE;
 
 	/*
 	 * If we have valid sense information, then some kind of recovery
@@ -3428,6 +3432,97 @@
 }
 
 #endif				/* MODULE */
+
+/*
+ * Function:    scsi_get_host_dev()
+ *
+ * Purpose:     Create a Scsi_Device that points to the host adapter itself.
+ *
+ * Arguments:   SHpnt   - Host that needs a Scsi_Device
+ *
+ * Lock status: None assumed.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:
+ */
+Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
+{
+        Scsi_Device * SDpnt;
+        Scsi_Cmnd   * SCpnt;
+        /*
+         * Attach a single Scsi_Device to the Scsi_Host - this should
+         * be made to look like a "pseudo-device" that points to the
+         * HA itself.  For the moment, we include it at the head of
+         * the host_queue itself - I don't think we want to show this
+         * to the HA in select_queue_depths(), as this would probably confuse
+         * matters.
+         * Note - this device is not accessible from any high-level
+         * drivers (including generics), which is probably not
+         * optimal.  We can add hooks later to attach 
+         */
+        SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
+                                        GFP_ATOMIC);
+        memset(SDpnt, 0, sizeof(Scsi_Device));
+
+        SDpnt->host = SHpnt;
+        SDpnt->id = SHpnt->this_id;
+        SDpnt->type = -1;
+        SDpnt->queue_depth = 1;
+        
+        SCpnt = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
+        memset(SCpnt, 0, sizeof(Scsi_Cmnd));
+        SCpnt->host = SHpnt;
+        SCpnt->device = SDpnt;
+        SCpnt->target = SDpnt->id;
+        SCpnt->state = SCSI_STATE_UNUSED;
+        SCpnt->owner = SCSI_OWNER_NOBODY;
+        SCpnt->request.rq_status = RQ_INACTIVE;
+
+        SDpnt->device_queue = SCpnt;
+
+        blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
+        blk_queue_headactive(&SDpnt->request_queue, 0);
+        SDpnt->request_queue.queuedata = (void *) SDpnt;
+
+	SDpnt->online = TRUE;
+
+        /*
+         * Initialize the object that we will use to wait for command blocks.
+         */
+	init_waitqueue_head(&SDpnt->scpnt_wait);
+        return SDpnt;
+}
+
+/*
+ * Function:    scsi_free_host_dev()
+ *
+ * Purpose:     Create a Scsi_Device that points to the host adapter itself.
+ *
+ * Arguments:   SHpnt   - Host that needs a Scsi_Device
+ *
+ * Lock status: None assumed.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:
+ */
+void scsi_free_host_dev(Scsi_Device * SDpnt)
+{
+        if( SDpnt->id != SDpnt->host->this_id )
+        {
+                panic("Attempt to delete wrong device\n");
+        }
+
+        blk_cleanup_queue(&SDpnt->request_queue);
+
+        /*
+         * We only have a single SCpnt attached to this device.  Free
+         * it now.
+         */
+        kfree(SDpnt->device_queue);
+        kfree(SDpnt);
+}
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.3.37/linux/drivers/scsi/scsi.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi.h	Fri Jan  7 11:55:28 2000
@@ -413,6 +413,10 @@
 extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
 
 /*
+ * Prototypes for functions in scsi.c
+ */
+
+/*
  *  scsi_abort aborts the current command that is executing on host host.
  *  The error code, if non zero is returned in the host byte, otherwise 
  *  DID_ABORT is returned in the hostbyte.
@@ -430,8 +434,6 @@
 
 extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int);
 
-extern Scsi_Cmnd *scsi_request_queueable(struct request *, Scsi_Device *);
-
 extern void scsi_release_command(Scsi_Cmnd *);
 
 extern int max_scsi_hosts;
@@ -461,6 +463,7 @@
 					   device is busy */
 	struct Scsi_Host *host;
 	request_queue_t request_queue;
+        atomic_t                device_active; /* commands checked out for device */
 	volatile unsigned short device_busy;	/* commands actually active on low-level */
 	int (*scsi_init_io_fn) (Scsi_Cmnd *);	/* Used to initialize
 						   new request */
@@ -679,7 +682,6 @@
 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
 
 extern int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason);
-extern int scsi_mlqueue_finish(struct Scsi_Host *host, Scsi_Device * device);
 
 extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
 				   int sectors);
@@ -687,33 +689,7 @@
 extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
 			       int block_sectors);
 
-
-#if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
-#include "hosts.h"
-
-
-/* This is just like INIT_REQUEST, but we need to be aware of the fact
- * that an interrupt may start another request, so we run this with interrupts
- * turned off 
- */
-#if MAJOR_NR == SCSI_DISK0_MAJOR
-#define CHECK_INITREQ_SD_MAJOR(major) SCSI_DISK_MAJOR(major)
-#else
-#define CHECK_INITREQ_SD_MAJOR(major) ((major) == MAJOR_NR)
-#endif
-
-#define INIT_SCSI_REQUEST       			\
-    if (!CURRENT) {             			\
-	CLEAR_INTR;             			\
-	return;                 			\
-    }                           			\
-    if (!CHECK_INITREQ_SD_MAJOR(MAJOR(CURRENT->rq_dev)))\
-	panic(DEVICE_NAME ": request list destroyed");	\
-    if (CURRENT->bh) {                                	\
-	if (!buffer_locked(CURRENT->bh))              	\
-	    panic(DEVICE_NAME ": block not locked");  	\
-    }
-#endif
+extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
 
 #define SCSI_SLEEP(QUEUE, CONDITION) {		    \
     if (CONDITION) {			            \
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- v2.3.37/linux/drivers/scsi/scsi_debug.c	Wed Dec 15 10:43:16 1999
+++ linux/drivers/scsi/scsi_debug.c	Fri Jan  7 11:55:28 2000
@@ -122,6 +122,9 @@
 static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] =
 {NULL,};
 
+struct Scsi_Host * SHpnt = NULL;
+
+static void scsi_debug_send_self_command(struct Scsi_Host * shpnt);
 static void scsi_debug_intr_handle(unsigned long);
 
 static struct timer_list timeout[SCSI_DEBUG_MAILBOXES];
@@ -232,6 +235,17 @@
 
 	buff = (unsigned char *) SCpnt->request_buffer;
 
+        /*
+         * If a command comes for the ID of the host itself, just print
+         * a silly message and return.
+         */
+        if( target == 7 ) {
+                printk("How do you do!\n");
+                SCpnt->result = 0;
+                done(SCpnt);
+                return 0;
+        }
+
 	if (target >= NR_FAKE_DISKS || SCpnt->lun != 0) {
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
@@ -295,6 +309,7 @@
 		break;
 	case READ_CAPACITY:
 		SCSI_LOG_LLQUEUE(3, printk("Read Capacity\n"));
+                SHpnt = SCpnt->host;
 		if (NR_REAL < 0)
 			NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;
 		memset(buff, 0, bufflen);
@@ -306,6 +321,7 @@
 		buff[5] = 0;
 		buff[6] = (SIZE(target) >> 8) & 0xff;	/* 512 byte sectors */
 		buff[7] = SIZE(target) & 0xff;
+
 		scsi_debug_errsts = 0;
 		break;
 	case READ_10:
@@ -528,6 +544,45 @@
 	return 0;
 }
 
+static void sd_test_done(Scsi_Cmnd * SCpnt)
+{
+	struct request *req;
+
+	req = &SCpnt->request;
+	req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
+
+	if (req->sem != NULL) {
+		up(req->sem);
+	}
+}
+
+static void scsi_debug_send_self_command(struct Scsi_Host * shpnt)
+{
+	static unsigned char cmd[6] =
+	{TEST_UNIT_READY, 0, 0, 0, 0, 0};
+
+        Scsi_Cmnd     * scp;
+        Scsi_Device   * sdev;
+        
+        printk("Allocating host dev\n");
+        sdev = scsi_get_host_dev(shpnt);
+        printk("Got %p. Allocating command block\n", sdev);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        printk("Got %p\n", scp);
+
+        scp->cmd_len = 6;
+        scp->use_sg = 0;
+        
+        printk("Sending command\n");
+        scsi_wait_cmd (scp, (void *) cmd, (void *) NULL,
+                       0, sd_test_done,  100, 3);
+        
+        printk("Releasing command\n");
+        scsi_release_command(scp);
+        printk("Freeing device\n");
+        scsi_free_host_dev(sdev);
+}
+
 /* A "high" level interrupt handler.  This should be called once per jiffy
  * to simulate a regular scsi disk.  We use a timer to do this. */
 
@@ -672,6 +727,11 @@
 			 * what we are supposed to do here.  Simulate bus lockups
 			 * to test our reset capability.
 			 */
+			if (length == 4 && strncmp(buffer, "test", length) == 0) {
+                                printk("Testing send self command %p\n", SHpnt);
+                                scsi_debug_send_self_command(SHpnt);
+                                return orig_length;
+                        }
 			if (length == 6 && strncmp(buffer, "lockup", length) == 0) {
 				scsi_debug_lockup = 1;
 				return orig_length;
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.3.37/linux/drivers/scsi/scsi_error.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/scsi/scsi_error.c	Fri Jan  7 11:55:28 2000
@@ -150,7 +150,7 @@
 
 	rtn = del_timer(&SCset->eh_timeout);
 
-	SCSI_LOG_ERROR_RECOVERY(5, printk("Clearing timer for command %p\n", SCset));
+	SCSI_LOG_ERROR_RECOVERY(5, printk("Clearing timer for command %p %d\n", SCset, rtn));
 
 	SCset->eh_timeout.data = (unsigned long) NULL;
 	SCset->eh_timeout.function = NULL;
@@ -1057,7 +1057,10 @@
 	if ((++SCpnt->retries) < SCpnt->allowed) {
 		return NEEDS_RETRY;
 	} else {
-		return FAILED;
+                /*
+                 * No more retries - report this one back to upper level.
+                 */
+		return SUCCESS;
 	}
 }
 
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.3.37/linux/drivers/scsi/scsi_ioctl.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi_ioctl.c	Fri Jan  7 11:55:28 2000
@@ -117,13 +117,7 @@
                 return -EINTR;
         }
 
-	{
-		DECLARE_MUTEX_LOCKED(sem);
-		SCpnt->request.sem = &sem;
-		scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries);
-		down(&sem);
-		SCpnt->request.sem = NULL;
-	}
+        scsi_wait_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries);
 
 	SCSI_LOG_IOCTL(2, printk("Ioctl returned  0x%x\n", SCpnt->result));
 
@@ -306,14 +300,8 @@
                 return -EINTR;
         }
 
-	{
-		DECLARE_MUTEX_LOCKED(sem);
-		SCpnt->request.sem = &sem;
-		scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done,
-			    timeout, retries);
-		down(&sem);
-		SCpnt->request.sem = NULL;
-	}
+        scsi_wait_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done,
+                      timeout, retries);
 
 	/* 
 	 * If there was an error condition, pass the info back to the user. 
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.3.37/linux/drivers/scsi/scsi_lib.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/scsi/scsi_lib.c	Fri Jan  7 11:55:28 2000
@@ -294,11 +294,12 @@
  * Function:    scsi_end_request()
  *
  * Purpose:     Post-processing of completed commands called from interrupt
- *              handler.
+ *              handler or a bottom-half handler.
  *
  * Arguments:   SCpnt    - command that is complete.
  *              uptodate - 1 if I/O indicates success, 0 for I/O error.
  *              sectors  - number of sectors we want to mark.
+ *		requeue  - indicates whether we should requeue leftovers.
  *
  * Lock status: Assumed that lock is not held upon entry.
  *
@@ -310,7 +311,10 @@
  *		We are guaranteeing that the request queue will be goosed
  *		at some point during this call.
  */
-Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
+static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, 
+				     int uptodate, 
+				     int sectors,
+				     int requeue)
 {
 	struct request *req;
 	struct buffer_head *bh;
@@ -348,6 +352,11 @@
 	if (req->bh) {
                 request_queue_t *q;
 
+		if( !requeue )
+		{
+			return SCpnt;
+		}
+
                 q = &SCpnt->device->request_queue;
 
 		req->buffer = bh->b_data;
@@ -377,6 +386,83 @@
 }
 
 /*
+ * Function:    scsi_end_request()
+ *
+ * Purpose:     Post-processing of completed commands called from interrupt
+ *              handler or a bottom-half handler.
+ *
+ * Arguments:   SCpnt    - command that is complete.
+ *              uptodate - 1 if I/O indicates success, 0 for I/O error.
+ *              sectors  - number of sectors we want to mark.
+ *
+ * Lock status: Assumed that lock is not held upon entry.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:       This is called for block device requests in order to
+ *              mark some number of sectors as complete.
+ * 
+ *		We are guaranteeing that the request queue will be goosed
+ *		at some point during this call.
+ */
+Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
+{
+	return __scsi_end_request(SCpnt, uptodate, sectors, 1);
+}
+
+/*
+ * Function:    scsi_release_buffers()
+ *
+ * Purpose:     Completion processing for block device I/O requests.
+ *
+ * Arguments:   SCpnt   - command that we are bailing.
+ *
+ * Lock status: Assumed that no lock is held upon entry.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:       In the event that an upper level driver rejects a
+ *		command, we must release resources allocated during
+ *		the __init_io() function.  Primarily this would involve
+ *		the scatter-gather table, and potentially any bounce
+ *		buffers.
+ */
+static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
+{
+	ASSERT_LOCK(&io_request_lock, 0);
+
+	/*
+	 * Free up any indirection buffers we allocated for DMA purposes. 
+	 */
+	if (SCpnt->use_sg) {
+		struct scatterlist *sgpnt;
+		int i;
+
+		sgpnt = (struct scatterlist *) SCpnt->request_buffer;
+
+		for (i = 0; i < SCpnt->use_sg; i++) {
+			if (sgpnt[i].alt_address) {
+				scsi_free(sgpnt[i].address, sgpnt[i].length);
+			}
+		}
+		scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);
+	} else {
+		if (SCpnt->request_buffer != SCpnt->request.buffer) {
+			scsi_free(SCpnt->request_buffer, SCpnt->request_bufflen);
+		}
+	}
+
+	/*
+	 * Zero these out.  They now point to freed memory, and it is
+	 * dangerous to hang onto the pointers.
+	 */
+	SCpnt->buffer  = NULL;
+	SCpnt->bufflen = 0;
+	SCpnt->request_buffer = NULL;
+	SCpnt->request_bufflen = 0;
+}
+
+/*
  * Function:    scsi_io_completion()
  *
  * Purpose:     Completion processing for block device I/O requests.
@@ -471,14 +557,23 @@
 		 * If multiple sectors are requested in one buffer, then
 		 * they will have been finished off by the first command.
 		 * If not, then we have a multi-buffer command.
-		 */
-		SCpnt = scsi_end_request(SCpnt, 1, good_sectors);
+		 *
+		 * If block_sectors != 0, it means we had a medium error
+		 * of some sort, and that we want to mark some number of
+		 * sectors as not uptodate.  Thus we want to inhibit
+		 * requeueing right here - we will requeue down below
+		 * when we handle the bad sectors.
+		 */
+		SCpnt = __scsi_end_request(SCpnt, 
+					   1, 
+					   good_sectors,
+					   result == 0);
 
 		/*
 		 * If the command completed without error, then either finish off the
 		 * rest of the command, or start a new one.
 		 */
-		if (result == 0) {
+		if (result == 0 || SCpnt == NULL ) {
 			return;
 		}
 	}
@@ -561,7 +656,11 @@
 		}
 	}			/* driver byte != 0 */
 	if (result) {
-		printk("SCSI disk error : host %d channel %d id %d lun %d return code = %x\n",
+		struct Scsi_Device_Template *STpnt;
+
+		STpnt = scsi_get_request_dev(&SCpnt->request);
+		printk("SCSI %s error : host %d channel %d id %d lun %d return code = %x\n",
+		       (STpnt ? STpnt->name : "device"),
 		       SCpnt->device->host->host_no,
 		       SCpnt->device->channel,
 		       SCpnt->device->id,
@@ -569,6 +668,11 @@
 
 		if (driver_byte(result) & DRIVER_SENSE)
 			print_sense("sd", SCpnt);
+		/*
+		 * Mark a single buffer as not uptodate.  Queue the remainder.
+		 * We sometimes get this cruft in the event that a medium error
+		 * isn't properly reported.
+		 */
 		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
 		return;
 	}
@@ -702,6 +806,31 @@
 		} else {
 			SDpnt->starved = 0;
 		}
+
+ 		/*
+		 * FIXME(eric)
+		 * I am not sure where the best place to do this is.  We need
+		 * to hook in a place where we are likely to come if in user
+		 * space.   Technically the error handling thread should be
+		 * doing this crap, but the error handler isn't used by
+		 * most hosts.
+		 */
+		if (SDpnt->was_reset) {
+			/*
+			 * We need to relock the door, but we might
+			 * be in an interrupt handler.  Only do this
+			 * from user space, since we do not want to
+			 * sleep from an interrupt.
+			 */
+			SDpnt->was_reset = 0;
+			if (SDpnt->removable && !in_interrupt()) {
+				spin_unlock_irq(&io_request_lock);
+				scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
+				spin_lock_irq(&io_request_lock);
+				continue;
+			}
+		}
+
 		/*
 		 * Loop through all of the requests in this queue, and find
 		 * one that is queueable.
@@ -768,30 +897,6 @@
 		SDpnt->device_busy++;
 
 		/*
-		 * FIXME(eric)
-		 * I am not sure where the best place to do this is.  We need
-		 * to hook in a place where we are likely to come if in user
-		 * space.   Technically the error handling thread should be
-		 * doing this crap, but the error handler isn't used by
-		 * most hosts.
-		 */
-		if (SDpnt->was_reset) {
-			/*
-			 * We need to relock the door, but we might
-			 * be in an interrupt handler.  Only do this
-			 * from user space, since we do not want to
-			 * sleep from an interrupt.
-			 */
-			if (SDpnt->removable && !in_interrupt()) {
-				spin_unlock_irq(&io_request_lock);
-				scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
-				SDpnt->was_reset = 0;
-				spin_lock_irq(&io_request_lock);
-				continue;
-			}
-			SDpnt->was_reset = 0;
-		}
-		/*
 		 * Finally, before we release the lock, we copy the
 		 * request to the command block, and remove the
 		 * request from the request list.   Note that we always
@@ -842,6 +947,10 @@
 			 * get those allocated here.  
 			 */
 			if (!SDpnt->scsi_init_io_fn(SCpnt)) {
+				SHpnt->host_busy--;
+				SDpnt->device_busy--;
+				scsi_end_request(SCpnt, 0, 
+						 SCpnt->request.nr_sectors);
 				spin_lock_irq(&io_request_lock);
 				continue;
 			}
@@ -849,6 +958,11 @@
 			 * Initialize the actual SCSI command for this request.
 			 */
 			if (!STpnt->init_command(SCpnt)) {
+				SHpnt->host_busy--;
+				SDpnt->device_busy--;
+				scsi_release_buffers(SCpnt);
+				scsi_end_request(SCpnt, 0, 
+						 SCpnt->request.nr_sectors);
 				spin_lock_irq(&io_request_lock);
 				continue;
 			}
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- v2.3.37/linux/drivers/scsi/scsi_merge.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/scsi/scsi_merge.c	Fri Jan  7 11:55:28 2000
@@ -61,6 +61,14 @@
 #include "constants.h"
 #include <scsi/scsi_ioctl.h>
 
+/*
+ * This means that bounce buffers cannot be allocated in chunks > PAGE_SIZE.
+ * Ultimately we should get away from using a dedicated DMA bounce buffer
+ * pool, and we should instead try and use kmalloc() instead.  If we can
+ * eliminate this pool, then this restriction would no longer be needed.
+ */
+#define DMA_SEGMENT_SIZE_LIMITED
+
 #ifdef CONFIG_SCSI_DEBUG_QUEUES
 /*
  * Enable a bunch of additional consistency checking.   Turn this off
@@ -97,12 +105,12 @@
  * This can be removed for optimization.
  */
 #define SANITY_CHECK(req, _CLUSTER, _DMA)				\
-    if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA) )	\
+    if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA, NULL) )	\
     {									\
 	__label__ here;							\
 here:									\
 	printk("Incorrect segment count at 0x%p", &&here);		\
-	dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA)); \
+	dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA, NULL)); \
     }
 #else
 #define SANITY_CHECK(req, _CLUSTER, _DMA)
@@ -166,6 +174,9 @@
  *              dma_host - 1 if this host has ISA DMA issues (bus doesn't
  *                      expose all of the address lines, so that DMA cannot
  *                      be done from an arbitrary address).
+ *		remainder - used to track the residual size of the last
+ *			segment.  Comes in handy when we want to limit the 
+ *			size of bounce buffer segments to PAGE_SIZE.
  *
  * Returns:     Count of the number of SG segments for the request.
  *
@@ -175,12 +186,36 @@
  */
 __inline static int __count_segments(struct request *req,
 				     int use_clustering,
-				     int dma_host)
+				     int dma_host,
+				     int * remainder)
 {
 	int ret = 1;
+	int reqsize = 0;
 	struct buffer_head *bh;
+	struct buffer_head *bhnext;
+
+	if( remainder != NULL ) {
+		reqsize = *remainder;
+	}
+
+	/*
+	 * Add in the size increment for the first buffer.
+	 */
+	bh = req->bh;
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+	if( reqsize + bh->b_size > PAGE_SIZE ) {
+		ret++;
+		reqsize = bh->b_size;
+	} else {
+		reqsize += bh->b_size;
+	}
+#else
+	reqsize += bh->b_size;
+#endif
 
-	for (bh = req->bh; bh->b_reqnext != NULL; bh = bh->b_reqnext) {
+	for (bh = req->bh, bhnext = bh->b_reqnext; 
+	     bhnext != NULL; 
+	     bh = bhnext, bhnext = bh->b_reqnext) {
 		if (use_clustering) {
 			/* 
 			 * See if we can do this without creating another
@@ -189,19 +224,45 @@
 			 * the DMA threshold boundary.  
 			 */
 			if (dma_host &&
-			    virt_to_phys(bh->b_data) - 1 == ISA_DMA_THRESHOLD) {
+			    virt_to_phys(bhnext->b_data) - 1 == ISA_DMA_THRESHOLD) {
 				ret++;
-			} else if (CONTIGUOUS_BUFFERS(bh, bh->b_reqnext)) {
+				reqsize = bhnext->b_size;
+			} else if (CONTIGUOUS_BUFFERS(bh, bhnext)) {
 				/*
 				 * This one is OK.  Let it go.
+				 */ 
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+				/* Note scsi_malloc is only able to hand out
+				 * chunks of memory in sizes of PAGE_SIZE or
+				 * less.  Thus we need to keep track of
+				 * the size of the piece that we have
+				 * seen so far, and if we have hit
+				 * the limit of PAGE_SIZE, then we are
+				 * kind of screwed and we need to start
+				 * another segment.
 				 */
+				if( dma_host
+				    && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD
+				    && reqsize + bhnext->b_size > PAGE_SIZE )
+				{
+					ret++;
+					reqsize = bhnext->b_size;
+					continue;
+				}
+#endif
+				reqsize += bhnext->b_size;
 				continue;
 			}
 			ret++;
+			reqsize = bhnext->b_size;
 		} else {
 			ret++;
+			reqsize = bhnext->b_size;
 		}
 	}
+	if( remainder != NULL ) {
+		*remainder = reqsize;
+	}
 	return ret;
 }
 
@@ -239,7 +300,7 @@
 
 	req->nr_segments = __count_segments(req, 
 					    CLUSTERABLE_DEVICE(SHpnt, SDpnt),
-					    SHpnt->unchecked_isa_dma);
+					    SHpnt->unchecked_isa_dma, NULL);
 }
 
 /*
@@ -282,6 +343,7 @@
 				    int dma_host)
 {
 	unsigned int sector, count;
+	unsigned int segment_size = 0;
 	Scsi_Device *SDpnt;
 	struct Scsi_Host *SHpnt;
 
@@ -310,6 +372,17 @@
 				goto new_segment;
 			}
 			if (CONTIGUOUS_BUFFERS(req->bhtail, bh)) {
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+				if( dma_host
+				    && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) {
+					segment_size = 0;
+					count = __count_segments(req, use_clustering, dma_host, &segment_size);
+					if( segment_size + bh->b_size > PAGE_SIZE )
+					{
+						goto new_segment;
+					}
+				}
+#endif
 				/*
 				 * This one is OK.  Let it go.
 				 */
@@ -330,6 +403,16 @@
 				goto new_segment;
 			}
 			if (CONTIGUOUS_BUFFERS(bh, req->bh)) {
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+				if( dma_host
+				    && virt_to_phys(bh->b_data) - 1 >= ISA_DMA_THRESHOLD ) {
+					segment_size = bh->b_size;
+					count = __count_segments(req, use_clustering, dma_host, &segment_size);
+					if( count != req->nr_segments ) {
+						goto new_segment;
+					}
+				}
+#endif
 				/*
 				 * This one is OK.  Let it go.
 				 */
@@ -453,6 +536,25 @@
 		    virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) {
 			goto dont_combine;
 		}
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+		/*
+		 * We currently can only allocate scatter-gather bounce
+		 * buffers in chunks of PAGE_SIZE or less.
+		 */
+		if (dma_host
+		    && CONTIGUOUS_BUFFERS(req->bhtail, next->bh)
+		    && virt_to_phys(req->bhtail->b_data) - 1 >= ISA_DMA_THRESHOLD )
+		{
+			int segment_size = 0;
+			int count = 0;
+
+			count = __count_segments(req, use_clustering, dma_host, &segment_size);
+			count += __count_segments(next, use_clustering, dma_host, &segment_size);
+			if( count != req->nr_segments + next->nr_segments ) {
+				goto dont_combine;
+			}
+		}
+#endif
 		if (CONTIGUOUS_BUFFERS(req->bhtail, next->bh)) {
 			/*
 			 * This one is OK.  Let it go.
@@ -587,7 +689,7 @@
 	 * First we need to know how many scatter gather segments are needed.
 	 */
 	if (!sg_count_valid) {
-		count = __count_segments(req, use_clustering, dma_host);
+		count = __count_segments(req, use_clustering, dma_host, NULL);
 	} else {
 		count = req->nr_segments;
 	}
@@ -648,14 +750,30 @@
 				/* Nothing - fall through */
 			} else if (CONTIGUOUS_BUFFERS(bhprev, bh)) {
 				/*
-				 * This one is OK.  Let it go.
+				 * This one is OK.  Let it go.  Note that we
+				 * do not have the ability to allocate
+				 * bounce buffer segments > PAGE_SIZE, so
+				 * for now we limit the thing.
 				 */
-				sgpnt[count - 1].length += bh->b_size;
-				if (!dma_host) {
+				if( dma_host ) {
+#ifdef DMA_SEGMENT_SIZE_LIMITED
+					if( virt_to_phys(bh->b_data) - 1 < ISA_DMA_THRESHOLD
+					    || sgpnt[count - 1].length + bh->b_size <= PAGE_SIZE ) {
+						sgpnt[count - 1].length += bh->b_size;
+						bhprev = bh;
+						continue;
+					}
+#else
+					sgpnt[count - 1].length += bh->b_size;
+					bhprev = bh;
+					continue;
+#endif
+				} else {
+					sgpnt[count - 1].length += bh->b_size;
 					SCpnt->request_bufflen += bh->b_size;
+					bhprev = bh;
+					continue;
 				}
-				bhprev = bh;
-				continue;
 			}
 		}
 		count++;
@@ -671,7 +789,8 @@
 	 * Verify that the count is correct.
 	 */
 	if (count != SCpnt->use_sg) {
-		panic("Incorrect sg segment count");
+		printk("Incorrect number of segments after building list\n");
+		dump_stats(req, use_clustering, dma_host, count);
 	}
 	if (!dma_host) {
 		return 1;
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.3.37/linux/drivers/scsi/scsi_obsolete.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/scsi_obsolete.c	Fri Jan  7 11:55:28 2000
@@ -1,5 +1,5 @@
 /*
- *  scsi.c Copyright (C) 1992 Drew Eckhardt
+ *  scsi_obsolete.c Copyright (C) 1992 Drew Eckhardt
  *         Copyright (C) 1993, 1994, 1995 Eric Youngdale
  *
  *  generic mid-level SCSI driver
@@ -87,9 +87,7 @@
 
 extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
 
-extern volatile struct Scsi_Host *host_active;
-#define SCSI_BLOCK(HOST) ((HOST->block && host_active && HOST != host_active) \
-			  || (HOST->can_queue && HOST->host_busy >= HOST->can_queue))
+#define SCSI_BLOCK(HOST) (HOST->can_queue && HOST->host_busy >= HOST->can_queue)
 
 static unsigned char generic_sense[6] =
 {REQUEST_SENSE, 0, 0, 0, 255, 0};
@@ -334,6 +332,7 @@
 	int checked;
 	int oldto;
 	struct Scsi_Host *host = SCpnt->host;
+        Scsi_Device * device = SCpnt->device;
 	int result = SCpnt->result;
 	SCpnt->serial_number = 0;
 	SCpnt->serial_number_at_timeout = 0;
@@ -655,6 +654,7 @@
 		printk("Calling done function - at address %p\n", SCpnt->done);
 #endif
 		host->host_busy--;	/* Indicate that we are free */
+                device->device_busy--;	/* Decrement device usage counter. */
 
 		SCpnt->result = result | ((exit & 0xff) << 24);
 		SCpnt->use_sg = SCpnt->old_use_sg;
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
--- v2.3.37/linux/drivers/scsi/scsi_queue.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi_queue.c	Fri Jan  7 11:55:28 2000
@@ -133,6 +133,13 @@
 	cmd->bh_next = NULL;
 
 	/*
+	 * Decrement the counters, since these commands are no longer
+	 * active on the host/device.
+	 */
+	cmd->host->host_busy--;
+	cmd->device->device_busy--;
+
+	/*
 	 * Insert this command at the head of the queue for it's device.
 	 * It will go before all other commands that are already in the queue.
 	 */
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.3.37/linux/drivers/scsi/scsi_syms.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/scsi_syms.c	Fri Jan  7 11:55:28 2000
@@ -69,6 +69,9 @@
 EXPORT_SYMBOL(scsi_logging_level);
 #endif
 
+EXPORT_SYMBOL(scsi_get_host_dev);
+EXPORT_SYMBOL(scsi_free_host_dev);
+
 EXPORT_SYMBOL(scsi_sleep);
 
 EXPORT_SYMBOL(proc_print_scsidevice);
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.37/linux/drivers/scsi/sd.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/scsi/sd.c	Fri Jan  7 11:55:28 2000
@@ -39,6 +39,7 @@
 #include <linux/hdreg.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 #include <linux/smp.h>
 
@@ -81,12 +82,9 @@
 #define SD_TIMEOUT (30 * HZ)
 #define SD_MOD_TIMEOUT (75 * HZ)
 
-#define CLUSTERABLE_DEVICE(SC) (SC->host->use_clustering && \
-				SC->device->type != TYPE_MOD)
-
 struct hd_struct *sd;
 
-Scsi_Disk *rscsi_disks = NULL;
+static Scsi_Disk *rscsi_disks = NULL;
 static int *sd_sizes;
 static int *sd_blocksizes;
 static int *sd_hardsizes;	/* Hardware sector size */
@@ -106,6 +104,23 @@
 
 static int sd_init_command(Scsi_Cmnd *);
 
+#if defined(CONFIG_PPC)
+/*
+ * Moved from arch/ppc/pmac_setup.c.  This is where it really belongs.
+ */
+kdev_t __init
+sd_find_target(void *host, int tgt)
+{
+    Scsi_Disk *dp;
+    int i;
+    for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
+        if (dp->device != NULL && dp->device->host == host
+            && dp->device->id == tgt)
+            return MKDEV_SD(i);
+    return 0;
+}
+#endif
+
 static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
 {
 	kdev_t dev = inode->i_rdev;
@@ -232,7 +247,9 @@
 {
 	int dev, devm, block, this_count;
 	Scsi_Disk *dpnt;
+#if CONFIG_SCSI_LOGGING
 	char nbuff[6];
+#endif
 
 	devm = SD_PARTITION(SCpnt->request.rq_dev);
 	dev = DEVICE_NR(SCpnt->request.rq_dev);
@@ -248,7 +265,6 @@
 	    !dpnt->device->online ||
  	    block + SCpnt->request.nr_sectors > sd[devm].nr_sects) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request.nr_sectors));
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
 		return 0;
 	}
@@ -259,7 +275,6 @@
 		 * bit has been reset
 		 */
 		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		return 0;
 	}
 	SCSI_LOG_HLQUEUE(2, sd_devname(devm, nbuff));
@@ -280,7 +295,6 @@
 	if (dpnt->device->sector_size == 1024) {
 		if ((block & 1) || (SCpnt->request.nr_sectors & 1)) {
 			printk("sd.c:Bad block number requested");
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		} else {
 			block = block >> 1;
@@ -290,7 +304,6 @@
 	if (dpnt->device->sector_size == 2048) {
 		if ((block & 3) || (SCpnt->request.nr_sectors & 3)) {
 			printk("sd.c:Bad block number requested");
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		} else {
 			block = block >> 2;
@@ -300,7 +313,6 @@
 	switch (SCpnt->request.cmd) {
 	case WRITE:
 		if (!dpnt->device->writeable) {
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		}
 		SCpnt->cmnd[0] = WRITE_6;
@@ -459,22 +471,13 @@
 
 static void sd_geninit(struct gendisk *);
 
-static struct file_operations sd_fops =
+static struct block_device_operations sd_fops =
 {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	sd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	sd_open,		/* open code */
-	NULL,			/* flush */
-	sd_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	check_scsidisk_media_change,	/* Disk change */
-	fop_revalidate_scsidisk	/* revalidate */
+	open:			sd_open,
+	release:		sd_release,
+	ioctl:			sd_ioctl,
+	check_media_change:	check_scsidisk_media_change,
+	revalidate:		fop_revalidate_scsidisk
 };
 
 /*
@@ -520,7 +523,9 @@
 static void rw_intr(Scsi_Cmnd * SCpnt)
 {
 	int result = SCpnt->result;
+#if CONFIG_SCSI_LOGGING
 	char nbuff[6];
+#endif
 	int this_count = SCpnt->bufflen >> 9;
 	int good_sectors = (result == 0 ? this_count : 0);
 	int block_sectors = 1;
@@ -658,20 +663,6 @@
 	return retval;
 }
 
-static void sd_wait_cmd(Scsi_Cmnd * SCpnt, const void *cmnd,
-	      void *buffer, unsigned bufflen, void (*done) (Scsi_Cmnd *),
-			int timeout, int retries)
-{
-	DECLARE_MUTEX_LOCKED(sem);
-
-	SCpnt->request.sem = &sem;
-	SCpnt->request.rq_status = RQ_SCSI_BUSY;
-	scsi_do_cmd(SCpnt, (void *) cmnd,
-		    buffer, bufflen, done, timeout, retries);
-	down(&sem);
-	SCpnt->request.sem = NULL;
-}
-
 static void sd_init_done(Scsi_Cmnd * SCpnt)
 {
 	struct request *req;
@@ -729,7 +720,7 @@
 			SCpnt->sense_buffer[0] = 0;
 			SCpnt->sense_buffer[2] = 0;
 
-			sd_wait_cmd (SCpnt, (void *) cmd, (void *) buffer,
+			scsi_wait_cmd (SCpnt, (void *) cmd, (void *) buffer,
 				0/*512*/, sd_init_done,  SD_TIMEOUT, MAX_RETRIES);
 
 			the_result = SCpnt->result;
@@ -755,7 +746,7 @@
 				SCpnt->sense_buffer[0] = 0;
 				SCpnt->sense_buffer[2] = 0;
 
-				sd_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
+				scsi_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
 					    512, sd_init_done, SD_TIMEOUT, MAX_RETRIES);
 			}
 			spintime = 1;
@@ -785,7 +776,7 @@
 		SCpnt->sense_buffer[0] = 0;
 		SCpnt->sense_buffer[2] = 0;
 
-		sd_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
+		scsi_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
 			    8, sd_init_done, SD_TIMEOUT, MAX_RETRIES);
 
 		the_result = SCpnt->result;
@@ -936,7 +927,7 @@
 		SCpnt->sense_buffer[2] = 0;
 
 		/* same code as READCAPA !! */
-		sd_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
+		scsi_wait_cmd(SCpnt, (void *) cmd, (void *) buffer,
 			    512, sd_init_done, SD_TIMEOUT, MAX_RETRIES);
 
 		the_result = SCpnt->result;
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/sd.h linux/drivers/scsi/sd.h
--- v2.3.37/linux/drivers/scsi/sd.h	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/sd.h	Fri Jan  7 11:55:28 2000
@@ -35,9 +35,12 @@
 	unsigned has_part_table:1;	/* has partition table */
 } Scsi_Disk;
 
-extern Scsi_Disk *rscsi_disks;
-
 extern int revalidate_scsidisk(kdev_t dev, int maxusage);
+
+/*
+ * Used by pmac to find the device associated with a target.
+ */
+extern kdev_t sd_find_target(void *host, int tgt);
 
 #define N_SD_MAJORS	8
 
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.3.37/linux/drivers/scsi/sg.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/scsi/sg.c	Fri Jan  7 11:43:09 2000
@@ -946,8 +946,6 @@
     sg_release,      /* release, was formerly sg_close */
     NULL,            /* fsync */
     sg_fasync,       /* fasync */
-    NULL,            /* check_media_change */
-    NULL,            /* revalidate */
     NULL,            /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.3.37/linux/drivers/scsi/sr.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/sr.c	Fri Jan  7 11:55:28 2000
@@ -267,7 +267,6 @@
 		/*
 		 * Umm, yeah, right.   Swapping to a cdrom.  Nice try.
 		 */
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		return 0;
 	}
 	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
@@ -276,7 +275,6 @@
 	    !scsi_CDs[dev].device ||
 	    !scsi_CDs[dev].device->online) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request.nr_sectors));
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
 		return 0;
 	}
@@ -286,7 +284,6 @@
 		 * bit has been reset
 		 */
 		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		return 0;
 	}
 	/*
@@ -300,14 +297,12 @@
 			printk("sr: can't switch blocksize: in interrupt\n");
 	}
 	if (SCpnt->request.cmd == WRITE) {
-		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 		return 0;
 	}
 	if (scsi_CDs[dev].device->sector_size == 1024) {
 		if ((block & 1) || (SCpnt->request.nr_sectors & 1)) {
 			printk("sr.c:Bad 1K block number requested (%d %ld)",
                                block, SCpnt->request.nr_sectors);
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		} else {
 			block = block >> 1;
@@ -318,7 +313,6 @@
 		if ((block & 3) || (SCpnt->request.nr_sectors & 3)) {
 			printk("sr.c:Bad 2K block number requested (%d %ld)",
                                block, SCpnt->request.nr_sectors);
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		} else {
 			block = block >> 2;
@@ -328,7 +322,6 @@
 	switch (SCpnt->request.cmd) {
 	case WRITE:
 		if (!scsi_CDs[dev].device->writeable) {
-			SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
 			return 0;
 		}
 		SCpnt->cmnd[0] = WRITE_10;
diff -u --recursive --new-file v2.3.37/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.3.37/linux/drivers/sgi/char/graphics.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/sgi/char/graphics.c	Fri Jan  7 11:43:09 2000
@@ -306,8 +306,6 @@
 	NULL,			/* flush */
 	sgi_graphics_close,	/* release */
 	NULL,			/* fsync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c
--- v2.3.37/linux/drivers/sgi/char/shmiq.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/sgi/char/shmiq.c	Fri Jan  7 11:43:09 2000
@@ -452,8 +452,6 @@
         shmiq_qcntl_close,      /* close */
         NULL,                   /* fsync */
         shmiq_qcntl_fasync,     /* fasync */
-        NULL,                   /* check_media_change */
-        NULL,                   /* revalidate */
 };
 
 void
diff -u --recursive --new-file v2.3.37/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c
--- v2.3.37/linux/drivers/sgi/char/streamable.c	Fri Jun 25 17:39:34 1999
+++ linux/drivers/sgi/char/streamable.c	Fri Jan  7 11:43:09 2000
@@ -83,8 +83,6 @@
 	NULL,			/* flush */
 	sgi_gfx_close,		/* release */
 	NULL,			/* fsync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
  
@@ -204,8 +202,6 @@
 	NULL,			/* flush */
 	NULL,			/* release */
 	NULL,			/* fsync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
@@ -345,8 +341,6 @@
 	NULL,			/* flush */
 	sgi_mouse_close,	/* release */
 	NULL,			/* fsync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c
--- v2.3.37/linux/drivers/sgi/char/usema.c	Mon Jul  5 19:44:57 1999
+++ linux/drivers/sgi/char/usema.c	Fri Jan  7 11:43:09 2000
@@ -181,8 +181,6 @@
 	NULL,			/* flush */
 	sgi_usemaclone_release,	/* release */
 	NULL,			/* fsync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.37/linux/drivers/sound/Makefile	Tue Dec  7 09:32:46 1999
+++ linux/drivers/sound/Makefile	Thu Jan  6 15:01:56 2000
@@ -25,7 +25,7 @@
 export-objs	:=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
 		    msnd.o opl3.o sb_card.o sequencer_syms.o \
 		    sound_core.o sound_syms.o uart401.o ad1816.o \
-		    nm256_audio.o
+		    nm256_audio.o ac97.o
 
 
 
@@ -53,7 +53,7 @@
 obj-$(CONFIG_SOUND_CS4232)	+= uart401.o
 obj-$(CONFIG_SOUND_GUS)		+= gus.o ad1848.o
 obj-$(CONFIG_SOUND_MAD16)	+= mad16.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx.o sb.o uart401.o
+obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx.o sb.o uart401.o ac97.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/ac97.c linux/drivers/sound/ac97.c
--- v2.3.37/linux/drivers/sound/ac97.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/sound/ac97.c	Thu Jan  6 15:01:56 2000
@@ -1,3 +1,6 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
 #include "ac97.h"
 
 /* Flag for mono controls. */
@@ -434,6 +437,14 @@
 	return put_user(ret, (int *) arg);
 }
 
+EXPORT_SYMBOL(ac97_init);
+EXPORT_SYMBOL(ac97_set_values);
+EXPORT_SYMBOL(ac97_set_mixer);
+EXPORT_SYMBOL(ac97_get_register);
+EXPORT_SYMBOL(ac97_put_register);
+EXPORT_SYMBOL(ac97_get_mixer_scaled);
+EXPORT_SYMBOL(ac97_mixer_ioctl);
+EXPORT_SYMBOL(ac97_reset);
 
 /*
  * Local variables:
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.37/linux/drivers/sound/cmpci.c	Tue Dec  7 09:32:46 1999
+++ linux/drivers/sound/cmpci.c	Fri Jan  7 11:43:09 2000
@@ -1192,8 +1192,6 @@
 	&cm_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1815,8 +1813,6 @@
 	&cm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2096,8 +2092,6 @@
 	&cm_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2270,8 +2264,6 @@
 	&cm_dmfm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.37/linux/drivers/sound/es1370.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/sound/es1370.c	Fri Jan  7 11:43:09 2000
@@ -1050,8 +1050,6 @@
 	&es1370_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1731,8 +1729,6 @@
 	&es1370_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2122,8 +2118,6 @@
 	&es1370_release_dac,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2396,8 +2390,6 @@
 	&es1370_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.37/linux/drivers/sound/es1371.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/sound/es1371.c	Fri Jan  7 11:43:09 2000
@@ -1632,8 +1632,6 @@
 	&es1371_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2308,8 +2306,6 @@
 	&es1371_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2689,8 +2685,6 @@
 	&es1371_release_dac,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2962,8 +2956,6 @@
 	&es1371_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.37/linux/drivers/sound/esssolo1.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/sound/esssolo1.c	Fri Jan  7 11:43:09 2000
@@ -934,8 +934,6 @@
 	&solo1_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1582,8 +1580,6 @@
 	&solo1_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1926,8 +1922,6 @@
 	&solo1_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2112,8 +2106,6 @@
 	&solo1_dmfm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.3.37/linux/drivers/sound/maestro.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/sound/maestro.c	Fri Jan  7 11:43:09 2000
@@ -2044,8 +2044,6 @@
 	&ess_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2920,8 +2918,6 @@
 	&ess_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.3.37/linux/drivers/sound/msnd_pinnacle.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/sound/msnd_pinnacle.c	Fri Jan  7 11:43:09 2000
@@ -1137,11 +1137,6 @@
 	dev_release,	/* release */
 	NULL,		/* fsync */
 	NULL,		/* fasync */
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
-#ifndef LINUX20
-	NULL,		/* lock */
-#endif
 };
 
 static int reset_dsp(void)
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c
--- v2.3.37/linux/drivers/sound/nm256_audio.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/sound/nm256_audio.c	Thu Jan  6 15:01:56 2000
@@ -14,6 +14,7 @@
  */
 
 #include <linux/config.h>
+#define __NO_VERSION__
 #include <linux/pci.h>
 #include <linux/module.h>
 #ifdef CONFIG_APM
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.3.37/linux/drivers/sound/sb_audio.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/sb_audio.c	Thu Jan  6 15:01:56 2000
@@ -460,7 +460,7 @@
 			speed = 44100;
 		if (devc->opened & OPEN_READ && speed > 15000)
 			speed = 15000;
-		devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
+		devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
 		tmp = 256 - devc->tconst;
 		speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
 
@@ -591,7 +591,7 @@
 		if (speed > 44100)
 			speed = 44100;
 
-		devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
+		devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
 
 		tmp = 256 - devc->tconst;
 		speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.3.37/linux/drivers/sound/sb_card.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/sound/sb_card.c	Thu Jan  6 15:01:56 2000
@@ -145,11 +145,6 @@
 int support = 0;	/* Set support to load this as a support module */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
 int acer = 0;		/* Do acer notebook init */
-#ifdef CONFIG_ISAPNP
-int isapnp = 1;
-#else
-int isapnp = 0;
-#endif
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -163,9 +158,6 @@
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
 MODULE_PARM(esstype, "i");
-#ifdef CONFIG_ISAPNP
-MODULE_PARM(isapnp, "i");
-#endif
 
 void *smw_free = NULL;
 
@@ -233,12 +225,7 @@
 	if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
 	{
 #ifdef CONFIG_ISAPNP			
-		if (isapnp == 1 && sb_probe_isapnp(&config, &config_mpu)<0)
-		{
-			printk(KERN_ERR "sb_card: No ISAPnP cards found\n");
-			return -EINVAL;
-		}
-		else
+		if (sb_probe_isapnp(&config, &config_mpu)<0)
 		{
 #endif			
 			if (io == -1 || dma == -1 || irq == -1)
@@ -251,6 +238,9 @@
 			config.dma = dma;
 			config.dma2 = dma16;
 			config.card_subtype = type;
+#ifdef CONFIG_MIDI
+			config_mpu.io_base = mpu_io;
+#endif
 #ifdef CONFIG_ISAPNP
 		}
 #endif
@@ -261,8 +251,6 @@
 		if(config.slots[0]==-1)
 			return -ENODEV;
 #ifdef CONFIG_MIDI
-		if (isapnp == 0) 
-			config_mpu.io_base = mpu_io;
 		if (probe_sbmpu(&config_mpu))
 			sbmpu = 1;
 		if (sbmpu)
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.37/linux/drivers/sound/sonicvibes.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/sound/sonicvibes.c	Fri Jan  7 11:43:09 2000
@@ -1255,8 +1255,6 @@
 	&sv_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -1915,8 +1913,6 @@
 	&sv_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2197,8 +2193,6 @@
 	&sv_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2376,8 +2370,6 @@
 	&sv_dmfm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.3.37/linux/drivers/sound/sound_core.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/sound/sound_core.c	Fri Jan  7 11:43:09 2000
@@ -284,21 +284,7 @@
 
 static struct file_operations soundcore_fops=
 {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	soundcore_open,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	open:	soundcore_open,
 };
 
 static struct sound_unit *__look_for_unit(int chain, int unit)
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.3.37/linux/drivers/sound/trident.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/sound/trident.c	Fri Jan  7 11:43:09 2000
@@ -29,6 +29,8 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.04 Dec 31 1999 Ollie Lho
+ *	Multiple Open, useing Middle Loop Interrupt to smooth playback
  *  v0.03 Dec 24 1999 Ollie Lho
  *	mem leak in prog_dmabuf and dealloc_dmabuf removed
  *  v0.02 Dec 15 1999 Ollie Lho
@@ -64,35 +66,32 @@
 #include "trident.h"
 #include "ac97.h"
 
-/* --------------------------------------------------------------------- */
-
 #undef DEBUG
 
-/* --------------------------------------------------------------------- */
 #define DRIVER_VERSION "0.03"
 
-#define TRIDENT_FMT_STEREO	0x01
-#define TRIDENT_FMT_16BIT	0x02
-#define TRIDENT_FMT_MASK	0x03
-#define TRIDENT_DAC_SHIFT	0   
-#define TRIDENT_ADC_SHIFT	4
-
-#define TRIDENT_ENABLE_PE		1
-#define TRIDENT_ENABLE_RE		2
-#define DAC_RUNNING		1
-#define ADC_RUNNING		2
-
+#define TRIDENT_FMT_STEREO     0x01
+#define TRIDENT_FMT_16BIT      0x02
+#define TRIDENT_FMT_MASK       0x03
+#define TRIDENT_DAC_SHIFT      0   
+#define TRIDENT_ADC_SHIFT      4
+
+#define TRIDENT_ENABLE_PE      1
+#define TRIDENT_ENABLE_RE      2
+#define DAC_RUNNING            1
+#define ADC_RUNNING            2
 
 #define TRIDENT_CARD_MAGIC	0x5072696E /* "Prin" */
 #define TRIDENT_STATE_MAGIC	0x63657373 /* "cess" */
 
-
-#define NR_DSPS		8
+/* number of instances of opening /dev/dsp, can your CPU handle this ? */
+#define NR_DSPS		32
 
 #define SND_DEV_DSP16	5 
 
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+static const char *sample_format[] = {"8 bits Mono", "8 bits Stereo", "16 bits Mono", "16 bits Stereo"};
 static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n";
 
 struct pci_audio_info {
@@ -143,29 +142,34 @@
 
 } CHANNELCONTROL;
 
-/* --------------------------------------------------------------------- */
-
+/* "software" or virtual channel, an instance of opened /dev/dsp */
 struct trident_state {
 	unsigned int magic;
-	int channel;
 	struct trident_card *card;	/* Card info */
+
 	/* wave stuff */
 	unsigned int rateadc, ratedac;
 	unsigned char fmt, enable;
 
+	/* single opne lock mechanism, should be removed */
 	struct semaphore open_sem;
-	mode_t open_mode;
 	wait_queue_head_t open_wait;
 
-	/* soundcore stuff */
-	int dev_audio;
+	/* file mode */
+	mode_t open_mode;
+
+	/* virtual channel number */
+	int virt;
 
 	struct dmabuf {
 		void *rawbuf;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
-		int chan[2];	/* Hardware channel */
+
+		/* hardware channel number */
+		int chan;
+
 		/* XXX zab - swptr only in here so that it can be referenced by
 		   clear_advance, as far as I can tell :( */
 		unsigned hwptr, swptr;
@@ -173,6 +177,7 @@
 		int count;
 		unsigned error; /* over/underrun */
 		wait_queue_head_t wait;
+
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -184,13 +189,22 @@
 		unsigned ossfragshift;
 		int ossmaxfrags;
 		unsigned subdivision;
-		u16 base;		/* Offset for ptr */
 	} dma_dac, dma_adc;
-	
+
 	u8 bDMAStart;
 
 };
 
+/* hardware channels */
+struct trident_channel {
+	int chan; /* channel number */
+	u32 lba;
+	u32 eso;
+	u32 delta;
+	u16 attribute;
+	
+};
+
 struct trident_pcm_bank {
 	/* registers to control bank operations */
 	u32 start;
@@ -207,6 +221,7 @@
 	int supported_mixers;
 	int stereo_mixers;
 	int record_sources;
+
 	/* the caller must guarantee arg sanity before calling these */
 	/* int (*read_mixer)(struct trident_card *card, int index);*/
 	void (*write_mixer)(struct trident_card *card,int mixer, unsigned int left,
@@ -225,32 +240,26 @@
 	   so we use a single per card lock */	   
 	spinlock_t lock;
 
+	/* PCI device stuff */
 	struct pci_audio_info *pci_info;
 	struct pci_dev * pci_dev;
 	u16 pci_id;
 
-	/* as most of this is static,
-	   perhaps it should be a pointer to a global struct */
+	/* soundcore stuff */
+	int dev_audio;
 	int dev_mixer;
-	struct mixer_goo {
-		int modcnt;
-		int supported_mixers;
-		int stereo_mixers;
-		int record_sources;
-		/* the caller must guarantee arg sanity before calling these */
-		/* int (*read_mixer)(struct trident_card *card, int index);*/
-		void (*write_mixer)(struct trident_card *card,int mixer, unsigned int left,unsigned int right);
-		int (*recmask_io)(struct trident_card *card,int rw,int mask);
-		unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
-	} mix;
-	
-	struct trident_state channels[NR_DSPS];
+
+	struct trident_mixer mix;
+	struct trident_state *channels[NR_DSPS];
 
 	/* hardware resources */
 	unsigned long iobase;
 	u32 irq;
 
+	/* hardware channel allocation bitmap */
 	u32 bitmap[2];
+
+	/* ugly stupid thing, remove ASAP */
 	CHANNELCONTROL ChRegs;
 	int ChanDwordCount;
 };
@@ -303,53 +312,53 @@
 
 static int trident_enable_end_interrupts(struct trident_card * trident)
 {
-	u32 GlobalControl;
+	u32 global_control;
 
-	GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
 
 	switch (trident->pci_id)
 	{
 	case PCI_DEVICE_ID_SI_7018:
-		GlobalControl |= (ENDLP_IE | BANK_B_EN);
+		global_control |= (ENDLP_IE | BANK_B_EN);
 		break;
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
-		GlobalControl |= ENDLP_IE;
+		global_control |= ENDLP_IE;
 		break;
 	default:
 		return FALSE;
 	}
 
-	outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+	outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
 
 #ifdef DEBUG
-	printk("trident: Enable End Interrupts, globctl = 0x%08X\n", GlobalControl);
+	printk("trident: Enable End Interrupts, globctl = 0x%08X\n", global_control);
 #endif
 	return (TRUE);
 }
 
 static int trident_enable_middle_interrupts(struct trident_card * trident)
 {
-	u32 GlobalControl;
+	u32 global_control;
 
-	GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
 
 	switch (trident->pci_id)
 	{
 	case PCI_DEVICE_ID_SI_7018:
-		GlobalControl |= (MIDLP_IE | BANK_B_EN);
+		global_control |= (MIDLP_IE | BANK_B_EN);
 		break;
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
 	default:
-		GlobalControl |= MIDLP_IE;
+		global_control |= MIDLP_IE;
 		break;
 	}
 
-	outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+	outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
 
 #ifdef DEBUG
-	printk("trident: Enable Middle Interrupts, globctl = 0x%08X\n", GlobalControl);
+	printk("trident: Enable Middle Interrupts, globctl = 0x%08X\n", global_control);
 #endif
 	return (TRUE);
 }
@@ -369,28 +378,28 @@
 
 static int trident_disable_end_interrupts(struct trident_card * trident)
 {
-	u32 GlobalControl;
+	u32 global_control;
 
-	GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
-	GlobalControl &= ~ENDLP_IE;
-	outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control &= ~ENDLP_IE;
+	outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
 
 #ifdef DEBUG
-	printk("trident: Disabled End Interrupts, globctl = 0x%08X\n", GlobalControl);
+	printk("trident: Disabled End Interrupts, globctl = 0x%08X\n", global_control);
 #endif
 	return (TRUE);
 }
 
 static int trident_disable_middle_interrupts(struct trident_card * trident)
 {
-	u32 GlobalControl;
+	u32 global_control;
 
-	GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
-	GlobalControl &= ~MIDLP_IE;
-	outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+	global_control &= ~MIDLP_IE;
+	outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
 
 #ifdef DEBUG
-	printk("trident: Disabled Middle Interrupts, globctl = 0x%08X\n", GlobalControl);
+	printk("trident: Disabled Middle Interrupts, globctl = 0x%08X\n", global_control);
 #endif
 	return (TRUE);
 }
@@ -475,7 +484,7 @@
 	int idx;
 
 	if (trident->bitmap[BANK_B] == ~0UL) {
-		/* not more free channels avaliable */
+		/* no more free channels avaliable */
 		printk(KERN_ERR "trident: no more channels available on Bank B.\n");
 		return -1;
 	}
@@ -490,7 +499,7 @@
 	/* channels in Bank A should be reserved for synthesizer 
 	   not for normal use (channels in Bank A can't record) */
 	if (trident->bitmap[BANK_A] == ~0UL) {
-		/* not more free channels avaliable */
+		/* no more free channels avaliable */
 		printk(KERN_ERR "trident: no channels available on Bank A.\n");
 		return -1;
 	}
@@ -800,7 +809,7 @@
 	trident->ratedac = rate;
 
 	if (set)
-		trident_load_hw_delta(trident->card, trident->dma_dac.chan[1],
+		trident_load_hw_delta(trident->card, trident->dma_dac.chan,
 				      delta);
 #ifdef DEBUG	 
 	printk("trident: called trident_set_dac_rate : rate = %d, "
@@ -838,7 +847,7 @@
 
 #if 0 /* It seems that 4D-Wave can not use wave tables channels for recording */
 	if (set)
-		trident_load_hw_delta(trident->card, trident->dma_dac.chan[0],
+		trident_load_hw_delta(trident->card, trident->dma_adc.chan,
 				      delta);
 #endif
 #ifdef DEBUG	 
@@ -1109,7 +1118,6 @@
 #ifdef DEBUG
 	printk(" 0x%04x", val);
 #endif
-
 	trident_ac97_set(card, mh->offset, val);
 
 #ifdef DEBUG
@@ -1237,12 +1245,12 @@
 	return 0;
 }
 
-/* this only fixes the output apu mode to be later set by start_dac and
-   company.  output apu modes are set in trident_rec_setup */
+/* this function only update fmt field in trident_state, the hardware channel attribute
+   will be update in trident_play(rec)_setup() which will be called every time a new
+   sample is played(recorded) */
 static void set_fmt(struct trident_state *s, unsigned char mask, unsigned char data)
 {
 	s->fmt = (s->fmt & mask) | data;
-	/* Set the chip ? */
 }
 
 /* the mode passed should be already shifted and masked */
@@ -1276,13 +1284,17 @@
 		ESO /= 2;
 	ESO = ESO - 1;
 
+	/* loop mode enable */
 	CTRL = 0x00000001;
 	if (mode & TRIDENT_FMT_16BIT) {
-		CTRL |= 0x00000008;	// 16-bit data
-		CTRL |= 0x00000002;	// signed data
+		/* 16-bits */
+		CTRL |= 0x00000008;
+		/* signed */
+		CTRL |= 0x00000002;
 	}
 	if (mode & TRIDENT_FMT_STEREO)
-		CTRL |= 0x00000004;	// stereo data
+		/* stereo */
+		CTRL |= 0x00000004;
 	
 	/* FIXME: some difference between 4D and 7018 in FMC_RVOL_CVOL */
 	/* right vol: mute, ledt vol: mute */
@@ -1293,7 +1305,7 @@
 	EC = 0;
 
 	trident_write_voice_regs(trident->card,
-				 trident->dma_dac.chan[1],
+				 trident->dma_dac.chan,
 				 LBA,
 				 0,	/* cso */
 				 ESO,
@@ -1314,7 +1326,8 @@
 /* FIXME: Not exammed yet */
 /* again, passed mode is alrady shifted/masked */
 
-static void trident_rec_setup(struct trident_state *trident, int mode, u32 rate, void *buffer, int size)
+static void trident_rec_setup(struct trident_state *trident, int mode, u32 rate,
+			      void *buffer, int size)
 {
 	unsigned int LBA;
 	unsigned int Delta;
@@ -1432,7 +1445,7 @@
 	EC = 0;
 
 	trident_write_voice_regs(card,
-			     trident->dma_adc.chan[0],
+			     trident->dma_adc.chan,
 			     LBA,
 			     0,	/* cso */
 			     ESO,
@@ -1457,7 +1470,7 @@
 	if (!(trident->enable & ADC_RUNNING))
 		return 0;
 #endif
-	outb(trident->dma_dac.chan[1], TRID_REG(trident->card, T4D_LFO_GC_CIR));
+	outb(trident->dma_dac.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
 
 	switch (trident->card->pci_id) 
 	{
@@ -1477,9 +1490,9 @@
 	}
 
 #ifdef DEBUG
-	printk("trident: get_dmaa: chip reported esc = %d, cso = %d\n", cso, eso);
+	printk("trident: get_dmaa: chip reported channel: %d, cso = %d, eso = %d\n",
+	       trident->dma_dac.chan, cso, eso);
 #endif
-	cso++;
 	/* ESO and CSO are in units of Samples, convert to byte offset */
 	if (cso > eso)
 		cso = eso;
@@ -1496,10 +1509,10 @@
 	u32 cso;
 #if 0
 	/* FIXME: does this mean that FULL duplex is not supported ? */
-	if (!(trident->enable&DAC_RUNNING))
+	if (!(trident->enable & DAC_RUNNING))
 		return 0;
 #endif
-	outb(trident->dma_adc.chan[0], TRID_REG(trident->card, T4D_LFO_GC_CIR));
+	outb(trident->dma_adc.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
 
 	switch (trident->card->pci_id) 
 	{
@@ -1518,7 +1531,6 @@
 #ifdef DEBUG
 	printk("(trident) get_dmac: chip reported cso = %d\n", cso);
 #endif
-	cso++;
 	/* ESO and CSO are in units of Samples, convert to byte offset */
 	if (trident->fmt & TRIDENT_FMT_16BIT)
 		cso *= 2;
@@ -1535,11 +1547,11 @@
 	printk("(trident) stopping ADC\n");
 #endif
 	s->enable &= ~ADC_RUNNING;
-	trident_disable_voice_irq(trident, s->dma_adc.chan[0]);
+	trident_disable_voice_irq(trident, s->dma_adc.chan);
 	outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
-	trident_disable_voice_irq(trident, s->dma_adc.chan[0]);
-	trident_stop_voice(trident, s->dma_adc.chan[0]);
-	ResetAinten(trident, s->dma_adc.chan[0]);
+	trident_disable_voice_irq(trident, s->dma_adc.chan);
+	trident_stop_voice(trident, s->dma_adc.chan);
+	ResetAinten(trident, s->dma_adc.chan);
 }	
 
 extern inline void stop_adc(struct trident_state *s)
@@ -1553,47 +1565,36 @@
 }	
 
 /* stop playback (lock held) */
-
-extern inline void __stop_dac(struct trident_state *s)
+extern inline void __stop_dac(struct trident_state *state)
 {
-	struct trident_card *trident = s->card;
-#ifdef DEBUG
-	printk("(trident) stopping DAC\n");
-#endif	
-	//trident_stop_voice(trident, s->dma_dac.chan[0]);
-	//trident_disable_voice_irq(trident, s->dma_dac.chan[0]);
-	trident_stop_voice(trident, s->dma_dac.chan[1]);
-	trident_disable_voice_irq(trident, s->dma_dac.chan[1]);
-	s->enable &= ~DAC_RUNNING;
+	struct trident_card *trident = state->card;
+	trident_stop_voice(trident, state->dma_dac.chan);
+	trident_disable_voice_irq(trident, state->dma_dac.chan);
+	state->enable &= ~DAC_RUNNING;
 }	
 
-extern inline void stop_dac(struct trident_state *s)
+extern inline void stop_dac(struct trident_state *state)
 {
-	struct trident_card *trident = s->card;
+	struct trident_card *trident = state->card;
 	unsigned long flags;
 
 	spin_lock_irqsave(&trident->lock, flags);
-	__stop_dac(s);
+	__stop_dac(state);
 	spin_unlock_irqrestore(&trident->lock, flags);
 }	
 
-static void start_dac(struct trident_state *s)
+static void start_dac(struct trident_state *state)
 {
 	unsigned long flags;
-	struct trident_card *trident = s->card;
+	struct trident_card *trident = state->card;
 
-	spin_lock_irqsave(&s->card->lock, flags);
-	if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) 
-	{
-		s->enable |= DAC_RUNNING;
-		trident_enable_voice_irq(trident, s->dma_dac.chan[1]);
-		trident_start_voice(trident, s->dma_dac.chan[1]);
-		//trident_start_voice(trident, s->dma_dac.chan[0]);
-#ifdef DEBUG
-		printk("(trident) starting DAC\n");
-#endif
+	spin_lock_irqsave(&state->card->lock, flags);
+	if ((state->dma_dac.mapped || state->dma_dac.count > 0) && state->dma_dac.ready) {
+		state->enable |= DAC_RUNNING;
+		trident_enable_voice_irq(trident, state->dma_dac.chan);
+		trident_start_voice(trident, state->dma_dac.chan);
 	}
-	spin_unlock_irqrestore(&s->card->lock, flags);
+	spin_unlock_irqrestore(&state->card->lock, flags);
 }	
 
 static void start_adc(struct trident_state *s)
@@ -1604,9 +1605,9 @@
 	if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) 
 	    && s->dma_adc.ready) {
 		s->enable |= ADC_RUNNING;
-		trident_enable_voice_irq(s->card, s->dma_adc.chan[0]);
+		trident_enable_voice_irq(s->card, s->dma_adc.chan);
 		outb(s->bDMAStart, TRID_REG(s->card, T4D_SBCTRL_SBE2R_SBDD));
-		trident_start_voice(s->card, s->dma_adc.chan[0]);
+		trident_start_voice(s->card, s->dma_adc.chan);
 #ifdef DEBUG
 		printk("(trident) starting ADC\n");
 #endif	
@@ -1615,7 +1616,7 @@
 }	
 
 #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
-#define DMABUF_MINORDER 2
+#define DMABUF_MINORDER 1
 
 /* allocate DMA buffer, playback and recording buffer should be allocated seperately */
 static int alloc_dmabuf(struct trident_state *state, unsigned rec)
@@ -1626,10 +1627,14 @@
 
 	/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
 	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-		if ((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
+		if ((rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
 			break;
 	if (!rawbuf)
 		return -ENOMEM;
+#ifdef DEBUG
+	printk("trident: allocated %ld (%d) bytes at %p\n",
+	       PAGE_SIZE << order, order, rawbuf);
+#endif
 
 	/* for 4DWave and 7018, there are only 30 (31) siginifcan bits for Loop Begin Address
 	   (LBA) which limits the address space to 1 (2) GB, bad T^2 design */
@@ -1744,10 +1749,15 @@
 	/* set the ready flag for the dma buffer */
 	db->ready = 1;
 
+#ifdef DEBUG
+	printk("trident: prog_dmabuf, sample rate = %d, format = %d, numfrag = %d, "
+	       "fragsize = %d dmasize = %d\n",
+	       rate, fmt, db->numfrag, db->fragsize, db->dmasize);
+#endif
+
 	return 0;
 }
 
-/* only called by trident_write */
 extern __inline__ void clear_advance(struct trident_state *s)
 {
 	unsigned char c = ((s->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_16BIT) ? 0 : 0x80;
@@ -1775,7 +1785,8 @@
 	/* update ADC pointer */
 	if (s->dma_adc.ready) {
 		hwptr = get_dmac(s) % s->dma_adc.dmasize;
-		diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
+		diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % 
+			s->dma_adc.dmasize;
 		s->dma_adc.hwptr = hwptr;
 		s->dma_adc.total_bytes += diff;
 		s->dma_adc.count += diff;
@@ -1791,30 +1802,20 @@
 	}
 
 	/* update DAC pointer */
-	if (s->dma_dac.ready) 
-	{
-		/* this is so gross.  */
-		hwptr = (/*s->dma_dac.dmasize -*/ get_dmaa(s)) % s->dma_dac.dmasize; 
-		diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
-#ifdef DEBUG
-		printk("(trident) updating dac: hwptr: %d diff: %d\n",hwptr,diff);
-#endif
+	if (s->dma_dac.ready) {
+		hwptr = get_dmaa(s) % s->dma_dac.dmasize; 
+		diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % 
+			s->dma_dac.dmasize;
 		s->dma_dac.hwptr = hwptr;
 		s->dma_dac.total_bytes += diff;
-		if (s->dma_dac.mapped) 
-		{
+		if (s->dma_dac.mapped) {
 			s->dma_dac.count += diff;
 			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 
 				wake_up(&s->dma_dac.wait);
 		} 
-		else 
-		{
+		else {
 			s->dma_dac.count -= diff;
-#ifdef DEBUG
-			printk("(trident) trident_update_ptr: diff: %d, count: %d\n", diff, s->dma_dac.count); 
-#endif
-			if (s->dma_dac.count <= 0) 
-			{
+			if (s->dma_dac.count <= 0) {
 				s->enable &= ~TRIDENT_ENABLE_PE;
 				/* Lock already held */
 				__stop_dac(s);
@@ -1825,8 +1826,7 @@
 				s->dma_dac.error++;
 			} 
 			else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && 
-					!s->dma_dac.endcleared) 
-			{
+				 !s->dma_dac.endcleared) {
 				clear_advance(s);
 				s->dma_dac.endcleared = 1;
 			}
@@ -1856,13 +1856,12 @@
 
 	if (event & ADDRESS_IRQ) {
 		/* Update the pointers for all channels we are running. */
-		/* the index variable i is the main bug make the original driver crash,
-		   the code mix "software" channel with "hardware" channel */
+		/* FIXME: improve interrupt latency !!! */
 		for (i = 0; i < NR_DSPS; i++) {
-			state = &card->channels[i];
+			state = card->channels[i];
 			if (trident_check_channel_interrupt(card, 63 - i)) {
 				trident_ack_channel_interrupt(card, 63 - i);
-				if (state->dev_audio != -1)
+				if (state != NULL)
 					trident_update_ptr(state);
 				else {
 					/* Spurious ? */
@@ -2040,7 +2039,6 @@
 	struct trident_card *card = (struct trident_card *)file->private_data;
 
 	VALIDATE_CARD(card);
-
 	return mixer_ioctl(card, cmd, arg);
 }
 
@@ -2062,8 +2060,6 @@
 	&trident_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2080,9 +2076,9 @@
 
 	if (s->dma_dac.mapped || !s->dma_dac.ready)
 		return 0;
+
 	current->state = TASK_INTERRUPTIBLE;
 	add_wait_queue(&s->dma_dac.wait, &wait);
-
 	for (;;) {
 		spin_lock_irqsave(&s->card->lock, flags);
 		count = s->dma_dac.count;
@@ -2107,12 +2103,15 @@
 		   or schedule_timeout is broken.
 		   or something.  who cares. - zach */
 		if (!schedule_timeout(tmo ? tmo : 1) && tmo)
-			printk(KERN_ERR "trident: dma timed out?? %ld\n", jiffies);
+			printk(KERN_ERR "trident: drain_dac, "
+			       "dma timed out? jiffies = %ld\n",
+			       jiffies);
 	}
 	remove_wait_queue(&s->dma_dac.wait, &wait);
 	current->state = TASK_RUNNING;
 	if (signal_pending(current))
 		return -ERESTARTSYS;
+
 	return 0;
 }
 
@@ -2168,8 +2167,6 @@
 				stop_adc(state);
 
 				spin_lock_irqsave(&state->card->lock, flags);
-				/*set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), 
-				  s->dma_adc.numfrag << s->dma_adc.fragshift); */
 				state->dma_adc.count = 0;
 				state->dma_adc.hwptr = 0;
 				state->dma_adc.swptr = 0;
@@ -2211,7 +2208,7 @@
 	int mode = (state->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_MASK;
 
 #ifdef DEBUG
-	printk("(trident) trident_write: count %d\n", count);
+	printk("trident: trident_write called, count = %d\n", count);
 #endif	
 
 	VALIDATE_STATE(state);
@@ -2247,7 +2244,7 @@
 				return ret;
 			}
 			if (!interruptible_sleep_on_timeout(&state->dma_dac.wait, HZ)) {
-				printk(KERN_DEBUG 
+				printk(KERN_ERR 
 				       "trident: write: chip lockup? "
 				       "dmasz %u fragsz %u count %i "
 				       "hwptr %u swptr %u\n", 
@@ -2258,8 +2255,6 @@
 				       state->dma_dac.swptr);
 				stop_dac(state);
 				spin_lock_irqsave(&state->card->lock, flags);
-				/* set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), 
-				   s->dma_dac.numfrag << s->dma_dac.fragshift); */
 				state->dma_dac.count = 0;
 				state->dma_dac.hwptr = 0;
 				state->dma_dac.swptr = 0;
@@ -2304,8 +2299,10 @@
 		poll_wait(file, &s->dma_dac.wait, wait);
 	if (file->f_mode & FMODE_READ)
 		poll_wait(file, &s->dma_adc.wait, wait);
+
 	spin_lock_irqsave(&s->card->lock, flags);
 	trident_update_ptr(s);
+
 	if (file->f_mode & FMODE_READ) {
 		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
 			mask |= POLLIN | POLLRDNORM;
@@ -2367,6 +2364,10 @@
 	VALIDATE_STATE(s);
 	mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
 		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+#ifdef DEBUG
+	printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",_IOC_NR(cmd), 
+	       arg ? *(int *)arg : 0);
+#endif
 
 	switch (cmd) 
 	{
@@ -2674,61 +2675,73 @@
 
 static int trident_open(struct inode *inode, struct file *file)
 {
+	int i = 0;
 	int minor = MINOR(inode->i_rdev);
 	struct trident_card *card = devs;
-	struct trident_state *state = NULL, *sp;
-	int i;
+	struct trident_state *state = NULL;
 	unsigned char fmtm = ~0, fmts = 0;
 
-	/* Scan the cards and find the channel. 
-	   We only do this at open time so it is ok */
+	/* find an avaiable virtual channel (instance of /dev/dsp) */
 	while (card != NULL) {
 		for (i = 0; i < NR_DSPS; i++) {
-			sp = &card->channels[i];
-			if (sp->dev_audio < 0)
-				continue;
-			if ((sp->dev_audio ^ minor) & ~0xf)
-				continue;
-			state = sp;
+			if (card->channels[i] == NULL) {
+				state = card->channels[i] = (struct trident_state *)
+					kmalloc(sizeof(struct trident_state), GFP_KERNEL);
+				if (state == NULL)
+					return -ENOMEM;
+				memset(state, 0, sizeof(struct trident_state));
+				goto found_virt;
+			}
 		}
 		card = card->next;
 	}
-
+	/* no more virtual channel avaiable */
 	if (!state)
 		return -ENODEV;
 
-	VALIDATE_STATE(state);
+ found_virt:
+	/* found a free virtual channel, allocate hardware channels */
+	if (file->f_mode & FMODE_READ)
+		if ((state->dma_adc.chan = trident_alloc_pcm_channel(card)) == -1) {
+			kfree (card->channels[i]);
+			card->channels[i] = NULL;;
+			return -ENODEV;
+		}
+	if (file->f_mode & FMODE_WRITE)
+		if ((state->dma_dac.chan = trident_alloc_pcm_channel(card)) == -1) {
+			kfree (card->channels[i]);
+			card->channels[i] = NULL;
+			if (file->f_mode & FMODE_READ)
+				/* free previously allocated hardware channel */
+				trident_free_pcm_channel(card, state->dma_adc.chan);
+			return -ENODEV;
+		}
+
+	/* initialize the virtual channel */
+	state->virt = i;
+	state->card = card;
+	state->magic = TRIDENT_STATE_MAGIC;
+	init_waitqueue_head(&state->dma_adc.wait);
+	init_waitqueue_head(&state->dma_dac.wait);
+	init_MUTEX(&state->open_sem);
 	file->private_data = state;
 
 	down(&state->open_sem);
 
-	while (state->open_mode & file->f_mode) {
-		/* the channel has been open for the same mode before */
-		if (file->f_flags & O_NONBLOCK) {
-			/* Non-blocking mode, return immediately */
-			up(&state->open_sem);
-			return -EWOULDBLOCK;
-		}
-		up(&state->open_sem);
-		/* blocking, wait for device to become free */
-		interruptible_sleep_on(&state->open_wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-		down(&state->open_sem);
-	}
-
+	/* set default sample format, Refer to  OSS Programmer's Guide */
 	if (file->f_mode & FMODE_READ) {
 		/* fmtm &= ~((TRIDENT_FMT_STEREO | TRIDENT_FMT_16BIT) << TRIDENT_ADC_SHIFT);
 		if ((minor & 0xf) == SND_DEV_DSP16)
 			fmts |= TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT; */
-
 		fmtm = (TRIDENT_FMT_STEREO|TRIDENT_FMT_16BIT) << TRIDENT_ADC_SHIFT;
-
 		state->dma_adc.ossfragshift = 0;
 		state->dma_adc.ossmaxfrags  = 0;
 		state->dma_adc.subdivision  = 0;
 		trident_set_adc_rate(state, 8000, 0);
 	}
+
+	/* according to OSS document, /dev/dsp should be default to unsigned 8-bits, 
+	   mono, with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
 	if (file->f_mode & FMODE_WRITE) {
 		fmtm &= ~((TRIDENT_FMT_STEREO | TRIDENT_FMT_16BIT) << TRIDENT_DAC_SHIFT);
 		if ((minor & 0xf) == SND_DEV_DSP16)
@@ -2756,27 +2769,31 @@
 	if (file->f_mode & FMODE_WRITE)
 		drain_dac(state, file->f_flags & O_NONBLOCK);
 
-	/* stop DMA state machine and free DMA buffers */
+	/* stop DMA state machine and free DMA buffers/channels */
 	down(&state->open_sem);
+
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(state);
 		dealloc_dmabuf(&state->dma_dac);
+		trident_free_pcm_channel(state->card, state->dma_dac.chan);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(state);
 		dealloc_dmabuf(&state->dma_adc);
+		trident_free_pcm_channel(state->card, state->dma_adc.chan);
 	}
+
+	kfree(state->card->channels[state->virt]);
+	state->card->channels[state->virt] = NULL;
 	state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+
 	/* we're covered by the open_sem */
 	up(&state->open_sem);
 
-	wake_up(&state->open_wait);
-
 	//FIXME put back in
 	//MOD_DEC_USE_COUNT;
 	return 0;
 }
-
 static /*const*/ struct file_operations trident_audio_fops = {
 	&trident_llseek,
 	&trident_read,
@@ -2790,88 +2807,57 @@
 	&trident_release,
 	NULL,	/* fsync */
 	NULL,	/* fasync */
-	NULL,	/* check_media_change */
-	NULL,	/* revalidate */
 	NULL,	/* lock */
 };
 
-#ifdef CONFIG_APM
-int trident_apm_callback(apm_event_t ae) {
-	return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
+/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
+   untill open time */
 static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_info)
 {
+	int i;
 	u16 w;
 	unsigned long iobase;
-	int i;
 	struct trident_card *card;
-	struct trident_state *trident;
-	int num = 0;
-	u32 ChanDwordCount;
-	
+    	u32 ChanDwordCount;
+
 	iobase = pcidev->resource[0].start;
-	
-	if(check_region(iobase, 256)) {
-		printk(KERN_WARNING "trident: can't allocate I/O space at 0x%4.4lx\n",
+	if (check_region(iobase, 256)) {
+		printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n",
 		       iobase);
 		return 0;
 	}
 
-	/* this was tripping up some machines */
-	if (pcidev->irq == 0) {
-		printk(KERN_WARNING "trident: pci subsystem reports irq 0,"
-		       " this might not be correct.\n");
-	}
-
-	/* just to be sure */
-	pci_set_master(pcidev);
-	
+	/* just to be sure that IO space and bus master is on */
+	pci_set_master(pcidev);	
 	pci_read_config_word(pcidev, PCI_COMMAND, &w);
-	if((w&(PCI_COMMAND_IO|PCI_COMMAND_MASTER)) != (PCI_COMMAND_IO|PCI_COMMAND_MASTER))
-	{
-		printk(KERN_WARNING "trident: BIOS did not enable I/O access.\n");
-		w|=PCI_COMMAND_IO|PCI_COMMAND_MASTER;
-		pci_write_config_word(pcidev, PCI_COMMAND, w);
-	}
-	
-	card = kmalloc(sizeof(struct trident_card), GFP_KERNEL);
+	w |= PCI_COMMAND_IO|PCI_COMMAND_MASTER;
+	pci_write_config_word(pcidev, PCI_COMMAND, w);
 
-	if (card == NULL) {
-		printk(KERN_WARNING "trident: out of memory\n");
+	if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "trident: out of memory\n");
 		return 0;
 	}
-	
 	memset(card, 0, sizeof(*card));
 
-#ifdef CONFIG_APM
-	printk("trident: apm_reg_callback: %d\n",
-	       apm_register_callback(trident_apm_callback));
-#endif
-
 	card->iobase = iobase;
 	card->pci_info = pci_info;
 	card->pci_id = pci_info->device;
 	card->irq = pcidev->irq;
 	card->next = devs;
 	card->magic = TRIDENT_CARD_MAGIC;
+	spin_lock_init(&card->lock);
 	devs = card;
 
+	/* ungly stupid thing, remove ASAP */
 	ChanDwordCount = card->ChanDwordCount = 2;
-
 	card->ChRegs.lpChStart = card->ChRegs.data;
 	card->ChRegs.lpChStop = card->ChRegs.lpChStart + ChanDwordCount;
 	card->ChRegs.lpChAint = card->ChRegs.lpChStop + ChanDwordCount;
 	card->ChRegs.lpChAinten = card->ChRegs.lpChAint + ChanDwordCount;
-
 	card->ChRegs.lpAChStart = card->ChRegs.lpChAinten + ChanDwordCount;
 	card->ChRegs.lpAChStop = card->ChRegs.lpAChStart + ChanDwordCount;
 	card->ChRegs.lpAChAint = card->ChRegs.lpAChStop + ChanDwordCount;
 	card->ChRegs.lpAChAinten = card->ChRegs.lpAChAint + ChanDwordCount;
-
 	// Assign Bank A addresses.
 	card->ChRegs.lpAChStart[0] = T4D_START_A;
 	card->ChRegs.lpAChStop[0] = T4D_STOP_A;
@@ -2883,68 +2869,43 @@
 	card->ChRegs.lpAChAint[1] = T4D_AINT_B;
 	card->ChRegs.lpAChAinten[1] = T4D_AINTEN_B;
 
-	outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-	
-
-	spin_lock_init(&card->lock);
-	
-	for (i = 0; i < NR_DSPS; i++) {
-		struct trident_state *s=&card->channels[i];
-
-		s->card = card;
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_MUTEX(&s->open_sem);
-		s->magic = TRIDENT_STATE_MAGIC;
-		s->channel = i;
-
-		if(s->dma_adc.ready || s->dma_dac.ready || s->dma_adc.rawbuf)
-			printk(KERN_ERR "trident: BOTCH!\n");
-
-		/*
-		 *	Now allocate the hardware resources
-		 */
-
-		//s->dma_dac.chan[0] = AllocateChannelPCM(card);
-		//s->dma_adc.chan[0] = AllocateChannelPCM(card);
-		s->dma_dac.chan[1] = trident_alloc_pcm_channel(card);
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0)
-			break;
-	}
-
-	num = i;
-
-	/* clear the rest if we ran out of slots to register */
-	for (;i < NR_DSPS; i++){
-		struct trident_state *s=&card->channels[i];
-		s->dev_audio = -1;
-	}
-
-	trident = &card->channels[0];
-
-	/*
-	 *	Ok card ready. Begin setup proper
-	 */
 
-	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", 
+	printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
 	       card->pci_info->name, card->iobase, card->irq);
 
+	/* claim our iospace and irq */
+	request_region(card->iobase, 256, card->pci_info->name);
+	if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card->pci_info->name, card)) {
+		printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq);
+		release_region(card->iobase, 256);
+		kfree(card);
+		return 0;
+	}
 
-	/* stake our claim on the iospace */
-	request_region(iobase, 256, card->pci_info->name);
-
+	/* initilize AC97 codec */
 	trident_ac97_init(card);
+	outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
 
+	/* register /dev/dsp */
+	if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
+		printk(KERN_ERR "trident: coundn't register DSP device!\n");
+		release_region(iobase, 256);
+		free_irq(card->irq, card);
+		kfree(card);
+		return 0;
+	}
+	/* register /dev/mixer */
 	if ((card->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1)) < 0) {
 		printk(KERN_ERR "trident: couldn't register mixer!\n");
-	} 
-	else {
-		int i;
-		for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++) {
+		unregister_sound_dsp(card->dev_audio);
+		release_region(iobase, 256);
+		free_irq(card->irq, card);
+		kfree(card);
+		return 0;
+	} else {
+		/* initilize mixer channels */
+		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 			struct mixer_defaults *md = &mixer_defaults[i];
-
 			if (md->mixer == -1) 
 				break;
 			if (!supported_mixer(card, md->mixer)) 
@@ -2953,24 +2914,13 @@
 		}
 	}
 
-	if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card->pci_info->name, card)) {
-		printk(KERN_ERR "trident: unable to allocate irq %d,\n", card->irq);
-		unregister_sound_mixer(card->dev_mixer);
-		for (i = 0; i < NR_DSPS; i++) {
-			struct trident_state *s = &card->channels[i];
-			if(s->dev_audio != -1)
-				unregister_sound_dsp(s->dev_audio);
-		}
-		release_region(card->iobase, 256);
-		kfree(card);
-		return 0;
-	}
-
+	/* Enable Address Engine Interrupts */
 	trident_enable_end_interrupts(card);
+	trident_enable_middle_interrupts(card);
+
 	return 1; 
 }
 
-
 #ifdef MODULE
 int init_module(void)
 #else
@@ -3001,40 +2951,33 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
 #ifdef MODULE
-
 MODULE_AUTHOR("Alan Cox <alan@redhat.com>");
 MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver");
+
 #ifdef DEBUG
 MODULE_PARM(debug,"i");
 #endif
 
 void cleanup_module(void)
 {
-#ifdef CONFIG_APM
-	apm_unregister_callback(trident_apm_callback);
-#endif
-
 	while (devs != NULL) {
-		int i;
-
 		/* Kill interrupts, and SP/DIF */
 		trident_disable_end_interrupts(devs);
+		trident_enable_middle_interrupts(devs);
+
+		/* free hardware resources */
 		free_irq(devs->irq, devs);
-		unregister_sound_mixer(devs->dev_mixer);
-		for (i = 0; i < NR_DSPS; i++) {
-			struct trident_state *trident = &devs->channels[i];
-			if (trident->dev_audio != -1)
-				unregister_sound_dsp(trident->dev_audio);
-		}
 		release_region(devs->iobase, 256);
+
+		/* unregister audio devices */
+		unregister_sound_mixer(devs->dev_mixer);
+		unregister_sound_dsp(devs->dev_audio);
+
 		kfree(devs);
 		devs = devs->next;
 	}
 }
-
 #endif /* MODULE */
 
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/trident.h linux/drivers/sound/trident.h
--- v2.3.37/linux/drivers/sound/trident.h	Tue Jan  4 13:57:17 2000
+++ linux/drivers/sound/trident.h	Thu Jan  6 15:01:56 2000
@@ -151,19 +151,26 @@
 #define DX_AC97_BUSY_WRITE 0x8000
 #define NX_AC97_BUSY_WRITE 0x0800
 #define SI_AC97_BUSY_READ  0x8000
-#define DX_AC97_BUSY_READ 0x8000
-#define NX_AC97_BUSY_READ 0x0800
+#define DX_AC97_BUSY_READ  0x8000
+#define NX_AC97_BUSY_READ  0x0800
 #define AC97_REG_ADDR      0x000000ff
-#define DX_AC97_REG_ADDR   0x000000ff
-#define NX_AC97_REG_ADDR   0x000000ff
+
+enum serial_intf_ctrl_bits {
+	WARM_REST   = 0x00000001, COLD_RESET  = 0x00000002,
+	I2S_CLOCK   = 0x00000004, PCM_SEC_AC97= 0x00000008,
+	AC97_DBL_RATE = 0x00000010, SPDIF_EN  = 0x00000020,
+	I2S_OUTPUT_EN = 0x00000040, I2S_INPUT_EN = 0x00000080,
+	PCMIN       = 0x00000100, LINE1IN     = 0x00000200,
+	MICIN       = 0x00000400, LINE2IN     = 0x00000800,
+};
 
 enum global_control_bits {
-	CHANNLE_IDX = 0x0000003f, PB_RESET   = 0x00000100,
+	CHANNLE_IDX = 0x0000003f, PB_RESET    = 0x00000100,
 	PAUSE_ENG   = 0x00000200,
 	OVERRUN_IE  = 0x00000400, UNDERRUN_IE = 0x00000800,
-	ENDLP_IE    = 0x00001000, MIDLP_IE   = 0x00002000,
+	ENDLP_IE    = 0x00001000, MIDLP_IE    = 0x00002000,
 	ETOG_IE     = 0x00004000,
-	EDROP_IE    = 0x00008000, BANK_B_EN  = 0x00010000
+	EDROP_IE    = 0x00008000, BANK_B_EN   = 0x00010000
 };
 
 enum miscint_bits {
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/via82cxxx.c linux/drivers/sound/via82cxxx.c
--- v2.3.37/linux/drivers/sound/via82cxxx.c	Tue Sep  7 12:14:07 1999
+++ linux/drivers/sound/via82cxxx.c	Thu Jan  6 15:01:56 2000
@@ -1,101 +1,555 @@
 /*
  * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
  *
  * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
  * See the "COPYING" file distributed with this software for more info.
  *
- ********************************************************************
- *
- * TODO:
- *
- *	- Integrate AC'97 support, when AC'97 interface released
+ * Documentation for this driver available as
+ * linux/Documentation/sound/via82cxxx.txt.
  *
+ * Since the mixer is called from the OSS glue the kernel lock is always held
+ * on our AC97 mixing
  */
  
+
+#define VIA_VERSION	"1.1.2"
+
+
+
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/proc_fs.h>
 
 #include <asm/io.h>
 
 #include "sound_config.h"
 #include "soundmodule.h"
 #include "sb.h"
+#include "ac97.h"
 
 #ifndef SOUND_LOCK
 #define SOUND_LOCK do {} while (0)
 #define SOUND_LOCK_END do {} while (0)
 #endif
 
+#define VIA_DEBUG 0	/* define to 1 to enable debugging output and checks */
+#if VIA_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define VIA_NDEBUG 0	/* define to 1 to disable lightweight runtime checks */
+#if VIA_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(!(expr)) {					\
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
+        #expr,__FILE__,__FUNCTION__,__LINE__);		\
+        }
+#endif
+
+#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
+
 #define MAX_CARDS	2
 
-#define PFX		"via82cxxx: "
+#define	LINE_SIZE	10
 
-#define VIA_VERSION	"1.0.0"
 #define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
+#define VIA_MODULE_NAME "via82cxxx"
+#define PFX		VIA_MODULE_NAME ": "
+
+#define VIA_COUNTER_LIMIT	100000
 
+/* 82C686 function 5 (audio codec) PCI configuration registers */
 #define VIA_FUNC_ENABLE		0x42
 #define VIA_PNP_CONTROL		0x43
+#define VIA_AC97_CTRL		0x80
+
+/* PCI configuration register bits and masks */
+#define VIA_CR40_AC97_READY	0x01
+#define VIA_CR40_AC97_LOW_POWER	0x02
+#define VIA_CR40_SECONDARY_READY 0x04
+
+#define VIA_CR41_ACLINK_ENABLE	0x80
 
 #define VIA_CR42_SB_ENABLE	0x01
 #define VIA_CR42_MIDI_ENABLE	0x02
 #define VIA_CR42_FM_ENABLE	0x04
+#define VIA_CR42_GAME_ENABLE	0x08
+
+#define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
+#define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
+
+#define VIA_CR80_FIRST_CODEC		0
+#define VIA_CR80_SECOND_CODEC		(1 << 30)
+#define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
+#define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
+#define VIA_CR80_BUSY			(1 << 24)
+#define VIA_CR80_READ_MODE		(1 << 23)
+#define VIA_CR80_WRITE_MODE		0
+#define VIA_CR80_REG_IDX(idx)		(((idx) & 0x7E) << 16)
+
+struct via_info {
+	struct address_info sb_data;
+	struct address_info opl3_data;
+	struct pci_dev *pdev;
+	struct ac97_hwint ac97;
+	int mixer_oss_dev;
+	int have_ac97;
+};
+static struct via_info		cards [MAX_CARDS];
+static unsigned			num_cards = 0;
+
+
+static const struct {
+	int revision;
+	const char *rev_name;
+} via_chip_revs[] __initdata = {
+	{ 0x10, "A" },
+	{ 0x11, "B" },
+	{ 0x12, "C" },
+	{ 0x13, "D" },
+	{ 0x14, "E" },
+	{ 0x20, "H" },
+};
+
+static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
+{
+	struct resource *rsrc = &pdev->resource[0];
+	outw ((u16)data,rsrc->start+port);	
+	outw ((u16)(data>>16),rsrc->start+port+2);	
+}
+
+static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
+{
+	struct resource *rsrc = &pdev->resource[0];
+	return
+		((u32)inw (rsrc->start+port)) |
+		(((u32)inw (rsrc->start+port+2)) << 16);
+}
+
+/****************************************************************
+ *
+ * Intel Audio Codec '97 interface
+ *
+ *
+ */
+ 
+static inline void via_ac97_wait_idle (struct pci_dev *pdev)
+{
+	u32 tmp;
+	int counter = VIA_COUNTER_LIMIT;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (pdev != NULL);
+	
+	do {
+		tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+	} while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
+
+	DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
+}
+
+
+static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
+{
+	u32 data;
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+
+	via_ac97_wait_idle (pdev);
+	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+		VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
+	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+	via_ac97_wait_idle (pdev);
+	data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+
+#if 0
+	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+		DPRINTK ("EXIT, first codec not valid, returning -1\n");
+		return -1;
+	}
+#endif
+
+	DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
+	return data & 0xFFFF;
+}
+
+
+static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
+{
+	u32 data;
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+
+	via_ac97_wait_idle (pdev);
+	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+		VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
+	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+
+#if 0
+	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+		DPRINTK ("EXIT, first codec invalid, returning -1\n");
+		return -1;
+	}
+#endif
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static int via_ac97_reset (struct ac97_hwint *dev)
+{
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+	
+	pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static struct via_info *via_ac97_find_card_for_mixer (int dev)
+{
+	int x;
+
+	DPRINTK ("ENTER\n");
+
+	for (x = 0; x < num_cards; x++)
+		if (cards[x].mixer_oss_dev == dev) {
+			DPRINTK ("EXIT, returning %p\n", cards + x);
+			return cards + x;
+		}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return NULL;
+}
+
+
+static int
+via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	int rc;
+	struct via_info *card = via_ac97_find_card_for_mixer (dev);
+
+	DPRINTK ("ENTER\n");
+
+	if (card != NULL) {
+		rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
+		DPRINTK ("EXIT, returning %d\n", rc);
+		return rc;
+	}
+	
+	DPRINTK ("EXIT, returning -ENODEV\n");
+	return -ENODEV;
+
+}
+
+static struct mixer_operations via_ac97_mixer_operations =
+{
+	"VIA82Cxxx",
+	"via82cxxxAC97Mixer",
+	via_ac97_default_mixer_ioctl
+};
+
+static int __init via_attach_ac97 (struct via_info *card)
+{
+	int mixer;
+	struct ac97_hwint *mdev;
+
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	mdev = &card->ac97;
+
+	memset (mdev, 0, sizeof (*mdev));
+	mdev->reset_device = via_ac97_reset;
+	mdev->read_reg = via_ac97_read_reg;
+	mdev->write_reg = via_ac97_write_reg;
+	mdev->driver_private = (void *) card;
+
+	if (ac97_init (mdev)) {
+		printk (KERN_ERR PFX "Unable to init AC97\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+	mixer = sound_alloc_mixerdev ();
+	if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
+		printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+	mixer_devs[mixer] = &via_ac97_mixer_operations;
+	card->mixer_oss_dev = mixer;
+
+	/* Some reasonable default values.  */
+	ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
+	ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
+	ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
+	ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
 
-#define via_probe_midi probe_uart401
-#define via_attach_midi attach_uart401
-#define via_unload_midi unload_uart401
-
-static struct address_info	sb_data[MAX_CARDS];
-static struct address_info	opl3_data[MAX_CARDS];
-static unsigned			cards = 0;
+	printk (KERN_INFO PFX "Initialized AC97 mixer\n");
+	
+	card->have_ac97 = mixer;
+	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static void via_unload_ac97 (struct via_info *card)
+{
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	if (card->have_ac97 >= 0)
+		sound_unload_mixerdev (card->have_ac97);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx/info
+ *
+ *
+ */
+
+static int via_info_read_proc (char *page, char **start, off_t off,
+			       int count, int *eof, void *data)
+{
+#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
+
+	int len = 0, i;
+	u8 r40, r41, r42, r44;
+	
+	DPRINTK ("ENTER\n");
+
+	len += sprintf (page+len, VIA_CARD_NAME "\n\n");
+	
+	for (i = 0; i < num_cards; i++) {
+		pci_read_config_byte (cards[i].pdev, 0x40, &r40);
+		pci_read_config_byte (cards[i].pdev, 0x42, &r41);
+		pci_read_config_byte (cards[i].pdev, 0x42, &r42);
+		pci_read_config_byte (cards[i].pdev, 0x44, &r44);
+	
+		len += sprintf (page+len,
+			"40  AC97 Codec Ready: %s\n"
+			"    AC97 Codec Low-power: %s\n"
+			"    Secondary Codec Ready: %s\n"
+
+			"41  AC-Link Interface Enable: %s\n"
+
+			"42  Game port enabled: %s\n"
+			"    SoundBlaster enabled: %s\n"
+			"    FM enabled: %s\n"
+			"    MIDI enabled: %s\n"
+			
+			"44  AC-Link Interface Access: %s\n"
+			"    Secondary Codec Support: %s\n"
+			
+			"\n",
+			
+			YN (r40, VIA_CR40_AC97_READY),
+			YN (r40, VIA_CR40_AC97_LOW_POWER),
+			YN (r40, VIA_CR40_SECONDARY_READY),
+
+			YN (r41, VIA_CR41_ACLINK_ENABLE),
+
+			YN (r42, VIA_CR42_GAME_ENABLE),
+			YN (r42, VIA_CR42_SB_ENABLE),
+			YN (r42, VIA_CR42_FM_ENABLE),
+			YN (r42, VIA_CR42_MIDI_ENABLE),
+
+			YN (r44, VIA_CR44_AC_LINK_ACCESS),
+			YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
+			
+			);
+	}
+	
+	DPRINTK("EXIT, returning %d\n", len);
+	return len;
+
+#undef YN
+}
+
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx
+ *
+ *
+ */
+
+static int __init via_init_proc (void)
+{
+	DPRINTK ("ENTER\n");
+
+	proc_mkdir ("driver/via_audio", 0);
+	create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
+	
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+
+
+static void __exit via_cleanup_proc (void)
+{
+	DPRINTK ("ENTER\n");
+	remove_proc_entry ("driver/via_audio/info", NULL);
+	remove_proc_entry ("driver/via_audio", NULL);
+	DPRINTK("EXIT\n");
+}
+
+
+#else
+
+static inline int via_init_proc (void) { return 0; }
+static inline void via_cleanup_proc (void) {}
 
+#endif /* CONFIG_PROC_FS */
+
+
+/****************************************************************
+ *
+ * Legacy SoundBlaster Pro, FM support via OSS
+ *
+ *
+ */
 
 static void __init via_attach_sb(struct address_info *hw_config)
 {
+	DPRINTK ("ENTER\n");
+
 	if(!sb_dsp_init(hw_config))
 		hw_config->slots[0] = -1;
+
+	DPRINTK("EXIT\n");
 }
 
 
 static int __init via_probe_sb(struct address_info *hw_config)
 {
+	DPRINTK ("ENTER\n");
+
 	if (check_region(hw_config->io_base, 16))
 	{
 		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
 		       hw_config->io_base);
 		return 0;
 	}
+	DPRINTK("EXIT after sb_dsp_detect\n");
 	return sb_dsp_detect(hw_config, 0, 0);
 }
 
 
-static void __exit via_unload_sb(struct address_info *hw_config, int unload_mpu)
+static void __exit via_unload_sb(struct address_info *hw_config)
 {
-	if(hw_config->slots[0]!=-1)
-		sb_dsp_unload(hw_config, unload_mpu);
+	DPRINTK ("ENTER\n");
+
+	if(hw_config->slots[0] != -1)
+		sb_dsp_unload(hw_config, 1);
+
+	DPRINTK("EXIT\n");
 }
 
 
+static const struct {
+	int sb_irq,
+	    sb_dma,
+	    midi_base,
+	    sb_io_base;
+} via_pnp_data[] __initdata = {
+	{ 5, 0, 0x300, 0x220 },
+	{ 7, 1, 0x310, 0x240 },
+	{ 9, 2, 0x320, 0x260 },
+	{ 10,3, 0x330, 0x280 },
+};
+
+
+/****************************************************************
+ *
+ * Chip setup and kernel registration
+ *
+ *
+ */
+
 static int __init via82cxxx_install (struct pci_dev *pcidev)
 {
-	int sb_io_base = 0;
-	int sb_irq = 0;
-	int sb_dma = 0;
-	int midi_base = 0;
+	int sb_io_base;
+	int sb_irq;
+	int sb_dma;
+	int midi_base, rc;
 	u8 tmp8;
+	struct via_info *card = &cards[num_cards];
 	
-	memset (&sb_data[cards], 0, sizeof (struct address_info));
-	memset (&opl3_data[cards], 0, sizeof (struct address_info));
+	DPRINTK ("ENTER\n");
 
-	sb_data[cards].name = opl3_data[cards].name = VIA_CARD_NAME;
-	opl3_data[cards].irq = -1;
+	card->pdev = pcidev;
+	card->have_ac97 = -1;
+	
+	/* turn off legacy features, if not already */
+	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+	tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+		  VIA_CR42_FM_ENABLE);
+	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
 
-	/* turn on features, if not already */
+	/* 
+	 * try to init AC97 mixer device
+	 */
+	rc = via_attach_ac97 (card);
+	if (rc) {
+		printk (KERN_WARNING PFX
+			"AC97 init failed, SB legacy mode only\n");
+	}
+	
+	/* turn on legacy features */
 	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
 	tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
 		VIA_CR42_FM_ENABLE;
@@ -105,34 +559,10 @@
 	pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
 	pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
 	
-	switch ((tmp8 >> 6) & 0x03) {
-		case 0: sb_irq = 5; break;
-		case 1: sb_irq = 7; break;
-		case 2: sb_irq = 9; break;
-		case 3: sb_irq = 10; break;
-		default: /* do nothing */ break;
-	}
-	switch ((tmp8 >> 4) & 0x03) {
-		case 0: sb_dma = 0; break;
-		case 1: sb_dma = 1; break;
-		case 2: sb_dma = 2; break;
-		case 3: sb_dma = 3; break;
-		default: /* do nothing */ break;
-	}
-	switch ((tmp8 >> 2) & 0x03) {
-		case 0: midi_base = 0x300; break;
-		case 1: midi_base = 0x310; break;
-		case 2: midi_base = 0x320; break;
-		case 3: midi_base = 0x330; break;
-		default: /* do nothing */ break;
-	}
-	switch (tmp8 & 0x03) {
-		case 0: sb_io_base = 0x220; break;
-		case 1: sb_io_base = 0x240; break;
-		case 2: sb_io_base = 0x260; break;
-		case 3: sb_io_base = 0x280; break;
-		default: /* do nothing */ break;
-	}
+	sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
+	sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
+	midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
+	sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
 
 	udelay(100);
 	
@@ -140,33 +570,38 @@
 	       "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
 		midi_base, sb_io_base, sb_irq, sb_dma);
 		
-	sb_data[cards].card_subtype = MDL_SBPRO;
-	sb_data[cards].io_base = sb_io_base;
-	sb_data[cards].irq = sb_irq;
-	sb_data[cards].dma = sb_dma;
-	
-	opl3_data[cards].io_base = midi_base;
+	card->sb_data.name = VIA_CARD_NAME;
+	card->sb_data.card_subtype = MDL_SBPRO;
+	card->sb_data.io_base = sb_io_base;
+	card->sb_data.irq = sb_irq;
+	card->sb_data.dma = sb_dma;
 	
 	/* register legacy SoundBlaster Pro */
-	if (!via_probe_sb (&sb_data[cards])) {
+	if (!via_probe_sb (&card->sb_data)) {
 		printk (KERN_ERR PFX
 			"SB probe @ 0x%X failed, aborting\n",
 			sb_io_base);
+		DPRINTK ("EXIT, returning -1\n");
 		return -1;
 	}
-	via_attach_sb (&sb_data[cards]);
+	via_attach_sb (&card->sb_data);
 
+	card->opl3_data.name = card->sb_data.name;
+	card->opl3_data.io_base = midi_base;
+	card->opl3_data.irq = -1;
+	
 	/* register legacy MIDI */
-	if (!via_probe_midi (&opl3_data[cards])) {
-		printk (KERN_ERR PFX
-			"MIDI probe @ 0x%X failed, aborting\n",
+	if (!probe_uart401 (&card->opl3_data)) {
+		printk (KERN_WARNING PFX
+			"MIDI probe @ 0x%X failed, continuing\n",
 			midi_base);
-		via_unload_sb (&sb_data[cards], 0);
-		return -1;
+		card->opl3_data.io_base = 0;
+	} else {
+		attach_uart401 (&card->opl3_data);
 	}
-	via_attach_midi (&opl3_data[cards]);
 
-	cards++;	
+	num_cards++;	
+	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 }
 
@@ -174,27 +609,28 @@
 /*
  * 	This loop walks the PCI configuration database and finds where
  *	the sound cards are.
+ *
+ *	Note - only a single PCI scan occurs, eliminating possibility
+ *	of multiple audio chips
+ *
  */
  
 static int __init probe_via82cxxx (void)
 {
 	struct pci_dev *pcidev = NULL;
 
-	while ((pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
-					  PCI_DEVICE_ID_VIA_82C686_5,
-					  pcidev)) != NULL) {
-
-		  if (via82cxxx_install (pcidev) != 0) {
-			  printk (KERN_ERR PFX "audio init failed\n");
-			  return -1;
-		  }
-
-		  if (cards == MAX_CARDS) {
-		  	  printk (KERN_DEBUG PFX "maximum number of cards reached\n");
-			  break;
-		  }
+	DPRINTK ("ENTER\n");
+
+	pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
+				  PCI_DEVICE_ID_VIA_82C686_5, NULL);
+
+	if (!pcidev || via82cxxx_install (pcidev) != 0) {
+		printk (KERN_ERR PFX "audio init failed\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
 	}
 
+	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 }
 
@@ -207,28 +643,49 @@
 
 static int __init init_via82cxxx_module(void)
 {
+	u8 tmp;
+	int i;
+	const char *rev = "unknown!";
+	
+	memset (cards, 0, sizeof (cards));
+	
+	DPRINTK ("ENTER\n");
+
 	if (!pci_present ()) {
 		printk (KERN_DEBUG PFX "PCI not present, exiting\n");
+		DPRINTK ("EXIT, returning -ENODEV\n");
 		return -ENODEV;
 	}
 
 	if (probe_via82cxxx() != 0) {
 		printk(KERN_ERR PFX "probe failed, aborting\n");
 		/* XXX unload cards registered so far, if any */
+		DPRINTK ("EXIT, returning -ENODEV\n");
 		return -ENODEV;
 	}
 
-	if (cards == 0) {
-		printk(KERN_DEBUG PFX "No chips found, aborting\n");
-		return -ENODEV;
-	}
-
+	pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
+	for (i = 0; i < arraysize(via_chip_revs); i++)
+		if (via_chip_revs[i].revision == tmp) {
+			rev = via_chip_revs[i].rev_name;
+			break;
+		}
 	printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
+	printk (KERN_INFO PFX "Chip rev %s.  Features: SBPro compat%s%s\n",
+		rev,
+		cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
+		cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
 	
+	if (via_init_proc () != 0) {
+		printk (KERN_WARNING PFX
+			"Unable to init experimental /proc, ignoring\n");
+	}
+
 	/*
 	 *	Binds us to the sound subsystem	
 	 */
 	SOUND_LOCK;
+	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 }
 
@@ -240,15 +697,23 @@
  
 static void __exit cleanup_via82cxxx_module(void)
 {
-	int i;
+	DPRINTK("ENTER\n");
+	
+	if (cards[0].opl3_data.io_base)
+		unload_uart401 (&cards[0].opl3_data);
+
+	via_unload_sb (&cards[0].sb_data);
 	
-	for (i = 0; i < cards; i++)
-		via_unload_sb (&sb_data[i], 1);
+	via_unload_ac97 (&cards[0]);
 
+	via_cleanup_proc ();
+	
 	/*
 	 *	Final clean up with the sound layer
 	 */
 	SOUND_LOCK_END;
+
+	DPRINTK("EXIT\n");
 }
 
 module_init(init_via82cxxx_module);
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c
--- v2.3.37/linux/drivers/sound/vwsnd.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/vwsnd.c	Fri Jan  7 11:43:09 2000
@@ -3041,8 +3041,6 @@
 	&vwsnd_audio_release,
 	NULL,				/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL,				/* lock */
 };
 
@@ -3252,8 +3250,6 @@
 	&vwsnd_mixer_release,
 	NULL,				/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL,				/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.3.37/linux/drivers/sound/wavfront.c	Mon Jul  5 19:58:25 1999
+++ linux/drivers/sound/wavfront.c	Fri Jan  7 11:43:09 2000
@@ -2014,8 +2014,6 @@
 	&wavefront_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- v2.3.37/linux/drivers/telephony/ixj.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/telephony/ixj.c	Fri Jan  7 11:43:09 2000
@@ -3935,8 +3935,6 @@
 	ixj_release,
 	NULL,			/* ixj_fsync */
 	ixj_fasync,		/* ixj_fasync */
-	NULL,			/* media change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.37/linux/drivers/usb/Config.in	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/Config.in	Fri Jan  7 16:57:13 2000
@@ -6,12 +6,10 @@
 
 tristate 'Support for USB' CONFIG_USB
 if [ ! "$CONFIG_USB" = "n" ]; then
-comment 'USB Controllers'
-   dep_tristate '  UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI \
-	$CONFIG_USB
 
-   dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, and others) support' \
-		CONFIG_USB_OHCI_HCD $CONFIG_USB
+comment 'USB Controllers'
+   dep_tristate '  UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI $CONFIG_USB
+   dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, and others) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
 
 comment 'Miscellaneous USB options'
    if [ "$CONFIG_PROC_FS" != "n" ]; then
@@ -19,24 +17,6 @@
    fi
 
 comment 'USB Devices'
-   dep_tristate '  USB Human Interface Device (HID) support' CONFIG_USB_HID $CONFIG_USB
-   if [ "$CONFIG_USB_HID" != "y" ]; then
-      dep_tristate '  USB HIDBP Keyboard support' CONFIG_USB_KBD $CONFIG_USB
-      dep_tristate '  USB HIDBP Mouse support' CONFIG_USB_MOUSE $CONFIG_USB
-   fi
-   if [ "$CONFIG_USB_HID" != "n" ]; then
-      dep_tristate '    Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB_HID
-      dep_tristate '    Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB_HID
-      if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
-	 bool '      Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX $CONFIG_USB_HID
-      fi
-      dep_tristate '    Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB_HID
-      dep_tristate '    Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB_HID
-      bool '    USB HID debug output' CONFIG_USB_HID_DEBUG
-      if [ "$CONFIG_USB_HID_DEBUG" != "n" ]; then
-	 bool '      USB HID lots of debug output' CONFIG_USB_HID_DEBUG_LOTS
-      fi
-   fi
    dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
    dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
    dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
@@ -52,6 +32,20 @@
    dep_tristate '  EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
    dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB 
+
+comment 'USB HID'
+   dep_tristate '  USB Human Interface Device (HID) support' CONFIG_USB_HID $CONFIG_USB
+   if [ "$CONFIG_USB_HID" != "y" ]; then
+      dep_tristate '  USB HIDBP Keyboard support' CONFIG_USB_KBD $CONFIG_USB
+      dep_tristate '  USB HIDBP Mouse support' CONFIG_USB_MOUSE $CONFIG_USB
+   fi
+   dep_tristate '  Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB
+   dep_tristate '  Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB
+   if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
+      bool '      Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX
+   fi
+   dep_tristate '  Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB
+   dep_tristate '  Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.37/linux/drivers/usb/Makefile	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/Makefile	Fri Jan  7 16:57:13 2000
@@ -2,233 +2,114 @@
 # Makefile for the kernel USB device drivers.
 #
 
-SUB_DIRS     :=
-MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS)
-
-L_TARGET := usb.a
-MOD_LIST_NAME := USB_MODULES
-
-ifeq ($(CONFIG_USB),y)
-  L_OBJS += usb-debug.o usb-core.o hub.o
-  LX_OBJS += usb.o
-  ifeq ($(CONFIG_USB_PROC),y)
-    L_OBJS += proc_usb.o
-  endif
-endif
-ifeq ($(CONFIG_USB),m)
-  M_OBJS += usbcore.o
-  MI_OBJS += usb-debug.o usb-core.o hub.o
-  MIX_OBJS += usb.o
-  ifeq ($(CONFIG_USB_PROC),y)
-    MI_OBJS += proc_usb.o
-  endif
-endif
-
-ifeq ($(CONFIG_USB_UHCI),y)
-    L_OBJS += uhci.o uhci-debug.o
-endif
-
-ifeq ($(CONFIG_USB_UHCI),m)
-      M_OBJS += usb-uhci.o
-      MI_OBJS += uhci.o uhci-debug.o
-endif
-
-ifeq ($(CONFIG_USB_OHCI_HCD),y)
-    L_OBJS += ohci-hcd.o
-endif
-ifeq ($(CONFIG_USB_OHCI_HCD),m)
-      M_OBJS += usb-ohci-hcd.o
-      MI_OBJS += ohci-hcd.o
-endif
-
-ifeq ($(CONFIG_USB_SCANNER),y)
-  L_OBJS += scanner.o
-endif
-ifeq ($(CONFIG_USB_SCANNER),m)
-  M_OBJS  +=scanner.o
-endif
-
-ifeq ($(CONFIG_USB_ACM),y)
-  L_OBJS += acm.o
-endif
-ifeq ($(CONFIG_USB_ACM),m)
-  M_OBJS += acm.o
-endif
-
-ifeq ($(CONFIG_USB_PRINTER),y)
-  L_OBJS += printer.o
-endif
-
-ifeq ($(CONFIG_USB_PRINTER),m)
-  M_OBJS += printer.o
-endif
-
-ifeq ($(CONFIG_USB_SERIAL),y)
-  L_OBJS += usb-serial.o
-endif
-
-ifeq ($(CONFIG_USB_SERIAL),m)
-  M_OBJS += usb-serial.o
-endif
-
-ifeq ($(CONFIG_USB_AUDIO),y)
-  L_OBJS += audio.o
-endif
-
-ifeq ($(CONFIG_USB_AUDIO),m)
-  M_OBJS += audio.o
-endif
-
-ifeq ($(CONFIG_USB_CPIA),y)
-  L_OBJS += cpia.o
-endif
-
-ifeq ($(CONFIG_USB_CPIA),m)
-  M_OBJS += cpia.o
-endif
-
-ifeq ($(CONFIG_USB_OV511),y)
-  L_OBJS += ov511.o
-endif
-
-ifeq ($(CONFIG_USB_OV511),m)
-  M_OBJS += ov511.o
-endif
-
-ifeq ($(CONFIG_USB_DC2XX),y)
-  L_OBJS += dc2xx.o
-endif
-ifeq ($(CONFIG_USB_DC2XX),m)
-  M_OBJS += dc2xx.o
-endif
+# Subdirs.
 
-ifeq ($(CONFIG_USB_SCSI),y)
-  L_OBJS += usb_scsi.o
-  ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
-    L_OBJS += usb_scsi_debug.o
-  endif
-endif
-
-ifeq ($(CONFIG_USB_SCSI),m)
-  M_OBJS += usb-scsi.o
-  MI_OBJS += usb_scsi.o
-  ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
-    MI_OBJS += usb_scsi_debug.o
-  endif
-endif
-
-ifeq ($(CONFIG_USB_EZUSB),y)
-  L_OBJS += ezusb.o
-endif
-
-ifeq ($(CONFIG_USB_EZUSB),m)
-  M_OBJS += ezusb.o
-endif
-
-ifeq ($(CONFIG_USB_HID),y)
-  L_OBJS += hid.o
-  ILX_OBJS := input.o
-endif
-
-ifeq ($(CONFIG_USB_HID),m)
-  M_OBJS += hid.o
-  IMX_OBJS := input.o
-endif
-
-ifeq ($(CONFIG_USB_KBD),y)
-  L_OBJS += usbkbd.o
-  ILX_OBJS := input.o
-endif
-
-ifeq ($(CONFIG_USB_KBD),m)
-  M_OBJS += usbkbd.o
-  IMX_OBJS := input.o
-endif
-
-ifeq ($(CONFIG_USB_MOUSE),y)
-  L_OBJS += usbmouse.o
-  ILX_OBJS := input.o
-endif
-
-ifeq ($(CONFIG_USB_MOUSE),m)
-  M_OBJS += usbmouse.o
-  IMX_OBJS := input.o
-endif
+SUB_DIRS	:=
+MOD_SUB_DIRS	:= $(SUB_DIRS)
+ALL_SUB_DIRS	:= $(SUB_DIRS)
 
-LX_OBJS += $(ILX_OBJS)
-MX_OBJS += $(IMX_OBJS)
+# The target object and module list name.
 
-ifeq ($(CONFIG_INPUT_KEYBDEV),y)
-  L_OBJS += keybdev.o
-endif
+O_TARGET	:= usbdrv.o
+M_OBJS		:=
+O_OBJS		:=
+MOD_LIST_NAME	:= USB_MODULES
 
-ifeq ($(CONFIG_INPUT_KEYBDEV),m)
-  M_OBJS += keybdev.o
-endif
+# Objects that export symbols.
 
-ifeq ($(CONFIG_INPUT_MOUSEDEV),y)
-  L_OBJS += mousedev.o
-endif
-
-ifeq ($(CONFIG_INPUT_MOUSEDEV),m)
-  M_OBJS += mousedev.o
-endif
+export-objs		:= usb.o input.o
 
-ifeq ($(CONFIG_INPUT_JOYDEV),y)
-  L_OBJS += joydev.o
-endif
+# Multipart objects.
 
-ifeq ($(CONFIG_INPUT_JOYDEV),m)
-  M_OBJS += joydev.o
-endif
+list-multi		:= usbcore.o usb-uhci.o usb-ohci-hcd.o
+usbcore-objs		:= usb.o usb-debug.o usb-core.o hub.o
+usb-uhci-objs		:= uhci.o uhci-debug.o
+usb-ohci-hcd-objs	:= ohci-hcd.o
+usb-scsi-objs		:= usb_scsi.o
 
-ifeq ($(CONFIG_INPUT_EVDEV),y)
-  L_OBJS += evdev.o
-endif
+# Optional parts of multipart objects.
 
-ifeq ($(CONFIG_INPUT_EVDEV),m)
-  M_OBJS += evdev.o
+ifeq ($(CONFIG_USB_PROC),y)
+	usbcore-objs	+= proc_usb.o
 endif
-
-ifeq ($(CONFIG_USB_USS720),y)
-  L_OBJS += uss720.o
+ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
+	usb-scsi-objs	+= usb_scsi_debug.o
 endif
 
-ifeq ($(CONFIG_USB_USS720),m)
-  M_OBJS += uss720.o
-endif
+# Object file lists.
 
-ifeq ($(CONFIG_USB_DABUSB),y)
-  L_OBJS += dabusb.o
-endif
+obj-y	:=
+obj-m	:=
+obj-n	:=
+obj-	:=
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_USB)		+= usbcore.o
+obj-$(CONFIG_USB_UHCI)		+= usb-uhci.o
+obj-$(CONFIG_USB_OHCI_HCD)	+= usb-ohci-hcd.o
+
+obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o input.o
+obj-$(CONFIG_USB_HID)		+= hid.o input.o
+obj-$(CONFIG_USB_KBD)		+= usbkbd.o input.o
+obj-$(CONFIG_INPUT_KEYBDEV)	+= keybdev.o input.o
+obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o input.o
+obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o input.o
+obj-$(CONFIG_INPUT_EVDEV)	+= evdev.o input.o
+
+obj-$(CONFIG_USB_SCANNER)	+= scanner.o
+obj-$(CONFIG_USB_ACM)		+= acm.o
+obj-$(CONFIG_USB_PRINTER)	+= printer.o
+obj-$(CONFIG_USB_SERIAL)	+= usb-serial.o
+obj-$(CONFIG_USB_AUDIO)		+= audio.o
+obj-$(CONFIG_USB_CPIA)		+= cpia.o
+obj-$(CONFIG_USB_DC2XX)		+= dc2xx.o
+obj-$(CONFIG_USB_SCSI)		+= usb-scsi.o
+obj-$(CONFIG_USB_EZUSB)		+= ezusb.o
+obj-$(CONFIG_USB_USS720)	+= uss720.o
+obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
+obj-$(CONFIG_USB_OV511)		+= ov511.o
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+
+multi-y		:= $(filter $(list-multi), $(obj-y))
+multi-m		:= $(filter $(list-multi), $(obj-m))
+int-y		:= $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m		:= $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m		:= $(filter-out $(obj-y), $(obj-m))
+int-m		:= $(filter-out $(int-y), $(int-m))
+
+# Take multi-part drivers out of obj-y and put components in.
+
+obj-y		:= $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+
+O_OBJS		:= $(filter-out $(export-objs), $(obj-y))
+OX_OBJS		:= $(filter     $(export-objs), $(obj-y))
+M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
+MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
+MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
 
-ifeq ($(CONFIG_USB_DABUSB),m)
-  M_OBJS += dabusb.o
-endif
+# The global Rules.make.
 
 include $(TOPDIR)/Rules.make
 
-ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
-usb-scsi.o: usb_scsi.o usb_scsi_debug.o
-	$(LD) $(LD_RFLAG) -r -o $@  usb_scsi.o usb_scsi_debug.o 
-else
-usb-scsi.o: usb_scsi.o
-	$(LD) $(LD_RFLAG) -r -o $@  usb_scsi.o
-endif
+# Link rules for multi-part drivers.
 
-usb-uhci.o: uhci.o uhci-debug.o 
-	$(LD) $(LD_RFLAG) -r -o $@  uhci.o uhci-debug.o 
+usbcore.o: $(usbcore-objs)
+	$(LD) -r -o $@ $(usbcore-objs)
 
-usb-ohci-hcd.o: ohci-hcd.o
-	$(LD) $(LD_RFLAG) -r -o $@ ohci-hcd.o
+usb-uhci.o: $(usb-uhci-objs)
+	$(LD) -r -o $@ $(usb-uhci-objs)
 
-ifeq ($(CONFIG_USB_PROC),y)
-usbcore.o: usb.o usb-debug.o usb-core.o proc_usb.o hub.o
-	$(LD) $(LD_RFLAG) -r -o $@ usb.o usb-debug.o usb-core.o proc_usb.o \
-	hub.o
-else
-usbcore.o: usb.o usb-debug.o usb-core.o hub.o
-	$(LD) $(LD_RFLAG) -r -o $@ usb.o usb-debug.o usb-core.o \
-	hub.o
-endif
+usb-ohci-hcd.o: $(usb-ohci-hcd-objs)
+	$(LD) -r -o $@ $(usb-ohci-hcd-objs)
+
+usb-scsi.o: $(usb-scsi-objs)
+	$(LD) -r -o $@ $(usb-scsi-objs)
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.37/linux/drivers/usb/acm.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/acm.c	Fri Jan  7 16:07:49 2000
@@ -1,5 +1,5 @@
 /*
- * acm.c  Version 0.10
+ * acm.c  Version 0.11
  *
  * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
@@ -11,8 +11,10 @@
  * Sponsored by SuSE
  *
  * ChangeLog:
- *	v0.9  Vojtech Pavlik - thorough cleaning, URBification, almost a rewrite
- *      v0.10 Vojtech Pavlik - some more cleanups
+ *	v0.9  - thorough cleaning, URBification, almost a rewrite
+ *	v0.10 - some more cleanups
+ *	v0.11 - fixed flow control, read error doesn't stop reads
+ *	v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
  */
 
 /*
@@ -43,22 +45,41 @@
 #include <linux/tty_flip.h>
 #include <linux/tty.h>
 #include <linux/module.h>
-#include <linux/config.h>
 
-#include "usb.h"
+#define DEBUG
 
-#ifdef CONFIG_USB_ACM_DEBUG
-#define acm_debug(fmt,arg...)	printk(KERN_DEBUG "acm: " fmt "\n" , ##arg)
-#else
-#define acm_debug(fmt,arg...)	do {} while(0)
-#endif
+#include "usb.h"
 
 /*
  * Major and minor numbers.
  */
 
 #define ACM_TTY_MAJOR		166
-#define ACM_TTY_MINORS		8
+#define ACM_TTY_MINORS		32
+
+/*
+ * Requests.
+ */
+
+#define USB_RT_ACM		(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
+
+#define ACM_REQ_COMMAND		0x00
+#define ACM_REQ_RESPONSE	0x01
+#define ACM_REQ_SET_FEATURE	0x02
+#define ACM_REQ_GET_FEATURE	0x03
+#define ACM_REQ_CLEAR_FEATURE	0x04
+
+#define ACM_REQ_SET_LINE	0x20
+#define ACM_REQ_GET_LINE	0x21
+#define ACM_REQ_SET_CONTROL	0x22
+#define ACM_REQ_SEND_BREAK	0x23
+
+/*
+ * IRQs
+ */
+
+#define ACM_IRQ_NETWORK		0x00
+#define ACM_IRQ_LINE_STATE	0x20
 
 /*
  * Output control lines.
@@ -99,46 +120,37 @@
 	struct usb_device *dev;				/* the coresponding usb device */
 	struct usb_config_descriptor *cfg;		/* configuration number on this device */
 	struct tty_struct *tty;				/* the coresponding tty */
+	unsigned int ctrlif;				/* interface number for acm control messages */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
 	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
 	struct acm_coding linecoding;			/* line coding (bits, stop, parity) */
 	unsigned int writesize;				/* max packet size for the output bulk endpoint */
 	struct urb ctrlurb, readurb, writeurb;		/* urbs */
-	unsigned char present;				/* this device is connected to the usb bus */
-	unsigned char used;				/* someone has this acm's device open */
+	unsigned int minor;				/* acm minor number */
+	unsigned int present;				/* this device is connected to the usb bus */
+	unsigned int used;				/* someone has this acm's device open */
 };
 
 static struct usb_driver acm_driver;
-static struct acm acm_table[ACM_TTY_MINORS];
+static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, NULL, NULL, /* .... */ };
 
-#define ACM_READY(acm)	(acm->present && acm->used)
+#define ACM_READY(acm)	(acm && acm->present && acm->used)
 
 /*
  * Functions for ACM control messages.
  */
 
-static void acm_set_control(unsigned int status, struct acm *acm)
+static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
 {
-	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x22, 0x22, status, 0, NULL, 0, HZ) < 0)
-		acm_debug("acm_set_control() failed");
-
-	acm_debug("output control lines: dtr%c rts%c",
-		acm->ctrlout & ACM_CTRL_DTR ? '+' : '-', acm->ctrlout & ACM_CTRL_RTS ? '+' : '-');
+	int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
+		request, USB_RT_ACM, value, acm->ctrlif, buf, len, HZ * 5);
+	dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
+	return retval < 0 ? retval : 0;
 }
 
-#if 0
-static void acm_set_coding(struct acm_coding *coding, struct acm *acm)
-{
-	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x22, 0, 0, coding, sizeof(struct acm_coding), HZ) < 0)
-		acm_debug("acm_set_coding() failed");
-}
-
-static void acm_send_break(int ms, struct acm *acm)
-{
-	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x33, ms, 0, NULL, 0, HZ) < 0)
-		acm_debug("acm_send_break() failed");
-}
-#endif
+#define	acm_set_control(acm, control)	acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
+#define acm_set_coding(acm, coding) 	acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, coding, sizeof(struct acm_coding))
+#define acm_send_break(acm, ms)		acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
 
 /*
  * Interrupt handler for various ACM control events
@@ -150,25 +162,25 @@
 	devrequest *dr = urb->transfer_buffer;
 	unsigned char *data = (unsigned char *)(dr + 1);
 
+	if (!ACM_READY(acm)) return;
+
 	if (urb->status < 0) {
-		acm_debug("nonzero ctrl irq status received: %d", urb->status);
+		dbg("nonzero ctrl irq status received: %d", urb->status);
 		return;
 	}
 
-	if (!ACM_READY(acm)) return;
-
 	switch (dr->request) {
 
-		case 0x20: /* Set serial line state */
+		case ACM_IRQ_NETWORK:
+	
+			dbg("%s network", data[0] ? "connected to" : "disconnected from");
+			return;
 
-			if ((dr->index != 1) || (dr->length != 2)) {
-				acm_debug("unknown set serial line request: index %d len %d", dr->index, dr->length);
-				return;
-			}
+		case ACM_IRQ_LINE_STATE:
 
 			acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8);
 
-			acm_debug("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
+			dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
 				acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',	acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
 				acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',	acm->ctrlin & ACM_CTRL_RI  ? '+' : '-',
 				acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',	acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
@@ -177,7 +189,7 @@
 			return;
 
 		default:
-			acm_debug("unknown control event received: request %d index %d len %d data0 %d data1 %d",
+			dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
 				dr->request, dr->index, dr->length, data[0], data[1]);
 			return;
 	}
@@ -192,20 +204,20 @@
 	unsigned char *data = urb->transfer_buffer;
 	int i;
 
-	if (urb->status) {
-		acm_debug("nonzero read bulk status received: %d", urb->status);
-		return;
-	}
-
 	if (!ACM_READY(acm)) return;
 
-	for (i = 0; i < urb->actual_length; i++)
-		tty_insert_flip_char(tty, data[i], 0);
+	if (!urb->status)  {
 
-	tty_flip_buffer_push(tty);
+		for (i = 0; i < urb->actual_length; i++)
+			tty_insert_flip_char(tty, data[i], 0);
+
+		tty_flip_buffer_push(tty);
+
+	} else
+		dbg("nonzero read bulk status received: %d", urb->status);
 
 	if (usb_submit_urb(urb))
-		acm_debug("failed resubmitting read urb");
+		dbg("failed resubmitting read urb");
 
 	return;
 }
@@ -215,13 +227,11 @@
 	struct acm *acm = (struct acm *)urb->context;
 	struct tty_struct *tty = acm->tty;
 
-	if (urb->status) {
-		acm_debug("nonzero write bulk status received: %d", urb->status);
-		return;
-	}
-
 	if (!ACM_READY(acm)) return;
 
+	if (urb->status)
+		dbg("nonzero write bulk status received: %d", urb->status);
+
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
 
@@ -236,24 +246,24 @@
 
 static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 {
-	struct acm *acm = &acm_table[MINOR(tty->device)];
+	struct acm *acm = acm_table[MINOR(tty->device)];
+
+	if (!acm || !acm->present) return -EINVAL;
 
 	tty->driver_data = acm;
 	acm->tty = tty;
 
-	if (!acm->present) return -EINVAL;
-
 	MOD_INC_USE_COUNT;
 
 	if (acm->used++) return 0;
 
 	if (usb_submit_urb(&acm->ctrlurb))
-		acm_debug("usb_submit_urb(ctrl irq) failed");
+		dbg("usb_submit_urb(ctrl irq) failed");
 
 	if (usb_submit_urb(&acm->readurb))
-		acm_debug("usb_submit_urb(read bulk) failed");
+		dbg("usb_submit_urb(read bulk) failed");
 
-	acm_set_control(acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS, acm);
+	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
 
 	return 0;
 }
@@ -262,18 +272,22 @@
 {
 	struct acm *acm = tty->driver_data;
 
-	if (!acm->used) return;
+	if (!acm || !acm->used) return;
 
 	MOD_DEC_USE_COUNT;
 
 	if (--acm->used) return;
 	
 	if (acm->present) {
-		acm_set_control(acm->ctrlout = 0, acm);
+		acm_set_control(acm, acm->ctrlout = 0);
 		usb_unlink_urb(&acm->ctrlurb);
 		usb_unlink_urb(&acm->writeurb);
 		usb_unlink_urb(&acm->readurb);
+		return;
 	}
+
+	acm_table[acm->minor] = NULL;
+	kfree(acm);
 }
 
 static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
@@ -293,7 +307,7 @@
 	acm->writeurb.transfer_buffer_length = count;
 
 	if (usb_submit_urb(&acm->writeurb))
-		acm_debug("usb_submit_urb(write bulk) failed");
+		dbg("usb_submit_urb(write bulk) failed");
 
 	return count;
 }
@@ -309,29 +323,72 @@
 {
 	struct acm *acm = tty->driver_data;
 	if (!ACM_READY(acm)) return -EINVAL;
-	return acm->writeurb.status == -EINPROGRESS ? acm->writesize : 0;
+	return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
 }
 
 static void acm_tty_throttle(struct tty_struct *tty)
 {
 	struct acm *acm = tty->driver_data;
 	if (!ACM_READY(acm)) return;
-	if (tty->termios->c_cflag & CRTSCTS)
-		acm_set_control(acm->ctrlout &= ~ACM_CTRL_RTS, acm);
+	usb_unlink_urb(&acm->readurb);	
 }
 
 static void acm_tty_unthrottle(struct tty_struct *tty)
 {
 	struct acm *acm = tty->driver_data;
 	if (!ACM_READY(acm)) return;
-	if (tty->termios->c_cflag & CRTSCTS)
-		acm_set_control(acm->ctrlout |= ACM_CTRL_RTS, acm);
+	if (usb_submit_urb(&acm->readurb))
+		dbg("usb_submit_urb(read bulk) in unthrottle() failed");
 }
 
-static void acm_tty_set_termios(struct tty_struct *tty, struct termios *old)
+static void acm_tty_break_ctl(struct tty_struct *tty, int state)
 {
-	acm_debug("set_termios called, but not there yet");
-	return;
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
+	if (acm_send_break(acm, state ? 0xffff : 0))
+		dbg("send break failed");
+}
+
+static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct acm *acm = tty->driver_data;
+	unsigned int retval, ctrl, old;
+
+	if (!ACM_READY(acm)) return -EINVAL;
+
+	switch (cmd) {
+
+		case TIOCMGET:
+
+			return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
+				(acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
+				(acm->ctrlin  & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
+				(acm->ctrlin  & ACM_CTRL_RI  ? TIOCM_RI  : 0) |
+				(acm->ctrlin  & ACM_CTRL_DCD ? TIOCM_CD  : 0) |
+				 TIOCM_CTS, (unsigned long *) arg);
+
+		case TIOCMSET:
+		case TIOCMBIS:
+		case TIOCMBIC:
+
+			if ((retval = get_user(ctrl, (unsigned long *) arg))) return retval;
+
+			ctrl = (ctrl & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (ctrl & TIOCM_RTS ? ACM_CTRL_RTS : 0);
+			old = acm->ctrlout;
+
+			switch (cmd) {
+				case TIOCMSET: acm->ctrlout  =  ctrl; break;
+				case TIOCMBIS: acm->ctrlout |=  ctrl; break;
+				case TIOCMBIC: acm->ctrlout &= ~ctrl; break;
+			}
+	
+			if (acm->ctrlout == old) return 0; 
+			return acm_set_control(acm, acm->ctrlout);
+	}
+
+	dbg("unknown ioctl %#x", cmd);
+
+	return -ENOIOCTLCMD;
 }
 
 /*
@@ -346,15 +403,18 @@
 	int readsize, ctrlsize, minor, i;
 	unsigned char *buf;
 
-	for (minor = 0; minor < ACM_TTY_MINORS &&
-		(acm_table[minor].present || acm_table[minor].used); minor++);
-	if (acm_table[minor].present || acm_table[minor].used) {
-		acm_debug("no more free acm devices");
+	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+
+	if (acm_table[minor]) {
+		dbg("no more free acm devices");
 		return NULL;
 	}
-	acm = acm_table + minor;
+
+	if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) return NULL;
 	memset(acm, 0, sizeof(struct acm));
 
+	acm_table[minor] = acm;
+	acm->minor = minor;
 	acm->dev = dev;
 
 	if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0
@@ -364,8 +424,8 @@
 
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 
-		acm_debug("probing config %d", i);
 		acm->cfg = dev->config + i;
+		dbg("probing config %d", acm->cfg->bConfigurationValue);
 
 		ifcom = acm->cfg->interface[0].altsetting + 0;
 		if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
@@ -402,8 +462,7 @@
 		readsize = epread->wMaxPacketSize;
 		acm->writesize = epwrite->wMaxPacketSize;
 
-		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL)))
-			return NULL;
+		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) return NULL;
 
 		FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
 			buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
@@ -414,13 +473,19 @@
 		FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
 			buf += readsize , acm->writesize, acm_write_bulk, acm);
 
+		acm->ctrlif = ifcom->bInterfaceNumber;
+	
 		printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
 
+		acm_set_control(acm, acm->ctrlout);
+
+		acm->linecoding.speed = 115200;
+		acm->linecoding.databits = 8;
+		acm_set_coding(acm, &acm->linecoding);
+
 		usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 0, acm);
 		usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 1, acm);
 
-		acm_set_control(acm->ctrlout, acm);
-
 		acm->present = 1;
 
 		return acm;
@@ -433,8 +498,8 @@
 {
 	struct acm *acm = ptr;
 
-	if (!acm->present) {
-		acm_debug("disconnect on nonexisting interface");
+	if (!acm || !acm->present) {
+		dbg("disconnect on nonexisting interface");
 		return;
 	}
 
@@ -448,6 +513,11 @@
 
 	usb_driver_release_interface(&acm_driver, acm->cfg->interface + 0);
 	usb_driver_release_interface(&acm_driver, acm->cfg->interface + 1);
+
+	if (!acm->used) {
+		acm_table[acm->minor] = NULL;
+		kfree(acm);
+	}
 }
 
 /*
@@ -491,10 +561,11 @@
 	close:			acm_tty_close,
 	write:			acm_tty_write,
 	write_room:		acm_tty_write_room,
-	set_termios:		acm_tty_set_termios,
+	ioctl:			acm_tty_ioctl,
 	throttle:		acm_tty_throttle,
 	unthrottle:		acm_tty_unthrottle,
-	chars_in_buffer:	acm_tty_chars_in_buffer
+	chars_in_buffer:	acm_tty_chars_in_buffer,
+	break_ctl:		acm_tty_break_ctl
 };
 
 /*
@@ -513,8 +584,6 @@
 int usb_acm_init(void)
 #endif
 {
-	memset(acm_table, 0, sizeof(struct acm) * ACM_TTY_MINORS);
-
 	acm_tty_driver.init_termios =		tty_std_termios;
 	acm_tty_driver.init_termios.c_cflag =	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 
@@ -528,4 +597,3 @@
 
 	return 0;
 }
-
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.37/linux/drivers/usb/audio.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/usb/audio.c	Fri Jan  7 11:43:09 2000
@@ -1916,8 +1916,6 @@
 	&usb_audio_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
@@ -2529,8 +2527,6 @@
 	&usb_audio_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL,  /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- v2.3.37/linux/drivers/usb/dabusb.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/dabusb.c	Fri Jan  7 11:43:09 2000
@@ -38,6 +38,9 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>
 
+#undef DEBUG
+#undef DEBUG_ALL
+
 #include "usb.h"
 
 #include "dabusb.h"
@@ -80,22 +83,22 @@
 #ifdef DEBUG
 static void dump_urb (purb_t purb)
 {
-	printk ("urb                   :%p\n", purb);
-	printk ("next                  :%p\n", purb->next);
-	printk ("dev                   :%p\n", purb->dev);
-	printk ("pipe                  :%08X\n", purb->pipe);
-	printk ("status                :%d\n", purb->status);
-	printk ("transfer_flags        :%08X\n", purb->transfer_flags);
-	printk ("transfer_buffer       :%p\n", purb->transfer_buffer);
-	printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
-	printk ("actual_length         :%d\n", purb->actual_length);
-	printk ("setup_packet          :%p\n", purb->setup_packet);
-	printk ("start_frame           :%d\n", purb->start_frame);
-	printk ("number_of_packets     :%d\n", purb->number_of_packets);
-	printk ("interval              :%d\n", purb->interval);
-	printk ("error_count           :%d\n", purb->error_count);
-	printk ("context               :%p\n", purb->context);
-	printk ("complete              :%p\n", purb->complete);
+	dbg("urb                   :%p", purb);
+	dbg("next                  :%p", purb->next);
+	dbg("dev                   :%p", purb->dev);
+	dbg("pipe                  :%08X", purb->pipe);
+	dbg("status                :%d", purb->status);
+	dbg("transfer_flags        :%08X", purb->transfer_flags);
+	dbg("transfer_buffer       :%p", purb->transfer_buffer);
+	dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
+	dbg("actual_length         :%d", purb->actual_length);
+	dbg("setup_packet          :%p", purb->setup_packet);
+	dbg("start_frame           :%d", purb->start_frame);
+	dbg("number_of_packets     :%d", purb->number_of_packets);
+	dbg("interval              :%d", purb->interval);
+	dbg("error_count           :%d", purb->error_count);
+	dbg("context               :%p", purb->context);
+	dbg("complete              :%p", purb->complete);
 }
 #endif
 /*-------------------------------------------------------------------*/
@@ -105,9 +108,7 @@
 	struct list_head *p;
 	pbuff_t b;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_cancel_queue\n");
-#endif
+	dbg("dabusb_cancel_queue");
 	spin_lock_irqsave (&s->lock, flags);
 
 	for (p = q->next; p != q; p = p->next) {
@@ -127,9 +128,7 @@
 	struct list_head *p;
 	pbuff_t b;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_free_queue\n");
-#endif
+	dbg("dabusb_free_queue");
 	for (p = q->next; p != q;) {
 		b = list_entry (p, buff_t, buff_list);
 #ifdef DEBUG
@@ -149,9 +148,7 @@
 /*-------------------------------------------------------------------*/
 static int dabusb_free_buffers (pdabusb_t s)
 {
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_free_buffers\n");
-#endif
+	dbg("dabusb_free_buffers");
 	dabusb_free_queue (&s->free_buff_list);
 	dabusb_free_queue (&s->rec_buff_list);
 	s->got_mem = 0;
@@ -168,7 +165,7 @@
 	void *buf = purb->transfer_buffer;
 
 #ifdef DEBUG_ALL
-	printk(KERN_DEBUG MODSTR"dabusb_iso_complete\n");
+	dbg("dabusb_iso_complete");
 #endif
 	if (purb->status != USB_ST_URB_KILLED) {
 		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
@@ -181,15 +178,15 @@
 					dst += len;
 				}
 				else
-					printk (KERN_ERR MODSTR "dabusb_iso_complete: invalid len %d\n", len);
+					err("dabusb_iso_complete: invalid len %d", len);
 			}
 		if (dst != purb->actual_length)
-			printk (KERN_ERR MODSTR "dst!=purb->actual_length:%d!=%d\n", dst, purb->actual_length);
+			err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
 	}
 
 	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
 		s->overruns++;
-		printk (KERN_ERR MODSTR "overrun (%d)\n", s->overruns);
+		err("overrun (%d)", s->overruns);
 	}
 	wake_up (&s->wait);
 }
@@ -205,22 +202,20 @@
 	int i;
 	int len = sizeof (urb_t) + packets * sizeof (iso_packet_descriptor_t);
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d\n",
+	dbg("dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d",
 		len, pipesize, packets, transfer_buffer_length);
-#endif
 
 	while (buffers < (s->total_buffer_size << 10)) {
 		b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
 		if (!b) {
-			printk (KERN_ERR MODSTR "kmalloc(sizeof(buff_t))==NULL\n");
+			err("kmalloc(sizeof(buff_t))==NULL");
 			goto err;
 		}
 		memset (b, sizeof (buff_t), 0);
 		b->s = s;
 		b->purb = (purb_t) kmalloc (len, GFP_KERNEL);
 		if (!b->purb) {
-			printk (KERN_ERR MODSTR "kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL\n");
+			err("kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL");
 			kfree (b);
 			goto err;
 		}
@@ -229,7 +224,7 @@
 		if (!b->purb->transfer_buffer) {
 			kfree (b->purb);
 			kfree (b);
-			printk (KERN_ERR MODSTR "kmalloc(%d)==NULL\n", transfer_buffer_length);
+			err("kmalloc(%d)==NULL", transfer_buffer_length);
 			goto err;
 		}
 
@@ -260,9 +255,7 @@
 /*-------------------------------------------------------------------*/
 static int dabusb_reset_pipe (struct usb_device *usbdev, unsigned int ep)
 {
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_reset_pipe\n");
-#endif
+	dbg("dabusb_reset_pipe");
 	if ((ep & ~0x80) >= 16)
 		return -EINVAL;
 
@@ -285,12 +278,12 @@
 
 	ret = usb_submit_urb (purb);
 	if (ret < 0) {
-		printk (KERN_DEBUG MODSTR "dabusb_bulk: usb_submit_urb returned %d\n", ret);
+		dbg("dabusb_bulk: usb_submit_urb returned %d", ret);
 		return -EINVAL;
 	}
 	interruptible_sleep_on_timeout (&context.wait, HZ);
 	if (purb->status == USB_ST_URB_PENDING) {
-		printk (KERN_ERR MODSTR "dabusb_usb_submit_urb: %p timed out\n", purb);
+		err("dabusb_usb_submit_urb: %p timed out", purb);
 		usb_unlink_urb (purb);
 		dabusb_reset_pipe(purb->dev, purb->pipe);
 		return -ETIMEDOUT;
@@ -303,7 +296,7 @@
 	pbulk_completion_context_t context = purb->context;
 
 #ifdef DEBUG_ALL
-	printk(KERN_DEBUG MODSTR"dabusb_bulk_complete\n");
+	dbg("dabusb_bulk_complete");
 	dump_urb(purb);
 #endif
 	wake_up (&context->wait);
@@ -317,7 +310,7 @@
 	unsigned int pipe;
 
 #ifdef DEBUG_ALL
-	printk(KERN_DEBUG MODSTR"dabusb_bulk\n");
+	dbg("dabusb_bulk");
 #endif
 
 	if (!pb->pipe)
@@ -342,12 +335,12 @@
 	unsigned char *transfer_buffer;
 
 	if (!setup) {
-		printk (KERN_ERR MODSTR "dabusb_writemem: kmalloc(8) failed.\n");
+		err("dabusb_writemem: kmalloc(8) failed.");
 		return -ENOMEM;
 	}
 	transfer_buffer = kmalloc (len, GFP_KERNEL);
 	if (!transfer_buffer) {
-		printk (KERN_ERR MODSTR "dabusb_writemem: kmalloc(%d) failed.\n", len);
+		err("dabusb_writemem: kmalloc(%d) failed.", len);
 		kfree (setup);
 		return -ENOMEM;
 	}
@@ -377,9 +370,7 @@
 /* --------------------------------------------------------------------- */
 static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
 {
-#ifdef DEBUG
-	printk("dabusb_8051_reset: %d\n",reset_bit);
-#endif
+	dbg("dabusb_8051_reset: %d",reset_bit);
 	return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
 }
 /* --------------------------------------------------------------------- */
@@ -388,25 +379,22 @@
 	int ret;
 	PINTEL_HEX_RECORD ptr = firmware;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "Enter dabusb_loadmem (internal)\n");
-#endif
+	dbg("Enter dabusb_loadmem (internal)");
+
 	ret = dabusb_8051_reset (s, 1);
 	while (ptr->Type == 0) {
 #ifdef DEBUG_ALL
-		printk(KERN_ERR MODSTR"dabusb_writemem: %04X %p %d)\n", ptr->Address, ptr->Data, ptr->Length);
+		err("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
 #endif
 		ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
 		if (ret < 0) {
-			printk (KERN_ERR MODSTR "dabusb_writemem failed (%04X %p %d)\n", ptr->Address, ptr->Data, ptr->Length);
+			err("dabusb_writemem failed (%04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
 			break;
 		}
 		ptr++;
 	}
 	ret = dabusb_8051_reset (s, 0);
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_loadmem: exit\n");
-#endif
+	dbg("dabusb_loadmem: exit");
 	return ret;
 }
 /* --------------------------------------------------------------------- */
@@ -418,9 +406,7 @@
 	b->data[2] = 0;
 	b->data[3] = 0;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_fpga_clear\n");
-#endif
+	dbg("dabusb_fpga_clear");
 	return dabusb_bulk (s, b);
 }
 /* --------------------------------------------------------------------- */
@@ -432,9 +418,7 @@
 	b->data[2] = 0;
 	b->data[3] = 0;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_fpga_init\n");
-#endif
+	dbg("dabusb_fpga_init");
 	return dabusb_bulk (s, b);
 }
 /* --------------------------------------------------------------------- */
@@ -445,11 +429,9 @@
 	int ret;
 	unsigned char *buf = bitstream;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "Enter dabusb_fpga_download (internal)\n");
-#endif
+	dbg("Enter dabusb_fpga_download (internal)");
 	if (!b) {
-		printk (KERN_ERR MODSTR "kmalloc(sizeof(bulk_transfer_t))==NULL\n");
+		err("kmalloc(sizeof(bulk_transfer_t))==NULL");
 		return -ENOMEM;
 	}
 
@@ -457,9 +439,7 @@
 	ret = dabusb_fpga_clear (s, b);
 	mdelay (10);
 	blen = buf[73] + (buf[72] << 8);
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "Bitstream len: %i\n", blen);
-#endif
+	dbg("Bitstream len: %i", blen);
 	b->data[0] = 0x2b;
 	b->data[1] = 0;
 	b->data[2] = 0;
@@ -471,7 +451,7 @@
 		memcpy (b->data + 4, buf + 74 + n, 60);
 		ret = dabusb_bulk (s, b);
 		if (ret < 0) {
-			printk (KERN_ERR MODSTR "dabusb_bulk failed.\n");
+			err("dabusb_bulk failed.");
 			break;
 		}
 		mdelay (1);
@@ -480,9 +460,7 @@
 	ret = dabusb_fpga_init (s, b);
 	kfree (b);
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "exit dabusb_fpga_download\n");
-#endif
+	dbg("exit dabusb_fpga_download");
 	return ret;
 }
 
@@ -493,16 +471,12 @@
 
 static int dabusb_stop (pdabusb_t s)
 {
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_stop\n");
-#endif
+	dbg("dabusb_stop");
 
 	s->state = _stopped;
 	dabusb_cancel_queue (s, &s->rec_buff_list);
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "pending_io: %d\n", s->pending_io.counter);
-#endif
+	dbg("pending_io: %d", s->pending_io.counter);
 
 	s->pending_io.counter = 0;
 	return 0;
@@ -511,9 +485,7 @@
 static int dabusb_startrek (pdabusb_t s)
 {
 	if (!s->got_mem && s->state != _started) {
-#ifdef DEBUG
-		printk (KERN_DEBUG MODSTR "dabusb_startrek\n");
-#endif
+		dbg("dabusb_startrek");
 
 		if (dabusb_alloc_buffers (s) < 0)
 			return -ENOMEM;
@@ -529,21 +501,21 @@
 
 		while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
 #ifdef DEBUG_ALL
-			printk("submitting: end:%p s->rec_buff_list:%p\n", s->rec_buff_list.prev, &s->rec_buff_list);
+			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
 #endif
 			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
 
 			ret = usb_submit_urb (end->purb);
 			if (ret) {
-				printk (KERN_ERR MODSTR "usb_submit_urb returned:%d\n", ret);
+				err("usb_submit_urb returned:%d", ret);
 				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-					printk (KERN_ERR MODSTR "startrek: dabusb_add_buf_tail failed");
+					err("startrek: dabusb_add_buf_tail failed");
 			}
 			else
 				atomic_inc (&s->pending_io);
 		}
 #ifdef DEBUG_ALL
-		printk(KERN_DEBUG MODSTR"pending_io: %d\n",s->pending_io.counter);
+		dbg("pending_io: %d",s->pending_io.counter);
 #endif
 	}
 	return 0;
@@ -559,7 +531,7 @@
 	purb_t purb = NULL;
 
 #ifdef DEBUG_ALL
-	printk(KERN_DEBUG MODSTR"dabusb_read\n");
+	dbg("dabusb_read");
 #endif
 
 	if (*ppos)
@@ -575,7 +547,7 @@
 	while (count > 0) {
 		dabusb_startrek (s);
 		if (list_empty (&s->rec_buff_list)) {
-			printk (KERN_ERR MODSTR "error: rec_buf_list is empty\n");
+			err("error: rec_buf_list is empty");
 			goto err;
 		}
 		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
@@ -597,7 +569,7 @@
 				goto err;
 			}
 			if (list_empty (&s->rec_buff_list)) {
-				printk (KERN_ERR MODSTR "error: still no buffer available.\n");
+				err("error: still no buffer available.");
 				goto err;
 			}
 			s->readptr = 0;
@@ -615,11 +587,11 @@
 			cnt = count;
 
 #ifdef DEBUG_ALL
-		printk("copy_to_user:%p %p %d\n",buf, purb->transfer_buffer + s->readptr, cnt);
+		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
 #endif
 
 		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
-			printk (KERN_ERR MODSTR "read: copy_to_user failed\n");
+			err("read: copy_to_user failed");
 			if (!ret)
 				ret = -EFAULT;
 			goto err;
@@ -633,7 +605,7 @@
 		if (s->readptr == purb->actual_length) {
 			// finished, take next buffer
 			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-				printk (KERN_ERR MODSTR "read: dabusb_add_buf_tail failed");
+				err("read: dabusb_add_buf_tail failed");
 			s->readptr = 0;
 		}
 	}
@@ -652,7 +624,7 @@
 	MOD_INC_USE_COUNT;
 	s = &dabusb[devnum - DABUSB_MINOR];
 
-	printk (KERN_DEBUG MODSTR "dabusb_open\n");
+	dbg("dabusb_open");
 	down (&s->mutex);
 
 	while (!s->usbdev || s->opened) {
@@ -674,7 +646,7 @@
 	up (&s->mutex);
 
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-		printk (KERN_ERR "dabusb: set_interface failed\n");
+		err("dabusb: set_interface failed");
 		MOD_DEC_USE_COUNT;
 		return -EINVAL;
 	}
@@ -688,7 +660,7 @@
 {
 	pdabusb_t s = (pdabusb_t) file->private_data;
 
-	printk (KERN_DEBUG MODSTR "dabusb_release\n");
+	dbg("dabusb_release");
 
 	down (&s->mutex);
 	dabusb_stop (s);
@@ -697,7 +669,7 @@
 
 	if (!s->remove_pending) {
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
-			printk (KERN_ERR "dabusb: set_interface failed\n");
+			err("dabusb: set_interface failed");
 	}
 	else
 		wake_up (&s->remove_ok);
@@ -715,7 +687,7 @@
 	int version = DABUSB_VERSION;
 	DECLARE_WAITQUEUE (wait, current);
 
-//        printk(KERN_DEBUG MODSTR"dabusb_ioctl\n");
+//        dbg("dabusb_ioctl");
 
 	if (s->remove_pending)
 		return -EIO;
@@ -778,8 +750,6 @@
 	dabusb_release,
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
@@ -801,10 +771,8 @@
 	int devnum;
 	pdabusb_t s;
 
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d\n",
+	dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
 	  usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-#endif
 
 	/* the 1234:5678 is just a self assigned test ID */
 	if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
@@ -829,7 +797,7 @@
 	s->usbdev = usbdev;
 
 	if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-		printk (KERN_ERR MODSTR "set_configuration failed\n");
+		err("set_configuration failed");
 		goto reject;
 	}
 	if (usbdev->descriptor.idProduct == 0x2131)
@@ -838,11 +806,11 @@
 		dabusb_fpga_download (s, NULL);
 
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
-			printk (KERN_ERR MODSTR "set_interface failed\n");
+			err("set_interface failed");
 			goto reject;
 		}
 	}
-	printk (KERN_DEBUG MODSTR "bound to interface: %d\n", ifnum);
+	dbg("bound to interface: %d", ifnum);
 	up (&s->mutex);
 	MOD_INC_USE_COUNT;
 	return s;
@@ -857,7 +825,7 @@
 {
 	pdabusb_t s = (pdabusb_t) ptr;
 
-	printk (KERN_DEBUG MODSTR "dabusb_disconnect\n");
+	dbg("dabusb_disconnect");
 
 	s->remove_pending = 1;
 	wake_up (&s->wait);
@@ -901,17 +869,13 @@
 	/* register misc device */
 	usb_register (&dabusb_driver);
 
-#ifdef DEBUG
-	printk (KERN_INFO "dabusb_init: driver registered\n");
-#endif
+	dbg("dabusb_init: driver registered");
 	return 0;
 }
 
 void __exit dabusb_cleanup (void)
 {
-#ifdef DEBUG
-	printk (KERN_DEBUG MODSTR "dabusb_cleanup\n");
-#endif
+	dbg("dabusb_cleanup");
 	usb_deregister (&dabusb_driver);
 }
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/dabusb.h linux/drivers/usb/dabusb.h
--- v2.3.37/linux/drivers/usb/dabusb.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/dabusb.h	Thu Jan  6 16:17:18 2000
@@ -14,14 +14,8 @@
 
 #ifdef __KERNEL__
 
-#ifdef MODSTR
-#undef MODSTR
-#endif
-#define MODSTR "dabusb: "
-
 typedef enum { _stopped=0, _started } driver_state_t;
 
-
 typedef struct
 {
 	struct semaphore mutex;
@@ -88,4 +82,4 @@
    BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
 } INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
 
-#endif
\ No newline at end of file
+#endif
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.3.37/linux/drivers/usb/dc2xx.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/usb/dc2xx.c	Fri Jan  7 11:43:09 2000
@@ -57,11 +57,9 @@
 #include <linux/malloc.h>
 #include <linux/module.h>
 
-#include "usb.h"
-
-
-// #define	CAMERA_DEBUG
+#undef DEBUG
 
+#include "usb.h"
 
 /* XXX need to get registered minor number, cdev 10/MINOR */
 /* XXX or: cdev USB_MAJOR(180)/USB_CAMERA_MINOR */
@@ -163,9 +161,8 @@
 			  usb_rcvbulkpipe (camera->dev, camera->inEP),
 			  camera->buf, len, &count, HZ*10);
 
-#ifdef	CAMERA_DEBUG
-		printk ("camera.r (%d) - 0x%x %ld\n", len, result, count);
-#endif
+		dbg("read (%d) - 0x%x %ld", len, result, count);
+
 		if (!result) {
 			if (copy_to_user (buf, camera->buf, count))
 				return -EFAULT;
@@ -175,9 +172,8 @@
 		if (result != USB_ST_TIMEOUT)
 			break;
 		interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
-#ifdef	CAMERA_DEBUG
-		printk ("camera.r (%d) - retry\n", len);
-#endif
+
+		dbg("read (%d) - retry", len);
 	}
 	camera->isActive = 0;
 	return -EIO;
@@ -230,10 +226,10 @@
 			result = usb_bulk_msg (camera->dev,
 				 usb_sndbulkpipe (camera->dev, camera->outEP),
 				 obuf, thistime, &count, HZ*10);
-#ifdef	CAMERA_DEBUG
+
 			if (result)
-				printk ("camera.w USB err - %x\n", result);
-#endif
+				dbg("write USB err - %x", result);
+
 			if (count) {
 				obuf += count;
 				thistime -= count;
@@ -262,9 +258,9 @@
 	}
 done:
 	camera->isActive = 0;
-#ifdef	CAMERA_DEBUG
-	printk ("camera.w %d\n", bytes_written); 
-#endif
+
+	dbg("write %d", bytes_written); 
+
 	return bytes_written;
 }
 
@@ -280,9 +276,8 @@
 		camera->isOpen = 0;
 		return -ENOMEM;
 	}
-#ifdef	CAMERA_DEBUG
-	printk ("camera.open\n"); 
-#endif
+
+	dbg("open"); 
 	
 	/* Keep driver from being unloaded while it's in use */
 	MOD_INC_USE_COUNT;
@@ -300,9 +295,8 @@
 	kfree (camera->buf);
 	camera->isOpen = 0;
 	MOD_DEC_USE_COUNT;
-#ifdef	CAMERA_DEBUG
-	printk ("camera.close\n"); 
-#endif
+
+	dbg("close"); 
 
 	return 0;
 }
@@ -324,8 +318,6 @@
 	camera_release,
 	NULL,		/* async */
 	NULL,		/* fasync */
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
 	NULL,		/* lock */
 };
 
@@ -363,7 +355,7 @@
 	/* these have one config, one interface */
 	if (dev->descriptor.bNumConfigurations != 1
 			|| dev->config[0].bNumInterfaces != 1) {
-		printk (KERN_INFO "Bogus camera config info\n");
+		dbg("Bogus camera config info");
 		return NULL;
 	}
 
@@ -375,16 +367,16 @@
 			|| interface->bInterfaceProtocol != 0
 			|| interface->bNumEndpoints != 2
 			) {
-		printk (KERN_INFO "Bogus camera interface info\n");
+		dbg("Bogus camera interface info");
 		return NULL;
 	}
 
 	/* can only show one camera at a time through /dev ... */
 	if (!camera->dev) {
 		camera->dev = dev;
-		printk(KERN_INFO "USB Camera is connected\n");
+		info("USB Camera is connected");
 	} else {
-		printk(KERN_INFO "Ignoring additional USB Camera\n");
+		info("Ignoring additional USB Camera");
 		return NULL;
 	}
 
@@ -410,14 +402,14 @@
 			|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
 			|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
 			) {
-		printk (KERN_INFO "Bogus camera endpoints\n");
+		dbg("Bogus camera endpoints");
 		camera->dev = NULL;
 		return NULL;
 	}
 
 
 	if (usb_set_configuration (dev, dev->config[0].bConfigurationValue)) {
-		printk (KERN_INFO "Failed usb_set_configuration: camera\n");
+		err("Failed usb_set_configuration");
 		camera->dev = NULL;
 		return NULL;
 	}
@@ -443,7 +435,7 @@
 	camera->info = NULL;
 	camera->dev = NULL;
 
-	printk (KERN_INFO "USB Camera disconnected\n");
+	info("USB Camera disconnected");
 }
 
 static /* const */ struct usb_driver camera_driver = {
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c
--- v2.3.37/linux/drivers/usb/ezusb.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/ezusb.c	Fri Jan  7 11:43:09 2000
@@ -965,8 +965,6 @@
 	ezusb_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
-	NULL,  /* check_media_change */
-	NULL,  /* revalidate */
 	NULL   /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.3.37/linux/drivers/usb/hid.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/hid.c	Fri Jan  7 14:11:21 2000
@@ -39,14 +39,14 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/config.h>
-#include <linux/input.h>
 #include <linux/spinlock.h>
-#include <linux/list.h>
+
+#undef DEBUG
 
 #include "usb.h"
 #include "hid.h"
 
-#ifdef CONFIG_USB_HID_DEBUG_LOTS
+#ifdef DEBUG
 #include "hid-debug.h"
 #else
 #define hid_dump_input(a,b)	do { } while (0)
@@ -57,7 +57,7 @@
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-	 27, 43,192, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
 	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
@@ -128,7 +128,7 @@
 		return field;
 	}
 
-	hid_debug("too many fields in report");
+	dbg("too many fields in report");
 	return NULL;
 }
 
@@ -152,7 +152,7 @@
 		return 0;
 	}
 
-	hid_debug("collection stack overflow");
+	dbg("collection stack overflow");
 	return -1;
 }
 
@@ -166,7 +166,7 @@
 		parser->collection_stack_ptr--;
 		return 0;
 	}
-	hid_debug("collection stack underflow");
+	dbg("collection stack underflow");
 	return -1;
 }
 
@@ -191,7 +191,7 @@
 static int hid_add_usage(struct hid_parser *parser, unsigned usage)
 {
 	if (parser->local.usage_index >= MAX_USAGES) {
-		hid_debug("usage index exceeded");
+		dbg("usage index exceeded");
 		return -1;
 	}
 	parser->local.usage[parser->local.usage_index++] = usage;
@@ -211,13 +211,13 @@
 	int i;
 
 	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
-    		hid_debug("hid_register_report failed");
+    		dbg("hid_register_report failed");
 		return -1;
 	}
 
 	if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */
 		if (parser->global.logical_maximum <= parser->global.logical_minimum) {
-			hid_debug("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+			dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
 			return -1;
 		}
 		usages = parser->local.usage_index;
@@ -287,20 +287,20 @@
 
 			if (parser->global_stack_ptr < HID_GLOBAL_STACK_SIZE) {
 				memcpy(parser->global_stack + parser->global_stack_ptr++,
-					&parser->global, sizeof(struct hid_parser));
+					&parser->global, sizeof(struct hid_global));
 				return 0;
 			}
-			hid_debug("global enviroment stack overflow");
+			dbg("global enviroment stack overflow");
 			return -1;
 
 		case HID_GLOBAL_ITEM_TAG_POP:
 
 			if (parser->global_stack_ptr > 0) {
 				memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
-					sizeof(struct hid_parser));
+					sizeof(struct hid_global));
 				return 0;
 			}
-			hid_debug("global enviroment stack underflow");
+			dbg("global enviroment stack underflow");
 			return -1;
 
 		case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
@@ -333,27 +333,27 @@
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
 			if ((parser->global.report_size = item_udata(item)) > 32) {
-				hid_debug("invalid report_size %d", parser->global.report_size);
+				dbg("invalid report_size %d", parser->global.report_size);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
 			if ((parser->global.report_count = item_udata(item)) > MAX_USAGES) {
-				hid_debug("invalid report_count %d", parser->global.report_count);
+				dbg("invalid report_count %d", parser->global.report_count);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
 			if ((parser->global.report_id = item_udata(item)) == 0) {
-				hid_debug("report_id 0 is invalid");
+				dbg("report_id 0 is invalid");
 				return -1;
 			}
 			return 0;
 
 		default:
-			hid_debug("unknown global tag 0x%x", item->tag);
+			dbg("unknown global tag 0x%x", item->tag);
 			return -1;
 	}
 }
@@ -367,7 +367,7 @@
 	__u32 data;
 
 	if (item->size == 0) {
-		hid_debug("item data expected for local item");
+		dbg("item data expected for local item");
 		return -1;
 	}
 
@@ -385,14 +385,14 @@
 				 * items and the first delimiter set.
 				 */
 				if (parser->local.delimiter_depth != 0) {
-					hid_debug("nested delimiters");
+					dbg("nested delimiters");
 					return -1;
 				}
 				parser->local.delimiter_depth++;
 				parser->local.delimiter_branch++;
 			} else {
 				if (parser->local.delimiter_depth < 1) {
-					hid_debug("bogus close delimiter");
+					dbg("bogus close delimiter");
 					return -1;
 				}
 				parser->local.delimiter_depth--;
@@ -406,7 +406,7 @@
 					data = (parser->global.usage_page << 16) + data;
 				return hid_add_usage(parser, data);
 			}
-			hid_debug("alternative usage ignored");
+			dbg("alternative usage ignored");
 			return 0;
 
 		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
@@ -417,7 +417,7 @@
 				parser->local.usage_minimum = data;
 				return 0;
 			}
-			hid_debug("alternative usage ignored");
+			dbg("alternative usage ignored");
 			return 0;
 
 		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
@@ -428,17 +428,17 @@
 					data = (parser->global.usage_page << 16) + data;
 				for (n = parser->local.usage_minimum; n <= data; n++)
 					if (hid_add_usage(parser, n)) {
-						hid_debug("hid_add_usage failed\n");
+						dbg("hid_add_usage failed\n");
 						return -1;
 					}
 				return 0;
 			}
-			hid_debug("alternative usage ignored");
+			dbg("alternative usage ignored");
 			return 0;
 
 		default:
 
-			hid_debug("unknown local item tag 0x%x", item->tag);
+			dbg("unknown local item tag 0x%x", item->tag);
 			return 0;
 	}
 }
@@ -471,7 +471,7 @@
 			ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
 			break;
 		default:
-			hid_debug("unknown main item tag 0x%x", item->tag);
+			dbg("unknown main item tag 0x%x", item->tag);
 			ret = 0;
 	}
 
@@ -486,7 +486,7 @@
 
 static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
 {
-	hid_debug("reserved item type, tag 0x%x", item->tag);
+	dbg("reserved item type, tag 0x%x", item->tag);
 	return 0;
 }
 
@@ -631,13 +631,13 @@
 	end = start + size;
 	while ((start = fetch_item(start, end, &item)) != 0) {
 		if (item.format != HID_ITEM_FORMAT_SHORT) {
-			hid_debug("unexpected long global item");
+			dbg("unexpected long global item");
 			hid_free_device(device);
 			kfree(parser);
 			return NULL;
 		}
 		if (dispatch_type[item.type](parser, &item)) {
-			hid_debug("item %u %u %u %u parsing failed\n",
+			dbg("item %u %u %u %u parsing failed\n",
 				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
 			hid_free_device(device);
 			kfree(parser);
@@ -646,13 +646,13 @@
 
 		if (start == end) {
 			if (parser->collection_stack_ptr) {
-				hid_debug("unbalanced collection at end of report description");
+				dbg("unbalanced collection at end of report description");
 				hid_free_device(device);
 				kfree(parser);
 				return NULL;
 			}
 			if (parser->local.delimiter_depth) {
-				hid_debug("unbalanced delimiter at end of report description");
+				dbg("unbalanced delimiter at end of report description");
 				hid_free_device(device);
 				kfree(parser);
 				return NULL;
@@ -662,7 +662,7 @@
 		}
 	}
 
-	hid_debug("item fetching failed at offset %d\n", (int)(end - start));
+	dbg("item fetching failed at offset %d\n", (int)(end - start));
 	hid_free_device(device);
 	kfree(parser);
 	return NULL;
@@ -896,17 +896,17 @@
 	int n;
 
 	if (urb->status) {
-		hid_debug("nonzero status in irq %d", urb->status);
+		dbg("nonzero status in irq %d", urb->status);
 		return;
 	}
 
 	if (!len) {
-		hid_debug("empty report");
+		dbg("empty report");
 		return;
 	}
 
-#ifdef CONFIG_USB_HID_DEBUG_LOTS
-	printk(KERN_DEBUG "hid: report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un");
+#ifdef DEBUG
+	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un");
 	for (n = 0; n < len; n++)
 		printk(" %02x", data[n]);
 	printk("\n");
@@ -920,9 +920,9 @@
 	} 
 
 	if (!(report = report_enum->report_id_hash[n])) {
-		hid_debug("undefined report_id %d received", n);
-#ifdef CONFIG_USB_HID_DEBUG
-			printk(KERN_DEBUG "hid: report (size %u) = ", len);
+		dbg("undefined report_id %d received", n);
+#ifdef DEBUG
+			printk(KERN_DEBUG __FILE__ ": report (size %u) = ", len);
 			for (n = 0; n < len; n++)
 				printk(" %02x", data[n]);
 			printk("\n");
@@ -932,7 +932,7 @@
 	}
 
 	if (len < ((report->size - 1) >> 3) + 1) {
-		hid_debug("report %d is too short, (%d < %d)", report->id, len, ((report->size - 1) >> 3) + 1);
+		dbg("report %d is too short, (%d < %d)", report->id, len, ((report->size - 1) >> 3) + 1);
 		return;
 	}
 
@@ -943,6 +943,45 @@
 }
 
 /*
+ * hid_read_report() s intended to read the hid devices values even
+ * before the input device is registered, so that the userland interface
+ * modules start with real values. This is especially important for joydev.c
+ * automagic calibration. Doesn't work yet, though. Don't know why, the control
+ * request just times out on most devices I have and returns nonsense on others.
+ */
+
+static void hid_read_report(struct hid_device *hid, struct hid_report *report)
+{
+#if 0
+	int rlen = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+	char rdata[rlen];
+	struct urb urb;
+	int read;
+
+	memset(&urb, 0, sizeof(struct urb));
+	memset(rdata, 0, rlen);
+
+	urb.transfer_buffer = rdata;
+	urb.actual_length = rlen;
+	urb.context = hid;
+
+	dbg("getting report type %d id %d len %d", report->type + 1, report->id, rlen);
+
+	if ((read = usb_get_report(hid->dev, report->type + 1, report->id, hid->ifnum, rdata, rlen)) != rlen) {
+		dbg("reading report failed rlen %d read %d", rlen, read);
+#ifdef DEBUG
+		printk(KERN_DEBUG __FILE__ ": report = ");
+		for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]);
+		printk("\n");
+#endif
+		continue;
+	}
+
+	hid_irq(&urb);
+#endif
+}
+
+/*
  * Configure the input layer interface
  * Read all reports and initalize the absoulte field values.
  */
@@ -958,8 +997,6 @@
 	while (list != &report_enum->report_list) {
 
 		struct hid_report *report = (struct hid_report *) list;
-		int rlen = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
-		int read;
 
 		list = list->next;
 
@@ -967,33 +1004,7 @@
 			for (j = 0; j < report->field[i]->maxusage; j++)
 				hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
 
-#if 1
-		{
-			char rdata[rlen];
-			struct urb urb;
-
-			memset(&urb, 0, sizeof(struct urb));
-			memset(rdata, 0, rlen);
-
-			urb.transfer_buffer = rdata;
-			urb.actual_length = rlen;
-			urb.context = hid;
-
-			hid_debug("getting report type %d id %d len %d", report->type + 1, report->id, rlen);
-
-			if ((read = usb_get_report(hid->dev, report->type + 1, report->id, hid->ifnum, rdata, rlen)) != rlen) {
-				hid_debug("reading report failed rlen %d read %d", rlen, read);
-#ifdef CONFIG_USB_HID_DEBUG
-				printk(KERN_DEBUG "hid: report = ");
-				for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]);
-				printk("\n");
-#endif
-				continue;
-			}
-
-			hid_irq(&urb);
-		}
-#endif
+		hid_read_report(hid, report);
 	}
 }
 
@@ -1043,18 +1054,18 @@
 	unsigned size = field->report_size;
 	
 	if (offset >= field->report_count) {
-		hid_debug("offset exceeds report_count");
+		dbg("offset exceeds report_count");
 		return -1;
 	}
 	if (field->logical_minimum < 0) {
 		if (value != snto32(s32ton(value, size), size)) {
-			hid_debug("value %d is out of range", value);
+			dbg("value %d is out of range", value);
 			return -1;
 		}
 	}
 	if (   (value > field->logical_maximum)
 	    || (value < field->logical_minimum)) {
-		hid_debug("value %d is invalid", value);
+		dbg("value %d is invalid", value);
 		return -1;
 	}
 	field->value[offset] = value;
@@ -1074,7 +1085,7 @@
 
 	if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc)
 		&& usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc)) {
-			hid_debug("class descriptor not present\n");
+			dbg("class descriptor not present\n");
 			return NULL;
 	}
 
@@ -1083,7 +1094,7 @@
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
 	if (!rsize || rsize > 1024) {
-		hid_debug("weird size of report descriptor (%u)", rsize);
+		dbg("weird size of report descriptor (%u)", rsize);
 		return NULL;
 	}
 
@@ -1091,19 +1102,19 @@
 		__u8 rdesc[rsize];
 
 		if ((n = usb_get_class_descriptor(dev, USB_DT_REPORT, 0, ifnum, rdesc, rsize)) < 0) {
-			hid_debug("reading report descriptor failed");
+			dbg("reading report descriptor failed");
 			return NULL;
 		}
 
-#ifdef CONFIG_USB_HID_DEBUG
-		printk(KERN_DEBUG "hid: report (size %u, read %d) = ", rsize, n);
+#ifdef DEBUG
+		printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n);
 		for (n = 0; n < rsize; n++)
 			printk(" %02x", (unsigned) rdesc[n]);
 		printk("\n");
 #endif
 
 		if (!(hid = hid_parse_report(rdesc, rsize))) {
-			hid_debug("parsing report descriptor failed");
+			dbg("parsing report descriptor failed");
 			return NULL;
 		}
 	}
@@ -1125,7 +1136,7 @@
 		FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval);
 	
 		if (usb_submit_urb(&hid->urb)) {
-			hid_debug("submitting interrupt URB failed");
+			dbg("submitting interrupt URB failed");
 			continue;
 		}
 
@@ -1133,7 +1144,7 @@
 	}
 
 	if (n == interface->bNumEndpoints) {
-		hid_debug("couldn't find an input interrupt endpoint");
+		dbg("couldn't find an input interrupt endpoint");
 		hid_free_device(hid);
 		return NULL;
 	}
@@ -1152,7 +1163,7 @@
 				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
 	struct hid_device *hid;
 
-	hid_debug("HID probe called for ifnum %d", ifnum);
+	dbg("HID probe called for ifnum %d", ifnum);
 
 	if (!(hid = usb_hid_configure(dev, ifnum)))
 		return NULL;
@@ -1173,7 +1184,7 @@
 {
 	struct hid_device *hid = ptr;
 
-	hid_debug("cleanup called");
+	dbg("cleanup called");
 	usb_unlink_urb(&hid->urb);
 	input_unregister_device(&hid->input);
 	hid_free_device(hid);
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.37/linux/drivers/usb/hub.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/usb/hub.c	Fri Jan  7 11:40:24 2000
@@ -13,11 +13,12 @@
 #include <linux/list.h>
 #include <linux/malloc.h>
 #include <linux/smp_lock.h>
-//#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
+#define DEBUG
+
 #include "usb.h"
 #include "hub.h"
 
@@ -47,11 +48,13 @@
 		USB_DT_HUB << 8, 0, data, size, HZ);
 }
 
+#if 0
 static int usb_clear_hub_feature(struct usb_device *dev,  int feature)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
 }
+#endif
 
 static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
 {
@@ -137,48 +140,44 @@
 	descriptor = (struct usb_hub_descriptor *)bitmap;
 
 	hub->nports = dev->maxchild = descriptor->bNbrPorts;
-	printk(KERN_INFO "hub: %d port%s detected\n", hub->nports,
-		(hub->nports == 1) ? "" : "s");
+	info("%d port%s detected", hub->nports, (hub->nports == 1) ? "" : "s");
 
 	switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
 		case 0x00:
-			printk(KERN_INFO "hub: ganged power switching\n");
+			dbg("ganged power switching");
 			break;
 		case 0x01:
-			printk(KERN_INFO "hub: individual port power switching\n");
+			dbg("individual port power switching");
 			break;
 		case 0x02:
 		case 0x03:
-			printk(KERN_INFO "hub: unknown reserved power switching mode\n");
+			dbg("unknown reserved power switching mode");
 			break;
 	}
 
 	if (descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
-		printk(KERN_INFO "hub: part of a compound device\n");
+		dbg("part of a compound device");
 	else
-		printk(KERN_INFO "hub: standalone hub\n");
+		dbg("standalone hub");
 
 	switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
 		case 0x00:
-			printk(KERN_INFO "hub: global over-current protection\n");
+			dbg("global over-current protection");
 			break;
 		case 0x08:
-			printk(KERN_INFO "hub: individual port over-current protection\n");
+			dbg("individual port over-current protection");
 			break;
 		case 0x10:
 		case 0x18:
-			printk(KERN_INFO "hub: no over-current protection\n");
+			dbg("no over-current protection");
                         break;
 	}
 
-	printk(KERN_INFO "hub: power on to power good time: %dms\n",
-		descriptor->bPwrOn2PwrGood * 2);
-
-	printk(KERN_INFO "hub: hub controller current requirement: %dmA\n",
-		descriptor->bHubContrCurrent);
+	dbg("power on to power good time: %dms", descriptor->bPwrOn2PwrGood * 2);
+	dbg("hub controller current requirement: %dmA", descriptor->bHubContrCurrent);
 
 	for (i = 0; i < dev->maxchild; i++)
-		printk(KERN_INFO "hub:  port %d is%s removable\n", i + 1,
+		dbg("port %d is%s removable", i + 1,
 			bitmap[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8))
 			? " not" : "");
 
@@ -188,14 +187,14 @@
 		return -1;
 
 	hubsts = (struct usb_hub_status *)buffer;
-	printk(KERN_INFO "hub: local power source is %s\n",
+	dbg("local power source is %s",
 		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
 
-	printk(KERN_INFO "hub: %sover-current condition exists\n",
+	dbg("%sover-current condition exists",
 		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
 	/* Enable power to the ports */
-	printk(KERN_INFO "hub: enabling power on all ports\n");
+	dbg("enabling power on all ports");
 	for (i = 0; i < hub->nports; i++)
 		usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
 	return 0;
@@ -236,10 +235,10 @@
 		return NULL;
 
 	/* We found a hub */
-	printk(KERN_INFO "USB hub found\n");
+	info("USB hub found");
 
 	if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "couldn't kmalloc hub struct\n");
+		err("couldn't kmalloc hub struct");
 		return NULL;
 	}
 
@@ -260,7 +259,7 @@
 			hub_irq, endpoint->bInterval,
 			hub, &hub->irq_handle);
 		if (ret) {
-			printk (KERN_WARNING "hub: usb_request_irq failed (%d)\n", ret);
+			err("usb_request_irq failed (%d)", ret);
 			/* free hub, but first clean up its list. */
 			spin_lock_irqsave(&hub_event_lock, flags);
 
@@ -317,14 +316,14 @@
 	wait_ms(100);
 	/* Check status */
 	if (usb_get_port_status(hub, port + 1, &portsts)<0) {
-		printk(KERN_ERR "get_port_status failed\n");
+		err("get_port_status failed");
 		return;
 	}
 
 	portstatus = le16_to_cpu(portsts.wPortStatus);
 	portchange = le16_to_cpu(portsts.wPortChange);
-	printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
-	(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+	dbg("portstatus %x, change %x, %s", portstatus, portchange,
+		portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
 	/* If it's not in CONNECT and ENABLE state, we're done */
 	if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
 	    (!(portstatus & USB_PORT_STAT_ENABLE))) {
@@ -345,13 +344,13 @@
 		wait_ms(200);	
 		
 		if (usb_get_port_status(hub, port + 1, &portsts)<0) {
-			printk(KERN_ERR "get_port_status failed\n");
+			err("get_port_status failed");
 			return;
 		}
 		portstatus = le16_to_cpu(portsts.wPortStatus);
 		portchange = le16_to_cpu(portsts.wPortChange);
-		printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
-		(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+		dbg("portstatus %x, change %x, %s", portstatus ,portchange,
+			portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
 
 		if ((portstatus&(1<<USB_PORT_FEAT_ENABLE))) 
 			break;
@@ -360,14 +359,14 @@
 	}
 
 	if (tries==MAX_TRIES) {
-		printk("hub.c: Can not enable port %i after %i retries, disabling port\n",port+1,MAX_TRIES);
+		err("can not enable port %i after %i retries, disabling port", port+1, MAX_TRIES);
 		return;
 	}
 	/* Allocate a new device struct for it */
 
 	usb = usb_alloc_dev(hub, hub->bus);
 	if (!usb) {
-		printk(KERN_ERR "couldn't allocate usb_device\n");
+		err("couldn't allocate usb_device");
 		return;
 	}
 
@@ -381,8 +380,7 @@
 	/* Run it through the hoops (find a driver, etc) */
 	if (usb_new_device(usb)) {
 		/* Woops, disable the port */
-		printk(KERN_DEBUG "hub: disabling port %d\n",
-			port + 1);
+		dbg("hub: disabling port %d", port + 1);
 		usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
 	}
 }
@@ -423,7 +421,7 @@
 			unsigned short portstatus, portchange;
 
 			if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
-				printk(KERN_ERR "get_port_status failed\n");
+				err("get_port_status failed");
 				continue;
 			}
 
@@ -431,35 +429,27 @@
 			portchange = le16_to_cpu(portsts.wPortChange);
 
 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
-				printk(KERN_INFO "hub: port %d connection change\n",
-					i + 1);
+				dbg("port %d connection change", i + 1);
 
-				usb_clear_port_feature(dev, i + 1,
-					USB_PORT_FEAT_C_CONNECTION);
+				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_CONNECTION);
 
 				usb_hub_port_connect_change(dev, i);
 			}
 
 			if (portchange & USB_PORT_STAT_C_ENABLE) {
-				printk(KERN_INFO "hub: port %d enable change\n",
-					i + 1);
-				usb_clear_port_feature(dev, i + 1,
-					USB_PORT_FEAT_C_ENABLE);
+				dbg("port %d enable change", i + 1);
+				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
 			}
 
 			if (portchange & USB_PORT_STAT_C_SUSPEND)
-				printk(KERN_INFO "hub: port %d suspend change\n",
-					i + 1);
+				dbg("port %d suspend change", i + 1);
 
 			if (portchange & USB_PORT_STAT_C_OVERCURRENT)
-				printk(KERN_INFO "hub: port %d over-current change\n",
-					i + 1);
+				dbg("port %d over-current change", i + 1);
 
 			if (portchange & USB_PORT_STAT_C_RESET) {
-				printk(KERN_INFO "hub: port %d reset change\n",
-					i + 1);
-				usb_clear_port_feature(dev, i + 1,
-					USB_PORT_FEAT_C_RESET);
+				dbg("port %d reset change", i + 1);
+				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
 			}
 		} /* end for i */
         } /* end while (1) */
@@ -482,9 +472,7 @@
 	 * This thread doesn't need any user-level access,
 	 * so get rid of all our resources
 	 */
-	exit_mm(current);
-	exit_files(current);
-	exit_fs(current);
+	daemonize();
 
 	/* Setup a nice name */
 	strcpy(current->comm, "khubd");
@@ -499,7 +487,7 @@
 	MOD_DEC_USE_COUNT;
 */
 
-	printk("usb_hub_thread exiting\n");
+	dbg("usb_hub_thread exiting");
 	khubd_running = 0;
 
 	return 0;
@@ -552,7 +540,7 @@
 		}
 
 		if (!count)
-			printk(KERN_ERR "hub: giving up on killing khubd\n");
+			err("giving up on killing khubd");
 	}
 
 	/*
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/joydev.c linux/drivers/usb/joydev.c
--- v2.3.37/linux/drivers/usb/joydev.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/joydev.c	Fri Jan  7 14:11:21 2000
@@ -60,8 +60,8 @@
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
 	int nkey;
-	__u16 keymap[KEY_MAX - BTN_0];
-	__u16 keypam[KEY_MAX - BTN_0];
+	__u16 keymap[KEY_MAX - BTN_MISC];
+	__u16 keypam[KEY_MAX - BTN_MISC];
 	__u8 absmap[ABS_MAX];
 	__u8 abspam[ABS_MAX];
 };
@@ -111,9 +111,9 @@
 	switch (type) {
 
 		case EV_KEY:
-			if (code < BTN_0 || value == 2) return;
+			if (code < BTN_MISC || value == 2) return;
 			event.type = JS_EVENT_BUTTON;
-			event.number = joydev->keymap[code - BTN_0];
+			event.number = joydev->keymap[code - BTN_MISC];
 			event.value = value;
 			break;
 
@@ -407,10 +407,17 @@
 			joydev->nabs++;
 		}
 
-	for (i = 0; i < KEY_MAX - BTN_0; i++)
-		if (test_bit(i + BTN_0, dev->keybit)) {
+	for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
+		if (test_bit(i + BTN_MISC, dev->keybit)) {
 			joydev->keymap[i] = joydev->nkey;
-			joydev->keypam[joydev->nkey] = i + BTN_0;
+			joydev->keypam[joydev->nkey] = i + BTN_MISC;
+			joydev->nkey++;
+		}
+
+	for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
+		if (test_bit(i + BTN_MISC, dev->keybit)) {
+			joydev->keymap[i] = joydev->nkey;
+			joydev->keypam[joydev->nkey] = i + BTN_MISC;
 			joydev->nkey++;
 		}
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c
--- v2.3.37/linux/drivers/usb/keybdev.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/keybdev.c	Fri Jan  7 11:40:24 2000
@@ -39,7 +39,9 @@
 
 static unsigned char keybdev_x86_e0s[] = 
 	{ 0x1c, 0x1d, 0x35, 0x2a, 0x38, 0x39, 0x47, 0x48,
-	  0x49, 0x4b, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53 };
+	  0x49, 0x4b, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53,
+	  0x26, 0x25, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00,
+	  0x23, 0x24, 0x25, 0x26, 0x27 };
 
 #elif CONFIG_MAC_KEYBOARD
 
@@ -49,7 +51,7 @@
 	  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
 	 11, 45, 46, 43, 47, 44,123, 67, 55, 49, 57,122,120, 99,118, 96,
 	 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
-	 84, 85, 82, 65,  0,  0,  0,103,111,  0,  0,  0,  0,  0,  0,  0,
+	 84, 85, 82, 65, 42,  0, 10,103,111,  0,  0,  0,  0,  0,  0,  0,
 	 76,125, 75,  0,124,  0,115, 62,116, 59, 60,119, 61,121,114,117,
 	  0,  0,  0,  0,127, 81,  0,113 };
 
@@ -61,7 +63,13 @@
 
 #ifdef CONFIG_X86
 
-	if (code >= 125) {
+	if (code >= 189) {
+  		printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
+		return; 
+	} else if (code >= 162) {
+		handle_scancode(0xe0, 1);
+		handle_scancode(code - 161, down);
+	} else if (code >= 125) {
 		handle_scancode(0xe0, 1);
 		handle_scancode(code - 34, down);
 	} else if (code == 119) {
@@ -79,8 +87,10 @@
 
 #elif CONFIG_MAC_KEYBOARD
 
-	if (keycode < 128) 
+	if (keycode < 128 && keybdev_mac_codes[code]) 
 		handle_scancode(keybdev_mac_codes[code], down);
+	else
+		printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
 
 #else
 #error "Cannot generate rawmode keyboard for your architecture yet."
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c
--- v2.3.37/linux/drivers/usb/mousedev.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/mousedev.c	Thu Jan  6 16:17:18 2000
@@ -212,10 +212,6 @@
 
 		c = buffer[i];
 
-#ifdef MOUSEDEV_DEBUG
-		printk(KERN_DEBUG "mousedev: received char %#x\n", c);
-#endif
-
 		if (c == mousedev_genius_seq[list->genseq]) {
 			if (++list->genseq == MOUSEDEV_GENIUS_LEN) {
 				list->genseq = 0;
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.37/linux/drivers/usb/ohci-hcd.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/usb/ohci-hcd.c	Fri Jan  7 11:17:45 2000
@@ -39,7 +39,6 @@
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-// #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
 
@@ -47,18 +46,11 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 
-// #define DEBUG
+#undef DEBUG
 
 #include "usb.h"
 #include "ohci-hcd.h"
 
-
-#ifdef DEBUG
-	#define dbg(format, arg...) printk(format, ## arg)
-#else
-	#define dbg(format, arg...)
-#endif
-
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
 static int handle_apm_event (apm_event_t event);
@@ -117,12 +109,11 @@
 	int i, len;
 	
 	if (!urb->dev || !urb->dev->bus) {
-		printk(KERN_DEBUG " %s URB: no dev\n", str);
+		dbg("%s URB: no dev", str);
 		return;
 	}
 	
-	printk (KERN_DEBUG "%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,"
-			"flags:%4x,len:%d/%d,stat:%d(%x)\n", 
+	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", 
 			str,
 		 	sohci_get_current_frame_number (urb->dev), 
 		 	usb_pipedevice (pipe),
@@ -136,13 +127,13 @@
 		 	urb->status, urb->status);
 	if (!small) {
 		if (usb_pipecontrol (pipe)) {
-			printk (KERN_DEBUG " cmd(8):");
+			printk (KERN_DEBUG __FILE__ ": cmd(8):");
 			for (i = 0; i < 8 ; i++) 
 				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
 			printk ("\n");
 		}
 		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
-			printk (KERN_DEBUG " data(%d/%d):", 
+			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
 				urb->actual_length, 
 				urb->transfer_buffer_length);
 			len = usb_pipeout (pipe)? 
@@ -160,10 +151,10 @@
 	 __u32 * ed_p;
 	for (i= 0; i < 32; i++) {
 		j = 5;
-		printk (KERN_DEBUG " %s branch int %2d(%2x): ", str, i, i);
+		printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i);
 		ed_p = &(ohci->hcca.int_table [i]);
 		while (*ed_p != 0 && j--) {
-			printk ("ed: %4x; ", (((ed_t *) bus_to_virt (*ed_p))->hwINFO));
+			printk (" ed: %4x;", (((ed_t *) bus_to_virt (*ed_p))->hwINFO));
 			ed_p = &(((ed_t *) bus_to_virt (*ed_p))->hwNextED);
 		}
 		printk ("\n");
@@ -388,7 +379,7 @@
 			if(schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
 				remove_wait_queue (&op_wakeup, &wait); 
 			else
-				printk (KERN_ERR MODSTR "unlink URB timeout!\n");
+				err("unlink URB timeout!");
 		} else 
 			urb_rm_priv (urb);
 		usb_dec_dev_use (urb->dev);		
@@ -803,7 +794,7 @@
 	urb_priv_t * urb_priv = urb->hcpriv;
 
 	if (index >= urb_priv->length) {
-		printk (KERN_ERR MODSTR "internal OHCI error: TD index > length\n");
+		err("internal OHCI error: TD index > length");
 		return;
 	}
 	
@@ -892,10 +883,8 @@
 			}
 			break;
 	} 
-#ifdef DEBUG
 	if (urb_priv->length != cnt) 
-		dbg (KERN_ERR MODSTR " ********* TD LENGTH %d != CNT %d\n", urb_priv->length, cnt);
-#endif 
+		dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
 }
 
 /*-------------------------------------------------------------------------*
@@ -923,7 +912,7 @@
 
 		if (TD_CC_GET (le32_to_cpu (td_list->hwINFO))) {
 			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
-			dbg (KERN_DEBUG MODSTR "**** USB-error/status: %x : %p \n", 
+			dbg(" USB-error/status: %x : %p", 
 					TD_CC_GET (le32_to_cpu (td_list->hwINFO)), td_list);
 			if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
 				if (urb_priv && ((td_list->index + 1) < urb_priv->length)) {
@@ -1402,10 +1391,8 @@
 			status = TD_CC_STALL;
 	}
 	
-	dbg (KERN_DEBUG MODSTR "USB HC roothubstat1: %x \n",
-			readl ( &(ohci->regs->roothub.portstatus[0]) ));
-	dbg (KERN_DEBUG MODSTR "USB HC roothubstat2: %x \n",
-			readl ( &(ohci->regs->roothub.portstatus[1]) ));
+	dbg("USB HC roothubstat1: %x", readl ( &(ohci->regs->roothub.portstatus[0]) ));
+	dbg("USB HC roothubstat2: %x", readl ( &(ohci->regs->roothub.portstatus[1]) ));
 
 	len = min(len, leni);
 	memcpy (data, data_buf, len);
@@ -1444,25 +1431,25 @@
 	 	
 	if (readl (&ohci->regs->control) & 0x100) { /* SMM owns the HC */
 		writel (0x08, &ohci->regs->cmdstatus); /* request ownership */
-		printk (KERN_DEBUG MODSTR "USB HC TakeOver from SMM\n");
+		dbg("USB HC TakeOver from SMM");
 		while (readl (&ohci->regs->control) & 0x100) {
 			wait_ms (10);
 			if (--smm_timeout == 0) {
-				printk (KERN_ERR MODSTR "USB HC TakeOver failed!\n");
+				err("USB HC TakeOver failed!");
 				break;
 			}
 		}
 	}	
 		
 	writel ((1 << 31), &ohci->regs->intrdisable); /* Disable HC interrupts */
-	dbg (KERN_DEBUG MODSTR "USB HC reset_hc: %x ; \n", readl (&ohci->regs->control));
+	dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control));
   	/* this seems to be needed for the lucent controller on powerbooks.. */
 	writel (0, &ohci->regs->control);           /* Move USB to reset state */
       	
 	writel (1,  &ohci->regs->cmdstatus);	   /* HC Reset */
 	while ((readl (&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */
 		if (--timeout == 0) {
-			printk (KERN_ERR MODSTR "USB HC reset timed out!\n");
+			err("USB HC reset timed out!");
 			return;
 		}	
 		udelay (1);
@@ -1536,7 +1523,7 @@
 			return;
 	} 
 
-	dbg (KERN_DEBUG MODSTR "Interrupt: %x frame: %x \n", ints, le16_to_cpu (ohci->hcca.frame_no));
+	dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no));
 	
 	if (ints & OHCI_INTR_WDH) {
 		writel (OHCI_INTR_WDH, &regs->intrdisable);	
@@ -1545,7 +1532,7 @@
 	}
   
 	if (ints & OHCI_INTR_SO) {
-		dbg (KERN_ERR MODSTR " USB Schedule overrun \n");
+		dbg("USB Schedule overrun");
 		writel (OHCI_INTR_SO, &regs->intrenable); 	 
 	}
 
@@ -1607,7 +1594,7 @@
 
 static void hc_release_ohci (ohci_t * ohci)
 {	
-	dbg (KERN_DEBUG MODSTR "USB HC release ohci\n");
+	dbg("USB HC release ohci");
 
 	/* disconnect all devices */    
 	if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub);
@@ -1638,7 +1625,7 @@
 static int hc_found_ohci (int irq, void * mem_base)
 {
 	ohci_t * ohci;
-	dbg (KERN_DEBUG MODSTR "USB HC found: irq= %d membase= %x \n", irq, (int) mem_base);
+	dbg("USB HC found: irq= %d membase= %x", irq, (int) mem_base);
     
 	ohci = hc_alloc_ohci (mem_base);
 	if (!ohci) {
@@ -1658,7 +1645,7 @@
 		hc_start (ohci);
 		return 0;
  	}	
- 	printk (KERN_ERR MODSTR "request interrupt %d failed\n", irq);
+ 	err("request interrupt %d failed", irq);
 	hc_release_ohci (ohci);
 	return -EBUSY;
 }
@@ -1679,7 +1666,7 @@
 	mem_base = (unsigned int) ioremap_nocache (mem_base, 4096);
 
 	if (!mem_base) {
-		printk (KERN_ERR MODSTR "Error mapping OHCI memory\n");
+		err("Error mapping OHCI memory");
 		return -EFAULT;
 	}
 	return hc_found_ohci (dev->irq, (void *) mem_base);
@@ -1735,12 +1722,12 @@
 	case APM_SYS_SUSPEND:
 	case APM_USER_SUSPEND:
 		if (down) {
-			printk(KERN_DEBUG MODSTR "received extra suspend event\n");
+			dbg("received extra suspend event");
 			break;
 		}
 		for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
 			ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list);
-			dbg (KERN_DEBUG MODSTR "USB-Bus suspend: %p\n", ohci);
+			dbg("USB-Bus suspend: %p", ohci);
 			writel (ohci->hc_control = 0xFF, &ohci->regs->control);
 		}
 		wait_ms (10);
@@ -1749,12 +1736,12 @@
 	case APM_NORMAL_RESUME:
 	case APM_CRITICAL_RESUME:
 		if (!down) {
-			printk (KERN_DEBUG MODSTR "received bogus resume event\n");
+			dbg("received bogus resume event");
 			break;
 		}
 		for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
 			ohci = list_entry(ohci_l, ohci_t, ohci_hcd_list);
-			dbg (KERN_DEBUG MODSTR "USB-Bus resume: %p\n", ohci);
+			dbg("USB-Bus resume: %p", ohci);
 			writel (ohci->hc_control = 0x7F, &ohci->regs->control);
 		}		
 		wait_ms (20);
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.3.37/linux/drivers/usb/ov511.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/usb/ov511.c	Fri Jan  7 11:51:56 2000
@@ -35,7 +35,7 @@
 
 /* Handle mangled (versioned) external symbols */
 
-#include <linux/autoconf.h> /* retrieve the CONFIG_* macros */
+#include <linux/config.h>   /* retrieve the CONFIG_* macros */
 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
 #	define MODVERSIONS  /* force it on */
 #endif
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.37/linux/drivers/usb/proc_usb.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/usb/proc_usb.c	Fri Jan  7 11:17:45 2000
@@ -673,7 +673,7 @@
 	switch (cmd) {
 	case EZUSB_CONTROL:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_CONTROL ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_CONTROL ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -705,7 +705,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "procusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+			warn("EZUSB_CONTROL failed rqt %u rq %u len %u ret %d", 
 			       ctrl.requesttype, ctrl.request, ctrl.length, i);
 			return i;
 		}
@@ -713,7 +713,7 @@
 
 	case EZUSB_BULK:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_BULK ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_BULK ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -748,7 +748,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "procusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n", 
+			warn("EZUSB_BULK failed ep 0x%x len %u ret %d", 
 			       bulk.ep, bulk.len, i);
 			return i;
 		}
@@ -756,7 +756,7 @@
 
 	case EZUSB_OLD_CONTROL:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -784,7 +784,7 @@
 					}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "procusb: EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+			warn("EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d", 
 			       octrl.requesttype, octrl.request, octrl.length, i);
 			return i;
 		}
@@ -792,7 +792,7 @@
 
 	case EZUSB_OLD_BULK:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_BULK ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_OLD_BULK ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -827,7 +827,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "procusb: EZUSB_OLD_BULK failed ep 0x%x len %u ret %d\n", 
+			warn("EZUSB_OLD_BULK failed ep 0x%x len %u ret %d", 
 			       obulk.ep, obulk.len, i);
 			return i;
 		}
@@ -835,7 +835,7 @@
 
 	case EZUSB_RESETEP:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_RESETEP ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_RESETEP ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -849,7 +849,7 @@
 
 	case EZUSB_SETINTERFACE:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -862,7 +862,7 @@
 
 	case EZUSB_SETCONFIGURATION:
 		if (obsolete_warn < 20) {
-			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl\n",
+			warn("process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl",
 			       current->pid, current->comm);
 			obsolete_warn++;
 		}
@@ -923,7 +923,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i<0) {
-			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+			warn("USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d", 
 			       ctrl.requesttype, ctrl.request, ctrl.length, i);
 			return i;
 		}
@@ -961,7 +961,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i) {
-			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_BULK failed ep 0x%x len %u ret %d\n", 
+			warn("USB_PROC_BULK failed ep 0x%x len %u ret %d", 
 			       bulk.ep, bulk.len, i);
 			return -ENXIO;
 		}
@@ -996,7 +996,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+			warn("USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d", 
 			       octrl.requesttype, octrl.request, octrl.length, i);
 			return i;
 		}
@@ -1034,7 +1034,7 @@
 		}
 		free_page((unsigned long)tbuf);
 		if (i < 0) {
-			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d\n", 
+			warn("USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d", 
 			       obulk.ep, obulk.len, i);
 			return i;
 		}
@@ -1163,13 +1163,13 @@
 	usbdir = proc_mkdir("usb", proc_bus);
 #endif	
 	if (!usbdir) {
-		printk ("proc_usb: cannot create /proc/bus/usb entry\n");
+		err("cannot create /proc/bus/usb entry");
 		return -1;
 	}
 
 	driversdir = create_proc_entry("drivers", 0, usbdir);
 	if (!driversdir) {
-		printk ("proc_usb: cannot create /proc/bus/usb/drivers entry\n");
+		err("cannot create /proc/bus/usb/drivers entry");
 		proc_usb_cleanup();
 		return -1;
 	}
@@ -1177,7 +1177,7 @@
 
 	devicesdir = create_proc_entry("devices", 0, usbdir);
 	if (!devicesdir) {
-		printk ("proc_usb: cannot create /proc/bus/usb/devices entry\n");
+		err("cannot create /proc/bus/usb/devices entry");
 		proc_usb_cleanup ();
 		return -1;
 	}
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/restart linux/drivers/usb/restart
--- v2.3.37/linux/drivers/usb/restart	Tue May 11 10:04:03 1999
+++ linux/drivers/usb/restart	Wed Dec 31 16:00:00 1969
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-ME=`basename $0`
-
-#UMOD=`lsmod | grep '^bp-mouse' | grep -v grep`
-#if test "$UMOD"; then
-#  echo "$ME: removing bp-mouse.o"
-#  if ! rmmod bp-mouse; then
-#    echo "$ME: cannot remove bp-mouse.o"
-#    exit 1
-#  fi
-#fi
-
-UPID=`ps aux | grep ohci-control | grep -v grep | awk '{print $2}'`
-if test "$UPID"; then
-  echo "$ME: killing $UPID"
-  kill $UPID
-fi
-
-UMOD=`lsmod | grep '^usb-ohci' | grep -v grep`
-if test "$UMOD"; then
-  echo "$ME: removing usb-ohci.o"
-  sleep 1
-  if ! rmmod usb-ohci; then
-    echo "$ME: cannot remove usb-ohci.o"
-    exit 1
-  fi
-fi
-
-dmesg -c > /dev/null
-
-echo "$ME: starting usb-ohci.o"
-insmod -m usb-ohci.o > usb-ohci.map
-
-sleep 1
-UPID=`ps aux | grep ohci-control | grep -v grep | awk '{print $2}'`
-if test "$UPID"; then echo "$ME: ohci-control is pid $UPID" ; fi
-
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- v2.3.37/linux/drivers/usb/scanner.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/usb/scanner.c	Thu Jan  6 16:17:18 2000
@@ -103,17 +103,11 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 
-#include "usb.h"
+#undef DEBUG		/* Enable to print results of read/write_scanner() calls */
+#undef RD_DATA_DUMP	/* Enable to dump data - limited to 24 bytes */
+#undef WR_DATA_DUMP
 
-// #define SCN_DBG /* Enable to print results of read/write_scanner() calls */
-// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
-// #define WR_DATA_DUMP
-
-#ifdef SCN_DBG
-#define SCN_DEBUG(X) X
-#else
-#define SCN_DEBUG(X)
-#endif
+#include "usb.h"
 
 #define IBUF_SIZE 32768
 #define OBUF_SIZE 4096
@@ -207,14 +201,14 @@
 		}
 
 		result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, hps->oep), obuf, copy_size, &partial, 30*HZ);
-		SCN_DEBUG(printk(KERN_DEBUG "write stats: result:%d copy_size:%lu partial:%lu\n", (int)result, copy_size, partial);)
+		dbg("write stats: result:%d copy_size:%lu partial:%lu", (int)result, copy_size, partial);
 
 		if (result == USB_ST_TIMEOUT) {	/* NAK -- shouldn't happen */
-			printk(KERN_WARNING "write_scanner: NAK recieved.\n");
+			warn("write_scanner: NAK recieved.");
 			ret = -ETIME;
 			break;
 		} else if (result < 0) { /* We should not get any I/O errors */
-			printk(KERN_WARNING "write_scanner: funky result: %d. Please notify the maintainer.\n", result);
+			warn("write_scanner: funky result: %d. Please notify the maintainer.", result);
 			ret = -EIO;
 			break;
 		} 
@@ -223,7 +217,7 @@
 		if (partial) {
 			unsigned char cnt, cnt_max;
 			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump: ");
+			printk(KERN_DEBUG __FILE__ ": dump: ");
 			for (cnt=0; cnt < cnt_max; cnt++) {
 				printk("%X ", obuf[cnt]);
 			}
@@ -277,14 +271,14 @@
 		this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
 		
 		result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, hps->iep), ibuf, this_read, &partial, 60*HZ);
-		SCN_DEBUG(printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", (int)result, this_read, partial);)
+		dbg("read stats: result:%d this_read:%u partial:%lu", (int)result, this_read, partial);
 
 		if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
-			printk(KERN_WARNING "read_scanner: NAK received\n");
+			warn("read_scanner: NAK received");
 			ret = -ETIME;
 			break;
 		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
-			printk(KERN_WARNING "read_scanner: funky result: %d. Please notify the maintainer.\n", (int)result);
+			warn("read_scanner: funky result: %d. Please notify the maintainer.", (int)result);
 			ret = -EIO;
 			break;
 		}
@@ -293,7 +287,7 @@
 		if (partial) {
 			unsigned char cnt, cnt_max;
 			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump: ");
+			printk(KERN_DEBUG __FILE__ ": dump: ");
 			for (cnt=0; cnt < cnt_max; cnt++) {
 				printk("%X ", ibuf[cnt]);
 			}
@@ -333,9 +327,8 @@
 
 	hps->present = 0;
 
-	if (vendor != 0 || product != 0) {
-		printk(KERN_INFO "USB Scanner Vendor:Product - %x:%x\n", vendor, product);
-	}
+	if (vendor != 0 || product != 0)
+		info("USB Scanner Vendor:Product - %x:%x\n", vendor, product);
 
 /* There doesn't seem to be an imaging class defined in the USB
  * Spec. (yet).  If there is, HP isn't following it and it doesn't
@@ -377,7 +370,7 @@
 
 	if (dev->descriptor.bNumConfigurations != 1 || 
 	    dev->config[0].bNumInterfaces != 1) {
-		printk(KERN_INFO "probe_scanner: only simple configurations supported\n");
+		dbg("probe_scanner: only simple configurations supported");
 		return NULL;
 	}
 
@@ -385,12 +378,12 @@
 
 	if (endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK
 	    || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) {
-		printk(KERN_INFO "probe_scanner: invalid bulk endpoints\n");
+		dbg("probe_scanner: invalid bulk endpoints");
 		return NULL;
 	}
 
 	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-                printk (KERN_INFO "probe_scanner: failed usb_set_configuration\n");
+                dbg("probe_scanner: failed usb_set_configuration");
 		hps->hpscan_dev = NULL;
                 return NULL;
         }
@@ -418,10 +411,10 @@
 	}
 
 	ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */
-	printk(KERN_INFO "USB Scanner (%s) found at address %d\n", ident, dev->devnum);
+	info("USB Scanner (%s) found at address %d", ident, dev->devnum);
 	kfree(ident);
 
-	SCN_DEBUG(printk(KERN_DEBUG "probe_scanner: using bulk endpoints - In: %x  Out: %x\n", hps->iep, hps->oep);)
+	dbg("probe_scanner: using bulk endpoints - In: %x  Out: %x", hps->iep, hps->oep);
 
 	hps->present = 1;
 	hps->hpscan_dev = dev;
@@ -485,7 +478,7 @@
         if (usb_register(&scanner_driver) < 0)
                 return -1;
 
-	printk(KERN_INFO "USB Scanner support registered.\n");
+	info("USB Scanner support registered.");
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/stopusb linux/drivers/usb/stopusb
--- v2.3.37/linux/drivers/usb/stopusb	Tue Jul 13 10:09:01 1999
+++ linux/drivers/usb/stopusb	Wed Dec 31 16:00:00 1969
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-killall khubd
-killall ohci-control
-killall uhci-control
-
-sleep 2
-
-rmmod hub
-rmmod usb-ohci
-rmmod usb-uhci
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/uhci-debug.c linux/drivers/usb/uhci-debug.c
--- v2.3.37/linux/drivers/usb/uhci-debug.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/uhci-debug.c	Thu Jan  6 16:17:18 2000
@@ -1,40 +1,34 @@
 /*
  * $Id: uhci-debug.c,v 1.12 1999/12/13 15:24:42 fliegl Exp $
  */
+
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <asm/io.h>
 
+#define DEBUG
+
 #include "usb.h"
 #include "uhci.h"
-#define DEBUG
-#ifdef DEBUG
-#define dbg printk
-#else
-#define dbg nix
-static void nix (const char *format,...)
-{
-}
 
-#endif
 void dump_urb (purb_t purb)
 {
-	printk ("urb                   :%p\n", purb);
-	printk ("next                  :%p\n", purb->next);
-	printk ("dev                   :%p\n", purb->dev);
-	printk ("pipe                  :%08X\n", purb->pipe);
-	printk ("status                :%d\n", purb->status);
-	printk ("transfer_flags        :%08X\n", purb->transfer_flags);
-	printk ("transfer_buffer       :%p\n", purb->transfer_buffer);
-	printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
-	printk ("actual_length         :%d\n", purb->actual_length);
-	printk ("setup_packet          :%p\n", purb->setup_packet);
-	printk ("start_frame           :%d\n", purb->start_frame);
-	printk ("number_of_packets     :%d\n", purb->number_of_packets);
-	printk ("interval              :%d\n", purb->interval);
-	printk ("error_count           :%d\n", purb->error_count);
-	printk ("context               :%p\n", purb->context);
-	printk ("complete              :%p\n", purb->complete);
+	dbg("urb                   :%p", purb);
+	dbg("next                  :%p", purb->next);
+	dbg("dev                   :%p", purb->dev);
+	dbg("pipe                  :%08X", purb->pipe);
+	dbg("status                :%d", purb->status);
+	dbg("transfer_flags        :%08X", purb->transfer_flags);
+	dbg("transfer_buffer       :%p", purb->transfer_buffer);
+	dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
+	dbg("actual_length         :%d", purb->actual_length);
+	dbg("setup_packet          :%p", purb->setup_packet);
+	dbg("start_frame           :%d", purb->start_frame);
+	dbg("number_of_packets     :%d", purb->number_of_packets);
+	dbg("interval              :%d", purb->interval);
+	dbg("error_count           :%d", purb->error_count);
+	dbg("context               :%p", purb->context);
+	dbg("complete              :%p", purb->complete);
 }
 
 void beep (long freq)
@@ -61,37 +55,36 @@
 void uhci_show_qh (puhci_desc_t qh)
 {
 	if (qh->type != QH_TYPE) {
-		dbg (KERN_DEBUG MODSTR "qh has not QH_TYPE\n");
+		dbg("qh has not QH_TYPE");
 		return;
 	}
-	dbg (KERN_DEBUG MODSTR "uhci_show_qh %p (%08lX):\n", qh, virt_to_bus (qh));
+	dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh));
 
 	if (qh->hw.qh.head & UHCI_PTR_TERM)
-		dbg (KERN_DEBUG MODSTR "Head Terminate\n");
+		dbg("Head Terminate");
 	else {
 		if (qh->hw.qh.head & UHCI_PTR_QH)
-			dbg (KERN_DEBUG MODSTR "Head points to QH\n");
+			dbg("Head points to QH");
 		else
-			dbg (KERN_DEBUG MODSTR "Head points to TD\n");
+			dbg("Head points to TD");
 
-		dbg (KERN_DEBUG MODSTR "head: %08X\n", qh->hw.qh.head & ~UHCI_PTR_BITS);
+		dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS);
 	}
 	if (qh->hw.qh.element & UHCI_PTR_TERM)
-		dbg (KERN_DEBUG MODSTR "Element Terminate\n");
+		dbg("Element Terminate");
 	else {
 
 		if (qh->hw.qh.element & UHCI_PTR_QH)
-			dbg (KERN_DEBUG MODSTR "Element points to QH\n");
+			dbg("Element points to QH");
 		else
-			dbg (KERN_DEBUG MODSTR "Element points to TD\n");
-		dbg (KERN_DEBUG MODSTR "element: %08X\n", qh->hw.qh.element & ~UHCI_PTR_BITS);
+			dbg("Element points to TD");
+		dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS);
 	}
 }
 
 void uhci_show_td (puhci_desc_t td)
 {
 	char *spid;
-	dbg (KERN_DEBUG MODSTR "uhci_show_td %p (%08lX) ", td, virt_to_bus (td));
 
 	switch (td->hw.td.info & 0xff) {
 	case USB_PID_SETUP:
@@ -108,7 +101,9 @@
 		break;
 	}
 
-	dbg ("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)\n",
+	dbg("uhci_show_td %p (%08lX) MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)",
+	     td,
+	     virt_to_bus(td),
 	     td->hw.td.info >> 21,
 	     ((td->hw.td.info >> 19) & 1),
 	     (td->hw.td.info >> 15) & 15,
@@ -117,7 +112,7 @@
 	     spid,
 	     td->hw.td.buffer);
 
-	dbg (KERN_DEBUG MODSTR "Len=%02x e%d %s%s%s%s%s%s%s%s%s%s\n",
+	dbg("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s",
 	     td->hw.td.status & 0x7ff,
 	     ((td->hw.td.status >> 27) & 3),
 	     (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "",
@@ -131,25 +126,24 @@
 	     (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
 	     (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
 		);
-#if 1
+
 	if (td->hw.td.link & UHCI_PTR_TERM)
-		dbg (KERN_DEBUG MODSTR "Link Terminate\n");
+		dbg("Link Terminate");
 	else {
 		if (td->hw.td.link & UHCI_PTR_QH)
-			dbg (KERN_DEBUG MODSTR "%s, link points to QH @ %08x\n",
+			dbg("%s, link points to QH @ %08x",
 			     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
 			     td->hw.td.link & ~UHCI_PTR_BITS);
 		else
-			dbg (KERN_DEBUG MODSTR "%s, link points to TD @ %08x \n",
+			dbg("%s, link points to TD @ %08x",
 			     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
 			     td->hw.td.link & ~UHCI_PTR_BITS);
 	}
-#endif
 }
 
 void uhci_show_td_queue (puhci_desc_t td)
 {
-	dbg (KERN_DEBUG MODSTR "uhci_show_td_queue %p (%08lX):\n", td, virt_to_bus (td));
+	dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
 	while (1) {
 		uhci_show_td (td);
 		if (td->hw.td.link & UHCI_PTR_TERM)
@@ -159,7 +153,7 @@
 		if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS))
 			td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS);
 		else {
-			dbg (KERN_DEBUG MODSTR "td points to itself!\n");
+			dbg("td points to itself!");
 			break;
 		}
 //              schedule();
@@ -168,12 +162,12 @@
 
 void uhci_show_queue (puhci_desc_t qh)
 {
-	dbg (KERN_DEBUG MODSTR "uhci_show_queue %p:\n", qh);
+	dbg("uhci_show_queue %p:", qh);
 	while (1) {
 		uhci_show_qh (qh);
 
 		if (qh->hw.qh.element & UHCI_PTR_QH)
-			dbg (KERN_DEBUG MODSTR "Warning: qh->element points to qh!\n");
+			dbg("Warning: qh->element points to qh!");
 		else if (!(qh->hw.qh.element & UHCI_PTR_TERM))
 			uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS));
 
@@ -183,7 +177,7 @@
 		if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
 			qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
 		else {
-			dbg (KERN_DEBUG MODSTR "qh points to itself!\n");
+			dbg("qh points to itself!");
 			break;
 		}
 	}
@@ -191,7 +185,7 @@
 
 static void uhci_show_sc (int port, unsigned short status)
 {
-	dbg ("  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
+	dbg("  stat%d     =     %04x   %s%s%s%s%s%s%s%s",
 	     port,
 	     status,
 	     (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
@@ -221,7 +215,7 @@
 	portsc1 = inw (io_addr + 16);
 	portsc2 = inw (io_addr + 18);
 
-	dbg ("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
+	dbg("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s",
 	     usbcmd,
 	     (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
 	     (usbcmd & USBCMD_CF) ? "CF " : "",
@@ -232,7 +226,7 @@
 	     (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
 	     (usbcmd & USBCMD_RS) ? "RS " : "");
 
-	dbg ("  usbstat   =     %04x   %s%s%s%s%s%s\n",
+	dbg("  usbstat   =     %04x   %s%s%s%s%s%s",
 	     usbstat,
 	     (usbstat & USBSTS_HCH) ? "HCHalted " : "",
 	     (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
@@ -241,11 +235,11 @@
 	     (usbstat & USBSTS_ERROR) ? "USBError " : "",
 	     (usbstat & USBSTS_USBINT) ? "USBINT " : "");
 
-	dbg ("  usbint    =     %04x\n", usbint);
-	dbg ("  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
+	dbg("  usbint    =     %04x", usbint);
+	dbg("  usbfrnum  =   (%d)%03x", (usbfrnum >> 10) & 1,
 	     0xfff & (4 * (unsigned int) usbfrnum));
-	dbg ("  flbaseadd = %08x\n", flbaseadd);
-	dbg ("  sof       =       %02x\n", sof);
+	dbg("  flbaseadd = %08x", flbaseadd);
+	dbg("  sof       =       %02x", sof);
 	uhci_show_sc (1, portsc1);
 	uhci_show_sc (2, portsc2);
 }
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.37/linux/drivers/usb/uhci.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/uhci.c	Thu Jan  6 16:17:19 2000
@@ -33,21 +33,13 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-//#include <asm/spinlock.h>
+
+#undef DEBUG
 
 #include "usb.h"
 #include "uhci.h"
 #include "uhci-debug.h"
 
-//#define DEBUG
-#ifdef DEBUG
-#define dbg(format, args...) printk(format, ## args)
-#else
-#define dbg(format, args...)
-#endif
-
-#define _static static
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
 #define __init 
 #define __exit
@@ -85,7 +77,7 @@
 static puhci_t devs = NULL;
 
 /*-------------------------------------------------------------------*/
-_static void queue_urb (puhci_t s, struct list_head *p, int do_lock)
+static void queue_urb (puhci_t s, struct list_head *p, int do_lock)
 {
 	unsigned long flags=0;
 
@@ -99,7 +91,7 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock)
+static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock)
 {
 	unsigned long flags=0;
 	
@@ -113,7 +105,7 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static int alloc_td (puhci_desc_t * new, int flags)
+static int alloc_td (puhci_desc_t * new, int flags)
 {
 #ifdef _UHCI_SLAB
 	*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
@@ -134,7 +126,7 @@
 }
 /*-------------------------------------------------------------------*/
 /* insert td at last position in td-list of qh (vertical) */
-_static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags)
+static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags)
 {
 	uhci_desc_t *prev;
 	unsigned long xxx;
@@ -160,7 +152,7 @@
 }
 /*-------------------------------------------------------------------*/
 /* insert new_td after td (horizontal) */
-_static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags)
+static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags)
 {
 	uhci_desc_t *next;
 	unsigned long xxx;
@@ -177,7 +169,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int unlink_td (puhci_t s, puhci_desc_t element)
+static int unlink_td (puhci_t s, puhci_desc_t element)
 {
 	uhci_desc_t *next, *prev;
 	int dir = 0;
@@ -213,7 +205,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int delete_desc (puhci_desc_t element)
+static int delete_desc (puhci_desc_t element)
 {
 #ifdef _UHCI_SLAB
 	kmem_cache_free(uhci_desc_kmem, element);
@@ -224,7 +216,7 @@
 }
 /*-------------------------------------------------------------------*/
 // Allocates qh element
-_static int alloc_qh (puhci_desc_t * new)
+static int alloc_qh (puhci_desc_t * new)
 {
 #ifdef _UHCI_SLAB
 	*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
@@ -241,14 +233,14 @@
 	INIT_LIST_HEAD (&(*new)->horizontal);
 	INIT_LIST_HEAD (&(*new)->vertical);
 	
-	dbg (KERN_DEBUG MODSTR "Allocated qh @ %p\n", *new);
+	dbg("Allocated qh @ %p", *new);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 // inserts new qh before/after the qh at pos
 // flags: 0: insert before pos, 1: insert after pos (for low speed transfers)
-_static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags)
+static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags)
 {
 	puhci_desc_t old;
 	unsigned long xxx;
@@ -279,7 +271,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int unlink_qh (puhci_t s, puhci_desc_t element)
+static int unlink_qh (puhci_t s, puhci_desc_t element)
 {
 	puhci_desc_t next, prev;
 	unsigned long xxx;
@@ -297,7 +289,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int delete_qh (puhci_t s, puhci_desc_t qh)
+static int delete_qh (puhci_t s, puhci_desc_t qh)
 {
 	puhci_desc_t td;
 	struct list_head *p;
@@ -332,12 +324,12 @@
 }
 /*-------------------------------------------------------------------*/
 // Removes ALL qhs in chain (paranoia!)
-_static void cleanup_skel (puhci_t s)
+static void cleanup_skel (puhci_t s)
 {
 	unsigned int n;
 	puhci_desc_t td;
 
-	printk (KERN_DEBUG MODSTR "Cleanup_skel\n");
+	dbg("cleanup_skel");
 	
 	for (n = 0; n < 8; n++) {
 		td = s->int_chain[n];
@@ -379,12 +371,12 @@
 /*-------------------------------------------------------------------*/
 // allocates framelist and qh-skeletons
 // only HW-links provide continous linking, SW-links stay in their domain (ISO/INT)
-_static int init_skel (puhci_t s)
+static int init_skel (puhci_t s)
 {
 	int n, ret;
 	puhci_desc_t qh, td;
 	
-	dbg (KERN_DEBUG MODSTR "init_skel\n");
+	dbg("init_skel");
 	
 	s->framelist = (__u32 *) get_free_page (GFP_KERNEL);
 
@@ -393,7 +385,7 @@
 
 	memset (s->framelist, 0, 4096);
 
-	dbg (KERN_DEBUG MODSTR "allocating iso desc pointer list\n");
+	dbg("allocating iso desc pointer list");
 	s->iso_td = (puhci_desc_t *) kmalloc (1024 * sizeof (puhci_desc_t), GFP_KERNEL);
 	
 	if (!s->iso_td)
@@ -403,7 +395,7 @@
 	s->bulk_chain = NULL;
 	s->chain_end = NULL;
 
-	dbg (KERN_DEBUG MODSTR "allocating iso descs\n");
+	dbg("allocating iso descs");
 	for (n = 0; n < 1024; n++) {
 	 	// allocate skeleton iso/irq-tds
 		ret = alloc_td (&td, 0);
@@ -413,7 +405,7 @@
 		s->framelist[n] = ((__u32) virt_to_bus (td));
 	}
 
-	dbg (KERN_DEBUG MODSTR "allocating qh: chain_end\n");
+	dbg("allocating qh: chain_end");
 	ret = alloc_qh (&qh);
 	
 	if (ret)
@@ -421,7 +413,7 @@
 	
 	s->chain_end = qh;
 
-	dbg (KERN_DEBUG MODSTR "allocating qh: bulk_chain\n");
+	dbg("allocating qh: bulk_chain");
 	ret = alloc_qh (&qh);
 	
 	if (ret)
@@ -429,7 +421,7 @@
 	
 	insert_qh (s, s->chain_end, qh, 0);
 	s->bulk_chain = qh;
-	dbg (KERN_DEBUG MODSTR "allocating qh: control_chain\n");
+	dbg("allocating qh: control_chain");
 	ret = alloc_qh (&qh);
 	
 	if (ret)
@@ -440,7 +432,7 @@
 	for (n = 0; n < 8; n++)
 		s->int_chain[n] = 0;
 
-	dbg (KERN_DEBUG MODSTR "Allocating skeleton INT-TDs\n");
+	dbg("allocating skeleton INT-TDs");
 	
 	for (n = 0; n < 8; n++) {
 		puhci_desc_t td;
@@ -457,12 +449,12 @@
 		}
 	}
 
-	dbg (KERN_DEBUG MODSTR "Linking skeleton INT-TDs\n");
+	dbg("linking skeleton INT-TDs");
 	
 	for (n = 0; n < 1024; n++) {
 		// link all iso-tds to the interrupt chains
 		int m, o;
-		//dbg("framelist[%i]=%x\n",n,s->framelist[n]);
+		//dbg("framelist[%i]=%x",n,s->framelist[n]);
 		for (o = 1, m = 2; m <= 128; o++, m += m) {
 			// n&(m-1) = n%m
 			if ((n & (m - 1)) == ((m - 1) / 2)) {
@@ -472,7 +464,7 @@
 	}
 
 	//uhci_show_queue(s->control_chain);   
-	dbg (KERN_DEBUG MODSTR "init_skel exit\n");
+	dbg("init_skel exit");
 	return 0;		// OK
 
       init_skel_cleanup:
@@ -481,7 +473,7 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer)
+static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer)
 {
 	td->hw.td.status = status;
 	td->hw.td.info = info;
@@ -492,7 +484,7 @@
 //                         LOW LEVEL STUFF
 //          assembles QHs und TDs for control, bulk and iso
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_control_urb (purb_t purb)
+static int uhci_submit_control_urb (purb_t purb)
 {
 	puhci_desc_t qh, td;
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
@@ -502,7 +494,7 @@
 	unsigned long len, bytesrequested;
 	char *data;
 
-	dbg (KERN_DEBUG MODSTR "uhci_submit_control start\n");
+	dbg("uhci_submit_control start");
 	alloc_qh (&qh);		// alloc qh for this request
 
 	if (!qh)
@@ -535,7 +527,7 @@
 
 	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
 #if 0
-	printk ("SETUP to pipe %x: %x %x %x %x %x %x %x %x\n", purb->pipe,
+	dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", purb->pipe,
 		purb->setup_packet[0], purb->setup_packet[1], purb->setup_packet[2], purb->setup_packet[3],
 		purb->setup_packet[4], purb->setup_packet[5], purb->setup_packet[6], purb->setup_packet[7]);
 	//uhci_show_td(td);
@@ -602,11 +594,11 @@
 		insert_qh (s, s->bulk_chain, qh, 0);	// insert before bulk chain
 	//uhci_show_queue(s->control_chain);
 
-	dbg (KERN_DEBUG MODSTR "uhci_submit_control end\n");
+	dbg("uhci_submit_control end");
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_bulk_urb (purb_t purb)
+static int uhci_submit_bulk_urb (purb_t purb)
 {
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
 	purb_priv_t purb_priv = purb->hcpriv;
@@ -641,7 +633,7 @@
 	/* Build the TDs for the bulk request */
 	len = purb->transfer_buffer_length;
 	data = purb->transfer_buffer;
-	dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: pipe %x, len %d\n", pipe, len);
+	dbg("uhci_submit_bulk_urb: pipe %x, len %d", pipe, len);
 	
 	while (len > 0) {
 		int pktsze = len;
@@ -667,7 +659,7 @@
 
 		if (!len)
 			td->hw.td.status |= TD_CTRL_IOC;	// last one generates INT
-		//dbg("insert td %p, len %i\n",td,pktsze);
+		//dbg("insert td %p, len %i",td,pktsze);
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH);
 		
@@ -680,14 +672,14 @@
 	insert_qh (s, s->chain_end, qh, 0);	// insert before end marker
 	//uhci_show_queue(s->bulk_chain);
 
-	dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: exit\n");
+	dbg("uhci_submit_bulk_urb: exit");
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 // unlinks an urb by dequeuing its qh, waits some frames and forgets it
 // Problem: unlinking in interrupt requires waiting for one frame (udelay)
 // to allow the whole structures to be safely removed
-_static int uhci_unlink_urb (purb_t purb)
+static int uhci_unlink_urb (purb_t purb)
 {
 	puhci_t s;
 	puhci_desc_t qh;
@@ -709,7 +701,7 @@
 		spin_lock_irqsave (&s->unlink_urb_lock, flags);		// do not allow interrupts
 	}
 	
-	//dbg("unlink_urb called %p\n",purb);
+	//dbg("unlink_urb called %p",purb);
 	if (purb->status == USB_ST_URB_PENDING) {
 		// URB probably still in work
 		purb_priv = purb->hcpriv;
@@ -760,7 +752,7 @@
 		kfree (purb->hcpriv);
 #endif
 		if (purb->complete) {
-			dbg (KERN_DEBUG MODSTR "unlink_urb: calling completion\n");
+			dbg("unlink_urb: calling completion");
 			purb->complete ((struct urb *) purb);
 			usb_dec_dev_use (purb->dev);
 		}
@@ -777,7 +769,7 @@
 // In case of ASAP iso transfer, search the URB-list for already queued URBs
 // for this EP and calculate the earliest start frame for the new
 // URB (easy seamless URB continuation!)
-_static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end)
+static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end)
 {
 	purb_t u, last_urb = NULL;
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
@@ -811,18 +803,18 @@
 /*-------------------------------------------------------------------*/
 // adjust start_frame according to scheduling constraints (ASAP etc)
 
-_static void jnx_show_desc (puhci_desc_t d)
+static void jnx_show_desc (puhci_desc_t d)
 {
 	switch (d->type) {
 	case TD_TYPE:
-		printk (KERN_DEBUG MODSTR "td @ 0x%08lx: link 0x%08x status 0x%08x info 0x%08x buffer 0x%08x\n",
+		dbg("td @ 0x%08lx: link 0x%08x status 0x%08x info 0x%08x buffer 0x%08x",
 			(unsigned long) d, d->hw.td.link, d->hw.td.status, d->hw.td.info, d->hw.td.buffer);
 		if (!(d->hw.td.link & UHCI_PTR_TERM))
 			jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.td.link & ~UHCI_PTR_BITS));
 		break;
 
 	case QH_TYPE:
-		printk (KERN_DEBUG MODSTR "qh @ 0x%08lx: head 0x%08x element 0x%08x\n",
+		dbg("qh @ 0x%08lx: head 0x%08x element 0x%08x",
 			(unsigned long) d, d->hw.qh.head, d->hw.qh.element);
 		if (!(d->hw.qh.element & UHCI_PTR_TERM))
 			jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.qh.element & ~UHCI_PTR_BITS));
@@ -831,13 +823,12 @@
 		break;
 
 	default:
-		printk (KERN_DEBUG MODSTR "desc @ 0x%08lx: invalid type %u\n",
-			(unsigned long) d, d->type);
+		dbg("desc @ 0x%08lx: invalid type %u", (unsigned long) d, d->type);
 	}
 }
 
 /*-------------------------------------------------------------------*/
-_static int iso_find_start (purb_t purb)
+static int iso_find_start (purb_t purb)
 {
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
 	unsigned int now;
@@ -862,8 +853,8 @@
 			purb->start_frame = stop_limit;		//seamless linkage
 
 			if (((now - purb->start_frame) & 1023) <= (unsigned) purb->number_of_packets) {
-				printk (KERN_DEBUG MODSTR "iso_find_start: warning, ASAP gap, should not happen\n");
-				printk (KERN_DEBUG MODSTR "iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x\n",
+				dbg("iso_find_start: warning, ASAP gap, should not happen");
+				dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x",
 					now, purb->start_frame, purb->number_of_packets, purb->pipe);
 				{
 					puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
@@ -879,7 +870,7 @@
 						u = list_entry (p, urb_t, urb_list);
 						if (purb->dev != u->dev)
 							continue;
-						printk (KERN_DEBUG MODSTR "urb: pipe 0x%08x status %d start_frame %u number_of_packets %u\n",
+						dbg("urb: pipe 0x%08x status %d start_frame %u number_of_packets %u",
 							u->pipe, u->status, u->start_frame, u->number_of_packets);
 						if (!usb_pipeisoc (u->pipe))
 							continue;
@@ -907,7 +898,7 @@
 	else {
 		purb->start_frame &= 1023;
 		if (((now - purb->start_frame) & 1023) < (unsigned) purb->number_of_packets) {
-			printk (KERN_DEBUG MODSTR "iso_find_start: now between start_frame and end\n");
+			dbg("iso_find_start: now between start_frame and end");
 			return -EAGAIN;
 		}
 	}
@@ -917,7 +908,7 @@
 		return 0;
 	if (((purb->start_frame - start_limit) & 1023) < queued_size ||
 	    ((purb->start_frame + purb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
-		printk (KERN_DEBUG MODSTR "iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u\n",
+		dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u",
 			purb->start_frame, purb->number_of_packets, start_limit, stop_limit);
 		return -EAGAIN;
 	}
@@ -929,7 +920,7 @@
 // ASAP-flag set implicitely
 // if period==0, the the transfer is only done once (usb_scsi need this...)
 
-_static int uhci_submit_int_urb (purb_t purb)
+static int uhci_submit_int_urb (purb_t purb)
 {
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
 	purb_priv_t purb_priv = purb->hcpriv;
@@ -940,7 +931,7 @@
 	int info;
 	unsigned int pipe = purb->pipe;
 
-	//printk("SUBMIT INT\n");
+	//dbg("SUBMIT INT");
 
 	if (purb->interval < 0 || purb->interval >= 256)
 		return -EINVAL;
@@ -957,7 +948,7 @@
 		}
 		nint--;
 	}
-	dbg(KERN_INFO "Rounded interval to %i, chain  %i\n", purb->interval, nint);
+	dbg("Rounded interval to %i, chain  %i", purb->interval, nint);
 
 	now = UHCI_GET_CURRENT_FRAME (s) & 1023;
 	purb->start_frame = now;	// remember start frame, just in case...
@@ -998,7 +989,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_iso_urb (purb_t purb)
+static int uhci_submit_iso_urb (purb_t purb)
 {
 	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
 	purb_priv_t purb_priv = purb->hcpriv;
@@ -1025,7 +1016,7 @@
 
 	// First try to get all TDs
 	for (n = 0; n < purb->number_of_packets; n++) {
-		dbg (KERN_DEBUG MODSTR "n:%d purb->iso_frame_desc[n].length:%d\n", n, purb->iso_frame_desc[n].length);
+		dbg("n:%d purb->iso_frame_desc[n].length:%d", n, purb->iso_frame_desc[n].length);
 		if (!purb->iso_frame_desc[n].length) {
 			// allows ISO striping by setting length to zero in iso_descriptor
 			tdm[n] = 0;
@@ -1066,7 +1057,7 @@
 	}
 
 	kfree (tdm);
-	dbg ("ISO-INT# %i, start %i, now %i\n", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
+	dbg("ISO-INT# %i, start %i, now %i", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
 	ret = 0;
 
       err:
@@ -1075,18 +1066,18 @@
 
 }
 /*-------------------------------------------------------------------*/
-_static int search_dev_ep (puhci_t s, purb_t purb)
+static int search_dev_ep (puhci_t s, purb_t purb)
 {
 	unsigned long flags;
 	struct list_head *p = s->urb_list.next;
 	purb_t tmp;
 
-	dbg (KERN_DEBUG MODSTR "search_dev_ep:\n");
+	dbg("search_dev_ep:");
 	spin_lock_irqsave (&s->urb_list_lock, flags);
 
 	for (; p != &s->urb_list; p = p->next) {
 		tmp = list_entry (p, urb_t, urb_list);
-		dbg (KERN_DEBUG MODSTR "urb: %p\n", tmp);
+		dbg("urb: %p", tmp);
 		// we can accept this urb if it is not queued at this time 
 		// or if non-iso transfer requests should be scheduled for the same device and pipe
 		if ((usb_pipetype (purb->pipe) != PIPE_ISOCHRONOUS &&
@@ -1101,7 +1092,7 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_urb (purb_t purb)
+static int uhci_submit_urb (purb_t purb)
 {
 	puhci_t s;
 	purb_priv_t purb_priv;
@@ -1111,7 +1102,7 @@
 		return -ENODEV;
 
 	s = (puhci_t) purb->dev->bus->hcpriv;
-	//printk( MODSTR"submit_urb: %p type %d\n",purb,usb_pipetype(purb->pipe));
+	//dbg("submit_urb: %p type %d",purb,usb_pipetype(purb->pipe));
 
 	if (usb_pipedevice (purb->pipe) == s->rh.devnum)
 		return rh_submit_urb (purb);	/* virtual root hub */
@@ -1137,7 +1128,7 @@
 	purb->hcpriv = purb_priv;
 	INIT_LIST_HEAD (&purb_priv->desc_list);
 	purb_priv->short_control_packet=0;
-	dbg (KERN_DEBUG MODSTR "submit_urb: scheduling %p\n", purb);
+	dbg("submit_urb: scheduling %p", purb);
 
 	switch (usb_pipetype (purb->pipe)) {
 	case PIPE_ISOCHRONOUS:
@@ -1157,7 +1148,7 @@
 		ret = -EINVAL;
 	}
 
-	dbg (KERN_DEBUG MODSTR "submit_urb: scheduled with ret: %d\n", ret);
+	dbg("submit_urb: scheduled with ret: %d", ret);
 
 	if (ret != USB_ST_NOERROR) {
 		usb_dec_dev_use (purb->dev);
@@ -1171,7 +1162,7 @@
 
 	purb->status = USB_ST_URB_PENDING;
 	queue_urb (s, &purb->urb_list,1);
-	dbg (KERN_DEBUG MODSTR "submit_urb: exit\n");
+	dbg("submit_urb: exit");
 
 	return 0;
 }
@@ -1179,7 +1170,7 @@
  Virtual Root Hub
  -------------------------------------------------------------------*/
 
-_static __u8 root_hub_dev_des[] =
+static __u8 root_hub_dev_des[] =
 {
 	0x12,			/*  __u8  bLength; */
 	0x01,			/*  __u8  bDescriptorType; Device */
@@ -1203,7 +1194,7 @@
 
 
 /* Configuration descriptor */
-_static __u8 root_hub_config_des[] =
+static __u8 root_hub_config_des[] =
 {
 	0x09,			/*  __u8  bLength; */
 	0x02,			/*  __u8  bDescriptorType; Configuration */
@@ -1238,7 +1229,7 @@
 };
 
 
-_static __u8 root_hub_hub_des[] =
+static __u8 root_hub_hub_des[] =
 {
 	0x09,			/*  __u8  bLength; */
 	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
@@ -1253,7 +1244,7 @@
 
 /*-------------------------------------------------------------------------*/
 /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-_static int rh_send_irq (purb_t purb)
+static int rh_send_irq (purb_t purb)
 {
 
 	int len = 1;
@@ -1272,7 +1263,7 @@
 	purb->status = USB_ST_NOERROR;
 
 	if ((data > 0) && (uhci->rh.send != 0)) {
-		dbg (KERN_DEBUG MODSTR "Root-Hub INT complete: port1: %x port2: %x data: %x\n",
+		dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
 		     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
 		purb->complete (purb);
 
@@ -1282,9 +1273,9 @@
 
 /*-------------------------------------------------------------------------*/
 /* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
-_static int rh_init_int_timer (purb_t purb);
+static int rh_init_int_timer (purb_t purb);
 
-_static void rh_int_timer_do (unsigned long ptr)
+static void rh_int_timer_do (unsigned long ptr)
 {
 	int len;
 
@@ -1304,7 +1295,7 @@
 
 /*-------------------------------------------------------------------------*/
 /* Root Hub INTs are polled by this timer */
-_static int rh_init_int_timer (purb_t purb)
+static int rh_init_int_timer (purb_t purb)
 {
 	puhci_t uhci = purb->dev->bus->hcpriv;
 
@@ -1338,7 +1329,7 @@
  *************************/
 
 
-_static int rh_submit_urb (purb_t purb)
+static int rh_submit_urb (purb_t purb)
 {
 	struct usb_device *usb_dev = purb->dev;
 	puhci_t uhci = usb_dev->bus->hcpriv;
@@ -1359,7 +1350,7 @@
 	__u16 wLength;
 
 	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
-		dbg (KERN_DEBUG MODSTR "Root-Hub submit IRQ: every %d ms\n", purb->interval);
+		dbg("Root-Hub submit IRQ: every %d ms", purb->interval);
 		uhci->rh.urb = purb;
 		uhci->rh.send = 1;
 		uhci->rh.interval = purb->interval;
@@ -1377,7 +1368,7 @@
 	for (i = 0; i < 8; i++)
 		uhci->rh.c_p_r[i] = 0;
 
-	dbg(KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x\n",
+	dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x",
 	     uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
 
 	switch (bmRType_bReq) {
@@ -1517,7 +1508,7 @@
 	}
 
 
-	printk (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n",
+	dbg("Root-Hub stat port1: %x port2: %x",
 	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
 
 	purb->actual_length = len;
@@ -1528,11 +1519,11 @@
 }
 /*-------------------------------------------------------------------------*/
 
-_static int rh_unlink_urb (purb_t purb)
+static int rh_unlink_urb (purb_t purb)
 {
 	puhci_t uhci = purb->dev->bus->hcpriv;
 
-	dbg (KERN_DEBUG MODSTR "Root-Hub unlink IRQ\n");
+	dbg("Root-Hub unlink IRQ");
 	uhci->rh.send = 0;
 	del_timer (&uhci->rh.rh_int_timer);
 	return 0;
@@ -1547,7 +1538,7 @@
  * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)
  * <dir_out> is True for output TDs and False for input TDs.
  */
-_static int uhci_map_status (int status, int dir_out)
+static int uhci_map_status (int status, int dir_out)
 {
 	if (!status)
 		return USB_ST_NOERROR;
@@ -1576,12 +1567,12 @@
 /*
  * Only the USB core should call uhci_alloc_dev and uhci_free_dev
  */
-_static int uhci_alloc_dev (struct usb_device *usb_dev)
+static int uhci_alloc_dev (struct usb_device *usb_dev)
 {
 	return 0;
 }
 
-_static int uhci_free_dev (struct usb_device *usb_dev)
+static int uhci_free_dev (struct usb_device *usb_dev)
 {
 	return 0;
 }
@@ -1591,7 +1582,7 @@
  *
  * returns the current frame number for a USB bus/controller.
  */
-_static int uhci_get_current_frame_number (struct usb_device *usb_dev)
+static int uhci_get_current_frame_number (struct usb_device *usb_dev)
 {
 	return UHCI_GET_CURRENT_FRAME ((puhci_t) usb_dev->bus->hcpriv);
 }
@@ -1615,7 +1606,7 @@
  * when the transfered length fits exactly in maxsze-packets. A bit
  * more intelligence is needed to detect this and finish without error.
  */
-_static int process_transfer (puhci_t s, purb_t purb)
+static int process_transfer (puhci_t s, purb_t purb)
 {
 	int ret = USB_ST_NOERROR;
 	purb_priv_t purb_priv = purb->hcpriv;
@@ -1632,7 +1623,7 @@
 	int actual_length;
 	int status = USB_ST_NOERROR;
 
-	dbg (KERN_DEBUG MODSTR "process_transfer: urb contains bulk/control request\n");
+	dbg("process_transfer: urb contains bulk/control request");
 
 
 	/* if the status phase has been retriggered and the
@@ -1683,7 +1674,7 @@
 		if ( (actual_length < maxlength)) {
 			if (purb->transfer_flags & USB_DISABLE_SPD) {
 				ret = USB_ST_SHORT_PACKET;	// treat as real error
-				printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n");
+				dbg("process_transfer: SPD!!");
 				break;	// exit after this TD because SP was detected
 			}
 
@@ -1692,7 +1683,7 @@
 				if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
 					uhci_show_td (last_desc);
 					qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
-					printk("uhci: short packet during control transfer, retrigger status stage @ %p\n",last_desc);
+					info("short packet during control transfer, retrigger status stage @ %p",last_desc);
 					purb_priv->short_control_packet=1;
 					return 0;
 				}
@@ -1703,7 +1694,7 @@
 		}
 
 		data_toggle = uhci_toggle (desc->hw.td.info);
-		//printk(KERN_DEBUG MODSTR"process_transfer: len:%d status:%x mapped:%x toggle:%d\n", actual_length, desc->hw.td.status,status, data_toggle);      
+		//dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle);      
 
 	}
 	usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle);
@@ -1725,13 +1716,13 @@
 
 	purb->status = status;
 	                                                  	
-	dbg(KERN_DEBUG MODSTR"process_transfer: urb %p, wanted len %d, len %d status %x err %d\n",
+	dbg("process_transfer: urb %p, wanted len %d, len %d status %x err %d",
 		purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count);
-	//dbg(KERN_DEBUG MODSTR"process_transfer: exit\n");
+	//dbg("process_transfer: exit");
 	return ret;
 }
 
-_static int process_interrupt (puhci_t s, purb_t purb)
+static int process_interrupt (puhci_t s, purb_t purb)
 {
 	int i, ret = USB_ST_URB_PENDING;
 	purb_priv_t purb_priv = purb->hcpriv;
@@ -1744,7 +1735,7 @@
 	int actual_length;
 	int status = USB_ST_NOERROR;
 
-	//printk(KERN_DEBUG MODSTR"urb contains interrupt request\n");
+	//dbg("urb contains interrupt request");
 
 	for (i = 0; p != &purb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
 	{
@@ -1752,7 +1743,7 @@
 
 		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
 			// do not process active TDs
-			//printk("TD ACT Status @%p %08x\n",desc,desc->hw.td.status);
+			//dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status);
 			break;
 		}
 
@@ -1785,7 +1776,7 @@
 
 		if (purb->complete && status != USB_ST_TIMEOUT) {
 			// for last td, no user completion is needed
-			dbg (KERN_DEBUG MODSTR "process_interrupt: calling completion\n");
+			dbg("process_interrupt: calling completion");
 			purb->status = status;
 			purb->complete ((struct urb *) purb);
 			purb->status = USB_ST_URB_PENDING;
@@ -1808,7 +1799,7 @@
 }
 
 
-_static int process_iso (puhci_t s, purb_t purb)
+static int process_iso (puhci_t s, purb_t purb)
 {
 	int i;
 	int ret = USB_ST_NOERROR;
@@ -1816,7 +1807,7 @@
 	struct list_head *p = purb_priv->desc_list.next;
 	puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
-	dbg ( /*KERN_DEBUG */ MODSTR "urb contains iso request\n");
+	dbg("urb contains iso request");
 	if (desc->hw.td.status & TD_CTRL_ACTIVE)
 		return USB_ST_PARTIAL_ERROR;	// last TD not finished
 
@@ -1830,7 +1821,7 @@
 		//uhci_show_td(desc);
 		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
 			// means we have completed the last TD, but not the TDs before
-			printk (KERN_DEBUG MODSTR "TD still active (%x)- grrr. paranoia!\n", desc->hw.td.status);
+			dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status);
 			ret = USB_ST_PARTIAL_ERROR;
 			purb->iso_frame_desc[i].status = ret;
 			unlink_td (s, desc);
@@ -1840,14 +1831,14 @@
 		unlink_td (s, desc);
 
 		if (purb->number_of_packets <= i) {
-			dbg (KERN_DEBUG MODSTR "purb->number_of_packets (%d)<=(%d)\n", purb->number_of_packets, i);
+			dbg("purb->number_of_packets (%d)<=(%d)", purb->number_of_packets, i);
 			ret = USB_ST_URB_INVALID_ERROR;
 			goto err;
 		}
 
 		if (purb->iso_frame_desc[i].offset + purb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
 			// Hm, something really weird is going on
-			dbg (KERN_DEBUG MODSTR "Pointer Paranoia: %p!=%p\n", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
+			dbg("Pointer Paranoia: %p!=%p", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
 			ret = USB_ST_URB_INVALID_ERROR;
 			purb->iso_frame_desc[i].status = ret;
 			goto err;
@@ -1862,25 +1853,25 @@
 			purb->error_count++;
 			purb->status = purb->iso_frame_desc[i].status;
 		}
-		dbg (KERN_DEBUG MODSTR "process_iso: len:%d status:%x\n",
+		dbg("process_iso: len:%d status:%x",
 		     purb->iso_frame_desc[i].length, purb->iso_frame_desc[i].status);
 
 		delete_desc (desc);
 		list_del (p);
 	}
-	dbg ( /*KERN_DEBUG */ MODSTR "process_iso: exit %i (%d)\n", i, ret);
+	dbg("process_iso: exit %i (%d)", i, ret);
 	return ret;
 }
 
 
-_static int process_urb (puhci_t s, struct list_head *p)
+static int process_urb (puhci_t s, struct list_head *p)
 {
 	int ret = USB_ST_NOERROR;
 	purb_t purb;
 
 	spin_lock(&s->urb_list_lock);
 	purb=list_entry (p, urb_t, urb_list);
-	dbg ( /*KERN_DEBUG */ MODSTR "found queued urb: %p\n", purb);
+	dbg("found queued urb: %p", purb);
 
 	switch (usb_pipetype (purb->pipe)) {
 	case PIPE_CONTROL:
@@ -1899,7 +1890,7 @@
 
 	if (purb->status != USB_ST_URB_PENDING) {
 		int proceed = 0;
-		dbg ( /*KERN_DEBUG */ MODSTR "dequeued urb: %p\n", purb);
+		dbg("dequeued urb: %p", purb);
 		dequeue_urb (s, p, 1);
 
 #ifdef _UHCI_SLAB
@@ -1927,7 +1918,7 @@
 
 			// In case you need the current URB status for your completion handler
 			if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
-				dbg (KERN_DEBUG MODSTR "process_transfer: calling early completion\n");
+				dbg("process_transfer: calling early completion");
 				purb->complete ((struct urb *) purb);
 				if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED))
 					uhci_submit_urb (purb);
@@ -1945,7 +1936,7 @@
 				while (tmp != NULL && tmp != purb->next);	// submit until we reach NULL or our own pointer or submit fails
 
 				if (purb->complete && !(purb->transfer_flags & USB_URB_EARLY_COMPLETE)) {
-					dbg ( /*KERN_DEBUG */ MODSTR "process_transfer: calling completion\n");
+					dbg("process_transfer: calling completion");
 					purb->complete ((struct urb *) purb);
 				}
 			}
@@ -1956,7 +1947,7 @@
 	return ret;
 }
 
-_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
+static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
 {
 	puhci_t s = __uhci;
 	unsigned int io_addr = s->io_addr;
@@ -1967,14 +1958,14 @@
 	 * Read the interrupt status, and write it back to clear the
 	 * interrupt cause
 	 */
-	dbg ("interrupt\n");
+	dbg("interrupt");
 	status = inw (io_addr + USBSTS);
 
 	if (!status)		/* shared interrupt, not mine */
 		return;
 
 	if (status != 1) {
-		printk (KERN_DEBUG MODSTR "interrupt, status %x\n", status);
+		dbg("interrupt, status %x", status);
 		//uhci_show_status (s);
 	}
 	//beep(1000);           
@@ -2004,10 +1995,10 @@
 #ifdef __alpha
 	mb ();			// ?
 #endif
-	dbg ("done\n");
+	dbg("done");
 }
 
-_static void reset_hc (puhci_t s)
+static void reset_hc (puhci_t s)
 {
 	unsigned int io_addr = s->io_addr;
 
@@ -2019,7 +2010,7 @@
 	wait_ms (10);
 }
 
-_static void start_hc (puhci_t s)
+static void start_hc (puhci_t s)
 {
 	unsigned int io_addr = s->io_addr;
 	int timeout = 1000;
@@ -2034,7 +2025,7 @@
 
 	while (inw (io_addr + USBCMD) & USBCMD_HCRESET) {
 		if (!--timeout) {
-			printk (KERN_ERR MODSTR "USBCMD_HCRESET timed out!\n");
+			err("USBCMD_HCRESET timed out!");
 			break;
 		}
 	}
@@ -2051,7 +2042,7 @@
 	s->apm_state = 1;
 }
 
-_static void __exit uhci_cleanup_dev(puhci_t s)
+static void __exit uhci_cleanup_dev(puhci_t s)
 {
 	struct usb_device *root_hub = s->bus->root_hub;
 	if (root_hub)
@@ -2068,7 +2059,7 @@
 
 }
 
-_static int __init uhci_start_usb (puhci_t s)
+static int __init uhci_start_usb (puhci_t s)
 {				/* start it up */
 	/* connect the virtual root hub */
 	struct usb_device *usb_dev;
@@ -2088,7 +2079,7 @@
 	return 0;
 }
 
-_static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size)
+static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size)
 {
 	puhci_t s;
 	struct usb_bus *bus;
@@ -2127,17 +2118,17 @@
 		unsigned int portstatus;
 
 		portstatus = inw (io_addr + 0x10 + (s->maxports * 2));
-		printk ("port %i, adr %x status %x\n", s->maxports,
+		dbg("port %i, adr %x status %x", s->maxports,
 			io_addr + 0x10 + (s->maxports * 2), portstatus);
 		if (!(portstatus & 0x0080))
 			break;
 	}
-	dbg (KERN_DEBUG MODSTR "Detected %d ports\n", s->maxports);
+	dbg("Detected %d ports", s->maxports);
 
 	/* This is experimental so anything less than 2 or greater than 8 is */
 	/*  something weird and we'll ignore it */
 	if (s->maxports < 2 || s->maxports > 8) {
-		dbg (KERN_DEBUG "Port count misdetected, forcing to 2 ports\n");
+		dbg("Port count misdetected, forcing to 2 ports");
 		s->maxports = 2;
 	}
 
@@ -2156,7 +2147,7 @@
 	start_hc (s);
 
 	if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) {
-		printk(MODSTR KERN_ERR"request_irq %d failed!\n",irq);
+		err("request_irq %d failed!",irq);
 		usb_free_bus (bus);
 		reset_hc (s);
 		release_region (s->io_addr, s->io_size);
@@ -2178,7 +2169,7 @@
 	return 0;
 }
 
-_static int __init start_uhci (struct pci_dev *dev)
+static int __init start_uhci (struct pci_dev *dev)
 {
 	int i;
 
@@ -2210,16 +2201,16 @@
 }
 
 #ifdef CONFIG_APM
-_static int handle_apm_event (apm_event_t event)
+static int handle_apm_event (apm_event_t event)
 {
 	static int down = 0;
 	puhci_t s = devs;
-	printk ("handle_apm_event(%d)\n", event);
+	dbg("handle_apm_event(%d)", event);
 	switch (event) {
 	case APM_SYS_SUSPEND:
 	case APM_USER_SUSPEND:
 		if (down) {
-			dbg (KERN_DEBUG MODSTR "received extra suspend event\n");
+			dbg("received extra suspend event");
 			break;
 		}
 		while (s) {
@@ -2231,7 +2222,7 @@
 	case APM_NORMAL_RESUME:
 	case APM_CRITICAL_RESUME:
 		if (!down) {
-			dbg (KERN_DEBUG MODSTR "received bogus resume event\n");
+			dbg("received bogus resume event");
 			break;
 		}
 		down = 0;
@@ -2262,7 +2253,7 @@
 	uhci_desc_kmem = kmem_cache_create(slabname, sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!uhci_desc_kmem) {
-		printk(KERN_ERR MODSTR"kmem_cache_create for uhci_desc failed (out of memory)\n");
+		err("kmem_cache_create for uhci_desc failed (out of memory)");
 		return -ENOMEM;
 	}
 
@@ -2275,11 +2266,11 @@
 	urb_priv_kmem = kmem_cache_create(slabname, sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!urb_priv_kmem) {
-		printk(KERN_ERR MODSTR"kmem_cache_create for urb_priv_t failed (out of memory)\n");
+		err("kmem_cache_create for urb_priv_t failed (out of memory)");
 		return -ENOMEM;
 	}
 #endif	
-	printk (KERN_INFO MODSTR VERSTR "\n");
+	info(VERSTR);
 
 	for (;;) {
 		dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev);
@@ -2296,7 +2287,7 @@
 #endif
 		if(!dev->irq)
 		{
-			printk(KERN_ERR MODSTR"Found UHCI device with no IRQ assigned. Check BIOS settings!\n");
+			err("Found UHCI device with no IRQ assigned. Check BIOS settings!");
 			continue;
 		}
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.37/linux/drivers/usb/uhci.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/uhci.h	Thu Jan  6 16:17:19 2000
@@ -5,7 +5,6 @@
    $Id: uhci.h,v 1.30 1999/12/15 17:57:25 fliegl Exp $
  */
 #define MODNAME "usb-uhci"
-#define MODSTR MODNAME": "
 #define VERSTR "version v0.9 time " __TIME__ " " __DATE__
 
 /* Command register */
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c
--- v2.3.37/linux/drivers/usb/usb-debug.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb-debug.c	Thu Jan  6 16:17:19 2000
@@ -6,6 +6,9 @@
  */
 #include <linux/version.h>
 #include <linux/kernel.h>
+
+#define DEBUG
+
 #include "usb.h"
 
 static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.37/linux/drivers/usb/usb-serial.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/usb-serial.c	Thu Jan  6 16:17:19 2000
@@ -77,17 +77,9 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
-#include "usb.h"
-
-/*#define SERIAL_DEBUG 1*/
-
-#ifdef SERIAL_DEBUG
-	#define debug_info(format,arg...)	printk(KERN_DEBUG "USB Serial: " format "\n" , ##arg)
-#else
-	#define debug_info(format,arg...)	do {} while (0)
-#endif
-
+#undef DEBUG
 
+#include "usb.h"
 
 /* Module information */
 MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
@@ -393,18 +385,15 @@
        	unsigned char *data = urb->transfer_buffer;
 	int i;
 
-	debug_info("serial_read_irq");
+	dbg("serial_read_irq");
 
 	if (urb->status) {
-		debug_info("nonzero read bulk status received: %d", urb->status);
+		dbg("nonzero read bulk status received: %d", urb->status);
 		return;
 	}
 
-#ifdef SERIAL_DEBUG
-	if (urb->actual_length) {
-		debug_info("%d %s\n", urb->actual_length, data);
-	}
-#endif
+	if (urb->actual_length)
+		dbg("%d %s", urb->actual_length, data);
 
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
@@ -415,7 +404,7 @@
 
 	/* Continue trying to always read  */
 	if (usb_submit_urb(urb))
-		debug_info("failed resubmitting read urb");
+		dbg("failed resubmitting read urb");
 
 	return;
 }
@@ -426,10 +415,10 @@
 	struct usb_serial_state *serial = (struct usb_serial_state *) urb->context; 
        	struct tty_struct *tty = serial->tty; 
 
-	debug_info("serial_write_irq");
+	dbg("serial_write_irq");
 
 	if (urb->status) {
-		debug_info("nonzero write bulk status received: %d", urb->status);
+		dbg("nonzero write bulk status received: %d", urb->status);
 		return;
 	}
 
@@ -450,18 +439,18 @@
 {
 	struct usb_serial_state *serial;
 	
-	debug_info("serial_open");
+	dbg("serial_open");
 
 	/* assign a serial object to the tty pointer */
 	serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start];
 
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
 
@@ -481,23 +470,23 @@
 static void serial_close(struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	debug_info("serial_close");
+	dbg("serial_close");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return;
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return;
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return;
 	}
 	if (!serial->active) {
-		debug_info ("device already open");
+		dbg ("device already open");
 		return;
 	}
 
@@ -512,23 +501,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 	
-	debug_info("serial_write");
+	dbg("serial_write");
 
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->present) {
-		debug_info("device not registered");
+		dbg("device not registered");
 		return (-EINVAL);
 	}
 	if (!serial->active) {
-		debug_info ("device not opened");
+		dbg ("device not opened");
 		return (-EINVAL);
 	}
 	
@@ -546,23 +535,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 	
-	debug_info("serial_put_char");
+	dbg("serial_put_char");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return;
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return;
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return;
 	}
 	if (!serial->active) {
-		debug_info ("device not open");
+		dbg ("device not open");
 		return;
 	}
 
@@ -579,23 +568,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 
-	debug_info("serial_write_room");
+	dbg("serial_write_room");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return (-EINVAL);
 	}
 	if (!serial->active) {
-		debug_info ("device not open");
+		dbg ("device not open");
 		return (-EINVAL);
 	}
 	
@@ -612,23 +601,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 
-	debug_info("serial_chars_in_buffer");
+	dbg("serial_chars_in_buffer");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return (-EINVAL);
 	}
 	if (!serial->active) {
-		debug_info ("device not open");
+		dbg ("device not open");
 		return (-EINVAL);
 	}
 	
@@ -645,23 +634,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("serial_throttle");
+	dbg("serial_throttle");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return;
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return;
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return;
 	}
 	if (!serial->active) {
-		debug_info ("device not open");
+		dbg ("device not open");
 		return;
 	}
 
@@ -678,23 +667,23 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("serial_unthrottle");
+	dbg("serial_unthrottle");
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
-		debug_info("serial == NULL!");
+		dbg("serial == NULL!");
 		return;
 	}
 	if (!serial->type) {
-		debug_info("serial->type == NULL!");
+		dbg("serial->type == NULL!");
 		return;
 	}
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return;
 	}
 	if (!serial->active) {
-		debug_info ("device not open");
+		dbg ("device not open");
 		return;
 	}
 
@@ -715,22 +704,22 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("etek_serial_open");
+	dbg("etek_serial_open");
 
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return -EINVAL;
 	}
 
 	if (serial->active) {
-		debug_info ("device already open");
+		dbg ("device already open");
 		return -EINVAL;
 	}
 	serial->active = 1;
  
 	/*Start reading from the device*/
 	if (usb_submit_urb(&serial->read_urb))
-		debug_info("usb_submit_urb(read bulk) failed");
+		dbg("usb_submit_urb(read bulk) failed");
 
 	/* Need to do device specific setup here (control lines, baud rate, etc.) */
 	/* FIXME!!! */
@@ -742,7 +731,7 @@
 static void etek_serial_close(struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	debug_info("etek_serial_close");
+	dbg("etek_serial_close");
 	
 	/* Need to change the control lines here */
 	/* FIXME */
@@ -761,22 +750,22 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("whiteheat_serial_open");
+	dbg("whiteheat_serial_open");
 
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return -EINVAL;
 	}
 
 	if (serial->active) {
-		debug_info ("device already open");
+		dbg ("device already open");
 		return -EINVAL;
 	}
 	serial->active = 1;
  
 	/*Start reading from the device*/
 	if (usb_submit_urb(&serial->read_urb))
-		debug_info("usb_submit_urb(read bulk) failed");
+		dbg("usb_submit_urb(read bulk) failed");
 
 	/* Need to do device specific setup here (control lines, baud rate, etc.) */
 	/* FIXME!!! */
@@ -788,7 +777,7 @@
 static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	debug_info("whiteheat_serial_close");
+	dbg("whiteheat_serial_close");
 	
 	/* Need to change the control lines here */
 	/* FIXME */
@@ -802,7 +791,7 @@
 
 static void whiteheat_throttle (struct tty_struct * tty)
 {
-	debug_info("whiteheat_throttle");
+	dbg("whiteheat_throttle");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -813,7 +802,7 @@
 
 static void whiteheat_unthrottle (struct tty_struct * tty)
 {
-	debug_info("whiteheat_unthrottle");
+	dbg("whiteheat_unthrottle");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -828,15 +817,15 @@
 static int visor_serial_open (struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
-	debug_info("visor_serial_open");
+	dbg("visor_serial_open");
 
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return -EINVAL;
 	}
 
 	if (serial->active) {
-		debug_info ("device already open");
+		dbg ("device already open");
 		return -EINVAL;
 	}
 
@@ -844,7 +833,7 @@
 
 	/*Start reading from the device*/
 	if (usb_submit_urb(&serial->read_urb))
-		debug_info("usb_submit_urb(read bulk) failed");
+		dbg("usb_submit_urb(read bulk) failed");
 
 	return (0);
 }
@@ -853,7 +842,7 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
 	
-	debug_info("USB: visor_serial_close");
+	dbg("USB: visor_serial_close");
 			 
 	/* shutdown our bulk reads and writes */
 	usb_unlink_urb (&serial->write_urb);
@@ -866,7 +855,7 @@
 {
 /*	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
 
-	debug_info("visor_throttle");
+	dbg("visor_throttle");
 
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -878,7 +867,7 @@
 {
 /*	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
 
-	debug_info("visor_unthrottle");
+	dbg("visor_unthrottle");
 
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -894,15 +883,15 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("generic_serial_open");
+	dbg("generic_serial_open");
 
 	if (!serial->present) {
-		debug_info("no device registered");
+		dbg("no device registered");
 		return -EINVAL;
 	}
 
 	if (serial->active) {
-		debug_info ("device already open");
+		dbg ("device already open");
 		return -EINVAL;
 	}
 	serial->active = 1;
@@ -911,7 +900,7 @@
 	if (serial->num_bulk_in) {
 		/*Start reading from the device*/
 		if (usb_submit_urb(&serial->read_urb))
-			debug_info("usb_submit_urb(read bulk) failed");
+			dbg("usb_submit_urb(read bulk) failed");
 	}
 
 	return (0);
@@ -921,7 +910,7 @@
 static void generic_serial_close(struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	debug_info("generic_serial_close");
+	dbg("generic_serial_close");
 	
 	/* shutdown any bulk reads that might be going on */
 	if (serial->num_bulk_out) {
@@ -939,17 +928,17 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 	
-	debug_info("generic_serial_write");
+	dbg("generic_serial_write");
 
 	if (count == 0) {
-		debug_info("write request of 0 bytes");
+		dbg("write request of 0 bytes");
 		return (0);
 	}
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
 		if (serial->write_urb.status == -EINPROGRESS) {
-			debug_info ("already writing");
+			dbg ("already writing");
 			return (0);
 		}
 
@@ -966,7 +955,7 @@
 		serial->write_urb.transfer_buffer_length = count;
 
 		if (usb_submit_urb(&serial->write_urb))
-			debug_info("usb_submit_urb(write bulk) failed");
+			dbg("usb_submit_urb(write bulk) failed");
 
 		return (count);
 	}
@@ -980,7 +969,7 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 	
-	debug_info("generic_serial_put_char");
+	dbg("generic_serial_put_char");
 	
 	/* if we have a bulk out endpoint, then shove a character out it */
 	if (serial->num_bulk_out) {
@@ -989,7 +978,7 @@
 		serial->write_urb.transfer_buffer_length = 1;
 
 		if (usb_submit_urb(&serial->write_urb))
-			debug_info("usb_submit_urb(write bulk) failed");
+			dbg("usb_submit_urb(write bulk) failed");
 
 	}
 
@@ -1002,14 +991,14 @@
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 	int room;
 
-	debug_info("generic_write_room");
+	dbg("generic_write_room");
 	
 	if (serial->num_bulk_out) {
 		if (serial->write_urb.status == -EINPROGRESS)
 			room = 0;
 		else
 			room = serial->bulk_out_size[0];
-		debug_info("generic_write_room returns %d", room);
+		dbg("generic_write_room returns %d", room);
 		return (room);
 	}
 	
@@ -1021,7 +1010,7 @@
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
 
-	debug_info("generic_chars_in_buffer");
+	dbg("generic_chars_in_buffer");
 	
 	if (serial->num_bulk_out) {
 		if (serial->write_urb.status == -EINPROGRESS) {
@@ -1068,13 +1057,13 @@
 	device_num = 0;
 	while (usb_serial_devices[device_num] != NULL) {
 		type = usb_serial_devices[device_num];
-		debug_info ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
+		dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
 
 		/* look at the device descriptor */
 		if ((dev->descriptor.idVendor == *(type->idVendor)) &&
 		    (dev->descriptor.idProduct == *(type->idProduct))) {
 
-			debug_info("descriptor matches...looking at the endpoints");
+			dbg("descriptor matches...looking at the endpoints");
 
 			/* descriptor matches, let's try to find the endpoints needed */
 			interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
@@ -1087,7 +1076,7 @@
 				if ((endpoint->bEndpointAddress & 0x80) &&
 				    ((endpoint->bmAttributes & 3) == 0x02)) {
 					/* we found a bulk in endpoint */
-					debug_info("found bulk in");
+					dbg("found bulk in");
 					bulk_in_pipe = HAS;
 					bulk_in_endpoint[num_bulk_in] = endpoint;
 					++num_bulk_in;
@@ -1096,7 +1085,7 @@
 				if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
 				    ((endpoint->bmAttributes & 3) == 0x02)) {
 					/* we found a bulk out endpoint */
-					debug_info("found bulk out");
+					dbg("found bulk out");
 					bulk_out_pipe = HAS;
 					bulk_out_endpoint[num_bulk_out] = endpoint;
 					++num_bulk_out;
@@ -1105,7 +1094,7 @@
 				if ((endpoint->bEndpointAddress & 0x80) &&
 				    ((endpoint->bmAttributes & 3) == 0x03)) {
 					/* we found a interrupt in endpoint */
-					debug_info("found interrupt in");
+					dbg("found interrupt in");
 					interrupt_pipe = HAS;
 					interrupt_in_endpoint[num_interrupt_in] = endpoint;
 					++num_interrupt_in;
@@ -1118,10 +1107,10 @@
 			    (bulk_in_pipe & type->needs_bulk_in) &&
 			    (bulk_out_pipe & type->needs_bulk_out)) {
 				/* found all that we need */
-				printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name);
+				info("%s converter detected", type->name);
 
 				if (0>(serial_num = Get_Free_Serial())) {
-					debug_info("Too many devices connected");
+					dbg("Too many devices connected");
 					return NULL;
 				}
 	
@@ -1143,7 +1132,7 @@
 					serial->bulk_in_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[i]);
 					serial->bulk_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
 					if (!serial->bulk_in_buffer[i]) {
-						printk("USB Serial: Couldn't allocate bulk_in_buffer\n");
+						err("Couldn't allocate bulk_in_buffer");
 						goto probe_error;
 					}
 				}
@@ -1158,7 +1147,7 @@
 					serial->bulk_out_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint[i]);
 					serial->bulk_out_buffer[i] = kmalloc (serial->bulk_out_size[i], GFP_KERNEL);
 					if (!serial->bulk_out_buffer[i]) {
-						printk("USB Serial: Couldn't allocate bulk_out_buffer\n");
+						err("Couldn't allocate bulk_out_buffer");
 						goto probe_error;
 					}
 				}
@@ -1174,7 +1163,7 @@
 					/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
 					serial->interrupt_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
 					if (!serial->interrupt_in_buffer[i]) {
-						printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
+						err("Couldn't allocate interrupt_in_buffer");
 						goto probe_error;
 					}
 				}
@@ -1188,7 +1177,7 @@
 				/* set up our interrupt to be the time for the bulk in read */
 				ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
 				if (ret) {
-					printk(KERN_INFO "USB Serial: failed usb_request_irq (0x%x)\n", ret);
+					info("failed usb_request_irq (0x%x)", ret);
 					goto probe_error;
 				}
 				#endif
@@ -1196,10 +1185,10 @@
 				serial->present = 1;
 				MOD_INC_USE_COUNT;
 
-				printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num);
+				info("%s converter now attached to ttyUSB%d", type->name, serial_num);
 				return serial;
 			} else {
-				printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n");
+				info("descriptors matched, but endpoints did not");
 			}
 		}
 
@@ -1231,7 +1220,7 @@
 	if (serial) {
 		if (!serial->present) {
 			/* something strange is going on */
-			debug_info("disconnect but not present?");
+			dbg("disconnect but not present?");
 			return;
 			}
 
@@ -1253,10 +1242,10 @@
 		serial->present = 0;
 		serial->active = 0;
 
-		printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number);
+		info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->number);
 
 	} else {
-		printk (KERN_INFO "USB Serial: device disconnected.\n");
+		info("device disconnected");
 	}
 	
 	MOD_DEC_USE_COUNT;
@@ -1317,7 +1306,7 @@
 	serial_tty_driver.init_termios		= tty_std_termios;
 	serial_tty_driver.init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	if (tty_register_driver (&serial_tty_driver)) {
-		printk( "USB Serial: failed to register tty driver\n" );
+		err("failed to register tty driver");
 		return -EPERM;
 	}
 	
@@ -1327,7 +1316,7 @@
 		return -1;
 	}
 
-	printk(KERN_INFO "USB Serial: support registered.\n");
+	info("support registered");
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.37/linux/drivers/usb/usb.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/usb.c	Fri Jan  7 14:59:03 2000
@@ -18,8 +18,6 @@
  * $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $
  */
 
-#define USB_DEBUG	1
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -27,15 +25,9 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
 
-#include "usb.h"
-
-#define MODSTR "usbcore: "
+#define DEBUG
 
-#ifdef USB_DEBUG
-	#define dbg(format, arg...) printk(format, ## arg)
-#else
-	#define dbg(format, arg...)
-#endif
+#include "usb.h"
 
 /*
  * Prototypes for the device driver probing/loading functions
@@ -60,14 +52,13 @@
 
 	if (new_driver->fops != NULL) {
 		if (usb_minors[new_driver->minor/16]) {
-			 printk(KERN_ERR "Error registering %s driver\n",
-				new_driver->name);
+			 err("error registering %s driver", new_driver->name);
 			return -EINVAL;
 		}
 		usb_minors[new_driver->minor/16] = new_driver;
 	}
 
-	printk("usbcore: Registered new driver %s\n", new_driver->name);
+	info("registered new driver %s", new_driver->name);
 	/* Add it to the list of known drivers */
 	list_add(&new_driver->driver_list, &usb_driver_list);
 
@@ -97,7 +88,7 @@
 	int i;
 
 	if (!dev) {
-		printk(KERN_ERR "usbcore: null device being purged!!!\n");
+		err("null device being purged!!!");
 		return;
 	}
 
@@ -130,7 +121,7 @@
 {
 	struct list_head *tmp;
 
-	printk("usbcore: Deregistering driver %s\n", driver->name);
+	info("deregistering driver %s", driver->name);
 	if (driver->fops != NULL)
 		usb_minors[driver->minor/16] = NULL;
 
@@ -218,7 +209,7 @@
 	new_alloc = old_alloc + bustime;
 		/* what new total allocated bus time would be */
 
-	PRINTD ("usb-bandwidth-alloc: was: %u, new: %u, "
+	dbg("usb-bandwidth-alloc: was: %u, new: %u, "
 		"bustime = %ld us, Pipe allowed: %s",
 		old_alloc, new_alloc, bustime,
 		(new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ?
@@ -270,19 +261,19 @@
 		set_bit(busnum, busmap.busmap);
 		bus->busnum = busnum;
 	} else
-		printk(KERN_INFO "usb: too many buses\n");
+		warn("too many buses");
 
 	proc_usb_add_bus(bus);
 
 	/* Add it to the list of buses */
 	list_add(&bus->bus_list, &usb_bus_list);
 
-	printk("New USB bus registered, assigned bus number %d\n", bus->busnum);
+	info("new USB bus registered, assigned bus number %d", bus->busnum);
 }
 
 void usb_deregister_bus(struct usb_bus *bus)
 {
-	printk("usbcore: USB bus %d deregistered\n", bus->busnum);
+	info("USB bus %d deregistered", bus->busnum);
 
 	/*
 	 * NOTE: make sure that all the devices are removed by the
@@ -305,7 +296,7 @@
 	int i;
 
 	if (!dev) {
-		printk(KERN_ERR "usbcore: null device being checked!!!\n");
+		err("null device being checked!!!");
 		return;
 	}
 
@@ -335,7 +326,7 @@
 	if (!iface || !driver)
 		return;
 
-	printk(KERN_DEBUG "usbcore: %s driver claimed interface %p\n", driver->name, iface);
+	dbg("%s driver claimed interface %p", driver->name, iface);
 
 	iface->driver = driver;
 	iface->private_data = priv;
@@ -384,7 +375,7 @@
 	struct usb_interface *interface;
 	
 	if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
-		printk(KERN_ERR "usb-core: bad find_interface_driver params\n");
+		err("bad find_interface_driver params");
 		return -1;
 	}
 
@@ -428,7 +419,11 @@
 	}
  
 	if (rejected)
-		printk(KERN_DEBUG "usbcore: unhandled interfaces on device.\n");
+		dbg("unhandled interfaces on device");
+
+#ifdef DEBUG
+	usb_show_device(dev);
+#endif
 }
 
 /*
@@ -478,7 +473,7 @@
 	      in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 	if (!urb)
 	{
-		printk(KERN_ERR MODSTR"alloc_urb: kmalloc failed\n");
+		err("alloc_urb: kmalloc failed");
 		return 0;
 	}
 	memset(urb,0,sizeof(urb_t));
@@ -522,7 +517,7 @@
 		wake_up(awd->wakeup);
 #if 0
 	else
-		dbg(KERN_DEBUG MODSTR "(blocking_completion): waitqueue empty!\n"); 
+		dbg("(blocking_completion): waitqueue empty!"); 
 		// even occurs if urb was unlinked by timeout...
 #endif
 }
@@ -573,7 +568,7 @@
 
 	if (!status) {
 		// timeout
-		printk(KERN_DEBUG MODSTR"usb_control/bulk_msg: timeout\n");
+		dbg("usb_control/bulk_msg: timeout");
 		usb_unlink_urb(urb);  // remove urb safely
 		status=-ETIMEDOUT;
 	}
@@ -621,7 +616,7 @@
 	dr.value = cpu_to_le16p(&value);
 	dr.index = cpu_to_le16p(&index);
 	dr.length = cpu_to_le16p(&size);
-	//dbg(KERN_DEBUG MODSTR"usb_control_msg\n");	
+	//dbg("usb_control_msg");	
 	return usb_internal_control_msg(dev, pipe, &dr, data, size, timeout);
 }
 
@@ -683,7 +678,7 @@
 int usb_terminate_bulk(struct usb_device *dev, void *first)
 {
 	urb_t *urb=(urb_t*)first;
-	dbg(KERN_DEBUG MODSTR"usb_terminate_bulk: urb:%p\n",urb);
+	dbg("usb_terminate_bulk: urb:%p",urb);
 	if (!urb) // none found? there is nothing to remove!
 		return -ENODEV;
   
@@ -702,7 +697,7 @@
 {
 	dev->bus->bandwidth_allocated -= bw_alloc;
 	dev->bus->bandwidth_int_reqs--;
-	PRINTD ("bw_alloc reduced to %d for %d requesters",
+	dbg("bw_alloc reduced to %d for %d requesters",
 		dev->bus->bandwidth_allocated,
 		dev->bus->bandwidth_int_reqs +
 		dev->bus->bandwidth_isoc_reqs);
@@ -716,7 +711,7 @@
 		return;
 #if 0 // verbose...
 	if (!wd->handler(urb->status, urb->transfer_buffer, urb->actual_length, wd->context))
-		printk(KERN_ERR "usb: legacy irq callback returned 0!!!\n");
+		err("legacy irq callback returned 0!!!");
 #else
 	wd->handler(urb->status, urb->transfer_buffer, urb->actual_length, wd->context);
 #endif
@@ -732,7 +727,7 @@
 
 	*handle = NULL;
 	
-	//printk("irq: dev:%p pipe:%08X handler:%p period:%d dev_id:%p max:%d\n", dev, pipe, handler, period, dev_id, maxsze);
+	//dbg("irq: dev:%p pipe:%08X handler:%p period:%d dev_id:%p max:%d", dev, pipe, handler, period, dev_id, maxsze);
 	
 	/* Check host controller's bandwidth for this int. request. */
 	bustime = calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), 0,
@@ -776,7 +771,7 @@
 	if (!ret) {
 		dev->bus->bandwidth_allocated += bustime;
 		dev->bus->bandwidth_int_reqs++;
-		PRINTD ("bw_alloc bumped to %d for %d requesters",
+		dbg("bw_alloc bumped to %d for %d requesters",
 			dev->bus->bandwidth_allocated,
 			dev->bus->bandwidth_int_reqs +
 			dev->bus->bandwidth_isoc_reqs);
@@ -830,12 +825,12 @@
 	/* Everything should be fine being passed into here, but we sanity */
 	/*  check JIC */
 	if (header->bLength > size) {
-		printk(KERN_ERR "usb: ran out of descriptors parsing\n");
+		err("ran out of descriptors parsing");
 		return -1;
 	}
 		
 	if (header->bDescriptorType != USB_DT_ENDPOINT) {
-		printk(KERN_INFO "usb: unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n",
+		warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
 			endpoint->bDescriptorType, USB_DT_ENDPOINT);
 		return parsed;
 	}
@@ -859,7 +854,7 @@
 		header = (struct usb_descriptor_header *)buffer;
 
 		if (header->bLength < 2) {
-			printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength);
+			err("invalid descriptor length of %d", header->bLength);
 			return -1;
 		}
 
@@ -871,7 +866,7 @@
 		    (header->bDescriptorType == USB_DT_DEVICE))
 			break;
 
-		printk(KERN_INFO "usb: skipping descriptor 0x%X\n",
+		dbg("skipping descriptor 0x%X",
 			header->bDescriptorType);
 		numskipped++;
 
@@ -880,7 +875,7 @@
 		parsed += header->bLength;
 	}
 	if (numskipped)
-		printk(KERN_INFO "usb: skipped %d class/vendor specific endpoint descriptors\n", numskipped);
+		dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
 
 	/* Copy any unknown descriptors into a storage area for drivers */
 	/*  to later parse */
@@ -894,7 +889,7 @@
 	endpoint->extra = kmalloc(len, GFP_KERNEL);
 
 	if (!endpoint->extra) {
-		printk(KERN_ERR "Couldn't allocate memory for endpoint extra descriptors\n");
+		err("couldn't allocate memory for endpoint extra descriptors");
 		endpoint->extralen = 0;
 		return parsed;
 	}
@@ -919,7 +914,7 @@
 	interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
 	
 	if (!interface->altsetting) {
-		printk(KERN_ERR "couldn't kmalloc interface->altsetting\n");
+		err("couldn't kmalloc interface->altsetting");
 		return -1;
 	}
 
@@ -931,7 +926,7 @@
 			oldmas = interface->max_altsetting;
 			interface->max_altsetting += USB_ALTSETTINGALLOC;
 			if (interface->max_altsetting > USB_MAXALTSETTING) {
-				printk(KERN_WARNING "usb: too many alternate settings (max %d)\n",
+				warn("too many alternate settings (max %d)",
 					USB_MAXALTSETTING);
 				return -1;
 			}
@@ -939,7 +934,7 @@
 			ptr = interface->altsetting;
 			interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
 			if (!interface->altsetting) {
-				printk("couldn't kmalloc interface->altsetting\n");
+				err("couldn't kmalloc interface->altsetting");
 				interface->altsetting = ptr;
 				return -1;
 			}
@@ -966,7 +961,7 @@
 			header = (struct usb_descriptor_header *)buffer;
 
 			if (header->bLength < 2) {
-				printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength);
+				err("invalid descriptor length of %d", header->bLength);
 				return -1;
 			}
 
@@ -986,7 +981,7 @@
 		}
 
 		if (numskipped)
-			printk(KERN_INFO "usb: skipped %d class/vendor specific interface descriptors\n", numskipped);
+			dbg("skipped %d class/vendor specific interface descriptors", numskipped);
 
 		/* Copy any unknown descriptors into a storage area for */
 		/*  drivers to later parse */
@@ -998,7 +993,7 @@
 			ifp->extra = kmalloc(len, GFP_KERNEL);
 
 			if (!ifp->extra) {
-				printk(KERN_ERR "couldn't allocate memory for interface extra descriptors\n");
+				err("couldn't allocate memory for interface extra descriptors");
 				ifp->extralen = 0;
 				return -1;
 			}
@@ -1014,7 +1009,7 @@
 			return parsed;
 
 		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
-			printk(KERN_WARNING "usb: too many endpoints\n");
+			warn("too many endpoints");
 			return -1;
 		}
 
@@ -1022,7 +1017,7 @@
 			kmalloc(ifp->bNumEndpoints *
 			sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
 		if (!ifp->endpoint) {
-			printk(KERN_WARNING "usb: out of memory\n");
+			err("out of memory");
 			return -1;	
 		}
 
@@ -1033,7 +1028,7 @@
 			header = (struct usb_descriptor_header *)buffer;
 
 			if (header->bLength > size) {
-				printk(KERN_ERR "usb: ran out of descriptors parsing\n");
+				err("ran out of descriptors parsing");
 				return -1;
 			}
 		
@@ -1065,21 +1060,20 @@
 	struct usb_descriptor_header *header;
 
 	memcpy(config, buffer, USB_DT_INTERFACE_SIZE);
-	usb_show_config_descriptor(config);
 	le16_to_cpus(&config->wTotalLength);
 	size = config->wTotalLength;
 
 	if (config->bNumInterfaces > USB_MAXINTERFACES) {
-		printk(KERN_WARNING "usb: too many interfaces\n");
+		warn("too many interfaces");
 		return -1;
 	}
 
 	config->interface = (struct usb_interface *)
 		kmalloc(config->bNumInterfaces *
 		sizeof(struct usb_interface), GFP_KERNEL);
-	printk("kmalloc IF %p, numif %i\n",config->interface,config->bNumInterfaces);
+	dbg("kmalloc IF %p, numif %i",config->interface,config->bNumInterfaces);
 	if (!config->interface) {
-		printk(KERN_WARNING "usb: out of memory\n");
+		err("out of memory");
 		return -1;	
 	}
 
@@ -1092,12 +1086,12 @@
 	for (i = 0; i < config->bNumInterfaces; i++) {
 		header = (struct usb_descriptor_header *)buffer;
 		if (header->bLength > size) {
-			printk(KERN_ERR "usb: ran out of descriptors parsing\n");
+			err("ran out of descriptors parsing");
 			return -1;
 		}
 		
 		if (header->bDescriptorType != USB_DT_INTERFACE) {
-			printk(KERN_INFO "usb: unexpected descriptor 0x%X\n",
+			warn("unexpected descriptor 0x%X",
 				header->bDescriptorType);
 
 			buffer += header->bLength;
@@ -1187,7 +1181,7 @@
 		header = (struct usb_descriptor_header *)buffer;
 
 		if (header->bLength < 2) {
-			printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength);
+			err("invalid descriptor length of %d", header->bLength);
 			return -1;
 		}
 
@@ -1215,7 +1209,7 @@
 
 	*pdev = NULL;
 
-	printk("usbcore: USB disconnect on device %d\n", dev->devnum);
+	info("USB disconnect on device %d", dev->devnum);
 
 	if (dev->actconfig) {
 		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
@@ -1427,7 +1421,7 @@
 		}
 	}
 	if (!iface) {
-		printk(KERN_INFO "usb: selecting invalid interface %d\n", interface);
+		warn("selecting invalid interface %d", interface);
 		return -EINVAL;
 	}
 
@@ -1453,7 +1447,7 @@
 		}
 	}
 	if (!cp) {
-		printk(KERN_INFO "usb: selecting invalid configuration %d\n", configuration);
+		warn("selecting invalid configuration %d", configuration);
 		return -1;
 	}
 
@@ -1478,7 +1472,7 @@
 
 int usb_set_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 		USB_REQ_SET_REPORT, USB_RT_HIDD,
 		(type << 8) + id, index, buf, size, HZ);
 }
@@ -1493,7 +1487,7 @@
 		(struct usb_config_descriptor *)buffer;
 
 	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
-		printk(KERN_WARNING "usb: too many configurations\n");
+		warn("too many configurations");
 		return -1;
 	}
 
@@ -1501,7 +1495,7 @@
 		kmalloc(dev->descriptor.bNumConfigurations *
 		sizeof(struct usb_config_descriptor), GFP_KERNEL);
 	if (!dev->config) {
-		printk(KERN_WARNING "usb: out of memory.\n");
+		err("out of memory");
 		return -1;	
 	}
 	memset(dev->config, 0, dev->descriptor.bNumConfigurations *
@@ -1514,7 +1508,7 @@
 		/*  configuration is */
 		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
 		if (result < 0) {
-			printk(KERN_ERR "usb: unable to get descriptor\n");
+			err("unable to get descriptor");
 			goto err;
 		}
 
@@ -1523,7 +1517,7 @@
 
 		bigbuffer = kmalloc(desc->wTotalLength, GFP_KERNEL);
 		if (!bigbuffer) {
-			printk(KERN_ERR "unable to allocate memory for configuration descriptors\n");
+			err("unable to allocate memory for configuration descriptors");
 			result=-ENOMEM;
 			goto err;
 		}
@@ -1531,7 +1525,7 @@
 		/* Now that we know the length, get the whole thing */
 		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength);
 		if (result < 0) {
-			printk(KERN_ERR "couldn't get all of config descriptors\n");
+			err("couldn't get all of config descriptors");
 			kfree(bigbuffer);
 			goto err;
 		}		
@@ -1539,7 +1533,7 @@
 		kfree(bigbuffer);
 
 		if (result > 0)
-			printk(KERN_INFO "usb: descriptor data left\n");
+			dbg("descriptor data left");
 		else if (result < 0)
 		{
 			result=-1;
@@ -1573,14 +1567,14 @@
 		if (ret >= 0 && u.desc.bLength >= 4)
 			dev->string_langid = le16_to_cpup(&u.desc.wData[0]);
 		else
-			printk(KERN_ERR "usb: error getting string!\n");
+			err("error getting string");
 		dev->string_langid |= 0x10000;	/* so it's non-zero */
 	}
 
 	if (usb_get_string(dev, dev->string_langid, index, u.buffer, 4) < 0 ||
 	    ((ret = usb_get_string(dev, dev->string_langid, index, u.buffer,
 			      u.desc.bLength)) < 0)) {
-		printk(KERN_ERR "usb: error retrieving string\n");
+		err("error retrieving string");
 		return NULL;
 	}
 
@@ -1591,7 +1585,7 @@
 
 	ptr = kmalloc(len, GFP_KERNEL);
 	if (!ptr) {
-		printk(KERN_ERR "usb: couldn't allocate memory for string\n");
+		err("couldn't allocate memory for string");
 		return NULL;
 	}
 
@@ -1614,7 +1608,7 @@
 {
 	int addr, err;
 
-	printk(KERN_INFO "USB new device connect, assigned device number %d\n",
+	info("USB new device connect, assigned device number %d",
 		dev->devnum);
  
 	dev->maxpacketsize = 0;		/* Default to 8 byte max packet size */
@@ -1627,7 +1621,7 @@
 
 	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
 	if (err < 0) {
-		printk(KERN_ERR "usbcore: USB device not responding, giving up (error=%d)\n", err);
+		err("USB device not responding, giving up (error=%d)", err);
 		clear_bit(addr, &dev->bus->devmap.devicemap);
 		dev->devnum = -1;
 		return 1;
@@ -1647,7 +1641,7 @@
 	err = usb_set_address(dev);
 	
 	if (err < 0) {
-		printk(KERN_ERR "usbcore: USB device not accepting new address (error=%d)\n", err);
+		err("USB device not accepting new address (error=%d)", err);
 		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 		dev->devnum = -1;
 		return 1;
@@ -1657,7 +1651,7 @@
 
 	err = usb_get_device_descriptor(dev);
 	if (err < 0) {
-		printk(KERN_ERR "usbcore: unable to get device descriptor (error=%d)\n",err);
+		err("unable to get device descriptor (error=%d)",err);
 		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 		dev->devnum = -1;
 		return 1;
@@ -1666,7 +1660,7 @@
 	err=usb_get_configuration(dev);
 	
 	if (err < 0) {
-		printk(KERN_ERR "usbcore: unable to get configuration (error=%d)\n", err);
+		err("unable to get configuration (error=%d)", err);
 		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 		dev->devnum = -1;
 		return 1;
@@ -1677,7 +1671,7 @@
 
 	/* we set the default configuration here */
 	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		printk(KERN_ERR "usbcore: failed to set default configuration\n");
+		err("failed to set default configuration");
 		return -1;
 	}
 
@@ -1723,7 +1717,7 @@
 int usb_major_init(void)
 {
 	if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) {
-		printk("unable to get major %d for usb devices\n", USB_MAJOR);
+		err("unable to get major %d for usb devices", USB_MAJOR);
 		return -EBUSY;
 	}
 	return 0;
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.37/linux/drivers/usb/usb.h	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/usb.h	Fri Jan  7 15:32:00 2000
@@ -5,7 +5,6 @@
 #include <linux/ioctl.h>
 #include <linux/version.h>
 
-
 /* USB constants */
 
 /*
@@ -784,13 +783,15 @@
 void usb_show_device(struct usb_device *);
 void usb_show_string(struct usb_device *dev, char *id, int index);
 
-#ifdef USB_DEBUG
-#define PRINTD(format, args...) printk(KERN_DEBUG "usb: " format "\n" , ## args);
-#else /* NOT DEBUGGING */
-#define PRINTD(fmt, arg...) do {} while (0)
-#endif /* USB_DEBUG */
-/* A simple way to change one line from DEBUG to NOT DEBUG: */
-#define XPRINTD(fmt, arg...)	do {} while (0)
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n", ## arg)
+#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n", ## arg)
+#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n", ## arg)
+
 
 /*
  * procfs stuff
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
--- v2.3.37/linux/drivers/usb/usb_scsi.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/usb/usb_scsi.c	Fri Jan  7 16:07:14 2000
@@ -3,9 +3,6 @@
  * (c) 1999 Michael Gee (michael@linuxspecific.com)
  * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
- * In order to support various 'strange' devices, this module supports plug-in
- * device-specific filter modules, which can do their own thing when required.
- *
  * Further reference:
  *	This driver is based on the 'USB Mass Storage Class' document. This
  *	describes in detail the protocol used to communicate with such
@@ -29,7 +26,6 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
-#include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
@@ -55,25 +51,17 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-#ifdef REWRITE_PROJECT
-#define IRQ_PERIOD		255
-#else
-#define IRQ_PERIOD		0    /* single IRQ transfer then remove it */
-#endif
-
 /*
  * Per device data
  */
 
 static int my_host_number;
 
-int usbscsi_debug = 1;
+int usb_stor_debug = 1;
 
 struct us_data {
-	struct us_data		*next;		/* next device */
+	struct us_data	*next;		/* next device */
 	struct usb_device	*pusb_dev;
-	struct usb_scsi_filter	*filter;	/* filter driver */
-	void			*fdata;		/* filter data */
 	unsigned int		flags;		/* from filter initially */
 	__u8			ifnum;		/* interface number */
 	__u8			ep_in;		/* in endpoint */
@@ -115,19 +103,20 @@
 
 static struct us_data *us_list;
 
-static struct usb_scsi_filter *filters;
-
-static void * scsi_probe(struct usb_device *dev, unsigned int ifnum);
-static void scsi_disconnect(struct usb_device *dev, void *ptr);
-static struct usb_driver scsi_driver = {
-	"usb_scsi",
-	scsi_probe,
-	scsi_disconnect,
+static void * storage_probe(struct usb_device *dev, unsigned int ifnum);
+static void storage_disconnect(struct usb_device *dev, void *ptr);
+static struct usb_driver storage_driver = {
+	"usb-storage",
+	storage_probe,
+	storage_disconnect,
 	{ NULL, NULL }
 };
 
-/* Data handling, using SG if required */
+/***********************************************************************
+ * Data transfer routines
+ ***********************************************************************/
 
+/* transfer one buffer (breaking into packets if necessary) */
 static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
 {
 	int max_size = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)) * 16;
@@ -135,17 +124,23 @@
 	int result;
 	unsigned long partial;
 	int maxtry = 100;
+
+	/* while we have data to transfer */
 	while (length) {
+
+		/* calculate how long this will be -- maximum or a remainder */
 		this_xfer = length > max_size ? max_size : length;
 		length -= this_xfer;
+
 		do {
+			/* transfer the data */
 			US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer);
 			result = usb_bulk_msg(us->pusb_dev, pipe, buf,
 					      this_xfer, &partial, HZ*5);
-
 			US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n",
 				  result, partial, this_xfer);
 
+			/* if we stall, we need to clear it before we go on */
 			if (result == USB_ST_STALL) {
 				US_DEBUGP("clearing endpoint halt for pipe %x\n", pipe);
 				usb_clear_halt(us->pusb_dev,
@@ -154,33 +149,50 @@
 
 			/* we want to retry if the device reported NAK */
 			if (result == USB_ST_TIMEOUT) {
-				if (partial != this_xfer) {
-					return 0;   /* I do not like this */
-				}
+
+				/* if our try counter reaches 0, bail out */
 				if (!maxtry--)
 					break;
+
+				/* otherwise, we did transmit some data, and we update pointers */
 				this_xfer -= partial;
 				buf += partial;
+
 			} else if (!result && partial != this_xfer) {
-				/* short data - assume end */
+				/* result is an error, not a NAK, and short data - assume end */
 				result = USB_ST_DATAUNDERRUN;
 				break;
+
 			} else if (result == USB_ST_STALL && us->protocol == US_PR_CB) {
+				/* for CB devices, a stall isn't fatal? */
+
+				/* if our try counter reaches 0, bail out */
 				if (!maxtry--)
 					break;
+
 				this_xfer -= partial;
 				buf += partial;
-			} else
-				break;
+			} 
+
+			/* continue until this transfer is done */
 		} while ( this_xfer );
+
+		/* if we have some nonzero result, we return it here */
 		if (result)
 			return result;
+
+		/* otherwise, we advance the buf pointer
+		 * note that the code above doesn't advance the pointer if all
+		 * goes well
+		 */
 		buf += this_xfer;
 	}
 
+	/* if we get here, we're done and successful */
 	return 0;
 }
 
+/* transfer one SCSI command, using scatter-gather if requested */
 static int us_transfer(Scsi_Cmnd *srb, int dir_in)
 {
 	struct us_data *us = (struct us_data *)srb->host_scribble;
@@ -207,6 +219,9 @@
 	return result;
 }
 
+/* calculate the length of the data transfer (not the command) for any
+ * given SCSI command
+ */
 static unsigned int us_transfer_length(Scsi_Cmnd *srb)
 {
 	int i;
@@ -238,11 +253,15 @@
 		return srb->request_bufflen;
 }
 
-static int pop_CBI_irq(int state, void *buffer, int len, void *dev_id)
+/***********************************************************************
+ * Transport routines
+ ***********************************************************************/
+
+static int CBI_irq(int state, void *buffer, int len, void *dev_id)
 {
 	struct us_data *us = (struct us_data *)dev_id;
 
-	US_DEBUGP("pop_CBI_irq() called!!\n");
+	US_DEBUGP("CBI_irq() called!!\n");
 
 	if (state != USB_ST_REMOVED) {
 		us->ip_data = le16_to_cpup((__u16 *)buffer);
@@ -254,7 +273,7 @@
 		wake_up(&us->ip_waitq);
 	}
 
-	/* we don't want another interrupt */
+	/* this return code is truly meaningless */
 	return 0;
 }
 
@@ -458,7 +477,7 @@
 	int result;
 
 	US_DEBUGP("CBI gets a command:\n");
-	us_show_command(srb);
+	US_DEBUG(us_show_command(srb));
 
 	/* run the command */
 	if ((result = pop_CB_command(srb)) < 0) {
@@ -658,10 +677,8 @@
 		usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);
 		us->irq_handle = NULL;
 	}
-	if (us->filter)
-		us->filter->release(us->fdata);
 	if (us->pusb_dev)
-		usb_deregister(&scsi_driver);
+		usb_deregister(&storage_driver);
 
 	/* FIXME - leaves hanging host template copy */
 	/* (because scsi layer uses it after removal !!!) */
@@ -709,6 +726,7 @@
 {
 	struct us_data *us = (struct us_data *)srb->host->hostdata[0];
 
+	US_DEBUGP("Bus reset requested\n");
 	us->pop_reset(us);
 	return SUCCESS;
 }
@@ -726,7 +744,7 @@
 #undef SPRINTF
 #define SPRINTF(args...) do { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } while (0)
 
-int usb_scsi_proc_info (char *buffer, char **start, off_t offset, 
+int usb_stor_proc_info (char *buffer, char **start, off_t offset, 
 			int length, int hostno, int inout)
 {
 	struct us_data *us = us_list;
@@ -814,7 +832,7 @@
 	NULL,			    /* next */
 	NULL,			    /* module */
 	NULL,			    /* proc_dir */
-	usb_scsi_proc_info,
+	usb_stor_proc_info,
 	NULL,			    /* name - points to unique */
 	us_detect,
 	us_release,
@@ -861,7 +879,7 @@
 	0x00
 };
 
-static int usbscsi_control_thread(void * __us)
+static int usb_stor_control_thread(void * __us)
 {
 	struct us_data *us = (struct us_data *)__us;
 	int action;
@@ -872,9 +890,7 @@
 	 * This thread doesn't need any user-level access,
 	 * so get rid of all our resources..
 	 */
-	exit_mm(current);
-	exit_files(current);
-	//exit_fs(current);
+	daemonize();
 
 	sprintf(current->comm, "usbscsi%d", us->host_number);
 
@@ -911,11 +927,9 @@
 			} else {
 				US_DEBUG(us_show_command(us->srb));
 
-				if (us->filter && us->filter->command)
-					us->srb->result = us->filter->command(us->fdata, us->srb);
-				else if (us->srb->cmnd[0] == START_STOP &&
-					 us->pusb_dev->descriptor.idProduct == 0x0001 &&
-					 us->pusb_dev->descriptor.idVendor == 0x04e6)
+				if (us->srb->cmnd[0] == START_STOP &&
+				    us->pusb_dev->descriptor.idProduct == 0x0001 &&
+				    us->pusb_dev->descriptor.idVendor == 0x04e6)
 					us->srb->result = DID_OK << 16;
 				else {
 					unsigned int savelen = us->srb->request_bufflen;
@@ -1162,8 +1176,8 @@
 			spin_unlock_irq(&current->sigmask_lock);
 
 			if (signr == SIGUSR2) {
-				usbscsi_debug = !usbscsi_debug;
-				printk(USB_SCSI "debug toggle = %d\n", usbscsi_debug);
+				usb_stor_debug = !usb_stor_debug;
+				printk(USB_SCSI "debug toggle = %d\n", usb_stor_debug);
 			} else {
 				break;	    /* exit the loop on any other signal */
 			}
@@ -1172,14 +1186,13 @@
 
 	//  MOD_DEC_USE_COUNT;
 
-	printk("usbscsi_control_thread exiting\n");
+	printk("usb_stor_control_thread exiting\n");
 
 	return 0;
 }	
 
-
 /* Probe to see if a new device is actually a SCSI device */
-static void * scsi_probe(struct usb_device *dev, unsigned int ifnum)
+static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
 	int i;
@@ -1187,8 +1200,6 @@
 	char *prod;		     /* product */
 	char *serial;		     /* serial number */
 	struct us_data *ss = NULL;
-	struct usb_scsi_filter *filter = filters;
-	void *fdata = NULL;
 	unsigned int flags = 0;
 	GUID(guid);		     /* Global Unique Identifier */
 	struct us_data *prev;
@@ -1204,77 +1215,54 @@
 	prod = usb_string(dev, dev->descriptor.iProduct);
 	serial = usb_string(dev, dev->descriptor.iSerialNumber);
 
-	/* probe with filters first */
-	/* MDD: What are filters?  What do they do? 
-	 * They look like some way to catch certain specific devices and set
-	 * flags for them.  Probably a good idea if we have lots of different
-	 * types of devices.
-	 */
-	if (mf && prod) {
-		while (filter) {
-			if ((fdata = filter->probe(dev, mf, prod, serial)) != NULL) {
-				flags = filter->flags;
-				printk(KERN_INFO "USB Scsi filter %s\n", filter->name);
-				break;
-			}
-			filter = filter->next;
-		}
-	}
-
-	/* generic devices next */
-    
-	/* MDD: Isn't this always true? */
-	if (fdata == NULL) {
+	/* let's examine the device now */
 
-		/* We make an exception for the shuttle E-USB */
-		if (dev->descriptor.idVendor == 0x04e6 &&
-		    dev->descriptor.idProduct == 0x0001) {
-			protocol = US_PR_CB;
-			subclass = US_SC_8070;	    /* an assumption */
-		} else if (dev->descriptor.bDeviceClass != 0 ||
-			   altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
-			   altsetting->bInterfaceSubClass < US_SC_MIN ||
-			   altsetting->bInterfaceSubClass > US_SC_MAX) {
-			/* if it's not a mass storage, we go no further */
-			return NULL;
-		}
+	/* We make an exception for the shuttle E-USB */
+	if (dev->descriptor.idVendor == 0x04e6 &&
+	    dev->descriptor.idProduct == 0x0001) {
+		protocol = US_PR_CB;
+		subclass = US_SC_8070;	    /* an assumption */
+	} else if (dev->descriptor.bDeviceClass != 0 ||
+		   altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
+		   altsetting->bInterfaceSubClass < US_SC_MIN ||
+		   altsetting->bInterfaceSubClass > US_SC_MAX) {
+		/* if it's not a mass storage, we go no further */
+		return NULL;
+	}
 
-		/* At this point, we know we've got a live one */
-		US_DEBUGP("USB Mass Storage device detected\n");
+	/* At this point, we know we've got a live one */
+	US_DEBUGP("USB Mass Storage device detected\n");
 
-		/* Create a GUID for this device */
-		if (dev->descriptor.iSerialNumber &&
-		    usb_string(dev, dev->descriptor.iSerialNumber) ) {
-			/* If we have a serial number, and it's a non-NULL string */
-			make_guid(guid, dev->descriptor.idVendor, 
-				  dev->descriptor.idProduct,
-				  usb_string(dev, dev->descriptor.iSerialNumber));
-		} else {
-			/* We don't have a serial number, so we use 0 */
-			make_guid(guid, dev->descriptor.idVendor, 
-				  dev->descriptor.idProduct, "0");
-		}
+	/* Create a GUID for this device */
+	if (dev->descriptor.iSerialNumber &&
+	    usb_string(dev, dev->descriptor.iSerialNumber) ) {
+		/* If we have a serial number, and it's a non-NULL string */
+		make_guid(guid, dev->descriptor.idVendor, 
+			  dev->descriptor.idProduct,
+			  usb_string(dev, dev->descriptor.iSerialNumber));
+	} else {
+		/* We don't have a serial number, so we use 0 */
+		make_guid(guid, dev->descriptor.idVendor, 
+			  dev->descriptor.idProduct, "0");
+	}
 
-		/* Now check if we have seen this GUID before, and restore
-		 * the flags if we find it
-		 */
-		for (ss = us_list; ss != NULL; ss = ss->next) {
-			if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid))    {
-				US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
-					  GUID_ARGS(guid));
-				flags = ss->flags;
-				break;
-			}
+	/* Now check if we have seen this GUID before, and restore
+	 * the flags if we find it
+	 */
+	for (ss = us_list; ss != NULL; ss = ss->next) {
+		if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid))    {
+			US_DEBUGP("Found existing GUID " GUID_FORMAT "\n",
+				  GUID_ARGS(guid));
+			flags = ss->flags;
+			break;
 		}
-	} /* if (fdata == NULL) */
+	}
 
 	/* If ss == NULL, then this is a new device.  Allocate memory for it */
 	if (!ss) {
 		if ((ss = (struct us_data *)kmalloc(sizeof(*ss), 
 						    GFP_KERNEL)) == NULL) {
 			printk(KERN_WARNING USB_SCSI "Out of memory\n");
-			if (filter)
-				filter->release(fdata);
 			return NULL;
 		}
 		memset(ss, 0, sizeof(struct us_data));
@@ -1282,8 +1270,6 @@
 
 	/* Initialize the us_data structure with some useful info */
 	interface = altsetting;
-	ss->filter = filter;
-	ss->fdata = fdata;
 	ss->flags = flags;
 	ss->ifnum = ifnum;
 	ss->pusb_dev = dev;
@@ -1365,8 +1351,7 @@
 			kfree(ss->htmplt->name);
 			kfree(ss->htmplt);
 		}
-		if (filter)
-			filter->release(fdata);
+
 		kfree(ss);
 		return NULL;
 	}
@@ -1420,8 +1405,7 @@
 		     kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) {
 
 			printk(KERN_WARNING USB_SCSI "Out of memory\n");
-			if (filter)
-				filter->release(fdata);
+
 			kfree(ss);
 			return NULL;
 		}
@@ -1451,19 +1435,12 @@
 			US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]);
 			init_waitqueue_head(&ss->ip_waitq);
 			ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
-			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
-						 IRQ_PERIOD, (void *)ss, &ss->irq_handle);
+			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
+						 255, (void *)ss, &ss->irq_handle);
 			if (result)
 				return NULL;
 
 			interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
-#ifdef REWRITE_PROJECT
-			/* FIXME: Don't know if this release_irq() call is at the
-			   right place/time. */
-			usb_release_irq(ss->pusb_dev, ss->irq_handle, ss->irqpipe);
-			ss->irq_handle = NULL;
-#endif
-
 		} else if (ss->protocol == US_PR_CBI)
 		{
 			int result; 
@@ -1473,7 +1450,7 @@
 			/* set up the IRQ pipe and handler */
 			/* FIXME: This needs to get the period from the device */
 			ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
-			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
+			result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq,
 						 255, (void *)ss, &ss->irq_handle);
 			if (result) {
 				US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n",
@@ -1489,13 +1466,12 @@
 			init_waitqueue_head(&ss->waitq);
 
 			ss->notify = &sem;
-			ss->pid = kernel_thread(usbscsi_control_thread, ss,
+			ss->pid = kernel_thread(usb_stor_control_thread, ss,
 						CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 			if (ss->pid < 0) {
 				printk(KERN_WARNING USB_SCSI "Unable to start control thread\n");
 				kfree(htmplt);
-				if (filter)
-					filter->release(fdata);
+
 				kfree(ss);
 				return NULL;
 			}
@@ -1523,14 +1499,13 @@
 }
 
 /* Handle a disconnect event from the USB core */
-static void scsi_disconnect(struct usb_device *dev, void *ptr)
+static void storage_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct us_data *ss = ptr;
 
 	if (!ss)
 		return;
-	if (ss->filter)
-		ss->filter->release(ss->fdata);
+
 	ss->pusb_dev = NULL;
 	//  MOD_DEC_USE_COUNT;
 }
@@ -1540,49 +1515,26 @@
  * Initialization and registration
  ***********************************************************************/
 
-int usb_scsi_init(void)
+int usb_stor_init(void)
 {
 	//  MOD_INC_USE_COUNT;
 
-	if (usb_register(&scsi_driver) < 0)
+	if (usb_register(&storage_driver) < 0)
 		return -1;
 
 	printk(KERN_INFO "USB SCSI support registered.\n");
 	return 0;
 }
 
-/* Functions to handle filters.	 These are designed to allow us to handle
- * certain odd devices 
- */
-int usb_scsi_register(struct usb_scsi_filter *filter)
-{
-	struct usb_scsi_filter *prev = (struct usb_scsi_filter *)&filters;
-
-	while (prev->next)
-		prev = prev->next;
-	prev->next = filter;
-	return 0;
-}
-
-void usb_scsi_deregister(struct usb_scsi_filter *filter)
-{
-	struct usb_scsi_filter *prev = (struct usb_scsi_filter *)&filters;
-
-	while (prev->next && prev->next != filter)
-		prev = prev->next;
-	if (prev->next)
-		prev->next = filter->next;
-}
-
 #ifdef MODULE
 int init_module(void)
 {
 	/* MDD: Perhaps we should register the host here */
-	return usb_scsi_init();
+	return usb_stor_init();
 }
 
 void cleanup_module(void)
 {
-	usb_deregister(&scsi_driver);
+	usb_deregister(&storage_driver);
 }
 #endif
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usb_scsi.h linux/drivers/usb/usb_scsi.h
--- v2.3.37/linux/drivers/usb/usb_scsi.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb_scsi.h	Fri Jan  7 16:07:14 2000
@@ -15,13 +15,13 @@
 
 #define USB_SCSI "usbscsi: "
 
-extern int usbscsi_debug;
+extern int usb_stor_debug;
 
 #ifdef CONFIG_USB_SCSI_DEBUG
 void us_show_command(Scsi_Cmnd *srb);
-#define US_DEBUGP(x...) { if(usbscsi_debug) printk( KERN_DEBUG USB_SCSI ## x ); }
-#define US_DEBUGPX(x...) { if(usbscsi_debug) printk( ## x ); }
-#define US_DEBUG(x)  { if(usbscsi_debug) x; }
+#define US_DEBUGP(x...) { if(usb_stor_debug) printk( KERN_DEBUG USB_SCSI ## x ); }
+#define US_DEBUGPX(x...) { if(usb_stor_debug) printk( ## x ); }
+#define US_DEBUG(x)  { if(usb_stor_debug) x; }
 #else
 #define US_DEBUGP(x...)
 #define US_DEBUGPX(x...)
diff -u --recursive --new-file v2.3.37/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.3.37/linux/drivers/usb/usbkbd.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/usbkbd.c	Fri Jan  7 11:40:24 2000
@@ -40,7 +40,7 @@
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-	 27, 43,  0, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
 	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
@@ -79,14 +79,14 @@
 			if (usb_kbd_keycode[kbd->old[i]])
 				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
 			else
-				printk(KERN_DEBUG "usbkbd.c: Unknown key (scancode %#x) released.\n", kbd->old[i]);
+				info("Unknown key (scancode %#x) released.", kbd->old[i]);
 		}
 
 		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
 			if (usb_kbd_keycode[kbd->new[i]])
 				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
 			else
-				printk(KERN_DEBUG "usbkbd.c: Unknown key (scancode %#x) pressed.\n", kbd->new[i]);
+				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
 		}
 	}
 
diff -u --recursive --new-file v2.3.37/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.37/linux/drivers/video/atyfb.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/video/atyfb.c	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.134 1999/12/23 21:32:09 geert Exp $
+/*  $Id: atyfb.c,v 1.136 2000/01/06 23:53:29 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -3657,7 +3657,7 @@
     u16 tmp;
 #endif
 
-    while ((pdev = pci_find_device(PCI_VENDOR_ID_ATY, PCI_ANY_ID, pdev))) {
+    while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
 	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 	    struct resource *rp;
 
diff -u --recursive --new-file v2.3.37/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.3.37/linux/drivers/video/fbcon.c	Wed Dec 15 10:43:16 1999
+++ linux/drivers/video/fbcon.c	Fri Jan  7 12:59:42 2000
@@ -311,6 +311,10 @@
        fb_display[unit]._fontheightlog = fontheightlog;
        fb_display[unit].userfont = userfont;
        fb_display[unit].fb_info = newfb;
+       if (conp)
+	   conp->vc_display_fg = &newfb->display_fg;
+       if (!newfb->display_fg)
+	   newfb->display_fg = conp;
        if (!newfb->changevar)
            newfb->changevar = oldfb->changevar;
        /* tell console var has changed */
@@ -1167,8 +1171,12 @@
 
 static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
 {
-    unsigned short *p = (unsigned short *)
-    	(conp->vc_origin + t * conp->vc_size_row);
+    unsigned short *p;
+
+    if (conp->vc_num != fg_console)
+	return;
+    p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
+
     while (count) {
     	scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
     	count--;
diff -u --recursive --new-file v2.3.37/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.37/linux/drivers/video/fbmem.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/video/fbmem.c	Fri Jan  7 12:59:42 2000
@@ -110,6 +110,13 @@
 	int (*init)(void);
 	int (*setup)(char*);
 } fb_drivers[] __initdata = {
+#ifdef CONFIG_FB_SBUS
+	/*
+	 * Sbusfb must be initialized _before_ other frame buffer devices that
+	 * use PCI probing
+	 */
+	{ "sbus", sbusfb_init, sbusfb_setup },
+#endif
 #ifdef CONFIG_FB_3DFX
 	{ "tdfx", tdfxfb_init, tdfxfb_setup },
 #endif
@@ -153,9 +160,6 @@
 	 */
 	{ "offb", offb_init, offb_setup },
 #endif
-#ifdef CONFIG_FB_SBUS
-	{ "sbus", sbusfb_init, sbusfb_setup },
-#endif
 #ifdef CONFIG_FB_ATY128
 	{ "aty128fb", aty128fb_init, aty128fb_setup },
 #endif
@@ -225,9 +229,6 @@
 static int num_pref_init_funcs __initdata = 0;
 
 
-#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
-#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) 
-
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb = 0;
 extern int fbcon_softback_size; 
@@ -507,6 +508,24 @@
 #endif /* !sparc32 */
 }
 
+#if 1 /* to go away in 2.4.0 */
+int GET_FB_IDX(kdev_t rdev)
+{
+    int fbidx = MINOR(rdev);
+    if (fbidx >= 32) {
+	int newfbidx = fbidx >> 5;
+	static int warned = 0;
+	if (!(warned & (1<<newfbidx))) {
+	    warned |= 1<<newfbidx;
+	    printk("Warning: Remapping obsolete /dev/fb* minor %d to %d\n",
+		   fbidx, newfbidx);
+	}
+	fbidx = newfbidx;
+    }
+    return fbidx;
+}
+#endif
+
 static int
 fb_open(struct inode *inode, struct file *file)
 {
@@ -559,7 +578,7 @@
 	for (i = 0 ; i < FB_MAX; i++)
 		if (!registered_fb[i])
 			break;
-	fb_info->node=GET_INODE(i);
+	fb_info->node = MKDEV(FB_MAJOR, i);
 	registered_fb[i] = fb_info;
 	if (!fb_ever_opened[i]) {
 		/*
@@ -703,3 +722,6 @@
 
 EXPORT_SYMBOL(register_framebuffer);
 EXPORT_SYMBOL(unregister_framebuffer);
+#if 1 /* to go away in 2.4.0 */
+EXPORT_SYMBOL(GET_FB_IDX);
+#endif
diff -u --recursive --new-file v2.3.37/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.3.37/linux/drivers/video/matroxfb.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/video/matroxfb.c	Thu Jan  6 16:17:19 2000
@@ -6020,8 +6020,8 @@
 		u_int16_t sid;
 
 		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-		svid = dev->subsystem_vendor;
-		sid = dev->subsystem_device;
+		svid = pdev->subsystem_vendor;
+		sid = pdev->subsystem_device;
 		for (b = dev_list; b->vendor; b++) {
 			if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
 			if (b->svid)
diff -u --recursive --new-file v2.3.37/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.3.37/linux/fs/adfs/dir.c	Tue Dec  7 09:32:46 1999
+++ linux/fs/adfs/dir.c	Fri Jan  7 11:43:09 2000
@@ -31,8 +31,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/fs/adfs/file.c linux/fs/adfs/file.c
--- v2.3.37/linux/fs/adfs/file.c	Tue Dec  7 09:32:46 1999
+++ linux/fs/adfs/file.c	Fri Jan  7 11:43:09 2000
@@ -44,8 +44,6 @@
 	NULL,			/* release		*/
 	file_fsync,		/* fsync		*/
 	NULL,			/* fasync		*/
-	NULL,			/* check_media_change	*/
-	NULL			/* revalidate		*/
 };
 
 struct inode_operations adfs_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.3.37/linux/fs/affs/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/affs/file.c	Fri Jan  7 11:43:09 2000
@@ -56,8 +56,6 @@
 	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
@@ -95,8 +93,6 @@
 	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.3.37/linux/fs/autofs/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/autofs/dir.c	Fri Jan  7 11:43:09 2000
@@ -47,17 +47,6 @@
 	NULL,			/* read */
 	NULL,			/* write */
 	autofs_dir_readdir,	/* readdir */
-	NULL,			/* poll */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
 };
 
 struct inode_operations autofs_dir_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.3.37/linux/fs/autofs/root.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/autofs/root.c	Fri Jan  7 11:43:09 2000
@@ -30,15 +30,6 @@
         autofs_root_readdir,    /* readdir */
         NULL,                   /* poll */
         autofs_root_ioctl,	/* ioctl */
-        NULL,                   /* mmap */
-        NULL,                   /* open */
-	NULL,			/* flush */
-        NULL,                   /* release */
-        NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
 };
 
 struct inode_operations autofs_root_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/bad_inode.c linux/fs/bad_inode.c
--- v2.3.37/linux/fs/bad_inode.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/bad_inode.c	Fri Jan  7 11:43:09 2000
@@ -42,8 +42,7 @@
 	EIO_ERROR,		/* release */
 	EIO_ERROR,		/* fsync */
 	EIO_ERROR,		/* fasync */
-	EIO_ERROR,		/* check_media_change */
-	EIO_ERROR		/* revalidate */
+	EIO_ERROR,		/* lock */
 };
 
 struct inode_operations bad_inode_ops =
diff -u --recursive --new-file v2.3.37/linux/fs/bfs/dir.c linux/fs/bfs/dir.c
--- v2.3.37/linux/fs/bfs/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/bfs/dir.c	Fri Jan  7 11:43:09 2000
@@ -89,8 +89,6 @@
 	release:		NULL,
 	fsync:			file_fsync,
 	fasync:			NULL,
-	check_media_change:	NULL,
-	revalidate:		NULL,
 };
 
 extern void dump_imap(const char *, struct super_block *);
diff -u --recursive --new-file v2.3.37/linux/fs/bfs/file.c linux/fs/bfs/file.c
--- v2.3.37/linux/fs/bfs/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/bfs/file.c	Fri Jan  7 11:43:09 2000
@@ -34,8 +34,6 @@
 	release:		NULL,
 	fsync:			NULL,
 	fasync:			NULL,
-	check_media_change:	NULL,
-	revalidate:		NULL,
 };
 
 static int bfs_get_block(struct inode * inode, long block, 
diff -u --recursive --new-file v2.3.37/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.3.37/linux/fs/block_dev.c	Thu Jan  6 12:57:48 2000
+++ linux/fs/block_dev.c	Fri Jan  7 15:20:58 2000
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/locks.h>
 #include <linux/fcntl.h>
@@ -389,6 +390,7 @@
 		return NULL;
 	atomic_set(&new_bdev->bd_count,1);
 	new_bdev->bd_dev = dev;
+	new_bdev->bd_op = NULL;
 	spin_lock(&bdev_lock);
 	bdev = bdfind(dev, head);
 	if (!bdev) {
@@ -415,7 +417,7 @@
 
 static struct {
 	const char *name;
-	struct file_operations *bdops;
+	struct block_device_operations *bdops;
 } blkdevs[MAX_BLKDEV] = {
 	{ NULL, NULL },
 };
@@ -438,9 +440,9 @@
 	Return the function table of a device.
 	Load the driver if needed.
 */
-struct file_operations * get_blkfops(unsigned int major)
+static const struct block_device_operations * get_blkfops(unsigned int major)
 {
-	const struct file_operations *ret = NULL;
+	const struct block_device_operations *ret = NULL;
 
 	/* major 0 is used for non-device mounts */
 	if (major && major < MAX_BLKDEV) {
@@ -456,7 +458,7 @@
 	return ret;
 }
 
-int register_blkdev(unsigned int major, const char * name, struct file_operations *bdops)
+int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
 {
 	if (major == 0) {
 		for (major = MAX_BLKDEV-1; major > 0; major--) {
@@ -502,7 +504,7 @@
 int check_disk_change(kdev_t dev)
 {
 	int i;
-	const struct file_operations * bdops;
+	const struct block_device_operations * bdops;
 	struct super_block * sb;
 
 	i = MAJOR(dev);
@@ -530,17 +532,16 @@
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
 {
 	kdev_t rdev = to_kdev_t(bdev->bd_dev);
-	struct file_operations *fops = get_blkfops(MAJOR(rdev));
 	struct inode inode_fake;
 	int res;
 	mm_segment_t old_fs = get_fs();
 
-	if (!fops || !fops->ioctl)
+	if (!bdev->bd_op->ioctl)
 		return -EINVAL;
 	inode_fake.i_rdev=rdev;
 	init_waitqueue_head(&inode_fake.i_wait);
 	set_fs(KERNEL_DS);
-	res = fops->ioctl(&inode_fake, NULL, cmd, arg);
+	res = bdev->bd_op->ioctl(&inode_fake, NULL, cmd, arg);
 	set_fs(old_fs);
 	return res;
 }
@@ -549,9 +550,10 @@
 {
 	int ret = -ENODEV;
 	kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
-	struct file_operations *fops = get_blkfops(MAJOR(rdev));
 	down(&bdev->bd_sem);
-	if (fops) {
+	if (!bdev->bd_op)
+		bdev->bd_op = get_blkfops(MAJOR(rdev));
+	if (bdev->bd_op) {
 		/*
 		 * This crockload is due to bad choice of ->open() type.
 		 * It will go away.
@@ -567,8 +569,8 @@
 			fake_dentry.d_inode = fake_inode;
 			fake_inode->i_rdev = rdev;
 			ret = 0;
-			if (fops->open)
-				ret = fops->open(fake_inode, &fake_file);
+			if (bdev->bd_op->open)
+				ret = bdev->bd_op->open(fake_inode, &fake_file);
 			if (!ret)
 				atomic_inc(&bdev->bd_openers);
 			iput(fake_inode);
@@ -578,74 +580,83 @@
 	return ret;
 }
 
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+	int ret = -ENODEV;
+	struct block_device *bdev = inode->i_bdev;
+	down(&bdev->bd_sem);
+	if (!bdev->bd_op)
+		bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
+	if (bdev->bd_op) {
+		ret = 0;
+		if (bdev->bd_op->open)
+			ret = bdev->bd_op->open(inode,filp);
+		if (!ret)
+			atomic_inc(&bdev->bd_openers);
+	}	
+	up(&bdev->bd_sem);
+	return ret;
+}	
+
 int blkdev_put(struct block_device *bdev, int kind)
 {
 	int ret = 0;
 	kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
-	struct file_operations *fops = get_blkfops(MAJOR(rdev));
 	down(&bdev->bd_sem);
 	/* syncing will go here */
 	if (atomic_dec_and_test(&bdev->bd_openers)) {
 		/* invalidating buffers will go here */
 	}
-	if (fops->release) {
+	if (bdev->bd_op->release) {
 		struct inode * fake_inode = get_empty_inode();
 		ret = -ENOMEM;
 		if (fake_inode) {
 			fake_inode->i_rdev = rdev;
-			ret = fops->release(fake_inode, NULL);
+			ret = bdev->bd_op->release(fake_inode, NULL);
 			iput(fake_inode);
 		}
 	}
+	if (!atomic_read(&bdev->bd_openers))
+		bdev->bd_op = NULL;	/* we can't rely on driver being */
+					/* kind to stay around. */
 	up(&bdev->bd_sem);
 	return ret;
 }
 
-char * bdevname(kdev_t dev)
+static int blkdev_close(struct inode * inode, struct file * filp)
 {
-	static char buffer[32];
-	const char * name = blkdevs[MAJOR(dev)].name;
-
-	if (!name)
-		name = "unknown-block";
-
-	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
-	return buffer;
+	return blkdev_put(inode->i_bdev, BDEV_FILE);
 }
 
-/*
- * Called every time a block special file is opened
- */
-int blkdev_open(struct inode * inode, struct file * filp)
+static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+			unsigned long arg)
 {
-	int ret = -ENODEV;
-	filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
-	if (filp->f_op != NULL){
-		ret = 0;
-		if (filp->f_op->open != NULL)
-			ret = filp->f_op->open(inode,filp);
-	}	
-	return ret;
-}	
+	if (inode->i_bdev->bd_op->ioctl)
+		return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
+	return -EINVAL;
+}
 
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
 struct file_operations def_blk_fops = {
-	NULL,		/* lseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	blkdev_open,	/* open */
-	NULL,		/* flush */
-	NULL,		/* release */
+	open:		blkdev_open,
+	release:	blkdev_close,
+	read:		block_read,
+	write:		block_write,
+	fsync:		block_fsync,
+	ioctl:		blkdev_ioctl,
 };
 
 struct inode_operations blkdev_inode_operations = {
 	&def_blk_fops,		/* default file operations */
 };
+
+char * bdevname(kdev_t dev)
+{
+	static char buffer[32];
+	const char * name = blkdevs[MAJOR(dev)].name;
+
+	if (!name)
+		name = "unknown-block";
+
+	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+	return buffer;
+}
diff -u --recursive --new-file v2.3.37/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.37/linux/fs/buffer.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/buffer.c	Thu Jan  6 16:17:18 2000
@@ -1629,7 +1629,6 @@
 	int		offset;
 	unsigned long	blocknr;
 	struct kiobuf *	iobuf = NULL;
-	unsigned long	page;
 	struct page *	map;
 	struct buffer_head *tmp, *bh[KIO_MAX_SECTORS];
 
@@ -1661,11 +1660,6 @@
 
 		for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
 			map  = iobuf->maplist[pageind];
-			if (map && PageHighMem(map)) {
-				err = -EIO;
-				goto error;
-			}
-			page = page_address(map);
 
 			while (length > 0) {
 				blocknr = b[bufind++];
diff -u --recursive --new-file v2.3.37/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.3.37/linux/fs/coda/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/coda/dir.c	Fri Jan  7 11:43:09 2000
@@ -97,9 +97,6 @@
 	NULL,
         coda_release,           /* release */
 	coda_fsync,             /* fsync */
-        NULL,                   
-	NULL,
-	NULL
 };
 
 
diff -u --recursive --new-file v2.3.37/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.3.37/linux/fs/coda/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/coda/file.c	Fri Jan  7 11:43:09 2000
@@ -68,8 +68,6 @@
 	coda_release,           /* release */
 	coda_fsync,		/* fsync */
 	NULL,                   /* fasync */
-	NULL,                   /* check_media_change */
-	NULL,                   /* revalidate */
 	NULL                    /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.3.37/linux/fs/coda/psdev.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/coda/psdev.c	Fri Jan  7 11:43:09 2000
@@ -327,8 +327,6 @@
       coda_psdev_release,    /* release */
       NULL,                  /* fsync */
       NULL,                  /* fasync */
-      NULL,                  /* check_media_change */
-      NULL,                  /* revalidate */
       NULL                   /* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.37/linux/fs/cramfs/inode.c	Wed Dec 29 13:13:20 1999
+++ linux/fs/cramfs/inode.c	Fri Jan  7 11:43:09 2000
@@ -366,8 +366,6 @@
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 /*
@@ -386,8 +384,6 @@
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 static struct inode_operations cramfs_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/dcache.c linux/fs/dcache.c
--- v2.3.37/linux/fs/dcache.c	Wed Dec  8 14:11:27 1999
+++ linux/fs/dcache.c	Thu Jan  6 16:21:23 2000
@@ -410,7 +410,7 @@
  *  ...
  *   6 - base-level: try to shrink a bit.
  */
-int shrink_dcache_memory(int priority, unsigned int gfp_mask)
+int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone)
 {
 	if (gfp_mask & __GFP_IO) {
 		int count = 0;
diff -u --recursive --new-file v2.3.37/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.3.37/linux/fs/devpts/root.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/devpts/root.c	Fri Jan  7 11:43:09 2000
@@ -25,17 +25,6 @@
 	NULL,                   /* read */
 	NULL,                   /* write */
 	devpts_root_readdir,    /* readdir */
-	NULL,                   /* poll */
-	NULL,			/* ioctl */
-	NULL,                   /* mmap */
-	NULL,                   /* open */
-	NULL,			/* flush */
-	NULL,                   /* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
 };
 
 struct inode_operations devpts_root_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/efs/dir.c linux/fs/efs/dir.c
--- v2.3.37/linux/fs/efs/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/efs/dir.c	Fri Jan  7 11:43:09 2000
@@ -21,8 +21,6 @@
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
diff -u --recursive --new-file v2.3.37/linux/fs/efs/file.c linux/fs/efs/file.c
--- v2.3.37/linux/fs/efs/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/efs/file.c	Fri Jan  7 11:43:09 2000
@@ -74,8 +74,6 @@
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 struct inode_operations efs_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.3.37/linux/fs/ext2/dir.c	Wed Dec 15 10:43:17 1999
+++ linux/fs/ext2/dir.c	Fri Jan  7 11:43:09 2000
@@ -43,8 +43,6 @@
 	NULL,			/* no special release code */
 	ext2_sync_file,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 /*
diff -u --recursive --new-file v2.3.37/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.3.37/linux/fs/ext2/file.c	Wed Dec 15 10:43:17 1999
+++ linux/fs/ext2/file.c	Fri Jan  7 11:43:09 2000
@@ -29,9 +29,7 @@
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
 static long long ext2_file_lseek(struct file *, long long, int);
-#if BITS_PER_LONG < 64
 static int ext2_open_file (struct inode *, struct file *);
-#endif
 
 #define EXT2_MAX_SIZE(bits)							\
 	(((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + 				\
@@ -121,11 +119,11 @@
 	return 0;
 }
 
-#if BITS_PER_LONG < 64
 /*
  * Called when an inode is about to be open.
  * We use this to disallow opening RW large files on 32bit systems if
- * the caller didn't specify O_LARGEFILE.
+ * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
+ * on this flag in sys_open.
  */
 static int ext2_open_file (struct inode * inode, struct file * filp)
 {
@@ -133,7 +131,6 @@
 		return -EFBIG;
 	return 0;
 }
-#endif
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -147,17 +144,11 @@
 	NULL,			/* poll - default */
 	ext2_ioctl,		/* ioctl */
 	generic_file_mmap,	/* mmap */
-#if BITS_PER_LONG == 64	
-	NULL,			/* no special open is needed */
-#else
 	ext2_open_file,
-#endif
 	NULL,			/* flush */
 	ext2_release_file,	/* release */
 	ext2_sync_file,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 struct inode_operations ext2_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/fifo.c linux/fs/fifo.c
--- v2.3.37/linux/fs/fifo.c	Thu Jan  6 12:57:48 2000
+++ linux/fs/fifo.c	Fri Jan  7 11:43:09 2000
@@ -153,18 +153,7 @@
  * depending on the access mode of the file...
  */
 static struct file_operations def_fifo_fops = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	fifo_open,		/* will set read or write pipe_fops */
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	open:	fifo_open,	/* will set read or write pipe_fops */
 };
 
 struct inode_operations fifo_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c
--- v2.3.37/linux/fs/hfs/dir_cap.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/dir_cap.c	Fri Jan  7 11:43:09 2000
@@ -70,8 +70,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
 	NULL,			/* fasync - default */
-	NULL,			/* check_media_change - none */
-	NULL			/* revalidate - none */
 };
 
 struct inode_operations hfs_cap_ndir_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c
--- v2.3.37/linux/fs/hfs/dir_dbl.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/dir_dbl.c	Fri Jan  7 11:43:09 2000
@@ -69,8 +69,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
-        NULL,			/* check_media_change - none */
-        NULL			/* revalidate - none */
 };
 
 struct inode_operations hfs_dbl_dir_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c
--- v2.3.37/linux/fs/hfs/dir_nat.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/dir_nat.c	Fri Jan  7 11:43:09 2000
@@ -75,8 +75,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
-        NULL,			/* check_media_change - none */
-        NULL,			/* revalidate - none */
 	NULL                    /* lock - none */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/file.c linux/fs/hfs/file.c
--- v2.3.37/linux/fs/hfs/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/file.c	Fri Jan  7 11:43:09 2000
@@ -45,8 +45,6 @@
 	NULL,			/* release */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
-        NULL,			/* check_media_change - none */
-        NULL,			/* revalidate - none */
         NULL			/* lock - none */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c
--- v2.3.37/linux/fs/hfs/file_cap.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/file_cap.c	Fri Jan  7 11:43:09 2000
@@ -59,8 +59,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
 	NULL,			/* fasync - default */
-	NULL,			/* check_media_change - none */
-	NULL,			/* revalidate - none */
 	NULL			/* lock - none */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.3.37/linux/fs/hfs/file_hdr.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/hfs/file_hdr.c	Fri Jan  7 11:43:09 2000
@@ -60,8 +60,6 @@
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
-        NULL,			/* check_media_change - none */
-        NULL,			/* revalidate - none */
         NULL			/* lock - none */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/hpfs/inode.c linux/fs/hpfs/inode.c
--- v2.3.37/linux/fs/hpfs/inode.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/hpfs/inode.c	Fri Jan  7 11:43:09 2000
@@ -22,8 +22,6 @@
 	hpfs_file_release,		/* release */
 	hpfs_file_fsync,		/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL,				/* lock */
 };
 
@@ -63,8 +61,6 @@
 	hpfs_dir_release,		/* no special release code */
 	hpfs_file_fsync,		/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL,				/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/inode.c linux/fs/inode.c
--- v2.3.37/linux/fs/inode.c	Thu Jan  6 12:57:48 2000
+++ linux/fs/inode.c	Thu Jan  6 16:21:23 2000
@@ -395,7 +395,7 @@
 	dispose_list(freeable);
 }
 
-int shrink_icache_memory(int priority, int gfp_mask)
+int shrink_icache_memory(int priority, int gfp_mask, zone_t *zone)
 {
 	if (gfp_mask & __GFP_IO)
 	{
diff -u --recursive --new-file v2.3.37/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.3.37/linux/fs/minix/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/minix/file.c	Fri Jan  7 11:43:09 2000
@@ -53,8 +53,6 @@
 	NULL,			/* release */
 	minix_sync_file,	/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 struct inode_operations minix_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.3.37/linux/fs/nfs/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/nfs/file.c	Fri Jan  7 11:43:09 2000
@@ -53,8 +53,6 @@
 	nfs_release,		/* release */
 	nfs_fsync,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	nfs_lock,		/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.3.37/linux/fs/ntfs/fs.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/ntfs/fs.c	Fri Jan  7 11:43:09 2000
@@ -421,8 +421,6 @@
 	NULL, /* release */
 	NULL, /* fsync */
 	NULL, /* fasync */
-	NULL, /* check_media_change */
-	NULL, /* revalidate */
 	NULL, /* lock */
 };
 
@@ -602,8 +600,6 @@
 	NULL, /* release */
 	NULL, /* fsync */
 	NULL, /* fasync */
-	NULL, /* check_media_change */
-	NULL, /* revalidate */
 	NULL, /* lock */
 };
 
@@ -633,17 +629,6 @@
 	NULL, /* read */
 	NULL, /* write */
 	ntfs_readdir, /* readdir */
-	NULL, /* poll */
-	NULL, /* ioctl */
-	NULL, /* mmap */
-	NULL, /* open */
-	NULL, /* flush */
-	NULL, /* release */
-	NULL, /* fsync */
-	NULL, /* fasync */
-	NULL, /* check_media_change */
-	NULL, /* revalidate */
-	NULL, /* lock */
 };
 
 static struct inode_operations ntfs_dir_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/open.c linux/fs/open.c
--- v2.3.37/linux/fs/open.c	Wed Dec  8 14:11:28 1999
+++ linux/fs/open.c	Thu Jan  6 16:17:19 2000
@@ -789,6 +789,9 @@
 	char * tmp;
 	int fd, error;
 
+#if BITS_PER_LONG != 32
+	flags |= O_LARGEFILE;
+#endif
 	tmp = getname(filename);
 	fd = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
diff -u --recursive --new-file v2.3.37/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.37/linux/fs/proc/base.c	Wed Dec 29 13:13:20 1999
+++ linux/fs/proc/base.c	Fri Jan  7 12:59:42 2000
@@ -643,7 +643,7 @@
 	 * grab the reference to task.
 	 */
 	inode->u.proc_i.task = task;
-	atomic_inc(&mem_map[MAP_NR(task)].count);
+	get_task_struct(task);
 	if (!task->p_pptr)
 		goto out_unlock;
 
@@ -932,7 +932,7 @@
 	read_lock(&tasklist_lock);
 	task = find_task_by_pid(pid);
 	if (task)
-		atomic_inc(&mem_map[MAP_NR(task)].count);
+		get_task_struct(task);
 	read_unlock(&tasklist_lock);
 	if (!task)
 		goto out;
diff -u --recursive --new-file v2.3.37/linux/fs/proc/omirr.c linux/fs/proc/omirr.c
--- v2.3.37/linux/fs/proc/omirr.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/proc/omirr.c	Fri Jan  7 11:43:09 2000
@@ -272,8 +272,6 @@
     omirr_release,
     NULL,	/* fsync */
     NULL,       /* fasync */
-    NULL,       /* check_media_change */
-    NULL        /* revalidate */
 };
 
 struct inode_operations proc_omirr_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.37/linux/fs/romfs/inode.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/romfs/inode.c	Fri Jan  7 11:43:09 2000
@@ -459,8 +459,6 @@
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 static struct inode_operations romfs_file_inode_operations = {
@@ -489,16 +487,6 @@
         NULL,			/* read */
 	NULL,			/* write - bad */
 	romfs_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 /* Merged dir/symlink op table.  readdir/lookup/readlink/follow_link
diff -u --recursive --new-file v2.3.37/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.3.37/linux/fs/smbfs/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/smbfs/file.c	Fri Jan  7 11:43:09 2000
@@ -379,8 +379,6 @@
 	smb_file_release,	/* release(struct inode*, struct file*) */
 	smb_fsync,		/* fsync(struct file*, struct dentry*) */
 	NULL,			/* fasync(struct file*, int) */
-	NULL,			/* check_media_change(kdev_t dev) */
-	NULL,			/* revalidate(kdev_t dev) */
 	NULL			/* lock(struct file*, int, struct file_lock*) */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v2.3.37/linux/fs/sysv/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/sysv/file.c	Fri Jan  7 11:43:09 2000
@@ -57,8 +57,6 @@
 	NULL,			/* release */
 	sysv_sync_file,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 struct inode_operations sysv_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/udf/dir.c linux/fs/udf/dir.c
--- v2.3.37/linux/fs/udf/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/udf/dir.c	Fri Jan  7 11:43:09 2000
@@ -62,8 +62,6 @@
 	NULL,			/* release */
 	udf_sync_file,	/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 	NULL			/* lock */
 };
 
diff -u --recursive --new-file v2.3.37/linux/fs/udf/file.c linux/fs/udf/file.c
--- v2.3.37/linux/fs/udf/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/udf/file.c	Fri Jan  7 11:43:09 2000
@@ -46,31 +46,23 @@
 static loff_t udf_file_llseek(struct file *, loff_t, int);
 static ssize_t udf_file_read_adinicb (struct file *, char *, size_t, loff_t *);
 static ssize_t udf_file_write (struct file *, const char *, size_t, loff_t *);
-#if BITS_PER_LONG < 64
 static int udf_open_file(struct inode *, struct file *);
-#endif
 static int udf_release_file(struct inode *, struct file *);
 
 static struct file_operations udf_file_operations = {
 	udf_file_llseek,	/* llseek */
 	generic_file_read,	/* read */
 	udf_file_write,		/* write */
-	NULL,				/* readdir */
-	NULL,				/* poll */
-	udf_ioctl,			/* ioctl */
+	NULL,			/* readdir */
+	NULL,			/* poll */
+	udf_ioctl,		/* ioctl */
 	generic_file_mmap,	/* mmap */
-#if BITS_PER_LONG == 64
-	NULL, 				/* open */
-#else
 	udf_open_file,		/* open */
-#endif
-	NULL,				/* flush */
+	NULL,			/* flush */
 	udf_release_file,	/* release */
 	udf_sync_file,		/* fsync */
-	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
-	NULL				/* lock */
+	NULL,			/* fasync */
+	NULL			/* lock */
 };
 
 struct inode_operations udf_file_inode_operations = {
@@ -111,8 +103,6 @@
 	udf_release_file,	/* release */
 	udf_sync_file,		/* fsync */
 	NULL,				/* fasync */
-	NULL,				/* check_media_change */
-	NULL,				/* revalidate */
 	NULL				/* lock */
 };
 
@@ -426,7 +416,6 @@
 	return 0;
 }
 
-#if BITS_PER_LONG < 64
 /*
  * udf_open_file
  *
@@ -435,6 +424,7 @@
  *
  * DESCRIPTION
  *  Use this to disallow opening RW large files on 32 bit systems.
+ *  On 64 bit systems we force on O_LARGEFILE in sys_open.
  *
  * HISTORY
  *
@@ -445,4 +435,3 @@
 		return -EFBIG;
 	return 0;
 }
-#endif
diff -u --recursive --new-file v2.3.37/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.3.37/linux/fs/ufs/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/ufs/dir.c	Fri Jan  7 11:43:09 2000
@@ -190,8 +190,6 @@
 	NULL,			/* release */
 	file_fsync,		/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
 };
 
 struct inode_operations ufs_dir_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/fs/ufs/file.c linux/fs/ufs/file.c
--- v2.3.37/linux/fs/ufs/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/ufs/file.c	Fri Jan  7 11:43:09 2000
@@ -133,8 +133,6 @@
 	ufs_release_file,	/* release */
 	NULL, 			/* fsync */
 	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL			/* revalidate */
 };
 
 struct inode_operations ufs_file_inode_operations = {
diff -u --recursive --new-file v2.3.37/linux/include/asm-alpha/fcntl.h linux/include/asm-alpha/fcntl.h
--- v2.3.37/linux/include/asm-alpha/fcntl.h	Wed Oct 21 10:02:48 1998
+++ linux/include/asm-alpha/fcntl.h	Thu Jan  6 16:17:19 2000
@@ -20,6 +20,7 @@
 #define O_DIRECT	040000	/* direct disk access - should check with OSF/1 */
 #define O_DIRECTORY	0100000	/* must be a directory */
 #define O_NOFOLLOW	0200000 /* don't follow links */
+#define O_LARGEFILE	0400000 /* will be set by the kernel on every open */
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -u --recursive --new-file v2.3.37/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.3.37/linux/include/asm-alpha/processor.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-alpha/processor.h	Fri Jan  7 12:59:42 2000
@@ -145,6 +145,7 @@
 #define alloc_task_struct() \
         ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)     free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.3.37/linux/include/asm-arm/processor.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-arm/processor.h	Fri Jan  7 12:59:42 2000
@@ -117,7 +117,6 @@
 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 put_task_struct(p)	free_task_struct(p)
 #define free_task_struct(p)					\
  do {								\
 	if (atomic_dec_and_test(&(p)->thread.refcount))		\
diff -u --recursive --new-file v2.3.37/linux/include/asm-i386/checksum.h linux/include/asm-i386/checksum.h
--- v2.3.37/linux/include/asm-i386/checksum.h	Sun Dec 27 10:39:50 1998
+++ linux/include/asm-i386/checksum.h	Thu Jan  6 16:18:30 2000
@@ -48,24 +48,6 @@
 	return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
 }
 
-#if 0
-
-/* Not used at the moment. It is difficult to imagine for what purpose
-   it can be used :-) Please, do not forget to verify_area before it --ANK
- */
-
-/*
- * This combination is currently not used, but possible:
- */
-
-extern __inline__
-unsigned int csum_partial_copy_to_user ( const char *src, char *dst,
-					int len, int sum, int *err_ptr)
-{
-	return csum_partial_copy_generic ( src, dst, len, sum, NULL, err_ptr);
-}
-#endif
-
 /*
  * These are the old (and unsafe) way of doing checksums, a warning message will be
  * printed if they are used and an exeption occurs.
diff -u --recursive --new-file v2.3.37/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.3.37/linux/include/asm-i386/processor.h	Thu Nov 11 20:11:51 1999
+++ linux/include/asm-i386/processor.h	Fri Jan  7 15:30:13 2000
@@ -413,6 +413,7 @@
 #define THREAD_SIZE (2*PAGE_SIZE)
 #define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p) free_pages((unsigned long) (p), 1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.3.37/linux/include/asm-m68k/processor.h	Thu Nov 18 20:25:38 1999
+++ linux/include/asm-m68k/processor.h	Fri Jan  7 12:59:42 2000
@@ -152,6 +152,7 @@
 #define alloc_task_struct() \
 	((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)	free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.3.37/linux/include/asm-mips/processor.h	Thu Nov 11 20:11:52 1999
+++ linux/include/asm-mips/processor.h	Fri Jan  7 12:59:42 2000
@@ -221,6 +221,7 @@
 #define alloc_task_struct() \
 	((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)	free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.37/linux/include/asm-ppc/processor.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-ppc/processor.h	Fri Jan  7 12:59:42 2000
@@ -326,6 +326,7 @@
 #define alloc_task_struct() \
 	((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)	free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 /* in process.c - for early bootup debug -- Cort */
 int ll_printk(const char *, ...);
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc/checksum.h linux/include/asm-sparc/checksum.h
--- v2.3.37/linux/include/asm-sparc/checksum.h	Sun Mar 21 07:23:38 1999
+++ linux/include/asm-sparc/checksum.h	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.29 1999/03/21 05:22:07 davem Exp $ */
+/* $Id: checksum.h,v 1.30 2000/01/05 21:27:39 davem Exp $ */
 #ifndef __SPARC_CHECKSUM_H
 #define __SPARC_CHECKSUM_H
 
@@ -30,7 +30,7 @@
  *
  * it's best to have buff aligned on a 32-bit boundary
  */
-extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 
 /* the same as csum_partial, but copies from fs:src while it
  * checksums
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.37/linux/include/asm-sparc/processor.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc/processor.h	Fri Jan  7 12:59:42 2000
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.73 1999/12/15 14:18:52 davem Exp $
+/* $Id: processor.h,v 1.75 2000/01/07 20:21:42 davem Exp $
  * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -204,6 +204,8 @@
 
 #define alloc_task_struct() BTFIXUP_CALL(alloc_task_struct)()
 #define free_task_struct(tsk) BTFIXUP_CALL(free_task_struct)(tsk)
+
+/* XXX Anton, here is where you implement get_task_struct et al. */
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v2.3.37/linux/include/asm-sparc/unistd.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc/unistd.h	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.59 1999/12/21 14:09:43 jj Exp $ */
+/* $Id: unistd.h,v 1.60 2000/01/05 07:37:50 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -276,15 +276,15 @@
 type name(void) \
 { \
 long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
-		      "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
 		      : "=r" (__res)\
-		      : "0" (__NR_##name) \
-		      : "g1", "o0", "cc"); \
+		      : "r" (__g1) \
+		      : "o0", "cc"); \
 if (__res < -255 || __res >= 0) \
     return (type) __res; \
 errno = -__res; \
@@ -295,16 +295,16 @@
 type name(type1 arg1) \
 { \
 long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
-		      "or %%g0, %1, %%o0\n\t" \
-		      "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)) \
-		      : "g1", "o0", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__g1) \
+		      : "cc"); \
 if (__res < -255 || __res >= 0) \
 	return (type) __res; \
 errno = -__res; \
@@ -315,17 +315,17 @@
 type name(type1 arg1,type2 arg2) \
 { \
 long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
-		      "or %%g0, %1, %%o0\n\t" \
-		      "or %%g0, %2, %%o1\n\t" \
-		      "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \
-		      : "g1", "o0", "o1", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__g1) \
+		      : "cc"); \
 if (__res < -255 || __res >= 0) \
 	return (type) __res; \
 errno = -__res; \
@@ -336,20 +336,18 @@
 type name(type1 arg1,type2 arg2,type3 arg3) \
 { \
 long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
-		      "or %%g0, %1, %%o0\n\t" \
-		      "or %%g0, %2, %%o1\n\t" \
-		      "or %%g0, %3, %%o2\n\t" \
-		      "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
-		        "=r" ((long)(arg3)) \
-		      : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \
-		        "3" ((long)(arg3)) \
-		      : "g1", "o0", "o1", "o2", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+		      : "cc"); \
 if (__res < -255 || __res>=0) \
 	return (type) __res; \
 errno = -__res; \
@@ -360,21 +358,19 @@
 type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
 { \
 long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
-		      "or %%g0, %1, %%o0\n\t" \
-		      "or %%g0, %2, %%o1\n\t" \
-		      "or %%g0, %3, %%o2\n\t" \
-		      "or %%g0, %4, %%o3\n\t" \
-		      "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
-		      "sub %%g0,%%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
+		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
-		        "=r" ((long)(arg3)), "=r" ((long)(arg4)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
-		        "3" ((long)(arg3)),"4" ((long)(arg4)) \
-		      : "g1", "o0", "o1", "o2", "o3", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+		      : "cc"); \
 if (__res < -255 || __res>=0) \
 	return (type) __res; \
 errno = -__res; \
@@ -385,24 +381,21 @@
 	  type5,arg5) \
 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 { \
-      long __res; \
-\
-__asm__ __volatile__ ("or %%g0, %1, %%o0\n\t" \
-		      "or %%g0, %2, %%o1\n\t" \
-		      "or %%g0, %3, %%o2\n\t" \
-		      "or %%g0, %4, %%o3\n\t" \
-		      "or %%g0, %5, %%o4\n\t" \
-		      "or %%g0, %6, %%g1\n\t" \
-		      "t 0x10\n\t" \
+long __res; \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+register long __o4 __asm__ ("o4") = (long)(arg5); \
+__asm__ __volatile__ ("t 0x10\n\t" \
 		      "bcc 1f\n\t" \
-		      "or %%g0, %%o0, %0\n\t" \
+		      "mov %%o0, %0\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "1:\n\t" \
-		      : "=r" (__res) \
-		      : "r" ((long)(arg1)),"r" ((long)(arg2)), \
-		        "r" ((long)(arg3)),"r" ((long)(arg4)),"r" ((long)(arg5)), \
-		        "i" (__NR_##name)  \
-		      : "g1", "o0", "o1", "o2", "o3", "o4", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+		      : "cc"); \
 if (__res < -255 || __res>=0) \
 	return (type) __res; \
 errno = -__res; \
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc64/checksum.h linux/include/asm-sparc64/checksum.h
--- v2.3.37/linux/include/asm-sparc64/checksum.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/checksum.h	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.13 1999/07/30 09:31:13 davem Exp $ */
+/* $Id: checksum.h,v 1.14 2000/01/05 21:27:42 davem Exp $ */
 #ifndef __SPARC64_CHECKSUM_H
 #define __SPARC64_CHECKSUM_H
 
@@ -29,7 +29,7 @@
  *
  * it's best to have buff aligned on a 32-bit boundary
  */
-extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 
 /* the same as csum_partial, but copies from user space while it
  * checksums
@@ -67,7 +67,7 @@
 }
 
 #if 0
-/* Not implemented, but nobody uses it yet... */
+/* XXX should implement this now... -DaveM */
 extern __inline__ unsigned int 
 csum_partial_copy_to_user(const char *src, char *dst, int len, 
 			  unsigned int sum, int *err)
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc64/fcntl.h linux/include/asm-sparc64/fcntl.h
--- v2.3.37/linux/include/asm-sparc64/fcntl.h	Tue Oct 27 09:52:21 1998
+++ linux/include/asm-sparc64/fcntl.h	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.5 1998/10/26 20:03:15 davem Exp $ */
+/* $Id: fcntl.h,v 1.7 2000/01/04 23:54:58 davem Exp $ */
 #ifndef _SPARC64_FCNTL_H
 #define _SPARC64_FCNTL_H
 
@@ -19,6 +19,7 @@
 #define O_NOCTTY	0x8000	/* not fcntl */
 #define O_DIRECTORY	0x10000	/* must be a directory */
 #define O_NOFOLLOW	0x20000	/* don't follow links */
+#define O_LARGEFILE	0x40000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.3.37/linux/include/asm-sparc64/processor.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/processor.h	Fri Jan  7 12:59:42 2000
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.58 1999/12/15 14:19:14 davem Exp $
+/* $Id: processor.h,v 1.60 2000/01/07 20:21:45 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -257,6 +257,7 @@
 /* Allocation and freeing of task_struct and kernel stack. */
 #define alloc_task_struct()   ((struct task_struct *)__get_free_pages(GFP_KERNEL, 1))
 #define free_task_struct(tsk) free_pages((unsigned long)(tsk),1)
+#define get_task_struct(tsk)      atomic_inc(&mem_map[MAP_NR(tsk)].count)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.37/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.3.37/linux/include/asm-sparc64/unistd.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/unistd.h	Thu Jan  6 16:17:19 2000
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.36 1999/12/21 14:09:51 jj Exp $ */
+/* $Id: unistd.h,v 1.37 2000/01/05 07:37:55 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -276,13 +276,13 @@
 type name(void) \
 { \
 long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
-		      "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+__asm__ __volatile__ ("t 0x6d\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
 		      : "=r" (__res)\
-		      : "0" (__NR_##name) \
-		      : "g1", "o0", "cc"); \
+		      : "r" (__g1) \
+		      : "o0", "cc"); \
 if (__res >= 0) \
     return (type) __res; \
 errno = -__res; \
@@ -293,14 +293,14 @@
 type name(type1 arg1) \
 { \
 long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
-		      "mov %1, %%o0\n\t" \
-		      "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)) \
-		      : "g1", "o0", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__g1) \
+		      : "cc"); \
 if (__res >= 0) \
 	return (type) __res; \
 errno = -__res; \
@@ -311,15 +311,15 @@
 type name(type1 arg1,type2 arg2) \
 { \
 long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
-		      "mov %1, %%o0\n\t" \
-		      "mov %2, %%o1\n\t" \
-		      "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \
-		      : "g1", "o0", "o1", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__g1) \
+		      : "cc"); \
 if (__res >= 0) \
 	return (type) __res; \
 errno = -__res; \
@@ -330,18 +330,16 @@
 type name(type1 arg1,type2 arg2,type3 arg3) \
 { \
 long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
-		      "mov %1, %%o0\n\t" \
-		      "mov %2, %%o1\n\t" \
-		      "mov %3, %%o2\n\t" \
-		      "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
-		        "=r" ((long)(arg3)) \
-		      : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \
-		        "3" ((long)(arg3)) \
-		      : "g1", "o0", "o1", "o2", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+		      : "cc"); \
 if (__res>=0) \
 	return (type) __res; \
 errno = -__res; \
@@ -352,19 +350,17 @@
 type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
 { \
 long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
-		      "mov %1, %%o0\n\t" \
-		      "mov %2, %%o1\n\t" \
-		      "mov %3, %%o2\n\t" \
-		      "mov %4, %%o3\n\t" \
-		      "t 0x6d\n\t" \
-		      "sub %%g0,%%o0, %0\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
+		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
-		      : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
-		        "=r" ((long)(arg3)), "=r" ((long)(arg4)) \
-		      : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
-		        "3" ((long)(arg3)),"4" ((long)(arg4)) \
-		      : "g1", "o0", "o1", "o2", "o3", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+		      : "cc"); \
 if (__res>=0) \
 	return (type) __res; \
 errno = -__res; \
@@ -375,22 +371,19 @@
 	  type5,arg5) \
 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 { \
-      long __res; \
-\
-__asm__ __volatile__ ("mov %1, %%o0\n\t" \
-		      "mov %2, %%o1\n\t" \
-		      "mov %3, %%o2\n\t" \
-		      "mov %4, %%o3\n\t" \
-		      "mov %5, %%o4\n\t" \
-		      "mov %6, %%g1\n\t" \
-		      "t 0x6d\n\t" \
+long __res; \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+register long __o4 __asm__ ("o4") = (long)(arg5); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
 		      "sub %%g0, %%o0, %0\n\t" \
 		      "movcc %%xcc, %%o0, %0\n\t" \
-		      : "=r" (__res) \
-		      : "r" ((long)(arg1)),"r" ((long)(arg2)), \
-		        "r" ((long)(arg3)),"r" ((long)(arg4)),"r" ((long)(arg5)), \
-		        "i" (__NR_##name)  \
-		      : "g1", "o0", "o1", "o2", "o3", "o4", "cc"); \
+		      : "=r" (__res), "=&r" (__o0) \
+		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+		      : "cc"); \
 if (__res>=0) \
 	return (type) __res; \
 errno = -__res; \
diff -u --recursive --new-file v2.3.37/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.3.37/linux/include/linux/blk.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/blk.h	Fri Jan  7 15:32:20 2000
@@ -361,16 +361,6 @@
 #elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
 
 #define DEVICE_NAME "ida"
-#define DEVICE_INTR do_ida
-#define TIMEOUT_VALUE (25*HZ)
-#define DEVICE_REQUEST do_ida_request0
-#define DEVICE_NR(device) (MINOR(device) >> 4)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
-
-#define DEVICE_NAME "ida"
 #define TIMEOUT_VALUE (25*HZ)
 #define DEVICE_REQUEST do_ida_request0
 #define DEVICE_NR(device) (MINOR(device) >> 4)
diff -u --recursive --new-file v2.3.37/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v2.3.37/linux/include/linux/cdrom.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/cdrom.h	Fri Jan  7 15:30:13 2000
@@ -763,8 +763,8 @@
 			       struct cdrom_generic_command *);
 };
 
-/* the general file operations structure: */
-extern struct file_operations cdrom_fops;
+/* the general block_device operations structure: */
+extern struct block_device_operations cdrom_fops;
 
 extern int register_cdrom(struct cdrom_device_info *cdi);
 extern int unregister_cdrom(struct cdrom_device_info *cdi);
diff -u --recursive --new-file v2.3.37/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.3.37/linux/include/linux/dcache.h	Sat Oct  9 11:47:50 1999
+++ linux/include/linux/dcache.h	Thu Jan  6 16:21:23 2000
@@ -136,13 +136,13 @@
 extern int d_invalidate(struct dentry *);
 
 #define shrink_dcache() prune_dcache(0)
-
+struct zone_struct;
 /* dcache memory management */
-extern int shrink_dcache_memory(int, unsigned int);
+extern int shrink_dcache_memory(int, unsigned int, struct zone_struct *);
 extern void prune_dcache(int);
 
 /* icache memory management (defined in linux/fs/inode.c) */
-extern int shrink_icache_memory(int, int);
+extern int shrink_icache_memory(int, int, struct zone_struct *);
 extern void prune_icache(int);
 
 /* only used at mount-time */
diff -u --recursive --new-file v2.3.37/linux/include/linux/errqueue.h linux/include/linux/errqueue.h
--- v2.3.37/linux/include/linux/errqueue.h	Mon Apr 26 12:19:37 1999
+++ linux/include/linux/errqueue.h	Fri Jan  7 15:31:50 2000
@@ -1,8 +1,6 @@
 #ifndef _LINUX_ERRQUEUE_H
 #define _LINUX_ERRQUEUE_H 1
 
-#include <linux/config.h>
-
 struct sock_extended_err
 {
 	__u32	ee_errno;	
@@ -22,6 +20,9 @@
 #define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
 
 #ifdef __KERNEL__
+
+#include <linux/config.h>
+
 #define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb))
 
 struct sock_exterr_skb
diff -u --recursive --new-file v2.3.37/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.37/linux/include/linux/fb.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/fb.h	Fri Jan  7 12:59:42 2000
@@ -6,12 +6,8 @@
 
 /* Definitions of frame buffers						*/
 
-#define FB_MAJOR	29
-
-#define FB_MODES_SHIFT		5	/* 32 modes per framebuffer */
-#define FB_NUM_MINORS		256	/* 256 Minors               */
-#define FB_MAX			(FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
-#define GET_FB_IDX(node)	(MINOR(node) >> FB_MODES_SHIFT)
+#define FB_MAJOR		29
+#define FB_MAX			32	/* sufficient for now */
 
 /* ioctls
    0x46 is 'F'								*/
@@ -210,6 +206,12 @@
 };
 
 #ifdef __KERNEL__
+
+#if 1 /* to go away in 2.4.0 */
+extern int GET_FB_IDX(kdev_t rdev);
+#else
+#define GET_FB_IDX(node)	(MINOR(node))
+#endif
 
 #include <linux/fs.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.3.37/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.37/linux/include/linux/fs.h	Thu Jan  6 12:57:48 2000
+++ linux/include/linux/fs.h	Fri Jan  7 15:30:15 2000
@@ -346,7 +346,7 @@
 /*	struct address_space	bd_data; */
 	dev_t			bd_dev;  /* not a kdev_t - it's a search key */
 	atomic_t		bd_openers;
-/*	struct bdev_operations *bd_op; */
+	const struct block_device_operations *bd_op;
 	struct semaphore	bd_sem;	/* open/close mutex */
 };
 
@@ -615,7 +615,15 @@
  * to have different dirent layouts depending on the binary type.
  */
 typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t);
-	
+
+struct block_device_operations {
+	int (*open) (struct inode *, struct file *);
+	int (*release) (struct inode *, struct file *);
+	int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
+	int (*check_media_change) (kdev_t);
+	int (*revalidate) (kdev_t);
+};
+
 struct file_operations {
 	loff_t (*llseek) (struct file *, loff_t, int);
 	ssize_t (*read) (struct file *, char *, size_t, loff_t *);
@@ -629,8 +637,6 @@
 	int (*release) (struct inode *, struct file *);
 	int (*fsync) (struct file *, struct dentry *);
 	int (*fasync) (int, struct file *, int);
-	int (*check_media_change) (kdev_t dev);
-	int (*revalidate) (kdev_t dev);
 	int (*lock) (struct file *, int, struct file_lock *);
 };
 
@@ -758,7 +764,7 @@
 
 enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
 extern void kill_fasync(struct fasync_struct *, int, int);
-extern int register_blkdev(unsigned int, const char *, struct file_operations *);
+extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bdput(struct block_device *);
diff -u --recursive --new-file v2.3.37/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.37/linux/include/linux/ide.h	Mon Dec 20 18:48:22 1999
+++ linux/include/linux/ide.h	Fri Jan  7 15:30:18 2000
@@ -789,7 +789,7 @@
 void ide_init_subdrivers (void);
 
 #ifndef _IDE_C
-extern struct file_operations ide_fops[];
+extern struct block_device_operations ide_fops[];
 extern ide_proc_entry_t generic_subdriver_entries[];
 #endif
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/if.h linux/include/linux/if.h
--- v2.3.37/linux/include/linux/if.h	Thu Apr 15 16:28:58 1999
+++ linux/include/linux/if.h	Thu Jan  6 16:18:30 2000
@@ -39,36 +39,11 @@
 
 #define IFF_MULTICAST	0x1000		/* Supports multicast		*/
 
-#define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ALLMULTI)
+#define IFF_VOLATILE	(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
 
 #define IFF_PORTSEL	0x2000          /* can set media type		*/
 #define IFF_AUTOMEDIA	0x4000		/* auto media select active	*/
 #define IFF_DYNAMIC	0x8000		/* dialup device with changing addresses*/
-
-#ifdef __KERNEL__
-/*
- * The ifaddr structure contains information about one address
- * of an interface.  They are maintained by the different address
- * families, are allocated and attached when an address is set,
- * and are linked together so all addresses for an interface can
- * be located.
- */
- 
-struct ifaddr 
-{
-	struct sockaddr	ifa_addr;	/* address of interface		*/
-	union {
-		struct sockaddr	ifu_broadaddr;
-		struct sockaddr	ifu_dstaddr;
-	} ifa_ifu;
-	struct iface		*ifa_ifp;	/* back-pointer to interface	*/
-	struct ifaddr		*ifa_next;	/* next address for interface	*/
-};
-
-#define	ifa_broadaddr	ifa_ifu.ifu_broadaddr	/* broadcast address	*/
-#define	ifa_dstaddr	ifa_ifu.ifu_dstaddr	/* other end of link	*/
-
-#endif /* __KERNEL__ */ 
 
 /*
  *	Device mapping structure. I'd just gone off and designed a 
diff -u --recursive --new-file v2.3.37/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.3.37/linux/include/linux/if_arp.h	Tue Nov 23 22:42:21 1999
+++ linux/include/linux/if_arp.h	Fri Jan  7 16:57:13 2000
@@ -78,6 +78,8 @@
 	/* 787->799 reserved for fibrechannel media types */
 #define ARPHRD_IEEE802_TR 800		/* Magic type ident for TR	*/
 
+#define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
+
 /* ARP protocol opcodes. */
 #define	ARPOP_REQUEST	1		/* ARP request			*/
 #define	ARPOP_REPLY	2		/* ARP reply			*/
diff -u --recursive --new-file v2.3.37/linux/include/linux/input.h linux/include/linux/input.h
--- v2.3.37/linux/include/linux/input.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/input.h	Fri Jan  7 15:32:00 2000
@@ -147,7 +147,7 @@
 #define KEY_KP3			81		
 #define KEY_KP0			82		
 #define KEY_KPDOT		83		
-
+#define KEY_103RD		84
 #define KEY_F13			85		
 #define KEY_102ND		86		
 #define KEY_F11			87		
@@ -207,7 +207,6 @@
 #define KEY_CALC		140		
 #define KEY_SETUP		141		
 #define KEY_SLEEP		142		
-
 #define KEY_WAKEUP		143		
 #define KEY_FILE		144		
 #define KEY_SENDFILE		145		
@@ -220,7 +219,11 @@
 #define KEY_COFFEE		152		
 #define KEY_DIRECTION		153		
 #define KEY_CYCLEWINDOWS	154		
-
+#define KEY_MAIL		155
+#define KEY_BOOKMARKS		156
+#define KEY_COMPUTER		157
+#define KEY_BACK		158
+#define KEY_FORWARD		159
 #define KEY_CLOSECD		160		
 #define KEY_EJECTCD		161		
 #define KEY_EJECTCLOSECD	162		
diff -u --recursive --new-file v2.3.37/linux/include/linux/ip.h linux/include/linux/ip.h
--- v2.3.37/linux/include/linux/ip.h	Wed Aug 18 16:44:22 1999
+++ linux/include/linux/ip.h	Fri Jan  7 15:31:23 2000
@@ -88,6 +88,8 @@
 #define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
 #define	IPOPT_TS_PRESPEC	3		/* specified modules only */
 
+#ifdef __KERNEL__
+
 struct ip_options {
   __u32		faddr;				/* Saved first hop address */
   unsigned char	optlen;
@@ -108,7 +110,6 @@
   unsigned char __data[0];
 };
 
-#ifdef __KERNEL__
 #define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
 #endif
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/irda.h linux/include/linux/irda.h
--- v2.3.37/linux/include/linux/irda.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/irda.h	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Mar  8 14:06:12 1999
- * Modified at:   Tue Dec 21 09:00:59 1999
+ * Modified at:   Sat Dec 25 16:06:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -20,9 +20,6 @@
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
- *     You probably need to include <sys/types.h> before this one if your
- *     including this file from user-space 
- *
  ********************************************************************/
 
 #ifndef KERNEL_IRDA_H
@@ -100,22 +97,22 @@
 #define LSAP_ANY              0xff
 
 struct sockaddr_irda {
-	sa_family_t   sir_family;   /* AF_IRDA */
-	u_int8_t      sir_lsap_sel; /* LSAP selector */
-	u_int32_t     sir_addr;     /* Device address */
-	char          sir_name[25]; /* Usually <service>:IrDA:TinyTP */
+	sa_family_t sir_family;   /* AF_IRDA */
+	__u8        sir_lsap_sel; /* LSAP selector */
+	__u32       sir_addr;     /* Device address */
+	char        sir_name[25]; /* Usually <service>:IrDA:TinyTP */
 };
 
 struct irda_device_info {
-	u_int32_t     saddr;    /* Address of local interface */
-	u_int32_t     daddr;    /* Address of remote device */
-	char          info[22]; /* Description */
-	u_int8_t      charset;  /* Charset used for description */
-	u_int8_t      hints[2]; /* Hint bits */
+	__u32       saddr;    /* Address of local interface */
+	__u32       daddr;    /* Address of remote device */
+	char        info[22]; /* Description */
+	__u8        charset;  /* Charset used for description */
+	__u8        hints[2]; /* Hint bits */
 };
 
 struct irda_device_list {
-       u_int32_t len;
+       __u32 len;
        struct irda_device_info dev[1];
 };
 
@@ -127,12 +124,12 @@
 		unsigned int irda_attrib_int;
 		struct {
 			unsigned short len;
-			u_char OctetSeq[IAS_MAX_OCTET_STRING];
+			__u8 octet_seq[IAS_MAX_OCTET_STRING];
 		} irda_attrib_octet_seq;
 		struct {
-			unsigned char len;
-			unsigned char charset;
-			unsigned char string[IAS_MAX_STRING];
+			__u8 len;
+			__u8 charset;
+			__u8 string[IAS_MAX_STRING];
 		} irda_attrib_string;
 	} attribute;
 };
@@ -165,8 +162,8 @@
 
 /* For setting RTS and DTR lines of a dongle */
 struct if_irda_line {
-	unsigned char dtr;
-	unsigned char rts;
+	__u8 dtr;
+	__u8 rts;
 };
 
 /* IrDA interface configuration (data part must not exceed 16 bytes) */
diff -u --recursive --new-file v2.3.37/linux/include/linux/isapnp.h linux/include/linux/isapnp.h
--- v2.3.37/linux/include/linux/isapnp.h	Thu Nov 18 20:25:38 1999
+++ linux/include/linux/isapnp.h	Fri Jan  7 15:30:16 2000
@@ -103,6 +103,13 @@
 	struct isapnp_mem32 *next;	/* next 32-bit memory resource */
 };
 
+struct isapnp_fixup {
+	unsigned short vendor;		/* matching vendor */
+	unsigned short device;		/* matching device */
+	void (*quirk_function)(struct pci_dev *dev);	/* fixup function */
+};
+
+
 #define ISAPNP_RES_PRIORITY_PREFERRED	0
 #define ISAPNP_RES_PRIORITY_ACCEPTABLE	1
 #define ISAPNP_RES_PRIORITY_FUNCTIONAL	2
@@ -137,6 +144,8 @@
 void isapnp_device(unsigned char device);
 void isapnp_activate(unsigned char device);
 void isapnp_deactivate(unsigned char device);
+void isapnp_fixup_device(struct pci_dev *dev);
+void *isapnp_alloc(long size);
 /* manager */
 struct pci_bus *isapnp_find_card(unsigned short vendor,
 				 unsigned short device,
diff -u --recursive --new-file v2.3.37/linux/include/linux/major.h linux/include/linux/major.h
--- v2.3.37/linux/include/linux/major.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/major.h	Fri Jan  7 14:11:21 2000
@@ -103,6 +103,8 @@
 #define COMPAQ_SMART2_MAJOR6	78
 #define COMPAQ_SMART2_MAJOR7	79
 
+#define LVM_BLK_MAJOR	58	/* Logical Volume Manager */
+
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.37/linux/include/linux/mm.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/mm.h	Fri Jan  7 15:30:19 2000
@@ -183,7 +183,6 @@
 #define ClearPageError(page)	clear_bit(PG_error, &(page)->flags)
 #define PageReferenced(page)	test_bit(PG_referenced, &(page)->flags)
 #define PageDecrAfter(page)	test_bit(PG_decr_after, &(page)->flags)
-#define PageDMA(page)		(contig_page_data.node_zones + ZONE_DMA == (page)->zone)
 #define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
 #define PageSwapCache(page)	test_bit(PG_swap_cache, &(page)->flags)
 #define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
@@ -432,10 +431,11 @@
 extern int do_munmap(unsigned long, size_t);
 extern unsigned long do_brk(unsigned long, unsigned long);
 
+struct zone_t;
 /* filemap.c */
 extern void remove_inode_page(struct page *);
 extern unsigned long page_unuse(struct page *);
-extern int shrink_mmap(int, int);
+extern int shrink_mmap(int, int, zone_t *);
 extern void truncate_inode_pages(struct inode *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
diff -u --recursive --new-file v2.3.37/linux/include/linux/mmzone.h linux/include/linux/mmzone.h
--- v2.3.37/linux/include/linux/mmzone.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/mmzone.h	Fri Jan  7 15:30:13 2000
@@ -25,6 +25,8 @@
 	unsigned int * map;
 } free_area_t;
 
+struct pglist_data;
+
 typedef struct zone_struct {
 	/*
 	 * Commonly accessed fields:
@@ -34,6 +36,7 @@
 	unsigned long free_pages;
 	int low_on_memory;
 	unsigned long pages_low, pages_high;
+	struct pglist_data *zone_pgdat;
 
 	/*
 	 * free areas of different sizes
@@ -80,6 +83,10 @@
 } pg_data_t;
 
 extern int numnodes;
+
+#define memclass(pgzone, tzone)	(((pgzone)->zone_pgdat == (tzone)->zone_pgdat) \
+			&& (((pgzone) - (pgzone)->zone_pgdat->node_zones) <= \
+			((tzone) - (pgzone)->zone_pgdat->node_zones)))
 
 #ifndef CONFIG_DISCONTIGMEM
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.37/linux/include/linux/netdevice.h	Wed Dec 29 13:13:21 1999
+++ linux/include/linux/netdevice.h	Fri Jan  7 16:57:13 2000
@@ -24,7 +24,6 @@
 #ifndef _LINUX_NETDEVICE_H
 #define _LINUX_NETDEVICE_H
 
-#include <linux/config.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
@@ -32,6 +31,7 @@
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
+#include <linux/config.h>
 #ifdef CONFIG_NET_PROFILE
 #include <net/profile.h>
 #endif
@@ -269,6 +269,7 @@
 	struct Qdisc		*qdisc;
 	struct Qdisc		*qdisc_sleeping;
 	struct Qdisc		*qdisc_list;
+	struct Qdisc		*qdisc_ingress;
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 
 	/* hard_start_xmit synchronizer */
diff -u --recursive --new-file v2.3.37/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.37/linux/include/linux/pci.h	Thu Jan  6 12:57:48 2000
+++ linux/include/linux/pci.h	Fri Jan  7 15:30:14 2000
@@ -487,10 +487,8 @@
 int pci_set_power_state(struct pci_dev *dev, int state);
 int pci_assign_resource(struct pci_dev *dev, int i);
 
-#define __pcidev(entry)	list_entry(entry, struct pci_dev, global_list)
-
 #define pci_for_each_dev(dev) \
-	for(dev = __pcidev(pci_devices.next); dev != __pcidev(&pci_devices); dev = __pcidev(dev->global_list.next))
+	for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))
 
 /* Helper functions for low-level code (drivers/pci/setup.c) */
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/pkt_cls.h linux/include/linux/pkt_cls.h
--- v2.3.37/linux/include/linux/pkt_cls.h	Sun Mar 21 07:22:00 1999
+++ linux/include/linux/pkt_cls.h	Fri Jan  7 16:57:13 2000
@@ -143,4 +143,19 @@
 
 #define TCA_FW_MAX TCA_FW_POLICE
 
+/* TC index filter */
+
+enum
+{
+	TCA_TCINDEX_UNSPEC,
+	TCA_TCINDEX_HASH,
+	TCA_TCINDEX_MASK,
+	TCA_TCINDEX_SHIFT,
+	TCA_TCINDEX_FALL_THROUGH,
+	TCA_TCINDEX_CLASSID,
+	TCA_TCINDEX_POLICE,
+};
+
+#define TCA_TCINDEX_MAX        TCA_TCINDEX_POLICE
+
 #endif
diff -u --recursive --new-file v2.3.37/linux/include/linux/pkt_sched.h linux/include/linux/pkt_sched.h
--- v2.3.37/linux/include/linux/pkt_sched.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/pkt_sched.h	Fri Jan  7 16:57:13 2000
@@ -74,6 +74,7 @@
 
 #define TC_H_UNSPEC	(0U)
 #define TC_H_ROOT	(0xFFFFFFFFU)
+#define TC_H_INGRESS    (0xFFFFFFF1U)
 
 struct tc_ratespec
 {
@@ -193,6 +194,50 @@
 	unsigned char   Scell_log;	/* cell size for idle damping */
 };
 
+/* GRED section */
+
+#define MAX_DPs 16
+
+enum
+{
+       TCA_GRED_UNSPEC,
+       TCA_GRED_PARMS,
+       TCA_GRED_STAB,
+       TCA_GRED_DPS,
+};
+
+#define TCA_SET_OFF TCA_GRED_PARMS
+struct tc_gred_qopt
+{
+       __u32           limit;          /* HARD maximal queue length (bytes)    
+*/
+       __u32           qth_min;        /* Min average length threshold (bytes) 
+*/
+       __u32           qth_max;        /* Max average length threshold (bytes) 
+*/
+       __u32           DP;             /* upto 2^32 DPs */
+       __u32           backlog;        
+       __u32           qave;   
+       __u32           forced; 
+       __u32           early;  
+       __u32           other;  
+       __u32           pdrop;  
+
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       __u8            prio;		/* prio of this VQ */
+       __u32	packets;
+       __u32	bytesin;
+};
+/* gred setup */
+struct tc_gred_sopt
+{
+       __u32           DPs;
+       __u32           def_DP;
+       __u8            grio;
+};
+
 /* CBQ section */
 
 #define TC_CBQ_MAXPRIO		8
@@ -276,6 +321,19 @@
 };
 
 #define TCA_CBQ_MAX	TCA_CBQ_POLICE
+
+/* dsmark section */
+
+enum {
+	TCA_DSMARK_UNSPEC,
+	TCA_DSMARK_INDICES,
+	TCA_DSMARK_DEFAULT_INDEX,
+	TCA_DSMARK_SET_TC_INDEX,
+	TCA_DSMARK_MASK,
+	TCA_DSMARK_VALUE
+};
+
+#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
 
 /* ATM  section */
 
diff -u --recursive --new-file v2.3.37/linux/include/linux/ppdev.h linux/include/linux/ppdev.h
--- v2.3.37/linux/include/linux/ppdev.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ppdev.h	Mon Oct 11 10:04:02 1999
@@ -0,0 +1,81 @@
+/*
+ * linux/drivers/char/ppdev.h
+ *
+ * User-space parallel port device driver (header file).
+ *
+ * Copyright (C) 1998-9 Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Added PPGETTIME/PPSETTIME, Fred Barnes, 1999
+ */
+
+#define PP_MAJOR	99
+
+#define PP_IOCTL	'p'
+
+/* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */
+#define PPSETMODE	_IOW(PP_IOCTL, 0x80, int)
+
+/* Read status */
+#define PPRSTATUS	_IOR(PP_IOCTL, 0x81, unsigned char)
+#define PPWSTATUS	OBSOLETE__IOW(PP_IOCTL, 0x82, unsigned char)
+
+/* Read/write control */
+#define PPRCONTROL	_IOR(PP_IOCTL, 0x83, unsigned char)
+#define PPWCONTROL	_IOW(PP_IOCTL, 0x84, unsigned char)
+
+struct ppdev_frob_struct {
+	unsigned char mask;
+	unsigned char val;
+};
+#define PPFCONTROL      _IOW(PP_IOCTL, 0x8e, struct ppdev_frob_struct)
+
+/* Read/write data */
+#define PPRDATA		_IOR(PP_IOCTL, 0x85, unsigned char)
+#define PPWDATA		_IOW(PP_IOCTL, 0x86, unsigned char)
+
+/* Read/write econtrol (not used) */
+#define PPRECONTROL	OBSOLETE__IOR(PP_IOCTL, 0x87, unsigned char)
+#define PPWECONTROL	OBSOLETE__IOW(PP_IOCTL, 0x88, unsigned char)
+
+/* Read/write FIFO (not used) */
+#define PPRFIFO		OBSOLETE__IOR(PP_IOCTL, 0x89, unsigned char)
+#define PPWFIFO		OBSOLETE__IOW(PP_IOCTL, 0x8a, unsigned char)
+
+/* Claim the port to start using it */
+#define PPCLAIM		_IO(PP_IOCTL, 0x8b)
+
+/* Release the port when you aren't using it */
+#define PPRELEASE	_IO(PP_IOCTL, 0x8c)
+
+/* Yield the port (release it if another driver is waiting,
+ * then reclaim) */
+#define PPYIELD		_IO(PP_IOCTL, 0x8d)
+
+/* Register device exclusively (must be before PPCLAIM). */
+#define PPEXCL		_IO(PP_IOCTL, 0x8f)
+
+/* Data line direction: non-zero for input mode. */
+#define PPDATADIR	_IOW(PP_IOCTL, 0x90, int)
+
+/* Negotiate a particular IEEE 1284 mode. */
+#define PPNEGOT		_IOW(PP_IOCTL, 0x91, int)
+
+/* Set control lines when an interrupt occurs. */
+#define PPWCTLONIRQ	_IOW(PP_IOCTL, 0x92, unsigned char)
+
+/* Clear (and return) interrupt count. */
+#define PPCLRIRQ	_IOR(PP_IOCTL, 0x93, int)
+
+/* Set the IEEE 1284 phase that we're in (e.g. IEEE1284_PH_FWD_IDLE) */
+#define PPSETPHASE	_IOW(PP_IOCTL, 0x94, int)
+
+/* Set and get port timeout (struct timeval's) */
+#define PPGETTIME	_IOR(PP_IOCTL, 0x95, struct timeval)
+#define PPSETTIME	_IOW(PP_IOCTL, 0x96, struct timeval)
+
+
diff -u --recursive --new-file v2.3.37/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.3.37/linux/include/linux/rtnetlink.h	Thu Jan  6 12:57:48 2000
+++ linux/include/linux/rtnetlink.h	Thu Jan  6 16:18:30 2000
@@ -1,7 +1,6 @@
 #ifndef __LINUX_RTNETLINK_H
 #define __LINUX_RTNETLINK_H
 
-#include <linux/config.h>
 #include <linux/netlink.h>
 
 #define RTNL_DEBUG 1
@@ -529,6 +528,8 @@
 /* End of information exported to user level */
 
 #ifdef __KERNEL__
+
+#include <linux/config.h>
 
 extern __inline__ int rtattr_strcmp(struct rtattr *rta, char *str)
 {
diff -u --recursive --new-file v2.3.37/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.37/linux/include/linux/sched.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/sched.h	Fri Jan  7 15:30:16 2000
@@ -507,10 +507,12 @@
 						    signed long timeout));
 extern void FASTCALL(wake_up_process(struct task_struct * tsk));
 
-#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
-#define wake_up_sync(x)			__wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
-#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE)
-#define wake_up_interruptible_sync(x)	__wake_up_sync((x),TASK_INTERRUPTIBLE)
+#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_all(x)			__wake_up_all((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#define wake_up_sync(x)			__wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_interruptible_all(x)	__wake_up_all((x),TASK_INTERRUPTIBLE)
+#define wake_up_interruptible_sync(x)	__wake_up_sync((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
 
 extern int in_group_p(gid_t);
 extern int in_egroup_p(gid_t);
diff -u --recursive --new-file v2.3.37/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.3.37/linux/include/linux/skbuff.h	Wed Dec 29 13:13:21 1999
+++ linux/include/linux/skbuff.h	Fri Jan  7 16:57:13 2000
@@ -133,6 +133,10 @@
 		__u32	ifield;
 	} private;
 #endif
+
+#ifdef CONFIG_NET_SCHED
+       __u32           tc_index;               /* traffic control index */
+#endif
 };
 
 /* These are just the default values. This is run time configurable.
diff -u --recursive --new-file v2.3.37/linux/include/linux/socket.h linux/include/linux/socket.h
--- v2.3.37/linux/include/linux/socket.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/socket.h	Thu Jan  6 16:18:30 2000
@@ -106,7 +106,7 @@
 
 	__ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) +  CMSG_ALIGN(__cmsg->cmsg_len));
 	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
+		return (struct cmsghdr *)0;
 
 	return __ptr;
 }
@@ -247,15 +247,6 @@
 
 /* IPX options */
 #define IPX_TYPE	1
-
-/* TCP options - this way around because someone left a set in the c library includes */
-#define TCP_NODELAY	1
-#define TCP_MAXSEG	2
-#define TCP_CORK	3	/* Linux specific (for use with sendfile) */
-#define TCP_KEEPIDLE	4
-#define TCP_KEEPINTVL	5
-#define TCP_KEEPCNT	6
-#define TCP_SYNCNT	7
 
 #ifdef __KERNEL__
 extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
diff -u --recursive --new-file v2.3.37/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.37/linux/include/linux/swap.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/swap.h	Fri Jan  7 15:30:14 2000
@@ -78,14 +78,15 @@
 struct vm_area_struct;
 struct sysinfo;
 
+struct zone_t;
 /* linux/ipc/shm.c */
-extern int shm_swap (int, int);
+extern int shm_swap (int, int, zone_t *);
 
 /* linux/mm/swap.c */
 extern void swap_setup (void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(unsigned int gfp_mask);
+extern int try_to_free_pages(unsigned int gfp_mask, zone_t *zone);
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *, int);
diff -u --recursive --new-file v2.3.37/linux/include/linux/tcp.h linux/include/linux/tcp.h
--- v2.3.37/linux/include/linux/tcp.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/tcp.h	Fri Jan  7 15:31:02 2000
@@ -34,11 +34,13 @@
 		psh:1,
 		ack:1,
 		urg:1,
-		res2:2;
+		ece:1,
+		cwr:1;
 #elif defined(__BIG_ENDIAN_BITFIELD)
 	__u16	doff:4,
 		res1:4,
-		res2:2,
+		cwr:1,
+		ece:1,
 		urg:1,
 		ack:1,
 		psh:1,
@@ -100,6 +102,8 @@
 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
 
 enum { 
+	TCP_FLAG_CWR = __constant_htonl(0x00800000), 
+	TCP_FLAG_ECE = __constant_htonl(0x00400000), 
 	TCP_FLAG_URG = __constant_htonl(0x00200000), 
 	TCP_FLAG_ACK = __constant_htonl(0x00100000), 
 	TCP_FLAG_PSH = __constant_htonl(0x00080000), 
@@ -109,5 +113,16 @@
 	TCP_RESERVED_BITS = __constant_htonl(0x0FC00000),
 	TCP_DATA_OFFSET = __constant_htonl(0xF0000000)
 }; 
+
+/* TCP socket options */
+#define TCP_NODELAY		1	/* Turn off Nagle's algorithm. */
+#define TCP_MAXSEG		2	/* Limit MSS */
+#define TCP_CORK		3	/* Never send partially complete segments */
+#define TCP_KEEPIDLE		4	/* Start keeplives after this period */
+#define TCP_KEEPINTVL		5	/* Interval between keepalives */
+#define TCP_KEEPCNT		6	/* Number of keepalives before death */
+#define TCP_SYNCNT		7	/* Number of SYN retransmits */
+#define TCP_LINGER2		8	/* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT	9	/* Wake up listener only when data arrive */
 
 #endif	/* _LINUX_TCP_H */
diff -u --recursive --new-file v2.3.37/linux/include/net/checksum.h linux/include/net/checksum.h
--- v2.3.37/linux/include/net/checksum.h	Wed Aug 18 16:44:37 1999
+++ linux/include/net/checksum.h	Fri Jan  7 15:31:29 2000
@@ -107,4 +107,22 @@
 }
 #endif
 
+#ifndef HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user
+(const char *src, char *dst, int len, unsigned int sum, int *err_ptr)
+{
+	sum = csum_partial(src, len, sum);
+
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (copy_to_user(dst, src, len) == 0)
+			return sum;
+	}
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return -1; /* invalid checksum */
+}
+#endif
+
+
 #endif
diff -u --recursive --new-file v2.3.37/linux/include/net/dsfield.h linux/include/net/dsfield.h
--- v2.3.37/linux/include/net/dsfield.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/dsfield.h	Fri Jan  7 16:57:13 2000
@@ -0,0 +1,79 @@
+/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
+
+/* Written 1998 by Werner Almesberger, EPFL ICA */
+
+
+#ifndef __NET_DSFIELD_H
+#define __NET_DSFIELD_H
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <asm/byteorder.h>
+
+
+extern __inline__ __u8 ipv4_get_dsfield(struct iphdr *iph)
+{
+	return iph->tos;
+}
+
+
+extern __inline__ __u8 ipv6_get_dsfield(struct ipv6hdr *ipv6h)
+{
+	return ntohs(*(__u16 *) ipv6h) >> 4;
+}
+
+
+extern __inline__ void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
+    __u8 value)
+{
+        __u32 check = ntohs(iph->check);
+	__u8 dsfield;
+
+	dsfield = (iph->tos & mask) | value;
+	check += iph->tos;
+	if ((check+1) >> 16) check = (check+1) & 0xffff;
+	check -= dsfield;
+	check += check >> 16; /* adjust carry */
+	iph->check = htons(check);
+	iph->tos = dsfield;
+}
+
+
+extern __inline__ void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
+    __u8 value)
+{
+        __u16 tmp;
+
+	tmp = ntohs(*(__u16 *) ipv6h);
+	tmp = (tmp & (mask << 4)) | (value << 4);
+	*(__u16 *) ipv6h = htons(tmp);
+}
+
+
+#if 0 /* put this later into asm-i386 or such ... */
+
+extern __inline__ void ip_change_dsfield(struct iphdr *iph,__u16 dsfield)
+{
+	__u16 check;
+
+	__asm__ __volatile__("
+		movw	10(%1),%0
+		xchg	%b0,%h0
+		addb	1(%1),%b0
+		adcb	$0,%h0
+		adcw	$1,%0
+		cmc
+		sbbw	%2,%0
+		sbbw	$0,%0
+		movb	%b2,1(%1)
+		xchg	%b0,%h0
+		movw	%0,10(%1)"
+	    : "=&r" (check)
+	    : "r" (iph), "r" (dsfield)
+	    : "cc");
+}
+
+#endif
+
+#endif
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.37/linux/include/net/irda/irda.h	Wed Dec 29 13:13:21 1999
+++ linux/include/net/irda/irda.h	Fri Jan  7 15:31:25 2000
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Tue Dec 14 19:01:26 1999
+ * Modified at:   Sat Dec 25 18:58:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -101,7 +101,7 @@
 #define IAS_ATTRIB_MAGIC   0x45232
 #define IRDA_TASK_MAGIC    0x38423
 
-#define IAS_DEVICE_ID 0x5342 
+#define IAS_DEVICE_ID 0x0000 /* Defined by IrDA, IrLMP section 4.1 (page 68) */
 #define IAS_PNP_ID    0xd342
 #define IAS_OBEX_ID   0x34323
 #define IAS_IRLAN_ID  0x34234
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.3.37/linux/include/net/irda/iriap.h	Wed Dec 29 13:13:21 1999
+++ linux/include/net/irda/iriap.h	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Dec 14 21:55:18 1999
+ * Modified at:   Sat Dec 25 16:42:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -99,7 +99,7 @@
 				  __u32 saddr, __u32 daddr,
 				  char *name, char *attr);
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
-
+void iriap_connect_request(struct iriap_cb *self);
 void iriap_send_ack( struct iriap_cb *self);
 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
 
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h
--- v2.3.37/linux/include/net/irda/irlap_frame.h	Tue Jan  4 13:57:21 2000
+++ linux/include/net/irda/irlap_frame.h	Fri Jan  7 15:24:57 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Dec 21 11:10:12 1999
+ * Modified at:   Sat Dec 25 21:07:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -113,7 +113,7 @@
 void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s, 
 				    __u8 command, discovery_t *discovery);
 void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr, 
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, 
 			   struct sk_buff *cmd);
 void irlap_send_ua_response_frame(struct irlap_cb *, struct qos_info *);
 void irlap_send_dm_frame(struct irlap_cb *self);
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.37/linux/include/net/irda/irport.h	Wed Dec 29 13:13:21 1999
+++ linux/include/net/irda/irport.h	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Sat Dec 11 14:34:18 1999
+ * Modified at:   Mon Jan  3 10:23:34 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1997, 1998-2000 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -66,6 +66,7 @@
  	__u32 flags;               /* Interface flags */
 	__u32 new_speed;
 	int mode;
+	int index;                 /* Instance index */
 
 	spinlock_t lock;           /* For serializing operations */
 
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/nsc_fir.h linux/include/net/irda/nsc_fir.h
--- v2.3.37/linux/include/net/irda/nsc_fir.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/nsc_fir.h	Thu Jan  6 14:46:18 2000
@@ -0,0 +1,238 @@
+/*********************************************************************
+ *                
+ * Filename:      nsc_fir.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Nov 13 14:37:40 1998
+ * Modified at:   Wed Jan  5 12:00:16 2000
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsų admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef NSC_FIR_H
+#define NSC_FIR_H
+
+#include <linux/time.h>
+
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#define PC87108         0x10
+#define PC97338         0xb0
+
+/* DMA modes needed */
+#define DMA_TX_MODE     0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE     0x04    /* I/O to mem, ++, demand. */
+
+/* Flags for configuration register CRF0 */
+#define APEDCRC		0x02
+#define ENBNKSEL	0x01
+
+/* Set 0 */
+#define TXD             0x00 /* Transmit data port */
+#define RXD             0x00 /* Receive data port */
+
+/* Register 1 */
+#define IER		0x01 /* Interrupt Enable Register*/
+#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
+#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
+#define IER_LS_IE	0x04//* Link Status Interrupt */
+#define IER_ETXURI      0x04 /* Tx underrun */
+#define IER_DMA_IE	0x10 /* DMA finished interrupt */
+#define IER_TXEMP_IE    0x20
+#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
+#define IER_TMR_IE      0x80 /* Timer event */
+
+#define FCR		0x02 /* (write only) */
+#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
+#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
+#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
+#define FCR_RXTH	0x40 /* Rx FIFO threshold (set to 16) */
+#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
+
+#define EIR		0x02 /* (read only) */
+#define EIR_RXHDL_EV	0x01
+#define EIR_TXLDL_EV    0x02
+#define EIR_LS_EV	0x04
+#define EIR_DMA_EV	0x10
+#define EIR_TXEMP_EV	0x20
+#define EIR_SFIF_EV     0x40
+#define EIR_TMR_EV      0x80
+
+#define LCR             0x03 /* Link control register */
+#define LCR_WLS_8       0x03 /* 8 bits */
+
+#define BSR 	        0x03 /* Bank select register */
+#define BSR_BKSE        0x80
+#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
+#define BANK1	        0x80
+#define BANK2	        0xe0
+#define BANK3	        0xe4
+#define BANK4	        0xe8
+#define BANK5	        0xec
+#define BANK6	        0xf0
+#define BANK7     	0xf4
+
+#define MCR		0x04 /* Mode Control Register */
+#define MCR_MODE_MASK	~(0xd0)
+#define MCR_UART        0x00
+#define MCR_RESERVED  	0x20	
+#define MCR_SHARP_IR    0x40
+#define MCR_SIR         0x60
+#define MCR_MIR  	0x80
+#define MCR_FIR		0xa0
+#define MCR_CEIR        0xb0
+#define MCR_IR_PLS      0x10
+#define MCR_DMA_EN	0x04
+#define MCR_EN_IRQ	0x08
+#define MCR_TX_DFR	0x08
+
+#define LSR             0x05 /* Link status register */
+#define LSR_RXDA        0x01 /* Receiver data available */
+#define LSR_TXRDY       0x20 /* Transmitter ready */
+#define LSR_TXEMP       0x40 /* Transmitter empty */
+
+#define ASCR            0x07 /* Auxillary Status and Control Register */
+#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
+#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
+#define ASCR_S_EOT      0x04 /* Set end of transmission */
+#define ASCT_RXBSY      0x20 /* Rx busy */
+#define ASCR_TXUR       0x40 /* Transeiver underrun */
+#define ASCR_CTE        0x80 /* Clear timer event */
+
+/* Bank 2 */
+#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
+#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
+
+#define ECR1		0x02 /* Extended Control Register 1 */
+#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
+#define ECR1_DMANF	0x02 /* DMA Fairness */
+#define ECR1_DMATH      0x04 /* DMA Threshold */
+#define ECR1_DMASWP	0x08 /* DMA Swap */
+
+#define EXCR2		0x04
+#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
+#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
+
+#define TXFLV           0x06 /* Tx FIFO level */
+#define RXFLV           0x07 /* Rx FIFO level */
+
+/* Bank 3 */
+#define MID		0x00
+
+/* Bank 4 */
+#define TMRL            0x00 /* Timer low byte */
+#define TMRH            0x01 /* Timer high byte */
+#define IRCR1           0x02 /* Infrared control register 1 */
+#define IRCR1_TMR_EN    0x01 /* Timer enable */
+
+#define TFRLL		0x04
+#define TFRLH		0x05
+#define RFRLL		0x06
+#define RFRLH		0x07
+
+/* Bank 5 */
+#define IRCR2           0x04 /* Infrared control register 2 */
+#define IRCR2_MDRS      0x04 /* MIR data rate select */
+#define IRCR2_FEND_MD   0x20 /* */
+
+#define FRM_ST          0x05 /* Frame status FIFO */
+#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
+#define FRM_ST_ERR_MSK  0x5f
+#define FRM_ST_LOST_FR  0x40 /* Frame lost */
+#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
+#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
+#define FRM_ST_BAD_CRC  0x04 
+#define FRM_ST_OVR1     0x02 /* Rx FIFO overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
+
+#define RFLFL           0x06
+#define RFLFH           0x07
+
+/* Bank 6 */
+#define IR_CFG2		0x00
+#define IR_CFG2_DIS_CRC	0x02
+
+/* Bank 7 */
+#define IRM_CR		0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL	0x40
+#define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+struct frame_cb {
+	void *start; /* Start of frame in DMA mem */
+	int len;     /* Lenght of frame in DMA mem */
+};
+
+#define MAX_WINDOW 7
+
+struct tx_fifo {
+	struct frame_cb queue[MAX_WINDOW]; /* Info about frames in queue */
+	int             ptr;               /* Currently being sent */
+	int             len;               /* Lenght of queue */
+	int             free;              /* Next free slot */
+	void           *tail;              /* Next free start in DMA mem */
+};
+
+/* Private data for each instance */
+struct nsc_fir_cb {
+	struct st_fifo st_fifo;    /* Info about received frames */
+	struct tx_fifo tx_fifo;    /* Info about frames to be transmitted */
+
+	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
+	int tx_len;                /* Number of frames in tx_buff */
+
+	struct net_device *netdev;     /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb *irlap;    /* The link layer we are binded to */
+	
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+	struct qos_info qos;       /* QoS capabilities for this device */
+
+	struct timeval  stamp;
+	struct timeval  now;
+
+	spinlock_t lock;           /* For serializing operations */
+	
+	__u32 flags;               /* Interface flags */
+	__u32 new_speed;
+	int suspend;
+};
+
+static inline void switch_bank(int iobase, int bank)
+{
+		outb(bank, iobase+BSR);
+}
+
+#endif /* NSC_FIR_H */
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/pc87108.h linux/include/net/irda/pc87108.h
--- v2.3.37/linux/include/net/irda/pc87108.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/irda/pc87108.h	Wed Dec 31 16:00:00 1969
@@ -1,205 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      pc87108.h
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Mon Nov  8 10:00:27 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- *     Copyright (c) 1998 Actisys Corp., www.actisys.com
- *     All Rights Reserved
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsų admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef PC87108_H
-#define PC87108_H
-
-#include <asm/io.h>
-
-/* Flags for configuration register CRF0 */
-#define APEDCRC		0x02
-#define ENBNKSEL	0x01
-
-/* Set 0 */
-#define TXD             0x00 /* Transmit data port */
-#define RXD             0x00 /* Receive data port */
-
-/* Register 1 */
-#define IER		0x01 /* Interrupt Enable Register*/
-#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
-#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
-#define IER_LS_IE	0x04//* Link Status Interrupt */
-#define IER_ETXURI      0x04 /* Tx underrun */
-#define IER_DMA_IE	0x10 /* DMA finished interrupt */
-#define IER_TXEMP_IE    0x20
-#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
-#define IER_TMR_IE      0x80 /* Timer event */
-
-#define FCR		0x02 /* (write only) */
-#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
-#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
-#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
-#define FCR_RXTH	0x80 /* Rx FIFO threshold (set to 16) */
-#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
-
-#define EIR		0x02 /* (read only) */
-#define EIR_RXHDL_EV	0x01
-#define EIR_TXLDL_EV    0x02
-#define EIR_LS_EV	0x04
-#define EIR_DMA_EV	0x10
-#define EIR_TXEMP_EV	0x20
-#define EIR_SFIF_EV     0x40
-#define EIR_TMR_EV      0x80
-
-#define LCR             0x03 /* Link control register */
-#define LCR_WLS_8       0x03 /* 8 bits */
-
-#define BSR 	        0x03 /* Bank select register */
-#define BSR_BKSE        0x80
-#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
-#define BANK1	        0x80
-#define BANK2	        0xe0
-#define BANK3	        0xe4
-#define BANK4	        0xe8
-#define BANK5	        0xec
-#define BANK6	        0xf0
-#define BANK7     	0xf4
-
-#define MCR		0x04 /* Mode Control Register */
-#define MCR_MODE_MASK	~(0xd0)
-#define MCR_UART        0x00
-#define MCR_RESERVED  	0x20	
-#define MCR_SHARP_IR    0x40
-#define MCR_SIR         0x60
-#define MCR_MIR  	0x80
-#define MCR_FIR		0xa0
-#define MCR_CEIR        0xb0
-#define MCR_DMA_EN	0x04
-#define MCR_EN_IRQ	0x08
-#define MCR_TX_DFR	0x08
-
-#define LSR             0x05 /* Link status register */
-#define LSR_RXDA        0x01 /* Receiver data available */
-#define LSR_TXRDY       0x20 /* Transmitter ready */
-#define LSR_TXEMP       0x40 /* Transmitter empty */
-
-#define ASCR            0x07 /* Auxillary Status and Control Register */
-#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
-#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
-#define ASCR_S_EOT      0x04 /* Set end of transmission */
-#define ASCT_RXBSY      0x20 /* Rx busy */
-#define ASCR_TXUR       0x40 /* Transeiver underrun */
-#define ASCR_CTE        0x80 /* Clear timer event */
-
-/* Bank 2 */
-#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
-#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
-
-#define ECR1		0x02 /* Extended Control Register 1 */
-#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
-#define ECR1_DMANF	0x02 /* DMA Fairness */
-#define ECR1_DMATH      0x04
-#define ECR1_DMASWP	0x08 /* DMA Swap */
-
-#define EXCR2		0x04
-#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
-#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
-
-#define TXFLV           0x06 /* Tx FIFO level */
-#define RXFLV           0x07 /* Rx FIFO level */
-
-/* Bank 3 */
-#define MID		0x00
-
-/* Bank 4 */
-#define TMRL            0x00 /* Timer low byte */
-#define TMRH            0x01 /* Timer high byte */
-#define IRCR1           0x02 /* Infrared control register 1 */
-#define IRCR1_TMR_EN    0x01 /* Timer enable */
-
-#define TFRLL		0x04
-#define TFRLH		0x05
-#define RFRLL		0x06
-#define RFRLH		0x07
-
-/* Bank 5 */
-#define IRCR2           0x04 /* Infrared control register 2 */
-#define IRCR2_MDRS      0x04 /* MIR data rate select */
-#define IRCR2_FEND_MD   0x20 /* */
-
-#define FRM_ST          0x05 /* Frame status FIFO */
-#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
-#define FRM_ST_ERR_MSK  0x5f
-#define FRM_ST_LOST_FR  0x40 /* Frame lost */
-#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
-#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
-#define FRM_ST_BAD_CRC  0x04 
-#define FRM_ST_OVR1     0x02 /* Receive overrun */
-#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
-
-#define RFLFL           0x06
-#define RFLFH           0x07
-
-/* Bank 6 */
-#define IR_CFG2		0x00
-#define IR_CFG2_DIS_CRC	0x02
-
-/* Bank 7 */
-#define IRM_CR		0x07 /* Infrared module control register */
-#define IRM_CR_IRX_MSL	0x40
-#define IRM_CR_AF_MNT   0x80 /* Automatic format */
-
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
-	int status;
-	int len;
-};
-
-struct st_fifo {
-	struct st_fifo_entry entries[10];
-	int head;
-	int tail;
-	int len;
-};
-
-/* Private data for each instance */
-struct pc87108 {
-	struct st_fifo st_fifo;
-
-	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
-	int tx_len;          /* Number of frames in tx_buff */
-
-	struct net_device *netdev; /* Yes! we are some kind of netdevice */
-	struct net_device_stats stats;
-	
-	struct irlap_cb    *irlap; /* The link layer we are binded to */
-	
-	struct chipio_t io;        /* IrDA controller information */
-	struct iobuff_t tx_buff;   /* Transmit buffer */
-	struct iobuff_t rx_buff;   /* Receive buffer */
-	struct qos_info qos;       /* QoS capabilities for this device */
-	
-	__u32 flags;               /* Interface flags */
-	__u32 new_speed;
-};
-
-static inline void switch_bank(int iobase, int bank)
-{
-		outb(bank, iobase+BSR);
-}
-
-#endif
diff -u --recursive --new-file v2.3.37/linux/include/net/irda/smc-ircc.h linux/include/net/irda/smc-ircc.h
--- v2.3.37/linux/include/net/irda/smc-ircc.h	Wed Dec 29 13:13:21 1999
+++ linux/include/net/irda/smc-ircc.h	Thu Jan  6 14:46:18 2000
@@ -1,140 +1,147 @@
 /*********************************************************************
  *                
  * Filename:      smc-ircc.h
- * Version:       
- * Description:   
+ * Version:       0.3
+ * Description:   Definitions for the SMC IrCC chipset
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  *
- *     Copyright (c) 1998, 1999 Thomas Davis (tadavis@jps.net>
+ *     Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
  *     All Rights Reserved
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, admit no liability nor provide warranty for any
- *     of this software. This material is provided "AS-IS" and at no charge.
- *     
- * Definitions for the SMC IrCC controller.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *
  ********************************************************************/
 
-#include <net/irda/irport.h>
-
 #ifndef SMC_IRCC_H
 #define SMC_IRCC_H
 
-#define UART_MASTER			0x07
-#define UART_MASTER_POWERDOWN	1<<7
-#define UART_MASTER_RESET		1<<6
-#define UART_MASTER_INT_EN		1<<5
-#define UART_MASTER_ERROR_RESET	1<<4
+#include <linux/spinlock.h>
 
-/* Register block 0 */
-
-#define UART_IIR	0x01
-#define UART_IER	0x02
-#define UART_LSR	0x03
-#define UART_LCR_A	0x04
-#define UART_LCR_B	0x05
-#define UART_BSR	0x06
-
-#define UART_IIR_ACTIVE_FRAME	1<<7
-#define UART_IIR_EOM 		1<<6
-#define UART_IIR_RAW_MODE		1<<5
-#define UART_IIR_FIFO		1<<4
-
-#define UART_IER_ACTIVE_FRAME	1<<7
-#define UART_IER_EOM 		1<<6
-#define UART_IER_RAW_MODE		1<<5
-#define UART_IER_FIFO		1<<4
-
-#define UART_LSR_UNDERRUN		1<<7
-#define UART_LSR_OVERRUN		1<<6
-#define UART_LSR_FRAME_ERROR 	1<<5
-#define UART_LSR_SIZE_ERROR		1<<4
-#define UART_LSR_CRC_ERROR		1<<3
-#define UART_LSR_FRAME_ABORT 	1<<2
-
-#define UART_LCR_A_FIFO_RESET        1<<7
-#define UART_LCR_A_FAST              1<<6
-#define UART_LCR_A_GP_DATA           1<<5
-#define UART_LCR_A_RAW_TX            1<<4
-#define UART_LCR_A_RAW_RX            1<<3
-#define UART_LCR_A_ABORT             1<<2
-#define UART_LCR_A_DATA_DONE         1<<1
-
-#define UART_LCR_B_SCE_DISABLED 	0x00<<6
-#define UART_LCR_B_SCE_TRANSMIT 	0x01<<6
-#define UART_LCR_B_SCE_RECEIVE		0x02<<6
-#define UART_LCR_B_SCE_UNDEFINED	0x03<<6
-#define UART_LCR_B_SIP_ENABLE		1<<5
-#define UART_LCR_B_BRICK_WALL		1<<4
-
-#define UART_BSR_NOT_EMPTY	1<<7
-#define UART_BSR_FIFO_FULL	1<<6
-#define UART_BSR_TIMEOUT	1<<5
+#include <net/irda/irport.h>
 
-/* Register block 1 */
+/* DMA modes needed */
+#define DMA_TX_MODE              0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE              0x04    /* I/O to mem, ++, demand. */
+
+#define IRCC_MASTER              0x07
+#define IRCC_MASTER_POWERDOWN	 1<<7
+#define IRCC_MASTER_RESET        1<<6
+#define IRCC_MASTER_INT_EN       1<<5
+#define IRCC_MASTER_ERROR_RESET	 1<<4
 
-#define UART_SCE_CFGA	0x00
-#define UART_SCE_CFGB	0x01
-#define UART_FIFO_THRESHOLD	0x02
-
-#define UART_CFGA_AUX_IR	0x01<<7
-#define UART_CFGA_HALF_DUPLEX	0x01<<2
-#define UART_CFGA_TX_POLARITY	0x01<<1
-#define UART_CFGA_RX_POLARITY	0x01
-
-#define UART_CFGA_COM		0x00<<3
-#define UART_CFGA_IRDA_SIR_A	0x01<<3
-#define UART_CFGA_ASK_SIR	0x02<<3
-#define UART_CFGA_IRDA_SIR_B	0x03<<3
-#define UART_CFGA_IRDA_HDLC 	0x04<<3
-#define UART_CFGA_IRDA_4PPM 	0x05<<3
-#define UART_CFGA_CONSUMER	0x06<<3
-#define UART_CFGA_RAW_IR	0x07<<3
-#define UART_CFGA_OTHER		0x08<<3
-
-#define UART_IR_HDLC			0x04
-#define UART_IR_4PPM			0x01
-#define UART_IR_CONSUMER		0x02
-
-#define UART_CFGB_LOOPBACK      0x01<<5
-#define UART_CFGB_LPBCK_TX_CRC	0x01<<4
-#define UART_CFGB_NOWAIT	0x01<<3
-#define UART_CFGB_STRING_MOVE	0x01<<2
-#define UART_CFGB_DMA_BURST 	0x01<<1
-#define UART_CFGB_DMA_ENABLE	0x01
-
-#define UART_CFGB_COM		0x00<<6
-#define UART_CFGB_IR		0x01<<6
-#define UART_CFGB_AUX		0x02<<6
-#define UART_CFGB_INACTIVE	0x03<<6
+/* Register block 0 */
+#define IRCC_IIR                 0x01
+#define IRCC_IER                 0x02
+#define IRCC_LSR                 0x03
+#define IRCC_LCR_A               0x04
+#define IRCC_LCR_B               0x05
+#define IRCC_BSR                 0x06
+
+#define IRCC_IIR_ACTIVE_FRAME    1<<7
+#define IRCC_IIR_EOM             1<<6
+#define IRCC_IIR_RAW_MODE        1<<5
+#define IRCC_IIR_FIFO		 1<<4
+
+#define IRCC_IER_ACTIVE_FRAME	 1<<7
+#define IRCC_IER_EOM 		 1<<6
+#define IRCC_IER_RAW_MODE        1<<5
+#define IRCC_IER_FIFO		 1<<4
+
+#define IRCC_LSR_UNDERRUN        1<<7
+#define IRCC_LSR_OVERRUN         1<<6
+#define IRCC_LSR_FRAME_ERROR     1<<5
+#define IRCC_LSR_SIZE_ERROR      1<<4
+#define IRCC_LSR_CRC_ERROR       1<<3
+#define IRCC_LSR_FRAME_ABORT 	 1<<2
+
+#define IRCC_LCR_A_FIFO_RESET    1<<7
+#define IRCC_LCR_A_FAST          1<<6
+#define IRCC_LCR_A_GP_DATA       1<<5
+#define IRCC_LCR_A_RAW_TX        1<<4
+#define IRCC_LCR_A_RAW_RX        1<<3
+#define IRCC_LCR_A_ABORT         1<<2
+#define IRCC_LCR_A_DATA_DONE     1<<1
+
+#define IRCC_LCR_B_SCE_DISABLED  0x00<<6
+#define IRCC_LCR_B_SCE_TRANSMIT  0x01<<6
+#define IRCC_LCR_B_SCE_RECEIVE	 0x02<<6
+#define IRCC_LCR_B_SCE_UNDEFINED 0x03<<6
+#define IRCC_LCR_B_SIP_ENABLE	 1<<5
+#define IRCC_LCR_B_BRICK_WALL    1<<4
+
+#define IRCC_BSR_NOT_EMPTY	 1<<7
+#define IRCC_BSR_FIFO_FULL	 1<<6
+#define IRCC_BSR_TIMEOUT	 1<<5
 
-/* Register block 2 - Consumer IR - not used */
+/* Register block 1 */
+#define IRCC_SCE_CFGA	         0x00
+#define IRCC_SCE_CFGB	         0x01
+#define IRCC_FIFO_THRESHOLD	 0x02
+
+#define IRCC_CFGA_AUX_IR	 0x01<<7
+#define IRCC_CFGA_HALF_DUPLEX	 0x01<<2
+#define IRCC_CFGA_TX_POLARITY	 0x01<<1
+#define IRCC_CFGA_RX_POLARITY	 0x01
+
+#define IRCC_CFGA_COM		 0x00<<3
+#define IRCC_CFGA_IRDA_SIR_A	 0x01<<3
+#define IRCC_CFGA_ASK_SIR	 0x02<<3
+#define IRCC_CFGA_IRDA_SIR_B	 0x03<<3
+#define IRCC_CFGA_IRDA_HDLC 	 0x04<<3
+#define IRCC_CFGA_IRDA_4PPM 	 0x05<<3
+#define IRCC_CFGA_CONSUMER	 0x06<<3
+#define IRCC_CFGA_RAW_IR	 0x07<<3
+#define IRCC_CFGA_OTHER		 0x08<<3
+
+#define IRCC_IR_HDLC             0x04
+#define IRCC_IR_4PPM             0x01
+#define IRCC_IR_CONSUMER         0x02
+
+#define IRCC_CFGB_LOOPBACK       0x01<<5
+#define IRCC_CFGB_LPBCK_TX_CRC	 0x01<<4
+#define IRCC_CFGB_NOWAIT	 0x01<<3
+#define IRCC_CFGB_STRING_MOVE	 0x01<<2
+#define IRCC_CFGB_DMA_BURST 	 0x01<<1
+#define IRCC_CFGB_DMA_ENABLE	 0x01
+
+#define IRCC_CFGB_COM		 0x00<<6
+#define IRCC_CFGB_IR		 0x01<<6
+#define IRCC_CFGB_AUX		 0x02<<6
+#define IRCC_CFGB_INACTIVE	 0x03<<6
 
 /* Register block 3 - Identification Registers! */
-
-#define UART_ID_HIGH	0x00   /* 0x10 */
-#define UART_ID_LOW	0x01   /* 0xB8 */
-#define UART_CHIP_ID 	0x02   /* 0xF1 */
-#define UART_VERSION	0x03   /* 0x01 */
-#define UART_INTERFACE	0x04   /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_ID_HIGH	         0x00   /* 0x10 */
+#define IRCC_ID_LOW	         0x01   /* 0xB8 */
+#define IRCC_CHIP_ID 	         0x02   /* 0xF1 */
+#define IRCC_VERSION	         0x03   /* 0x01 */
+#define IRCC_INTERFACE	         0x04   /* low 4 = DMA, high 4 = IRQ */
 
 /* Register block 4 - IrDA */
-#define UART_CONTROL             0x00
-#define UART_BOF_COUNT_LO        0x01
-#define UART_BRICKWALL_CNT_LO    0x02
-#define UART_BRICKWALL_TX_CNT_HI 0x03
-#define UART_TX_SIZE_LO          0x04
-#define UART_RX_SIZE_HI          0x05
-#define UART_RX_SIZE_LO          0x06
+#define IRCC_CONTROL             0x00
+#define IRCC_BOF_COUNT_LO        0x01
+#define IRCC_BRICKWALL_CNT_LO    0x02
+#define IRCC_BRICKWALL_TX_CNT_HI 0x03
+#define IRCC_TX_SIZE_LO          0x04
+#define IRCC_RX_SIZE_HI          0x05
+#define IRCC_RX_SIZE_LO          0x06
 
-#define UART_1152     0x01<<7
-#define UART_CRC      0x01<<6
+#define IRCC_1152                0x01<<7
+#define IRCC_CRC                 0x01<<6
 
 /* For storing entries in the status FIFO */
 struct st_fifo_entry {
@@ -157,17 +164,18 @@
 	struct chipio_t io;        /* IrDA controller information */
 	struct iobuff_t tx_buff;   /* Transmit buffer */
 	struct iobuff_t rx_buff;   /* Receive buffer */
-	struct qos_info qos;       /* QoS capabilities for this device */
 
 	struct irport_cb *irport;
+
+	spinlock_t lock;           /* For serializing operations */
 	
 	__u32 new_speed;
 	__u32 flags;               /* Interface flags */
 
 	struct st_fifo st_fifo;
 
-	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
-	int tx_len;              /* Number of frames in tx_buff */
+	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
+	int tx_len;                /* Number of frames in tx_buff */
 };
 
-#endif
+#endif /* SMC_IRCC_H */
diff -u --recursive --new-file v2.3.37/linux/include/net/route.h linux/include/net/route.h
--- v2.3.37/linux/include/net/route.h	Thu Jan  6 12:57:48 2000
+++ linux/include/net/route.h	Fri Jan  7 15:31:26 2000
@@ -34,8 +34,6 @@
 #warning This file is not supposed to be used outside of kernel.
 #endif
 
-#define RT_HASH_DIVISOR	    	256
-
 #define RTO_ONLINK	0x01
 #define RTO_TPROXY	0x80000000
 
diff -u --recursive --new-file v2.3.37/linux/init/main.c linux/init/main.c
--- v2.3.37/linux/init/main.c	Thu Jan  6 12:57:48 2000
+++ linux/init/main.c	Thu Jan  6 16:17:18 2000
@@ -88,6 +88,7 @@
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
+extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
 
 extern void free_initmem(void);
diff -u --recursive --new-file v2.3.37/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.37/linux/ipc/shm.c	Mon Dec 20 18:48:22 1999
+++ linux/ipc/shm.c	Thu Jan  6 16:21:23 2000
@@ -799,7 +799,7 @@
 static unsigned long swap_id = 0; /* currently being swapped */
 static unsigned long swap_idx = 0; /* next to swap */
 
-int shm_swap (int prio, int gfp_mask)
+int shm_swap (int prio, int gfp_mask, zone_t *zone)
 {
 	pte_t page;
 	struct shmid_kernel *shp;
@@ -849,9 +849,7 @@
 	if (!pte_present(page))
 		goto check_table;
 	page_map = pte_page(page);
-	if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))
-		goto check_table;
-	if (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page_map))
+	if (zone && (!memclass(page_map->zone, zone)))
 		goto check_table;
 	swap_attempts++;
 
diff -u --recursive --new-file v2.3.37/linux/ipc/util.c linux/ipc/util.c
--- v2.3.37/linux/ipc/util.c	Wed Dec 15 10:43:17 1999
+++ linux/ipc/util.c	Thu Jan  6 16:21:23 2000
@@ -214,7 +214,7 @@
     return;
 }
 
-int shm_swap (int prio, int gfp_mask)
+int shm_swap (int prio, int gfp_mask, zone_t *zone)
 {
     return 0;
 }
diff -u --recursive --new-file v2.3.37/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.3.37/linux/kernel/kmod.c	Thu Nov 11 20:11:54 1999
+++ linux/kernel/kmod.c	Thu Jan  6 16:17:18 2000
@@ -7,6 +7,10 @@
 
 	Modified to avoid chroot and file sharing problems.
 	Mikael Pettersson
+
+	Limit the concurrent number of kmod modprobes to catch loops from
+	"modprobe needs a service that is in a module".
+	Keith Owens <kaos@ocs.com.au> December 1999
 */
 
 #define __KERNEL_SYSCALLS__
@@ -22,6 +26,8 @@
 */
 char modprobe_path[256] = "/sbin/modprobe";
 
+extern int max_threads;
+
 static inline void
 use_init_fs_context(void)
 {
@@ -113,6 +119,10 @@
 	int pid;
 	int waitpid_result;
 	sigset_t tmpsig;
+	int i;
+	static atomic_t kmod_concurrent = ATOMIC_INIT(0);
+#define MAX_KMOD_CONCURRENT 50	/* Completely arbitrary value - KAO */
+	static int kmod_loop_msg;
 
 	/* Don't allow request_module() before the root fs is mounted!  */
 	if ( ! current->fs->root ) {
@@ -121,9 +131,31 @@
 		return -EPERM;
 	}
 
+	/* If modprobe needs a service that is in a module, we get a recursive
+	 * loop.  Limit the number of running kmod threads to max_threads/2 or
+	 * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
+	 * would be to run the parents of this process, counting how many times
+	 * kmod was invoked.  That would mean accessing the internals of the
+	 * process tables to get the command line, proc_pid_cmdline is static
+	 * and it is not worth changing the proc code just to handle this case. 
+	 * KAO.
+	 */
+	i = max_threads/2;
+	if (i > MAX_KMOD_CONCURRENT)
+		i = MAX_KMOD_CONCURRENT;
+	atomic_inc(&kmod_concurrent);
+	if (atomic_read(&kmod_concurrent) > i) {
+		if (kmod_loop_msg++ < 5)
+			printk(KERN_ERR
+			       "kmod: runaway modprobe loop assumed and stopped\n");
+		atomic_dec(&kmod_concurrent);
+		return -ENOMEM;
+	}
+
 	pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
 	if (pid < 0) {
 		printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
+		atomic_dec(&kmod_concurrent);
 		return pid;
 	}
 
@@ -135,6 +167,7 @@
 	spin_unlock_irq(&current->sigmask_lock);
 
 	waitpid_result = waitpid(pid, NULL, __WCLONE);
+	atomic_dec(&kmod_concurrent);
 
 	/* Allow signals again.. */
 	spin_lock_irq(&current->sigmask_lock);
diff -u --recursive --new-file v2.3.37/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.37/linux/kernel/ksyms.c	Thu Jan  6 12:57:48 2000
+++ linux/kernel/ksyms.c	Thu Jan  6 16:18:30 2000
@@ -97,6 +97,7 @@
 #ifndef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(contig_page_data);
 #endif
+EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(kmem_find_general_cachep);
 EXPORT_SYMBOL(kmem_cache_create);
 EXPORT_SYMBOL(kmem_cache_destroy);
diff -u --recursive --new-file v2.3.37/linux/kernel/sched.c linux/kernel/sched.c
--- v2.3.37/linux/kernel/sched.c	Tue Jan  4 13:57:21 2000
+++ linux/kernel/sched.c	Thu Jan  6 16:39:31 2000
@@ -673,7 +673,7 @@
 #endif
 		p = curr->task;
 		state = p->state;
-		if (state & mode) {
+		if (state & (mode & ~TASK_EXCLUSIVE)) {
 #if WAITQUEUE_DEBUG
 			curr->__waker = (long)__builtin_return_address(0);
 #endif
@@ -681,7 +681,7 @@
 				wake_up_process_synchronous(p);
 			else
 				wake_up_process(p);
-			if (state & TASK_EXCLUSIVE)
+			if (state & mode & TASK_EXCLUSIVE)
 				break;
 		}
 	}
diff -u --recursive --new-file v2.3.37/linux/lib/string.c linux/lib/string.c
--- v2.3.37/linux/lib/string.c	Fri Aug  6 15:25:47 1999
+++ linux/lib/string.c	Fri Jan  7 11:15:27 2000
@@ -369,7 +369,7 @@
 	const unsigned char *p = s;
 	while (n-- != 0) {
         	if ((unsigned char)c == *p++) {
-			return p-1;
+			return (void *)p-1;
 		}
 	}
 	return NULL;
diff -u --recursive --new-file v2.3.37/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.37/linux/mm/filemap.c	Tue Jan  4 13:57:21 2000
+++ linux/mm/filemap.c	Thu Jan  6 16:21:23 2000
@@ -211,7 +211,7 @@
 	spin_unlock(&pagecache_lock);
 }
 
-int shrink_mmap(int priority, int gfp_mask)
+int shrink_mmap(int priority, int gfp_mask, zone_t *zone)
 {
 	int ret = 0, count;
 	LIST_HEAD(young);
@@ -239,9 +239,7 @@
 
 		dispose = &old;
 		/* don't account passes over not DMA pages */
-		if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
-			goto dispose_continue;
-		if (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page))
+		if (zone && (!memclass(page->zone, zone)))
 			goto dispose_continue;
 
 		count--;
diff -u --recursive --new-file v2.3.37/linux/mm/highmem.c linux/mm/highmem.c
--- v2.3.37/linux/mm/highmem.c	Tue Jan  4 13:57:21 2000
+++ linux/mm/highmem.c	Thu Jan  6 16:17:18 2000
@@ -131,13 +131,17 @@
 static unsigned long map_new_virtual(struct page *page)
 {
 	unsigned long vaddr;
-	int count = LAST_PKMAP;
+	int count;
 
+start:
+	count = LAST_PKMAP;
 	/* Find an empty entry */
 	for (;;) {
 		last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK;
-		if (!last_pkmap_nr)
+		if (!last_pkmap_nr) {
 			flush_all_zero_pkmaps();
+			count = LAST_PKMAP;
+		}
 		if (!pkmap_count[last_pkmap_nr])
 			break;	/* Found a usable entry */
 		if (--count)
@@ -161,7 +165,7 @@
 				return page->virtual;
 
 			/* Re-start */
-			count = LAST_PKMAP;
+			goto start;
 		}
 	}
 	vaddr = PKMAP_ADDR(last_pkmap_nr);
diff -u --recursive --new-file v2.3.37/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.3.37/linux/mm/page_alloc.c	Tue Dec 14 01:27:24 1999
+++ linux/mm/page_alloc.c	Thu Jan  6 16:21:23 2000
@@ -224,7 +224,7 @@
 		return 1;
 
 	current->flags |= PF_MEMALLOC;
-	freed = try_to_free_pages(gfp_mask);
+	freed = try_to_free_pages(gfp_mask, zone);
 	current->flags &= ~PF_MEMALLOC;
 
 	if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
@@ -235,7 +235,7 @@
 /*
  * We are still balancing memory in a global way:
  */
-static inline int balance_memory (int gfp_mask)
+static inline int balance_memory (zone_t *zone, int gfp_mask)
 {
 	unsigned long free = nr_free_pages();
 	static int low_on_memory = 0;
@@ -264,7 +264,7 @@
 		return 1;
 
 	current->flags |= PF_MEMALLOC;
-	freed = try_to_free_pages(gfp_mask);
+	freed = try_to_free_pages(gfp_mask, zone);
 	current->flags &= ~PF_MEMALLOC;
 
 	if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
@@ -340,7 +340,7 @@
  * The main chunk of the balancing code is in this offline branch:
  */
 balance:
-	if (!balance_memory(gfp_mask))
+	if (!balance_memory(z, gfp_mask))
 		goto nopage;
 	goto ready;
 }
@@ -533,9 +533,9 @@
 		i = 10;
 	if (i > 256)
 		i = 256;
-	freepages.min = i;
-	freepages.low = i * 2;
-	freepages.high = i * 3;
+	freepages.min += i;
+	freepages.low += i * 2;
+	freepages.high += i * 3;
 
 	/*
 	 * Some architectures (with lots of mem and discontinous memory
@@ -574,6 +574,7 @@
 		zone->size = size;
 		zone->name = zone_names[j];
 		zone->lock = SPIN_LOCK_UNLOCKED;
+		zone->zone_pgdat = pgdat;
 		if (!size)
 			continue;
 
diff -u --recursive --new-file v2.3.37/linux/mm/slab.c linux/mm/slab.c
--- v2.3.37/linux/mm/slab.c	Tue Nov 23 22:42:21 1999
+++ linux/mm/slab.c	Thu Jan  6 16:21:23 2000
@@ -503,6 +503,11 @@
 {
 	void	*addr;
 
+	/*
+	 * If we requested dmaable memory, we will get it. Even if we 
+	 * did not request dmaable memory, we might get it, but that
+	 * would be relatively rare and ignorable.
+	 */
 	*dma = flags & SLAB_DMA;
 	addr = (void*) __get_free_pages(flags, cachep->c_gfporder);
 	/* Assume that now we have the pages no one else can legally
@@ -511,18 +516,6 @@
 	 * it is a named-page or buffer-page.  The members it tests are
 	 * of no interest here.....
 	 */
-	if (!*dma && addr) {
-		/* Need to check if can dma. */
-		struct page *page = mem_map + MAP_NR(addr);
-		*dma = 1<<cachep->c_gfporder;
-		while ((*dma)--) {
-			if (!PageDMA(page)) {
-				*dma = 0;
-				break;
-			}
-			page++;
-		}
-	}
 	return addr;
 }
 
diff -u --recursive --new-file v2.3.37/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.37/linux/mm/vmscan.c	Wed Dec 29 13:13:21 1999
+++ linux/mm/vmscan.c	Thu Jan  6 16:21:23 2000
@@ -33,7 +33,7 @@
  * using a process that no longer actually exists (it might
  * have died while we slept).
  */
-static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
+static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask, zone_t *zone)
 {
 	pte_t pte;
 	swp_entry_t entry;
@@ -60,8 +60,7 @@
 
 	if (PageReserved(page)
 	    || PageLocked(page)
-	    || ((gfp_mask & __GFP_DMA) && !PageDMA(page))
-	    || (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page)))
+	    || (zone && (!memclass(page->zone, zone))))
 		goto out_failed;
 
 	/*
@@ -196,7 +195,7 @@
  * (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
  */
 
-static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask, zone_t *zone)
 {
 	pte_t * pte;
 	unsigned long pmd_end;
@@ -218,7 +217,7 @@
 	do {
 		int result;
 		vma->vm_mm->swap_address = address + PAGE_SIZE;
-		result = try_to_swap_out(vma, address, pte, gfp_mask);
+		result = try_to_swap_out(vma, address, pte, gfp_mask, zone);
 		if (result)
 			return result;
 		address += PAGE_SIZE;
@@ -227,7 +226,7 @@
 	return 0;
 }
 
-static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask, zone_t *zone)
 {
 	pmd_t * pmd;
 	unsigned long pgd_end;
@@ -247,7 +246,7 @@
 		end = pgd_end;
 	
 	do {
-		int result = swap_out_pmd(vma, pmd, address, end, gfp_mask);
+		int result = swap_out_pmd(vma, pmd, address, end, gfp_mask, zone);
 		if (result)
 			return result;
 		address = (address + PMD_SIZE) & PMD_MASK;
@@ -256,7 +255,7 @@
 	return 0;
 }
 
-static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask)
+static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask, zone_t *zone)
 {
 	pgd_t *pgdir;
 	unsigned long end;
@@ -271,7 +270,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask);
+		int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask, zone);
 		if (result)
 			return result;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -280,7 +279,7 @@
 	return 0;
 }
 
-static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
+static int swap_out_mm(struct mm_struct * mm, int gfp_mask, zone_t *zone)
 {
 	unsigned long address;
 	struct vm_area_struct* vma;
@@ -301,7 +300,7 @@
 			address = vma->vm_start;
 
 		for (;;) {
-			int result = swap_out_vma(vma, address, gfp_mask);
+			int result = swap_out_vma(vma, address, gfp_mask, zone);
 			if (result)
 				return result;
 			vma = vma->vm_next;
@@ -323,7 +322,7 @@
  * N.B. This function returns only 0 or 1.  Return values != 1 from
  * the lower level routines result in continued processing.
  */
-static int swap_out(unsigned int priority, int gfp_mask)
+static int swap_out(unsigned int priority, int gfp_mask, zone_t *zone)
 {
 	struct task_struct * p;
 	int counter;
@@ -384,7 +383,7 @@
 			int ret;
 
 			atomic_inc(&best->mm_count);
-			ret = swap_out_mm(best, gfp_mask);
+			ret = swap_out_mm(best, gfp_mask, zone);
 			mmdrop(best);
 
 			if (!ret)
@@ -410,7 +409,7 @@
  * cluster them so that we get good swap-out behaviour. See
  * the "free_memory()" macro for details.
  */
-static int do_try_to_free_pages(unsigned int gfp_mask)
+static int do_try_to_free_pages(unsigned int gfp_mask, zone_t *zone)
 {
 	int priority;
 	int count = SWAP_CLUSTER_MAX;
@@ -420,7 +419,7 @@
 
 	priority = 6;
 	do {
-		while (shrink_mmap(priority, gfp_mask)) {
+		while (shrink_mmap(priority, gfp_mask, zone)) {
 			if (!--count)
 				goto done;
 		}
@@ -428,21 +427,21 @@
 		/* don't be too light against the d/i cache since
 		   shrink_mmap() almost never fail when there's
 		   really plenty of memory free. */
-		count -= shrink_dcache_memory(priority, gfp_mask);
-		count -= shrink_icache_memory(priority, gfp_mask);
+		count -= shrink_dcache_memory(priority, gfp_mask, zone);
+		count -= shrink_icache_memory(priority, gfp_mask, zone);
 		if (count <= 0)
 			goto done;
 
 		/* Try to get rid of some shared memory pages.. */
 		if (gfp_mask & __GFP_IO) {
-			while (shm_swap(priority, gfp_mask)) {
+			while (shm_swap(priority, gfp_mask, zone)) {
 				if (!--count)
 					goto done;
 			}
 		}
 
 		/* Then, try to page stuff out.. */
-		while (swap_out(priority, gfp_mask)) {
+		while (swap_out(priority, gfp_mask, zone)) {
 			if (!--count)
 				goto done;
 		}
@@ -506,7 +505,7 @@
 			   allocations (not GFP_HIGHMEM ones). */
 			if (nr_free_buffer_pages() >= freepages.high)
 				break;
-			if (!do_try_to_free_pages(GFP_KSWAPD))
+			if (!do_try_to_free_pages(GFP_KSWAPD, 0))
 				break;
 			run_task_queue(&tq_disk);
 		} while (!tsk->need_resched);
@@ -530,13 +529,13 @@
  * can be done by just dropping cached pages without having
  * any deadlock issues.
  */
-int try_to_free_pages(unsigned int gfp_mask)
+int try_to_free_pages(unsigned int gfp_mask, zone_t *zone)
 {
 	int retval = 1;
 
 	wake_up_process(kswapd_process);
 	if (gfp_mask & __GFP_WAIT)
-		retval = do_try_to_free_pages(gfp_mask);
+		retval = do_try_to_free_pages(gfp_mask, zone);
 	return retval;
 }
 
diff -u --recursive --new-file v2.3.37/linux/net/README linux/net/README
--- v2.3.37/linux/net/README	Mon Dec 20 18:48:22 1999
+++ linux/net/README	Thu Jan  6 15:01:56 2000
@@ -5,14 +5,14 @@
 -------------------+-------------------------------------------
 802 [other	]	alan@lxorguk.ukuu.org.uk	
     [token ring	]	p.norton@computer.org
-appletalk		Jay.Schulist@spacs.k12.wi.us
+appletalk		jschlst@turbolinux.com
 ax25			g4klx@g4klx.demon.co.uk
 core			alan@lxorguk.ukuu.org.uk
 decnet			SteveW@ACM.org
 ethernet		alan@lxorguk.ukuu.org.uk
 ipv4			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
 ipv6			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
-ipx/spx			Jay.Schulist@spacs.k12.wi.us
+ipx/spx			jschlst@turbolinux.com
 irda                    dagb@cs.uit.no
 lapb			g4klx@g4klx.demon.co.uk
 netrom			g4klx@g4klx.demon.co.uk
diff -u --recursive --new-file v2.3.37/linux/net/core/filter.c linux/net/core/filter.c
--- v2.3.37/linux/net/core/filter.c	Tue Aug 31 17:29:15 1999
+++ linux/net/core/filter.c	Thu Jan  6 14:46:18 2000
@@ -2,7 +2,7 @@
  * Linux Socket Filter - Kernel level socket filtering
  *
  * Author:
- *     Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *     Jay Schulist <jschlst@turbolinux.com>
  *
  * Based on the design of:
  *     - The Berkeley Packet Filter
diff -u --recursive --new-file v2.3.37/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.37/linux/net/decnet/dn_route.c	Tue Nov 23 22:42:21 1999
+++ linux/net/decnet/dn_route.c	Thu Jan  6 16:18:30 2000
@@ -22,6 +22,9 @@
  *              Steve Whitehouse : More SMP locking changes & dn_cache_dump()
  *              Steve Whitehouse : Prerouting NF hook, now really is prerouting.
  *				   Fixed possible skb leak in rtnetlink funcs.
+ *              Steve Whitehouse : Dave Miller's dynamic hash table sizing and
+ *                                 Alexey Kuznetsov's finer grained locking
+ *                                 from ipv4/route.c.
  */
 
 /******************************************************************************
@@ -44,7 +47,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
@@ -69,9 +71,14 @@
 #include <net/dn_fib.h>
 #include <net/dn_raw.h>
 
+struct dn_rt_hash_bucket
+{
+	struct dn_route *chain;
+	rwlock_t lock;
+} __attribute__((__aligned__(8)));
+
 extern struct neigh_table dn_neigh_table;
 
-#define DN_HASHBUCKETS 16
 
 static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
 
@@ -82,8 +89,8 @@
 static void dn_dst_link_failure(struct sk_buff *);
 static int dn_route_input(struct sk_buff *);
 
-static struct dn_route *dn_route_cache[DN_HASHBUCKETS];
-static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
+static struct dn_rt_hash_bucket *dn_rt_hash_table;
+static unsigned dn_rt_hash_mask;
 
 static struct timer_list dn_route_timer = { NULL, NULL, 0, 0L, NULL };
 int decnet_dst_gc_interval = 2;
@@ -104,8 +111,11 @@
 
 static __inline__ unsigned dn_hash(unsigned short dest)
 {
-	unsigned short tmp = (dest&0xff) ^ (dest>>8);
-	return (tmp&0x0f) ^ (tmp>>4);
+	unsigned short tmp = dest;
+	tmp ^= (dest >> 3);
+	tmp ^= (dest >> 5);
+	tmp ^= (dest >> 10);
+	return dn_rt_hash_mask & (unsigned)tmp;
 }
 
 static void dn_dst_check_expire(unsigned long dummy)
@@ -115,10 +125,10 @@
 	unsigned long now = jiffies;
 	unsigned long expire = 120 * HZ;
 
-	for(i = 0; i < DN_HASHBUCKETS; i++) {
-		rtp = &dn_route_cache[i];
+	for(i = 0; i <= dn_rt_hash_mask; i++) {
+		rtp = &dn_rt_hash_table[i].chain;
 
-		write_lock(&dn_hash_lock);
+		write_lock(&dn_rt_hash_table[i].lock);
 		for(;(rt=*rtp); rtp = &rt->u.rt_next) {
 			if (atomic_read(&rt->u.dst.__refcnt) ||
 					(now - rt->u.dst.lastuse) < expire)
@@ -127,7 +137,7 @@
 			rt->u.rt_next = NULL;
 			dst_free(&rt->u.dst);
 		}
-		write_unlock(&dn_hash_lock);
+		write_unlock(&dn_rt_hash_table[i].lock);
 
 		if ((jiffies - now) > 0)
 			break;
@@ -144,9 +154,9 @@
 	unsigned long now = jiffies;
 	unsigned long expire = 10 * HZ;
 
-	write_lock_bh(&dn_hash_lock);
-	for(i = 0; i < DN_HASHBUCKETS; i++) {
-		rtp = &dn_route_cache[i];
+	for(i = 0; i <= dn_rt_hash_mask; i++) {
+		write_lock_bh(&dn_rt_hash_table[i].lock);
+		rtp = &dn_rt_hash_table[i].chain;
 		for(; (rt=*rtp); rtp = &rt->u.rt_next) {
 			if (atomic_read(&rt->u.dst.__refcnt) ||
 					(now - rt->u.dst.lastuse) < expire)
@@ -156,8 +166,8 @@
 			dst_free(&rt->u.dst);
 			break;
 		}
+		write_unlock_bh(&dn_rt_hash_table[i].lock);
 	}
-	write_unlock_bh(&dn_hash_lock);
 
 	return 0;
 }
@@ -194,15 +204,15 @@
 	unsigned hash = dn_hash(rt->rt_daddr);
 	unsigned long now = jiffies;
 
-	write_lock_bh(&dn_hash_lock);
-	rt->u.rt_next = dn_route_cache[hash];
-	dn_route_cache[hash] = rt;
+	write_lock_bh(&dn_rt_hash_table[hash].lock);
+	rt->u.rt_next = dn_rt_hash_table[hash].chain;
+	dn_rt_hash_table[hash].chain = rt;
 	
 	dst_hold(&rt->u.dst);
 	rt->u.dst.__use++;
 	rt->u.dst.lastuse = now;
 
-	write_unlock_bh(&dn_hash_lock);
+	write_unlock_bh(&dn_rt_hash_table[hash].lock);
 }
 
 void dn_run_flush(unsigned long dummy)
@@ -210,18 +220,21 @@
 	int i;
 	struct dn_route *rt, *next;
 
-	write_lock_bh(&dn_hash_lock);
-	for(i = 0; i < DN_HASHBUCKETS; i++) {
-		if ((rt = xchg(&dn_route_cache[i], NULL)) == NULL)
-			continue;
+	for(i = 0; i < dn_rt_hash_mask; i++) {
+		write_lock_bh(&dn_rt_hash_table[i].lock);
+
+		if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL)
+			goto nothing_to_declare;
 
 		for(; rt; rt=next) {
 			next = rt->u.rt_next;
 			rt->u.rt_next = NULL;
 			dst_free((struct dst_entry *)rt);
 		}
+
+nothing_to_declare:
+		write_unlock_bh(&dn_rt_hash_table[i].lock);
 	}
-	write_unlock_bh(&dn_hash_lock);
 }
 
 static int dn_route_rx_packet(struct sk_buff *skb)
@@ -607,8 +620,8 @@
 	struct dn_route *rt = NULL;
 
 	if (!(flags & MSG_TRYHARD)) {
-		read_lock_bh(&dn_hash_lock);
-		for(rt = dn_route_cache[hash]; rt; rt = rt->u.rt_next) {
+		read_lock_bh(&dn_rt_hash_table[hash].lock);
+		for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
 			if ((dst == rt->rt_daddr) &&
 					(src == rt->rt_saddr) &&
 					(rt->rt_iif == 0) &&
@@ -616,12 +629,12 @@
 				rt->u.dst.lastuse = jiffies;
 				dst_hold(&rt->u.dst);
 				rt->u.dst.__use++;
-				read_unlock_bh(&dn_hash_lock);
+				read_unlock_bh(&dn_rt_hash_table[hash].lock);
 				*pprt = &rt->u.dst;
 				return 0;
 			}
 		}
-		read_unlock_bh(&dn_hash_lock);
+		read_unlock_bh(&dn_rt_hash_table[hash].lock);
 	}
 
 	return dn_route_output_slow(pprt, dst, src, flags);
@@ -731,8 +744,8 @@
 	if (skb->dst)
 		return 0;
 
-	read_lock_bh(&dn_hash_lock);
-	for(rt = dn_route_cache[hash]; rt != NULL; rt = rt->u.rt_next) {
+	read_lock(&dn_rt_hash_table[hash].lock);
+	for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
 		if ((rt->rt_saddr == cb->dst) &&
 				(rt->rt_daddr == cb->src) &&
 				(rt->rt_oif == 0) &&
@@ -740,12 +753,12 @@
 			rt->u.dst.lastuse = jiffies;
 			dst_hold(&rt->u.dst);
 			rt->u.dst.__use++;
-			read_unlock_bh(&dn_hash_lock);
+			read_unlock(&dn_rt_hash_table[hash].lock);
 			skb->dst = (struct dst_entry *)rt;
 			return 0;
 		}
 	}
-	read_unlock_bh(&dn_hash_lock);
+	read_unlock(&dn_rt_hash_table[hash].lock);
 
 	return dn_route_input_slow(skb);
 }
@@ -831,7 +844,9 @@
 		skb->rx_dev = dev;
 		cb->src = src;
 		cb->dst = dst;
+		local_bh_disable();
 		err = dn_route_input(skb);
+		local_bh_enable();
 		memset(cb, 0, sizeof(struct dn_skb_cb));
 		rt = (struct dn_route *)skb->dst;
 	} else {
@@ -885,25 +900,25 @@
 
 	s_h = cb->args[0];
 	s_idx = idx = cb->args[1];
-	for(h = 0; h < DN_HASHBUCKETS; h++) {
+	for(h = 0; h <= dn_rt_hash_mask; h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
 			s_idx = 0;
-		read_lock_bh(&dn_hash_lock);
-		for(rt = dn_route_cache[h], idx = 0; rt; rt = rt->u.rt_next, idx++) {
+		read_lock_bh(&dn_rt_hash_table[h].lock);
+		for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
 					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				read_unlock_bh(&dn_hash_lock);
+				read_unlock_bh(&dn_rt_hash_table[h].lock);
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		read_unlock_bh(&dn_hash_lock);
+		read_unlock_bh(&dn_rt_hash_table[h].lock);
 	}
 
 done:
@@ -924,9 +939,9 @@
 	int i;
 	char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
 
-	read_lock_bh(&dn_hash_lock);
-	for(i = 0; i < DN_HASHBUCKETS; i++) {
-		rt = dn_route_cache[i];
+	for(i = 0; i <= dn_rt_hash_mask; i++) {
+		read_lock_bh(&dn_rt_hash_table[i].lock);
+		rt = dn_rt_hash_table[i].chain;
 		for(; rt != NULL; rt = rt->u.rt_next) {
 			len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n",
 					rt->u.dst.dev ? rt->u.dst.dev->name : "*",
@@ -937,6 +952,7 @@
 					(int)rt->u.dst.rtt
 					);
 
+
 	                pos = begin + len;
 	
         	        if (pos < offset) {
@@ -946,10 +962,10 @@
               		if (pos > offset + length)
                 	        break;
 		}
+		read_unlock_bh(&dn_rt_hash_table[i].lock);
 		if (pos > offset + length)
 			break;
 	}
-	read_unlock_bh(&dn_hash_lock);
 
         *start = buffer + (offset - begin);
         len   -= (offset - begin);
@@ -963,16 +979,54 @@
 
 void __init dn_route_init(void)
 {
-	memset(dn_route_cache, 0, sizeof(struct dn_route *) * DN_HASHBUCKETS);
+	int i, goal, order;
 
 	dn_dst_ops.kmem_cachep = kmem_cache_create("dn_dst_cache",
 						   sizeof(struct dn_route),
 						   0, SLAB_HWCACHE_ALIGN,
 						   NULL, NULL);
 
+	if (!dn_dst_ops.kmem_cachep)
+		panic("DECnet: Failed to allocate dn_dst_cache\n");
+
 	dn_route_timer.function = dn_dst_check_expire;
 	dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
 	add_timer(&dn_route_timer);
+
+	goal = num_physpages >> (26 - PAGE_SHIFT);
+
+	for(order = 0; (1UL << order) < goal; order++)
+		/* NOTHING */;
+
+	/*
+	 * Only want 1024 entries max, since the table is very, very unlikely
+	 * to be larger than that.
+	 */
+	while(order && ((((1UL << order) * PAGE_SIZE) / 
+				sizeof(struct dn_rt_hash_bucket)) >= 2048))
+		order--;
+
+	do {
+		dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
+			sizeof(struct dn_rt_hash_bucket);
+		while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
+			dn_rt_hash_mask--;
+		dn_rt_hash_table = (struct dn_rt_hash_bucket *)
+			__get_free_pages(GFP_ATOMIC, order);
+	} while (dn_rt_hash_table == NULL && --order > 0);
+
+	if (!dn_rt_hash_table)
+		panic("Failed to allocate DECnet route cache hash table\n");
+
+	printk(KERN_INFO "DECnet: Routing cache hash table of %u buckets, %dKbytes\n", dn_rt_hash_mask, (dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
+
+	dn_rt_hash_mask--;
+	for(i = 0; i <= dn_rt_hash_mask; i++) {
+		dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
+		dn_rt_hash_table[i].chain = NULL;
+	}
+
+	dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
 
 #ifdef CONFIG_PROC_FS
 	proc_net_create("decnet_cache",0,decnet_cache_get_info);
diff -u --recursive --new-file v2.3.37/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.37/linux/net/ipv4/route.c	Thu Jan  6 12:57:48 2000
+++ linux/net/ipv4/route.c	Thu Jan  6 16:18:30 2000
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.75 1999/12/23 01:41:44 davem Exp $
+ * Version:	$Id: route.c,v 1.77 2000/01/06 00:41:59 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -103,8 +103,7 @@
 
 int ip_rt_min_delay = 2*HZ;
 int ip_rt_max_delay = 10*HZ;
-int ip_rt_gc_thresh = RT_HASH_DIVISOR;
-int ip_rt_max_size = RT_HASH_DIVISOR*16;
+int ip_rt_max_size;
 int ip_rt_gc_timeout = RT_GC_TIMEOUT;
 int ip_rt_gc_interval = 60*HZ;
 int ip_rt_gc_min_interval = 5*HZ;
@@ -122,12 +121,8 @@
 
 #define RTprint(a...)	printk(KERN_DEBUG a)
 
-static void rt_run_flush(unsigned long dummy);
-
-static struct timer_list rt_flush_timer =
-	{ NULL, NULL, 0, 0L, rt_run_flush };
-static struct timer_list rt_periodic_timer =
-	{ NULL, NULL, 0, 0L, NULL };
+static struct timer_list rt_flush_timer;
+static struct timer_list rt_periodic_timer;
 
 /*
  *	Interface to generic destination cache.
@@ -146,7 +141,7 @@
 {
 	AF_INET,
 	__constant_htons(ETH_P_IP),
-	RT_HASH_DIVISOR,
+	0,
 
 	rt_garbage_collect,
 	ipv4_dst_check,
@@ -183,7 +178,7 @@
 
 /* The locking scheme is rather straight forward:
  *
- * 1) A BH protected rwlock protects the central route hash.
+ * 1) A BH protected rwlocks protect buckets of the central route hash.
  * 2) Only writers remove entries, and they hold the lock
  *    as they look at rtable reference counts.
  * 3) Only readers acquire references to rtable entries,
@@ -191,17 +186,23 @@
  *    lock held.
  */
 
-static struct rtable 	*rt_hash_table[RT_HASH_DIVISOR];
-static rwlock_t		 rt_hash_lock = RW_LOCK_UNLOCKED;
+struct rt_hash_bucket {
+	struct rtable	*chain;
+	rwlock_t	lock;
+} __attribute__((__aligned__(8)));
+
+static struct rt_hash_bucket 	*rt_hash_table;
+static unsigned			rt_hash_mask;
+static int			rt_hash_log;
 
 static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res);
 
 static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
 {
 	unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4);
-	hash = hash^saddr^tos;
-	hash = hash^(hash>>16);
-	return (hash^(hash>>8)) & 0xFF;
+	hash ^= saddr^tos;
+	hash ^= (hash>>16);
+	return (hash^(hash>>8)) & rt_hash_mask;
 }
 
 #ifndef CONFIG_PROC_FS
@@ -222,11 +223,9 @@
 		len = 128;
   	}
 	
-  	
-	read_lock_bh(&rt_hash_lock);
-
-	for (i = 0; i<RT_HASH_DIVISOR; i++) {
-		for (r = rt_hash_table[i]; r; r = r->u.rt_next) {
+	for (i = rt_hash_mask; i>=0; i--) {
+		read_lock_bh(&rt_hash_table[i].lock);
+		for (r = rt_hash_table[i].chain; r; r = r->u.rt_next) {
 			/*
 			 *	Spin through entries until we are ready
 			 */
@@ -253,14 +252,15 @@
 				r->rt_spec_dst);
 			sprintf(buffer+len,"%-127s\n",temp);
 			len += 128;
-			if (pos >= offset+length)
+			if (pos >= offset+length) {
+				read_unlock_bh(&rt_hash_table[i].lock);
 				goto done;
+			}
 		}
+		read_unlock_bh(&rt_hash_table[i].lock);
         }
 
 done:
-	read_unlock_bh(&rt_hash_lock);
-  	
   	*start = buffer+len-(pos-offset);
   	len = pos-offset;
   	if (len>length)
@@ -315,21 +315,23 @@
 /* This runs via a timer and thus is always in BH context. */
 static void rt_check_expire(unsigned long dummy)
 {
-	int i;
+	int i, t;
 	static int rover;
 	struct rtable *rth, **rthp;
 	unsigned long now = jiffies;
 
-	for (i=0; i<RT_HASH_DIVISOR/5; i++) {
+	i = rover;
+
+	for (t=(ip_rt_gc_interval<<rt_hash_log); t>=0; t -= ip_rt_gc_timeout) {
 		unsigned tmo = ip_rt_gc_timeout;
 
-		rover = (rover + 1) & (RT_HASH_DIVISOR-1);
-		rthp = &rt_hash_table[rover];
+		i = (i + 1) & rt_hash_mask;
+		rthp = &rt_hash_table[i].chain;
 
-		write_lock(&rt_hash_lock);
+		write_lock(&rt_hash_table[i].lock);
 		while ((rth = *rthp) != NULL) {
 			if (rth->u.dst.expires) {
-				/* Entrie is expired even if it is in use */
+				/* Entry is expired even if it is in use */
 				if ((long)(now - rth->u.dst.expires) <= 0) {
 					tmo >>= 1;
 					rthp = &rth->u.rt_next;
@@ -347,14 +349,14 @@
 			*rthp = rth->u.rt_next;
 			rt_free(rth);
 		}
-		write_unlock(&rt_hash_lock);
+		write_unlock(&rt_hash_table[i].lock);
 
 		/* Fallback loop breaker. */
 		if ((jiffies - now) > 0)
 			break;
 	}
-	rt_periodic_timer.expires = now + ip_rt_gc_interval;
-	add_timer(&rt_periodic_timer);
+	rover = i;
+	mod_timer(&rt_periodic_timer, now + ip_rt_gc_interval);
 }
 
 /* This can run from both BH and non-BH contexts, the latter
@@ -367,11 +369,12 @@
 
 	rt_deadline = 0;
 
-	for (i=0; i<RT_HASH_DIVISOR; i++) {
-		write_lock_bh(&rt_hash_lock);
-		rth = rt_hash_table[i];
-		rt_hash_table[i] = NULL;
-		write_unlock_bh(&rt_hash_lock);
+	for (i=rt_hash_mask; i>=0; i--) {
+		write_lock_bh(&rt_hash_table[i].lock);
+		rth = rt_hash_table[i].chain;
+		if (rth)
+			rt_hash_table[i].chain = NULL;
+		write_unlock_bh(&rt_hash_table[i].lock);
 
 		for (; rth; rth=next) {
 			next = rth->u.rt_next;
@@ -418,8 +421,7 @@
 	if (rt_deadline == 0)
 		rt_deadline = now + ip_rt_max_delay;
 
-	rt_flush_timer.expires = now + delay;
-	add_timer(&rt_flush_timer);
+	mod_timer(&rt_flush_timer, now+delay);
 	spin_unlock_bh(&rt_flush_lock);
 }
 
@@ -455,20 +457,20 @@
 		return 0;
 
 	/* Calculate number of entries, which we want to expire now. */
-	goal = atomic_read(&ipv4_dst_ops.entries) - RT_HASH_DIVISOR*ip_rt_gc_elasticity;
+	goal = atomic_read(&ipv4_dst_ops.entries) - (ip_rt_gc_elasticity<<rt_hash_log);
 	if (goal <= 0) {
 		if (equilibrium < ipv4_dst_ops.gc_thresh)
 			equilibrium = ipv4_dst_ops.gc_thresh;
 		goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		if (goal > 0) {
-			equilibrium += min(goal/2, RT_HASH_DIVISOR);
+			equilibrium += min(goal/2, rt_hash_mask+1);
 			goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		}
 	} else {
 		/* We are in dangerous area. Try to reduce cache really
 		 * aggressively.
 		 */
-		goal = max(goal/2, RT_HASH_DIVISOR);
+		goal = max(goal/2, rt_hash_mask+1);
 		equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
 	}
 
@@ -483,15 +485,12 @@
 	do {
 		int i, k;
 
-		/* The write lock is held during the entire hash
-		 * traversal to ensure consistent state of the rover.
-		 */
-		write_lock_bh(&rt_hash_lock);
-		for (i=0, k=rover; i<RT_HASH_DIVISOR; i++) {
+		for (i=rt_hash_mask, k=rover; i>=0; i--) {
 			unsigned tmo = expire;
 
-			k = (k + 1) & (RT_HASH_DIVISOR-1);
-			rthp = &rt_hash_table[k];
+			k = (k + 1) & rt_hash_mask;
+			rthp = &rt_hash_table[k].chain;
+			write_lock_bh(&rt_hash_table[k].lock);
 			while ((rth = *rthp) != NULL) {
 				if (!rt_may_expire(rth, tmo, expire)) {
 					tmo >>= 1;
@@ -502,11 +501,11 @@
 				rt_free(rth);
 				goal--;
 			}
+			write_unlock_bh(&rt_hash_table[k].lock);
 			if (goal <= 0)
 				break;
 		}
 		rover = k;
-		write_unlock_bh(&rt_hash_lock);
 
 		if (goal <= 0)
 			goto work_done;
@@ -556,20 +555,20 @@
 	int attempts = !in_interrupt();
 
 restart:
-	rthp = &rt_hash_table[hash];
+	rthp = &rt_hash_table[hash].chain;
 
-	write_lock_bh(&rt_hash_lock);
+	write_lock_bh(&rt_hash_table[hash].lock);
 	while ((rth = *rthp) != NULL) {
 		if (memcmp(&rth->key, &rt->key, sizeof(rt->key)) == 0) {
 			/* Put it first */
 			*rthp = rth->u.rt_next;
-			rth->u.rt_next = rt_hash_table[hash];
-			rt_hash_table[hash] = rth;
+			rth->u.rt_next = rt_hash_table[hash].chain;
+			rt_hash_table[hash].chain = rth;
 
 			rth->u.dst.__use++;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.lastuse = now;
-			write_unlock_bh(&rt_hash_lock);
+			write_unlock_bh(&rt_hash_table[hash].lock);
 
 			rt_drop(rt);
 			*rp = rth;
@@ -584,7 +583,7 @@
 	 */
 	if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) {
 		if (!arp_bind_neighbour(&rt->u.dst)) {
-			write_unlock_bh(&rt_hash_lock);
+			write_unlock_bh(&rt_hash_table[hash].lock);
 
 			/* Neighbour tables are full and nothing
 			   can be released. Try to shrink route cache,
@@ -613,7 +612,7 @@
 		}
 	}
 
-	rt->u.rt_next = rt_hash_table[hash];
+	rt->u.rt_next = rt_hash_table[hash].chain;
 #if RT_CACHE_DEBUG >= 2
 	if (rt->u.rt_next) {
 		struct rtable * trt;
@@ -623,8 +622,8 @@
 		printk("\n");
 	}
 #endif
-	rt_hash_table[hash] = rt;
-	write_unlock_bh(&rt_hash_lock);
+	rt_hash_table[hash].chain = rt;
+	write_unlock_bh(&rt_hash_table[hash].lock);
 	*rp = rt;
 	return 0;
 }
@@ -692,16 +691,16 @@
 {
 	struct rtable **rthp;
 
-	write_lock_bh(&rt_hash_lock);
+	write_lock_bh(&rt_hash_table[hash].lock);
 	ip_rt_put(rt);
-	for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
+	for (rthp = &rt_hash_table[hash].chain; *rthp; rthp = &(*rthp)->u.rt_next) {
 		if (*rthp == rt) {
 			*rthp = rt->u.rt_next;
 			rt_free(rt);
 			break;
 		}
 	}
-	write_unlock_bh(&rt_hash_lock);
+	write_unlock_bh(&rt_hash_table[hash].lock);
 }
 
 void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
@@ -736,9 +735,9 @@
 		for (k=0; k<2; k++) {
 			unsigned hash = rt_hash_code(daddr, skeys[i]^(ikeys[k]<<5), tos);
 
-			rthp=&rt_hash_table[hash];
+			rthp=&rt_hash_table[hash].chain;
 
-			read_lock(&rt_hash_lock);
+			read_lock(&rt_hash_table[hash].lock);
 			while ( (rth = *rthp) != NULL) {
 				struct rtable *rt;
 
@@ -759,7 +758,7 @@
 					break;
 
 				dst_clone(&rth->u.dst);
-				read_unlock(&rt_hash_lock);
+				read_unlock(&rt_hash_table[hash].lock);
 
 				rt = dst_alloc(&ipv4_dst_ops);
 				if (rt == NULL) {
@@ -806,7 +805,7 @@
 					ip_rt_put(rt);
 				goto do_next;
 			}
-			read_unlock(&rt_hash_lock);
+			read_unlock(&rt_hash_table[hash].lock);
 		do_next:
 			;
 		}
@@ -974,8 +973,8 @@
 	for (i=0; i<2; i++) {
 		unsigned hash = rt_hash_code(daddr, skeys[i], tos);
 
-		read_lock(&rt_hash_lock);
-		for (rth = rt_hash_table[hash]; rth; rth = rth->u.rt_next) {
+		read_lock(&rt_hash_table[hash].lock);
+		for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
 			if (rth->key.dst == daddr &&
 			    rth->key.src == skeys[i] &&
 			    rth->rt_dst == daddr &&
@@ -1008,7 +1007,7 @@
 				}
 			}
 		}
-		read_unlock(&rt_hash_lock);
+		read_unlock(&rt_hash_table[hash].lock);
 	}
 	return est_mtu ? : new_mtu;
 }
@@ -1550,8 +1549,8 @@
 	tos &= IPTOS_TOS_MASK;
 	hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
 
-	read_lock_bh(&rt_hash_lock);
-	for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+	read_lock(&rt_hash_table[hash].lock);
+	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
 		if (rth->key.dst == daddr &&
 		    rth->key.src == saddr &&
 		    rth->key.iif == iif &&
@@ -1565,12 +1564,12 @@
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
-			read_unlock_bh(&rt_hash_lock);
+			read_unlock(&rt_hash_table[hash].lock);
 			skb->dst = (struct dst_entry*)rth;
 			return 0;
 		}
 	}
-	read_unlock_bh(&rt_hash_lock);
+	read_unlock(&rt_hash_table[hash].lock);
 
 	/* Multicast recognition logic is moved from route cache to here.
 	   The problem was that too many Ethernet cards have broken/missing
@@ -1885,8 +1884,8 @@
 
 	hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
 
-	read_lock_bh(&rt_hash_lock);
-	for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+	read_lock_bh(&rt_hash_table[hash].lock);
+	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
 		if (rth->key.dst == daddr &&
 		    rth->key.src == saddr &&
 		    rth->key.iif == 0 &&
@@ -1897,12 +1896,12 @@
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
-			read_unlock_bh(&rt_hash_lock);
+			read_unlock_bh(&rt_hash_table[hash].lock);
 			*rp = rth;
 			return 0;
 		}
 	}
-	read_unlock_bh(&rt_hash_lock);
+	read_unlock_bh(&rt_hash_table[hash].lock);
 
 	return ip_route_output_slow(rp, daddr, saddr, tos, oif);
 }
@@ -2043,7 +2042,9 @@
 			return -ENODEV;
 		skb->protocol = __constant_htons(ETH_P_IP);
 		skb->dev = dev;
+		local_bh_disable();
 		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+		local_bh_enable();
 		rt = (struct rtable*)skb->dst;
 		if (!err && rt->u.dst.error)
 			err = -rt->u.dst.error;
@@ -2085,24 +2086,24 @@
 
 	s_h = cb->args[0];
 	s_idx = idx = cb->args[1];
-	for (h=0; h < RT_HASH_DIVISOR; h++) {
+	for (h=0; h <= rt_hash_mask; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
 			s_idx = 0;
-		read_lock_bh(&rt_hash_lock);
-		for (rt = rt_hash_table[h], idx = 0; rt; rt = rt->u.rt_next, idx++) {
+		read_lock_bh(&rt_hash_table[h].lock);
+		for (rt = rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
 					 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				read_unlock_bh(&rt_hash_lock);
+				read_unlock_bh(&rt_hash_table[h].lock);
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		read_unlock_bh(&rt_hash_lock);
+		read_unlock_bh(&rt_hash_table[h].lock);
 	}
 
 done:
@@ -2231,17 +2232,56 @@
 #endif
 #endif
 
-
 void __init ip_rt_init(void)
 {
+	int i, order, goal;
+
 	ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
 						     sizeof(struct rtable),
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
-	
+
+	if (!ipv4_dst_ops.kmem_cachep)
+		panic("IP: failed to allocate ip_dst_cache\n");
+
+	goal = num_physpages >> (26 - PAGE_SHIFT);
+
+	for (order = 0; (1UL << order) < goal; order++)
+		/* NOTHING */;
+
+	do {
+		rt_hash_mask = (1UL << order) * PAGE_SIZE /
+			sizeof(struct rt_hash_bucket);
+		while (rt_hash_mask & (rt_hash_mask-1))
+			rt_hash_mask--;
+		rt_hash_table = (struct rt_hash_bucket *)
+			__get_free_pages(GFP_ATOMIC, order);
+	} while (rt_hash_table == NULL && --order > 0);
+
+	if (!rt_hash_table)
+		panic("Failed to allocate IP route cache hash table\n");
+
+	printk("IP: routing cache hash table of %u buckets, %dKbytes\n",
+	       rt_hash_mask, (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
+
+	for (rt_hash_log=0; (1<<rt_hash_log) != rt_hash_mask; rt_hash_log++)
+		/* NOTHING */;
+
+	rt_hash_mask--;
+	for (i = 0; i <= rt_hash_mask; i++) {
+		rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
+		rt_hash_table[i].chain = NULL;
+	}
+
+	ipv4_dst_ops.gc_thresh = (rt_hash_mask+1);
+	ip_rt_max_size = (rt_hash_mask+1)*16;
+
 	devinet_init();
 	ip_fib_init();
+
+	rt_flush_timer.function = rt_run_flush;
 	rt_periodic_timer.function = rt_check_expire;
+
 	/* All the timers, started at system startup tend
 	   to synchronize. Perturb it a bit.
 	 */
diff -u --recursive --new-file v2.3.37/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.3.37/linux/net/ipv4/udp.c	Wed Dec 29 13:13:21 1999
+++ linux/net/ipv4/udp.c	Thu Jan  6 16:18:30 2000
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.75 1999/12/15 22:39:34 davem Exp $
+ * Version:	$Id: udp.c,v 1.76 2000/01/05 21:27:51 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -664,10 +664,6 @@
 	}
 	return(0);
 }
-
-#ifndef HAVE_CSUM_COPY_USER
-#undef CONFIG_UDP_DELAY_CSUM
-#endif
 
 /*
  * 	This should be easy, if there is something there we
diff -u --recursive --new-file v2.3.37/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.3.37/linux/net/ipv6/udp.c	Wed Dec 29 13:13:21 1999
+++ linux/net/ipv6/udp.c	Thu Jan  6 16:18:30 2000
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.46 1999/12/15 22:40:03 davem Exp $
+ *	$Id: udp.c,v 1.47 2000/01/05 21:27:54 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -340,10 +340,6 @@
 {
 	inet_sock_release(sk);
 }
-
-#ifndef HAVE_CSUM_COPY_USER
-#undef CONFIG_UDP_DELAY_CSUM
-#endif
 
 /*
  * 	This should be easy, if there is something there we
diff -u --recursive --new-file v2.3.37/linux/net/ipx/af_spx.c linux/net/ipx/af_spx.c
--- v2.3.37/linux/net/ipx/af_spx.c	Fri Oct 15 15:25:14 1999
+++ linux/net/ipx/af_spx.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  *		 Revision Date:  February 9, 1993
  *
  *	Developers:
- *      Jay Schulist    <Jay.Schulist@spacs.k12.wi.us>
+ *      Jay Schulist    <jschlst@turbolinux.com>
  *	Jim Freeman	<jfree@caldera.com>
  *
  *	Changes:
diff -u --recursive --new-file v2.3.37/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.37/linux/net/irda/af_irda.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/af_irda.c	Fri Jan  7 11:51:56 2000
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Fri Dec 17 22:37:53 1999
+ * Modified at:   Sat Dec 25 21:10:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
@@ -324,13 +324,13 @@
 }
 
 /*
- * Function irda_get_value_confirm (obj_id, value, priv)
+ * Function irda_getvalue_confirm (obj_id, value, priv)
  *
  *    Got answer from remote LM-IAS
  *
  */
-static void irda_get_value_confirm(int result, __u16 obj_id, 
-				   struct ias_value *value, void *priv)
+static void irda_getvalue_confirm(int result, __u16 obj_id, 
+				  struct ias_value *value, void *priv)
 {
 	struct irda_sock *self;
 	
@@ -348,12 +348,12 @@
 	iriap_close(self->iriap);
 	self->iriap = NULL;
 
+	self->errno = result;
+
 	/* Check if request succeeded */
 	if (result != IAS_SUCCESS) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
 
-		self->errno = result;
-
 		/* Wake up any processes waiting for result */
 		wake_up_interruptible(&self->ias_wait);
 
@@ -483,7 +483,7 @@
 	}
 
 	self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
-				 irda_get_value_confirm);
+				 irda_getvalue_confirm);
 
 	/* Query remote LM-IAS */
 	iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr,
@@ -1652,7 +1652,7 @@
 			irias_add_octseq_attrib(
 			      ias_obj,
 			      ias_opt.irda_attrib_name, 
-			      ias_opt.attribute.irda_attrib_octet_seq.OctetSeq,
+			      ias_opt.attribute.irda_attrib_octet_seq.octet_seq,
 			      ias_opt.attribute.irda_attrib_octet_seq.len);
 			break;
 		case IAS_STRING:
@@ -1716,14 +1716,14 @@
 }
 
  /*
- * Function irda_simple_get_value_confirm (obj_id, value, priv)
+ * Function irda_simple_getvalue_confirm (obj_id, value, priv)
  *
  *    Got answer from remote LM-IAS, just copy object to requester...
  *
  * Note : duplicate from above, but we need our own version that
  * doesn't touch the dtsap_sel and save the full value structure...
  */
-static void irda_simple_get_value_confirm(int result, __u16 obj_id, 
+static void irda_simple_getvalue_confirm(int result, __u16 obj_id, 
 					  struct ias_value *value, void *priv)
 {
 	struct irda_sock *self;
@@ -1746,7 +1746,7 @@
 	if (result != IAS_SUCCESS) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
 
-		self->errno = result;
+		self->errno = -EHOSTUNREACH;
 
 		/* Wake up any processes waiting for result */
 		wake_up_interruptible(&self->ias_wait);
@@ -1757,6 +1757,9 @@
 	/* Clone the object (so the requester can free it) */
 	self->ias_result = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
 	memcpy(self->ias_result, value, sizeof(struct ias_value));
+	irias_delete_value(value);
+
+	self->errno = 0;
 
 	/* Wake up any processes waiting for result */
 	wake_up_interruptible(&self->ias_wait);
@@ -1778,7 +1781,7 @@
 				  struct ias_value *ias_value)
 {
 	/* Look at the type */
-	switch(ias_value->type) {
+	switch (ias_value->type) {
 	case IAS_INTEGER:
 		/* Copy the integer */
 		ias_opt->attribute.irda_attrib_int = ias_value->t.integer;
@@ -1787,7 +1790,7 @@
 		/* Set length */
 		ias_opt->attribute.irda_attrib_octet_seq.len = ias_value->len;
 		/* Copy over */
-		memcpy(ias_opt->attribute.irda_attrib_octet_seq.OctetSeq,
+		memcpy(ias_opt->attribute.irda_attrib_octet_seq.octet_seq,
 		       ias_value->t.oct_seq, ias_value->len);
 		break;
 	case IAS_STRING:
@@ -1803,10 +1806,10 @@
 	default :
 		return -EINVAL;
 	}
-
+	
 	/* Copy type over */
 	ias_opt->irda_attrib_type = ias_value->type;
-
+	
 	return 0;
 }
 
@@ -1827,7 +1830,6 @@
 	struct irda_ias_set	ias_opt;	/* IAS get/query params */
 	struct ias_object *	ias_obj;	/* Object in IAS */
 	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
-	int daddr = 0;		/* Destination address for IAS queries */
 	int val = 0;
 	int len = 0;
 	int err;
@@ -1962,21 +1964,6 @@
 		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
 		  	return -EFAULT;
 
-		/* Check the destination address requested */
-		daddr = ias_opt.attribute.irda_attrib_int;
-		if(self->daddr != DEV_ADDR_ANY) {
-			/* If we are connected, we must use the correct
-			 * destination address (or leave it unspecified) */
-			if((daddr != DEV_ADDR_ANY) || (daddr != self->daddr))
-				return -EINVAL;
-			daddr = self->daddr;
-		} else {
-			/* If we are not connected, we must specify a valid
-			 * destination address */
-			if(daddr == DEV_ADDR_ANY)
-				return -EINVAL;
-		}
-
 		/* Check that we can proceed with IAP */
 		if (self->iriap) {
 			WARNING(__FUNCTION__
@@ -1985,24 +1972,27 @@
 		}
 
 		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
-					 irda_simple_get_value_confirm);
+					 irda_simple_getvalue_confirm);
+
+		/* Treat unexpected signals as disconnect */
+		self->errno = -EHOSTUNREACH;
 
 		/* Query remote LM-IAS */
-		self->errno = 0;
-		iriap_getvaluebyclass_request(self->iriap, self->saddr,
-					      daddr,
+		iriap_getvaluebyclass_request(self->iriap, 
+					      self->saddr, self->daddr,
 					      ias_opt.irda_class_name,
 					      ias_opt.irda_attrib_name);
 		/* Wait for answer */
 		interruptible_sleep_on(&self->ias_wait);
 		/* Check what happened */
-		if(self->errno)
-			return(self->errno);
+		if (self->errno)
+			return (self->errno);
 
 		/* Translate from internal to user structure */
 		err = irda_extract_ias_value(&ias_opt, self->ias_result);
-		kfree(self->ias_result); /* Cleanup (need to be *here*) */
-		if(err)
+		if (self->ias_result)
+			kfree(self->ias_result);
+		if (err)
 			return err;
 
 		/* Copy reply to the user */
@@ -2014,7 +2004,7 @@
 	default:
 		return -ENOPROTOOPT;
 	}
-
+	
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.37/linux/net/irda/ircomm/ircomm_core.c linux/net/irda/ircomm/ircomm_core.c
--- v2.3.37/linux/net/irda/ircomm/ircomm_core.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/ircomm/ircomm_core.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:37:34 1999
- * Modified at:   Thu Dec 16 21:15:26 1999
+ * Modified at:   Tue Dec 21 13:26:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
--- v2.3.37/linux/net/irda/ircomm/ircomm_tty.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/ircomm/ircomm_tty.c	Thu Jan  6 14:46:18 2000
@@ -6,11 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 21:00:56 1999
- * Modified at:   Thu Dec 16 22:07:37 1999
+ * Modified at:   Tue Jan  4 14:12:06 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -280,13 +280,15 @@
 	}
 
 	if (self->flags & ASYNC_CALLOUT_ACTIVE) {
-		if (self->normal_termios.c_cflag & CLOCAL)
+		if (self->normal_termios.c_cflag & CLOCAL) {
 			IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
 			do_clocal = 1;
+		}
 	} else {
-		if (tty->termios->c_cflag & CLOCAL)
+		if (tty->termios->c_cflag & CLOCAL) {
 			IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
 			do_clocal = 1;
+		}
 	}
 	
 	/* Wait for carrier detect and the line to become
@@ -459,10 +461,12 @@
 	/* Check if this is a "normal" ircomm device, or an irlpt device */
 	if (line < 0x10) {
 		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
+		self->settings.service_type = IRCOMM_9_WIRE; /* Default */
 		IRDA_DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");
 	} else {
 		IRDA_DEBUG(2, __FUNCTION__ "(), IrLPT device\n");
 		self->service_type = IRCOMM_3_WIRE_RAW;
+		self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
 	}
 
 	ret = ircomm_tty_startup(self);
diff -u --recursive --new-file v2.3.37/linux/net/irda/ircomm/ircomm_tty_attach.c linux/net/irda/ircomm/ircomm_tty_attach.c
--- v2.3.37/linux/net/irda/ircomm/ircomm_tty_attach.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/ircomm/ircomm_tty_attach.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jun  5 17:42:00 1999
- * Modified at:   Wed Dec 15 23:32:08 1999
+ * Modified at:   Tue Jan  4 14:20:49 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -496,10 +496,11 @@
 	
 	del_timer(&self->watchdog_timer);
 
-	/*  
+	/* 
 	 * IrCOMM link is now up, and if we are not using hardware
-	 * flow-control, then declare the hardware as running. Otherwise
-	 * the client will have to wait for the CTS to be set.
+	 * flow-control, then declare the hardware as running. Otherwise we
+	 * will have to wait for the peer device (DCE) to raise the CTS
+	 * line.  
 	 */
 	if (self->flags & ASYNC_CTS_FLOW) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), waiting for CTS ...\n");
diff -u --recursive --new-file v2.3.37/linux/net/irda/ircomm/ircomm_tty_ioctl.c linux/net/irda/ircomm/ircomm_tty_ioctl.c
--- v2.3.37/linux/net/irda/ircomm/ircomm_tty_ioctl.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/ircomm/ircomm_tty_ioctl.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 10 14:39:09 1999
- * Modified at:   Tue Dec 14 18:08:09 1999
+ * Modified at:   Wed Jan  5 14:45:43 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -93,10 +93,11 @@
 	/* CTS flow control flag and modem status interrupts */
 	if (cflag & CRTSCTS) {
 		self->flags |= ASYNC_CTS_FLOW;
-		/* self->settings.flow_control |= IRCOMM_RTS_CTS_IN; */
-	} else
+		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+	} else {
 		self->flags &= ~ASYNC_CTS_FLOW;
-	
+		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
+	}
 	if (cflag & CLOCAL)
 		self->flags &= ~ASYNC_CHECK_CD;
 	else
diff -u --recursive --new-file v2.3.37/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.37/linux/net/irda/irda_device.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/irda_device.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Oct  9 09:22:27 1999
- * Modified at:   Tue Dec 21 21:53:45 1999
+ * Modified at:   Wed Jan  5 14:17:16 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
diff -u --recursive --new-file v2.3.37/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.3.37/linux/net/irda/iriap.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/iriap.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Fri Dec 17 15:58:16 1999
+ * Modified at:   Sat Dec 25 16:42:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -85,6 +85,7 @@
 {
 	struct ias_object *obj;
 	struct iriap_cb *server;
+	__u8 oct_seq[6];
 	__u16 hints;
 
 	/* Allocate master array */
@@ -102,14 +103,19 @@
 	 *  Register some default services for IrLMP 
 	 */
 	hints  = irlmp_service_to_hint(S_COMPUTER);
-	/*hints |= irlmp_service_to_hint(S_PNP);*/
 	service_handle = irlmp_register_service(hints);
 
-	/* 
-	 *  Register the Device object with LM-IAS
-	 */
+	/* Register the Device object with LM-IAS */
 	obj = irias_new_object("Device", IAS_DEVICE_ID);
 	irias_add_string_attrib(obj, "DeviceName", "Linux");
+
+	oct_seq[0] = 0x01;  /* Version 1 */
+	oct_seq[1] = 0x00;  /* IAS support bits */
+	oct_seq[2] = 0x00;  /* LM-MUX support bits */
+#ifdef CONFIG_IRDA_ULTRA
+	oct_seq[2] |= 0x04; /* Connectionless Data support */
+#endif
+	irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3);
 	irias_insert_object(obj);
 
 	/*  
@@ -580,7 +586,7 @@
 	tmp_be16 = cpu_to_be16(obj_id);
 	memcpy(fp+n, &tmp_be16, 2); n += 2;
 
-	switch(value->type) {
+	switch (value->type) {
 	case IAS_STRING:
 		skb_put(skb, 3 + value->len);
 		fp[n++] = value->type;
@@ -710,6 +716,22 @@
 	irlmp_data_request(self->lsap, skb);
 }
 
+void iriap_connect_request(struct iriap_cb *self)
+{
+	int ret;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+
+	ret = irlmp_connect_request(self->lsap, LSAP_IAS, 
+				    self->saddr, self->daddr, 
+				    NULL, NULL);
+	if (ret < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+	}
+}
+
 /*
  * Function iriap_connect_confirm (handle, skb)
  *
@@ -734,9 +756,7 @@
 	
 	del_timer(&self->watchdog_timer);
 
-	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, NULL);
-
-	dev_kfree_skb(userdata);
+	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
 }
 
 /*
@@ -855,7 +875,7 @@
 			 * no to use self anymore after calling confirm 
 			 */
 			if (self->confirm)
-				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
+				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
 					      self->priv);
 			dev_kfree_skb(skb);
 			break;
diff -u --recursive --new-file v2.3.37/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.3.37/linux/net/irda/iriap_event.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/iriap_event.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Fri Dec 17 15:59:13 1999
+ * Modified at:   Sat Dec 25 21:09:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -168,8 +168,6 @@
 static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event, 
 			       struct sk_buff *skb) 
 {
-	int ret;
-
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
@@ -178,9 +176,7 @@
 		iriap_next_client_state(self, S_CONNECTING);
 		ASSERT(self->skb == NULL, return;);
 		self->skb = skb;
-		ret = irlmp_connect_request(self->lsap, LSAP_IAS, 
-					    self->saddr, self->daddr, 
-					    NULL, NULL);
+		iriap_connect_request(self);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
@@ -207,7 +203,7 @@
 		/*
 		 *  Jump to S-Call FSM
 		 */
-		iriap_do_call_event(self, IAP_CALL_REQUEST, NULL);
+		iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
 		/* iriap_call_request(self, 0,0,0); */
 		iriap_next_client_state(self, S_CALL);
 		break;
@@ -261,12 +257,14 @@
 	case IAP_CALL_REQUEST:
 		skb = self->skb;
 		self->skb = NULL;
-
+		
 		irlmp_data_request(self->lsap, skb);
 		iriap_next_call_state(self, S_OUTSTANDING);
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
+		if (skb)
+			dev_kfree_skb(skb);
 		break;
 	}
 }
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c
--- v2.3.37/linux/net/irda/irlan/irlan_client_event.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/irlan/irlan_client_event.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Sun Oct 31 19:41:55 1999
+ * Modified at:   Sun Dec 26 21:52:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -194,7 +194,7 @@
 	
 	ASSERT(self != NULL, return -1;);
 	
-	switch(event) {
+	switch (event) {
 	case IRLAN_CONNECT_COMPLETE:
 		/* Send getinfo cmd */
 		irlan_get_provider_info(self);
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.37/linux/net/irda/irlan/irlan_common.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/irlan/irlan_common.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Dec 16 21:16:14 1999
+ * Modified at:   Sun Dec 26 21:53:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -705,7 +705,6 @@
  	frame[0] = CMD_GET_PROVIDER_INFO;
 	frame[1] = 0x00;                 /* Zero parameters */
 	
-	/* irttp_data_request(self->client.tsap_ctrl, skb); */
 	irlan_ctrl_data_request(self, skb);
 }
 
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.37/linux/net/irda/irlan/irlan_eth.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/irlan/irlan_eth.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Thu Dec 16 21:21:53 1999
+ * Modified at:   Thu Nov  4 14:50:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.3.37/linux/net/irda/irlap.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/irlap.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Dec 16 22:59:17 1999
+ * Modified at:   Tue Dec 14 09:26:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.37/linux/net/irda/irlap_event.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/irlap_event.c	Thu Jan  6 14:46:18 2000
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Dec 21 11:27:22 1999
+ * Modified at:   Sat Dec 25 21:07:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -446,7 +446,7 @@
 		 * Send response. This skb will not be sent out again, and
 		 * will only be used to send out the same info as the cmd
 		 */
-		irlap_send_test_frame(self, info->daddr, skb);
+		irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
 	case RECV_TEST_RSP:
@@ -1963,13 +1963,12 @@
 		irlap_start_wd_timer(self, self->wd_timeout);
 
 		/* Send response (info will be copied) */
-		irlap_send_test_frame(self, info->daddr, skb);
+		irlap_send_test_frame(self, self->caddr, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
 			   event, irlap_event[event]);
-
 		if (skb)
 			dev_kfree_skb(skb);
 
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.37/linux/net/irda/irlap_frame.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/irlap_frame.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Dec 21 11:19:19 1999
+ * Modified at:   Wed Jan  5 08:59:04 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -440,7 +440,7 @@
 		text = (char *) &discovery_info[2];
 	}
 	/* 
-	 *  Terminate string, should be safe since this is where the 
+	 *  Terminate info string, should be safe since this is where the 
 	 *  FCS bytes resides.
 	 */
 	skb->data[skb->len] = '\0'; 
@@ -1205,7 +1205,7 @@
  *    Send a test frame response
  *
  */
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr, 
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr, 
 			   struct sk_buff *cmd)
 {
 	struct sk_buff *skb;
@@ -1216,22 +1216,20 @@
 	if (!skb)
 		return;
 
-	skb_put(skb, sizeof(struct test_frame));
+	/* Broadcast frames must include saddr and daddr fields */
+	if (caddr == CBROADCAST) {
+		frame = (struct test_frame *) 
+			skb_put(skb, sizeof(struct test_frame));
 
-	frame = (struct test_frame *) skb->data;
-
-	/* Build header */
-	if (self->state == LAP_NDM)
-		frame->caddr = CBROADCAST; /* Send response */
-	else
-		frame->caddr = self->caddr;
+		/* Insert the swapped addresses */
+		frame->saddr = cpu_to_le32(self->saddr);
+		frame->daddr = cpu_to_le32(daddr);
+	} else
+		frame = (struct test_frame *) skb_put(skb, LAP_MAX_HEADER);
 
+	frame->caddr = caddr;
 	frame->control = TEST_RSP;
 
-	/* Insert the swapped addresses */
-	frame->saddr = cpu_to_le32(self->saddr);
-	frame->daddr = cpu_to_le32(daddr);
-
 	/* Copy info */
 	info = skb_put(skb, cmd->len);
 	memcpy(info, cmd->data, cmd->len);
@@ -1254,22 +1252,27 @@
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
-	if (skb->len < sizeof(struct test_frame)) {
-		IRDA_DEBUG(0, __FUNCTION__ "() test frame to short!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
 	frame = (struct test_frame *) skb->data;
+		
+	/* Broadcast frames must carry saddr and daddr fields */
+	if (info->caddr == CBROADCAST) {
+		if (skb->len < sizeof(struct test_frame)) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "() test frame to short!\n");
+			dev_kfree_skb(skb);
+			return;
+		}
+		
+		/* Read and swap addresses */
+		info->daddr = le32_to_cpu(frame->saddr);
+		info->saddr = le32_to_cpu(frame->daddr);
 
-	/* Read and swap addresses */
-	info->daddr = le32_to_cpu(frame->saddr);
-	info->saddr = le32_to_cpu(frame->daddr);
-
-	/* Make sure frame is addressed to us */
-	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-		dev_kfree_skb(skb);
-		return;
+		/* Make sure frame is addressed to us */
+		if ((info->saddr != self->saddr) && 
+		    (info->saddr != BROADCAST)) {
+			dev_kfree_skb(skb);
+			return;
+		}
 	}
 
 	if (command)
@@ -1378,7 +1381,7 @@
 	case DM_RSP:
 		irlap_do_event(self, RECV_DM_RSP, skb, &info);
 		break;
-	case DISC_CMD: /* And RD_RSP */
+	case DISC_CMD: /* And RD_RSP since they have the same value */
 		irlap_recv_disc_frame(self, skb, &info, command);
 		break;
 	case TEST_CMD:
diff -u --recursive --new-file v2.3.37/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.37/linux/net/irda/irlmp.c	Wed Dec 29 13:13:21 1999
+++ linux/net/irda/irlmp.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Thu Dec 16 22:59:40 1999
+ * Modified at:   Wed Jan  5 11:26:03 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -69,20 +69,19 @@
 /*
  * Function irlmp_init (void)
  *
- *    Create (allocate) the main IrLMP structure and the pointer array
- *    which will contain pointers to each instance of a LSAP.
+ *    Create (allocate) the main IrLMP structure
+ *
  */
 int __init irlmp_init(void)
 {
 	/* Initialize the irlmp structure. */
-	if ( irlmp == NULL) {
-		irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
-		if ( irlmp == NULL)
-			return -ENOMEM;
-	}
-	memset( irlmp, 0, sizeof(struct irlmp_cb));
+	irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+	if (irlmp == NULL)
+		return -ENOMEM;
+	memset(irlmp, 0, sizeof(struct irlmp_cb));
 	
 	irlmp->magic = LMP_MAGIC;
+	spin_lock_init(&irlmp->lock);
 
 	irlmp->clients = hashbin_new(HB_GLOBAL);
 	irlmp->services = hashbin_new(HB_GLOBAL);
@@ -377,9 +376,18 @@
 	 * device with the given daddr 
 	 */
 	if (!saddr) {
-		discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
-		if (discovery)
+		if (daddr != DEV_ADDR_ANY)
+			discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
+		else {
+			IRDA_DEBUG(2, __FUNCTION__ "(), no daddr\n");
+			discovery = (discovery_t *) 
+				hashbin_get_first(irlmp->cachelog);
+		}
+
+		if (discovery) {
 			saddr = discovery->saddr;
+			daddr = discovery->daddr;
+		}
 	}
 	lap = hashbin_find(irlmp->links, saddr, NULL);	
 	if (lap == NULL) {
diff -u --recursive --new-file v2.3.37/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.37/linux/net/irda/irmod.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/irmod.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Tue Dec 21 21:39:31 1999
+ * Modified at:   Wed Jan  5 15:12:41 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -332,8 +332,7 @@
 	struct irmanager_event event;
 
 	/* Make sure irmanager is running */
-	if ( !irda.in_use) {
-		printk( KERN_ERR "irmanager is not running!\n");
+	if (!irda.in_use) {
 		return;
 	}
 
@@ -372,7 +371,6 @@
 	
 	/* Make sure irmanager is running */
 	if (!irda.in_use) {
-		printk( KERN_ERR "irmanager is not running!\n");
 		return;
 	}
 
diff -u --recursive --new-file v2.3.37/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.37/linux/net/irda/irttp.c	Tue Jan  4 13:57:21 2000
+++ linux/net/irda/irttp.c	Thu Jan  6 14:46:18 2000
@@ -6,10 +6,10 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Thu Dec 16 23:00:03 1999
+ * Modified at:   Wed Jan  5 11:31:27 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -144,6 +144,7 @@
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct tsap_cb));
+	spin_lock_init(&self->lock);
 
 	init_timer(&self->todo_timer);
 
diff -u --recursive --new-file v2.3.37/linux/net/sched/Config.in linux/net/sched/Config.in
--- v2.3.37/linux/net/sched/Config.in	Mon Dec 20 18:48:22 1999
+++ linux/net/sched/Config.in	Fri Jan  7 16:57:13 2000
@@ -15,12 +15,16 @@
 tristate '  SFQ queue' CONFIG_NET_SCH_SFQ
 tristate '  TEQL queue' CONFIG_NET_SCH_TEQL
 tristate '  TBF queue' CONFIG_NET_SCH_TBF
+tristate '  GRED queue' CONFIG_NET_SCH_GRED
+tristate '  Diffserv field marker' CONFIG_NET_SCH_DSMARK
+tristate '  Ingress Qdisc' CONFIG_NET_SCH_INGRESS
 bool '  QoS support' CONFIG_NET_QOS
 if [ "$CONFIG_NET_QOS" = "y" ]; then
    bool '    Rate estimator' CONFIG_NET_ESTIMATOR
 fi
 bool '  Packet classifier API' CONFIG_NET_CLS
 if [ "$CONFIG_NET_CLS" = "y" ]; then
+   tristate '    TC index classifier' CONFIG_NET_CLS_TCINDEX
    tristate '    Routing table based classifier' CONFIG_NET_CLS_ROUTE4
    if [ "$CONFIG_NET_CLS_ROUTE4" != "n" ]; then
       define_bool CONFIG_NET_CLS_ROUTE y
@@ -30,7 +34,7 @@
    if [ "$CONFIG_NET_QOS" = "y" ]; then
       tristate '    Special RSVP classifier' CONFIG_NET_CLS_RSVP
       tristate '    Special RSVP classifier for IPv6' CONFIG_NET_CLS_RSVP6
-      bool '    Ingres traffic policing' CONFIG_NET_CLS_POLICE
+      bool '    Traffic policing (needed for in/egress)' CONFIG_NET_CLS_POLICE
    fi
 fi
 
diff -u --recursive --new-file v2.3.37/linux/net/sched/Makefile linux/net/sched/Makefile
--- v2.3.37/linux/net/sched/Makefile	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/Makefile	Fri Jan  7 16:57:13 2000
@@ -28,6 +28,14 @@
 
 endif
 
+ifeq ($(CONFIG_NET_SCH_INGRESS), y)
+O_OBJS += sch_ingress.o 
+else
+  ifeq ($(CONFIG_NET_SCH_INGRESS), m)
+	M_OBJS += sch_ingress.o 
+  endif
+endif
+
 ifeq ($(CONFIG_NET_SCH_CBQ), y)
 O_OBJS += sch_cbq.o
 else
@@ -98,6 +106,30 @@
 else
   ifeq ($(CONFIG_NET_SCH_TEQL), m)
 	M_OBJS += sch_teql.o
+  endif
+endif
+
+ifeq ($(CONFIG_NET_SCH_GRED), y)
+O_OBJS += sch_gred.o
+else
+  ifeq ($(CONFIG_NET_SCH_GRED), m)
+       M_OBJS += sch_gred.o
+  endif
+endif
+
+ifeq ($(CONFIG_NET_SCH_DSMARK), y)
+O_OBJS += sch_dsmark.o
+else
+  ifeq ($(CONFIG_NET_SCH_DSMARK), m)
+       M_OBJS += sch_dsmark.o
+  endif
+endif
+
+ifeq ($(CONFIG_NET_CLS_TCINDEX), y)
+O_OBJS += cls_tcindex.o
+else
+  ifeq ($(CONFIG_NET_CLS_TCINDEX), m)
+       M_OBJS += cls_tcindex.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.37/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
--- v2.3.37/linux/net/sched/cls_api.c	Tue Aug 31 17:29:15 1999
+++ linux/net/sched/cls_api.c	Fri Jan  7 16:57:13 2000
@@ -466,6 +466,9 @@
 #ifdef CONFIG_NET_CLS_RSVP
 	INIT_TC_FILTER(rsvp);
 #endif
+#ifdef CONFIG_NET_CLS_TCINDEX
+	INIT_TC_FILTER(tcindex);
+#endif
 #ifdef CONFIG_NET_CLS_RSVP6
 	INIT_TC_FILTER(rsvp6);
 #endif
diff -u --recursive --new-file v2.3.37/linux/net/sched/cls_tcindex.c linux/net/sched/cls_tcindex.c
--- v2.3.37/linux/net/sched/cls_tcindex.c	Wed Dec 31 16:00:00 1969
+++ linux/net/sched/cls_tcindex.c	Fri Jan  7 16:57:13 2000
@@ -0,0 +1,503 @@
+/*
+ * net/sched/cls_tcindex.c	Packet classifier for skb->tc_index
+ *
+ * Written 1998,1999 by Werner Almesberger, EPFL ICA
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/pkt_sched.h>
+#include <net/route.h>
+
+
+/*
+ * Not quite sure if we need all the xchgs Alexey uses when accessing things.
+ * Can always add them later ... :)
+ */
+
+/*
+ * Passing parameters to the root seems to be done more awkwardly than really
+ * necessary. At least, u32 doesn't seem to use such dirty hacks. To be
+ * verified. FIXME.
+ */
+
+#define PERFECT_HASH_THRESHOLD	64	/* use perfect hash if not bigger */
+#define DEFAULT_HASH_SIZE	64	/* optimized for diffserv */
+
+
+#if 1 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+#if 0 /* data */
+#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define D2PRINTK(format,args...)
+#endif
+
+
+#define	PRIV(tp)	((struct tcindex_data *) (tp)->root)
+
+
+struct tcindex_filter_result {
+	struct tcf_police *police;
+	struct tcf_result res;
+};
+
+struct tcindex_filter {
+	__u16 key;
+	struct tcindex_filter_result result;
+	struct tcindex_filter *next;
+};
+
+
+struct tcindex_data {
+	struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */
+	struct tcindex_filter **h; /* imperfect hash; only used if !perfect;
+				      NULL if unused */
+	__u16 mask;		/* AND key with mask */
+	int shift;		/* shift ANDed key to the right */
+	int hash;		/* hash table size; 0 if undefined */
+	int alloc_hash;		/* allocated size */
+	int fall_through;	/* 0: only classify if explicit match */
+};
+
+
+static struct tcindex_filter_result *lookup(struct tcindex_data *p,__u16 key)
+{
+	struct tcindex_filter *f;
+
+	if (p->perfect)
+		return p->perfect[key].res.classid ? p->perfect+key : NULL;
+	if (!p->h)
+		return NULL;
+	for (f = p->h[key % p->hash]; f; f = f->next) {
+		if (f->key == key)
+			return &f->result;
+	}
+	return NULL;
+}
+
+
+static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
+			  struct tcf_result *res)
+{
+	struct tcindex_data *p = PRIV(tp);
+	struct tcindex_filter_result *f;
+
+	D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
+
+	f = lookup(p,(skb->tc_index & p->mask) >> p->shift);
+	if (!f) {
+		if (!p->fall_through)
+			return -1;
+		res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle),
+		    (skb->tc_index& p->mask) >> p->shift);
+		res->class = 0;
+		D2PRINTK("alg 0x%x\n",res->classid);
+		return 0;
+	}
+	*res = f->res;
+	D2PRINTK("map 0x%x\n",res->classid);
+#ifdef CONFIG_NET_CLS_POLICE
+	if (f->police) {
+		int result;
+
+		result = tcf_police(skb,f->police);
+		D2PRINTK("police %d\n",res);
+		return result;
+	}
+#endif
+	return 0;
+}
+
+
+static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
+{
+	DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
+	return (unsigned long) lookup(PRIV(tp),handle);
+}
+
+
+static void tcindex_put(struct tcf_proto *tp, unsigned long f)
+{
+	DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
+}
+
+
+static int tcindex_init(struct tcf_proto *tp)
+{
+	struct tcindex_data *p;
+
+	DPRINTK("tcindex_init(tp %p)\n",tp);
+	MOD_INC_USE_COUNT;
+	p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL);
+	if (!p) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+	tp->root = p;
+	p->perfect = NULL;
+	p->h = NULL;
+	p->hash = 0;
+	p->mask = 0xffff;
+	p->shift = 0;
+	p->fall_through = 1;
+	return 0;
+}
+
+
+static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
+{
+	struct tcindex_data *p = PRIV(tp);
+	struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
+	struct tcindex_filter *f = NULL;
+	unsigned long cl;
+
+	DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
+	if (p->perfect) {
+		if (!r->res.classid)
+			return -ENOENT;
+	} else {
+		int i;
+		struct tcindex_filter **walk = NULL;
+
+		for (i = 0; !f && i < p->hash; i++) {
+			for (walk = p->h+i; !f && *walk; walk = &(*walk)->next) {
+				if (&(*walk)->result == r)
+					f = *walk;
+			}
+		}
+		if (!f)
+			return -ENOENT;
+/*
+ @@@ OK?  -- No (jhs)
+Look more into it
+		tcf_tree_lock(tp); 
+*/
+		*walk = f->next;
+/*
+		tcf_tree_unlock(tp);
+*/
+	}
+	cl = __cls_set_class(&r->res.class,0);
+	if (cl)
+		tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
+#ifdef CONFIG_NET_CLS_POLICE
+	tcf_police_release(r->police);
+#endif
+	if (f)
+		kfree(f);
+	return 0;
+}
+
+
+/*
+ * There are no parameters for tcindex_init, so we overload tcindex_change
+ */
+
+
+static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
+    struct rtattr **tca,unsigned long *arg)
+{
+	struct tcindex_filter_result new_filter_result = {
+		NULL,		/* no policing */
+		{ 0,0 },	/* no classification */
+	};
+	struct rtattr *opt = tca[TCA_OPTIONS-1];
+	struct rtattr *tb[TCA_TCINDEX_MAX];
+	struct tcindex_data *p = PRIV(tp);
+	struct tcindex_filter *f;
+	struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
+	struct tcindex_filter **walk;
+	int hash;
+	__u16 mask;
+
+	DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
+	    "p %p,r %p\n",tp,handle,tca,arg,opt,p,r);
+	if (arg)
+		DPRINTK("*arg = 0x%lx\n",*arg);
+	if (!opt)
+		return 0;
+	if (rtattr_parse(tb,TCA_TCINDEX_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0)
+		return -EINVAL;
+	if (!tb[TCA_TCINDEX_HASH-1]) {
+		hash = p->hash;
+	} else {
+		if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(int))
+			return -EINVAL;
+		hash = *(int *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
+	}
+	if (!tb[TCA_TCINDEX_MASK-1]) {
+		mask = p->mask;
+	} else {
+		if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(__u16))
+			return -EINVAL;
+		mask = *(__u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
+	}
+	if (p->perfect && hash <= mask)
+		return -EBUSY;
+	if ((p->perfect || p->h) && hash > p->alloc_hash)
+		return -EBUSY;
+	p->hash = hash;
+	p->mask = mask;
+	if (tb[TCA_TCINDEX_SHIFT-1]) {
+		if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
+			return -EINVAL;
+		p->shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
+	}
+	if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
+		if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(int))
+			return -EINVAL;
+		p->fall_through =
+		    *(int *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
+	}
+	DPRINTK("classid/police %p/%p\n",tb[TCA_TCINDEX_CLASSID-1],
+	    tb[TCA_TCINDEX_POLICE-1]);
+	if (!tb[TCA_TCINDEX_CLASSID-1] && !tb[TCA_TCINDEX_POLICE-1])
+		return 0;
+	if (!p->hash) {
+		if (p->mask < PERFECT_HASH_THRESHOLD) {
+			p->hash = p->mask+1;
+		} else {
+			p->hash = DEFAULT_HASH_SIZE;
+		}
+	}
+	if (!p->perfect && !p->h) {
+		p->alloc_hash = p->hash;
+		DPRINTK("hash %d mask %d\n",p->hash,p->mask);
+		if (p->hash > p->mask) {
+			p->perfect = kmalloc(p->hash*
+			    sizeof(struct tcindex_filter_result),GFP_KERNEL);
+			if (!p->perfect)
+				return -ENOMEM;
+			memset(p->perfect, 0,
+			       p->hash * sizeof(struct tcindex_filter_result));
+		} else {
+			p->h = kmalloc(p->hash*sizeof(struct tcindex_filter *),
+			    GFP_KERNEL);
+			if (!p->h)
+				return -ENOMEM;
+			memset(p->h, 0, p->hash*sizeof(struct tcindex_filter *));
+		}
+	}
+	if (handle > p->mask)
+		return -EINVAL;
+	if (p->perfect) {
+		r = p->perfect+handle;
+	} else {
+		r = lookup(p,handle);
+		DPRINTK("r=%p\n",r);
+		if (!r)
+			r = &new_filter_result;
+	}
+	DPRINTK("r=%p\n",r);
+	if (tb[TCA_TCINDEX_CLASSID-1]) {
+		unsigned long cl = cls_set_class(tp,&r->res.class,0);
+
+		if (cl)
+			tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
+		r->res.classid = *(__u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
+		r->res.class = tp->q->ops->cl_ops->bind_tcf(tp->q,base,
+							    r->res.classid);
+		if (!r->res.class) {
+			r->res.classid = 0;
+			return -ENOENT;
+		}
+        }
+#ifdef CONFIG_NET_CLS_POLICE
+	if (!tb[TCA_TCINDEX_POLICE-1]) {
+		r->police = NULL;
+	} else {
+		struct tcf_police *police =
+		    tcf_police_locate(tb[TCA_TCINDEX_POLICE-1],NULL);
+
+                tcf_tree_lock(tp);
+		police = xchg(&r->police,police);
+                tcf_tree_unlock(tp);
+		tcf_police_release(police);
+        }
+#endif
+	if (r != &new_filter_result)
+		return 0;
+	f = kmalloc(sizeof(struct tcindex_filter),GFP_KERNEL);
+	if (!f)
+		return -ENOMEM;
+	f->key = handle;
+	f->result = new_filter_result;
+	f->next = NULL;
+	for (walk = p->h+(handle % p->hash); *walk; walk = &(*walk)->next)
+		/* nothing */;
+	wmb();
+	*walk = f;
+	return 0;
+}
+
+
+static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
+{
+	struct tcindex_data *p = PRIV(tp);
+	struct tcindex_filter *f;
+	int i;
+
+	DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
+	if (p->perfect) {
+		for (i = 0; i < p->hash; i++) {
+			if (!p->perfect[i].res.classid)
+				continue;
+			if (walker->count >= walker->skip) {
+				if (walker->fn(tp,
+				    (unsigned long) (p->perfect+i), walker)
+				     < 0) {
+					walker->stop = 1;
+					return;
+				}
+			}
+			walker->count++;
+		}
+	}
+	if (!p->h)
+		return;
+	for (i = 0; i < p->hash; i++) {
+		for (f = p->h[i]; f; f = f->next) {
+			if (walker->count >= walker->skip) {
+				if (walker->fn(tp,(unsigned long) &f->result,
+				    walker) < 0) {
+					walker->stop = 1;
+					return;
+				}
+			}
+			walker->count++;
+		}
+	}
+}
+
+
+static int tcindex_destroy_element(struct tcf_proto *tp,
+    unsigned long arg, struct tcf_walker *walker)
+{
+	return tcindex_delete(tp,arg);
+}
+
+
+static void tcindex_destroy(struct tcf_proto *tp)
+{
+	struct tcindex_data *p = PRIV(tp);
+	struct tcf_walker walker;
+
+	DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
+	walker.count = 0;
+	walker.skip = 0;
+	walker.fn = &tcindex_destroy_element;
+	tcindex_walk(tp,&walker);
+	if (p->perfect)
+		kfree(p->perfect);
+	if (p->h)
+		kfree(p->h);
+	kfree(p);
+	tp->root = NULL;
+	MOD_DEC_USE_COUNT;
+}
+
+
+#ifdef CONFIG_RTNETLINK
+
+static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
+    struct sk_buff *skb, struct tcmsg *t)
+{
+	struct tcindex_data *p = PRIV(tp);
+	struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
+	unsigned char *b = skb->tail;
+	struct rtattr *rta;
+
+	DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
+	    tp,fh,skb,t,p,r,b);
+	DPRINTK("p->perfect %p p->h %p\n",p->perfect,p->h);
+	rta = (struct rtattr *) b;
+	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
+	if (!fh) {
+		t->tcm_handle = ~0; /* whatever ... */
+		RTA_PUT(skb,TCA_TCINDEX_HASH,sizeof(p->hash),&p->hash);
+		RTA_PUT(skb,TCA_TCINDEX_MASK,sizeof(p->mask),&p->mask);
+		RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
+		RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
+		    &p->fall_through);
+	} else {
+		if (p->perfect) {
+			t->tcm_handle = r-p->perfect;
+		} else {
+			struct tcindex_filter *f;
+			int i;
+
+			t->tcm_handle = 0;
+			for (i = 0; !t->tcm_handle && i < p->hash; i++) {
+				for (f = p->h[i]; !t->tcm_handle && f;
+				     f = f->next) {
+					if (&f->result == r)
+						t->tcm_handle = f->key;
+				}
+			}
+		}
+		DPRINTK("handle = %d\n",t->tcm_handle);
+		if (r->res.class)
+			RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
+#ifdef CONFIG_NET_CLS_POLICE
+		if (r->police) {
+			struct rtattr *p_rta = (struct rtattr *) skb->tail;
+
+			RTA_PUT(skb,TCA_TCINDEX_POLICE,0,NULL);
+			if (tcf_police_dump(skb,r->police) < 0)
+				goto rtattr_failure;
+			p_rta->rta_len = skb->tail-(u8 *) p_rta;
+		}
+#endif
+	}
+	rta->rta_len = skb->tail-b;
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+#endif
+
+
+struct tcf_proto_ops cls_tcindex_ops = {
+	NULL,
+	"tcindex",
+	tcindex_classify,
+	tcindex_init,
+	tcindex_destroy,
+
+	tcindex_get,
+	tcindex_put,
+	tcindex_change,
+	tcindex_delete,
+	tcindex_walk,
+#ifdef CONFIG_RTNETLINK
+	tcindex_dump
+#else
+	NULL
+#endif
+};
+
+
+#ifdef MODULE
+int init_module(void)
+{
+	return register_tcf_proto_ops(&cls_tcindex_ops);
+}
+
+void cleanup_module(void) 
+{
+	unregister_tcf_proto_ops(&cls_tcindex_ops);
+}
+#endif
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.37/linux/net/sched/sch_api.c	Mon Nov  1 13:56:27 1999
+++ linux/net/sched/sch_api.c	Fri Jan  7 16:57:13 2000
@@ -12,6 +12,7 @@
  *
  * Rani Assaf <rani@magic.metawire.com> :980802: JIFFIES and CPU clock sources are repaired.
  * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
+ * Jamal Hadi Salim <hadi@nortelnetworks.com>: 990601: ingress support
  */
 
 #include <linux/config.h>
@@ -210,6 +211,7 @@
 	if (cops == NULL)
 		return NULL;
 	cl = cops->get(p, classid);
+
 	if (cl == 0)
 		return NULL;
 	leaf = cops->leaf(p, cl);
@@ -306,17 +308,32 @@
 
 	write_lock(&qdisc_tree_lock);
 	spin_lock_bh(&dev->queue_lock);
-	oqdisc = dev->qdisc_sleeping;
+	if (qdisc && qdisc->flags&TCQ_F_INGRES) {
+		oqdisc = dev->qdisc_ingress;
+		/* Prune old scheduler */
+		if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
+			/* delete */
+			qdisc_reset(oqdisc);
+			dev->qdisc_ingress = NULL;
+		} else {  /* new */
+			dev->qdisc_ingress = qdisc;
+		}
+
+	} else {
+
+		oqdisc = dev->qdisc_sleeping;
+
+		/* Prune old scheduler */
+		if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
+			qdisc_reset(oqdisc);
+
+		/* ... and graft new one */
+		if (qdisc == NULL)
+			qdisc = &noop_qdisc;
+		dev->qdisc_sleeping = qdisc;
+		dev->qdisc = &noop_qdisc;
+	}
 
-	/* Prune old scheduler */
-	if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
-		qdisc_reset(oqdisc);
-
-	/* ... and graft new one */
-	if (qdisc == NULL)
-		qdisc = &noop_qdisc;
-	dev->qdisc_sleeping = qdisc;
-	dev->qdisc = &noop_qdisc;
 	spin_unlock_bh(&dev->queue_lock);
 	write_unlock(&qdisc_tree_lock);
 
@@ -337,9 +354,15 @@
 		struct Qdisc *new, struct Qdisc **old)
 {
 	int err = 0;
+	struct Qdisc *q = *old;
 
-	if (parent == NULL) {
-		*old = dev_graft_qdisc(dev, new);
+
+	if (parent == NULL) { 
+		if (q && q->flags&TCQ_F_INGRES) {
+			*old = dev_graft_qdisc(dev, q);
+		} else {
+			*old = dev_graft_qdisc(dev, new);
+		}
 	} else {
 		struct Qdisc_class_ops *cops = parent->ops->cl_ops;
 
@@ -406,6 +429,10 @@
 	memset(sch, 0, size);
 
 	skb_queue_head_init(&sch->q);
+
+	if (handle == TC_H_INGRESS)
+		sch->flags |= TCQ_F_INGRES;
+
 	sch->ops = ops;
 	sch->enqueue = ops->enqueue;
 	sch->dequeue = ops->dequeue;
@@ -418,7 +445,11 @@
 		if (handle == 0)
 			goto err_out;
 	}
-	sch->handle = handle;
+
+	if (handle == TC_H_INGRESS)
+                sch->handle =TC_H_MAKE(TC_H_INGRESS, 0);
+        else
+                sch->handle = handle;
 
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
 		write_lock(&qdisc_tree_lock);
@@ -518,12 +549,16 @@
 
 	if (clid) {
 		if (clid != TC_H_ROOT) {
-			if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
-				return -ENOENT;
-			q = qdisc_leaf(p, clid);
-		} else
+			if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
+				if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
+					return -ENOENT;
+				q = qdisc_leaf(p, clid);
+			} else { /* ingress */
+				q = dev->qdisc_ingress;
+                        }
+		} else {
 			q = dev->qdisc_sleeping;
-
+		}
 		if (!q)
 			return -ENOENT;
 
@@ -575,9 +610,13 @@
 
 	if (clid) {
 		if (clid != TC_H_ROOT) {
-			if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
-				return -ENOENT;
-			q = qdisc_leaf(p, clid);
+			if (clid != TC_H_INGRESS) {
+				if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
+					return -ENOENT;
+				q = qdisc_leaf(p, clid);
+			} else { /*ingress */
+				q = dev->qdisc_ingress;
+			}
 		} else {
 			q = dev->qdisc_sleeping;
 		}
@@ -655,7 +694,10 @@
 create_n_graft:
 	if (!(n->nlmsg_flags&NLM_F_CREATE))
 		return -ENOENT;
-	q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
+	if (clid == TC_H_INGRESS)
+		q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
+        else
+		q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
 	if (q == NULL)
 		return err;
 
@@ -1189,6 +1231,9 @@
 #endif
 #ifdef CONFIG_NET_SCH_GRED
        INIT_QDISC(gred);
+#endif
+#ifdef CONFIG_NET_SCH_INGRESS
+       INIT_QDISC(ingress);
 #endif
 #ifdef CONFIG_NET_SCH_DSMARK
        INIT_QDISC(dsmark);
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_dsmark.c linux/net/sched/sch_dsmark.c
--- v2.3.37/linux/net/sched/sch_dsmark.c	Wed Dec 31 16:00:00 1969
+++ linux/net/sched/sch_dsmark.c	Fri Jan  7 16:57:13 2000
@@ -0,0 +1,476 @@
+/* net/sched/sch_dsmark.c - Differentiated Services field marker */
+
+/* Written 1998,1999 by Werner Almesberger, EPFL ICA */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h> /* for pkt_sched */
+#include <linux/rtnetlink.h>
+#include <net/pkt_sched.h>
+#include <net/dsfield.h>
+#include <asm/byteorder.h>
+
+
+#if 1 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+#if 0 /* data */
+#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define D2PRINTK(format,args...)
+#endif
+
+
+#define PRIV(sch) ((struct dsmark_qdisc_data *) (sch)->data)
+
+
+/*
+ * classid	class		marking
+ * -------	-----		-------
+ *   n/a	  0		n/a
+ *   x:0	  1		use entry [0]
+ *   ...	 ...		...
+ *   x:y y>0	 y+1		use entry [y]
+ *   ...	 ...		...
+ * x:indices-1	indices		use entry [indices-1]
+ */
+
+
+struct dsmark_qdisc_data {
+	struct Qdisc		*q;
+	struct tcf_proto	*filter_list;
+	__u8			*mask;	/* "owns" the array */
+	__u8			*value;
+	__u16			indices;
+	__u16			default_index;
+	int			set_tc_index;
+};
+
+
+/* ------------------------- Class/flow operations ------------------------- */
+
+
+static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
+    struct Qdisc *new,struct Qdisc **old)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
+	    old);
+	if (!new)
+		new = &noop_qdisc;
+	sch_tree_lock(sch);
+	*old = xchg(&p->q,new);
+	if (*old)
+		qdisc_reset(*old);
+	sch_tree_unlock(sch); /* @@@ move up ? */
+        return 0;
+}
+
+
+static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	return NULL;
+}
+
+
+static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
+	return TC_H_MIN(classid)+1;
+}
+
+
+static unsigned long dsmark_bind_filter(struct Qdisc *sch,
+    unsigned long parent, u32 classid)
+{
+	return dsmark_get(sch,classid);
+}
+
+
+static void dsmark_put(struct Qdisc *sch, unsigned long cl)
+{
+}
+
+
+static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
+    struct rtattr **tca, unsigned long *arg)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	struct rtattr *opt = tca[TCA_OPTIONS-1];
+	struct rtattr *tb[TCA_DSMARK_MAX];
+
+	DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
+	    "arg 0x%lx\n",sch,p,classid,parent,*arg);
+	if (*arg > p->indices)
+		return -ENOENT;
+	if (!opt || rtattr_parse(tb, TCA_DSMARK_MAX, RTA_DATA(opt),
+				 RTA_PAYLOAD(opt)))
+		return -EINVAL;
+	if (tb[TCA_DSMARK_MASK-1]) {
+		if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
+			return -EINVAL;
+		p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
+	}
+	if (tb[TCA_DSMARK_VALUE-1]) {
+		if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
+			return -EINVAL;
+		p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
+	}
+	return 0;
+}
+
+
+static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	if (!arg || arg > p->indices)
+		return -EINVAL;
+	p->mask[arg-1] = 0xff;
+	p->value[arg-1] = 0;
+	return 0;
+}
+
+
+static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	int i;
+
+	DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
+	if (walker->stop)
+		return;
+	for (i = 0; i < p->indices; i++) {
+		if (p->mask[i] == 0xff && !p->value[i])
+			continue;
+		if (walker->count >= walker->skip) {
+			if (walker->fn(sch, i+1, walker) < 0) {
+				walker->stop = 1;
+				break;
+			}
+		}
+                walker->count++;
+        }
+}
+
+
+static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	return &p->filter_list;
+}
+
+
+/* --------------------------- Qdisc operations ---------------------------- */
+
+
+static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	struct tcf_result res;
+	int result;
+	int ret;
+
+	D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
+	if (p->set_tc_index) {
+		switch (skb->protocol) {
+			case __constant_htons(ETH_P_IP):
+				skb->tc_index = ipv4_get_dsfield(skb->nh.iph);
+				break;
+			case __constant_htons(ETH_P_IPV6):
+				skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h);
+				break;
+			default:
+				skb->tc_index = 0;
+				break;
+		};
+	}
+	result = TC_POLICE_OK; /* be nice to gcc */
+	if (TC_H_MAJ(skb->priority) == sch->handle) {
+		skb->tc_index = TC_H_MIN(skb->priority);
+	} else {
+		result = tc_classify(skb,p->filter_list,&res);
+		D2PRINTK("result %d class 0x%04x\n",result,res.classid);
+		switch (result) {
+#ifdef CONFIG_NET_CLS_POLICE
+			case TC_POLICE_SHOT:
+				kfree_skb(skb);
+				break;
+#if 0
+			case TC_POLICE_RECLASSIFY:
+				/* FIXME: what to do here ??? */
+#endif
+#endif
+			case TC_POLICE_OK:
+				skb->tc_index = TC_H_MIN(res.classid);
+				break;
+			case TC_POLICE_UNSPEC:
+				/* fall through */
+			default:
+				if (p->default_index)
+					skb->tc_index = p->default_index;
+				break;
+		};
+	}
+	if (
+#ifdef CONFIG_NET_CLS_POLICE
+	    result == TC_POLICE_SHOT ||
+#endif
+
+	    ((ret = p->q->enqueue(skb,p->q)) != 0)) {
+		sch->stats.drops++;
+		return 0;
+	}
+	sch->stats.bytes += skb->len;
+	sch->stats.packets++;
+	sch->q.qlen++;
+	return ret;
+}
+
+
+static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	struct sk_buff *skb;
+	int index;
+
+	D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p);
+	skb = p->q->ops->dequeue(p->q);
+	if (!skb)
+		return NULL;
+	sch->q.qlen--;
+	index = skb->tc_index & (p->indices-1);
+	D2PRINTK("index %d->%d\n",skb->tc_index,index);
+	switch (skb->protocol) {
+		case __constant_htons(ETH_P_IP):
+			ipv4_change_dsfield(skb->nh.iph,
+			    p->mask[index],p->value[index]);
+			break;
+		case __constant_htons(ETH_P_IPV6):
+			ipv6_change_dsfield(skb->nh.ipv6h,
+			    p->mask[index],p->value[index]);
+			break;
+		default:
+			/*
+			 * Only complain if a change was actually attempted.
+			 * This way, we can send non-IP traffic through dsmark
+			 * and don't need yet another qdisc as a bypass.
+			 */
+			if (p->mask[index] != 0xff || p->value[index])
+				printk(KERN_WARNING "dsmark_dequeue: "
+				       "unsupported protocol %d\n",
+				       htons(skb->protocol));
+			break;
+	};
+	return skb;
+}
+
+
+static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
+	return p->q->ops->requeue(skb,p->q);
+}
+
+
+static int dsmark_drop(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
+	if (!p->q->ops->drop)
+		return 0;
+	if (!p->q->ops->drop(p->q))
+		return 0;
+	sch->q.qlen--;
+	return 1;
+}
+
+
+int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	struct rtattr *tb[TCA_DSMARK_MAX];
+	__u16 tmp;
+
+	DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
+	if (rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 ||
+	    !tb[TCA_DSMARK_INDICES-1] ||
+	    RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
+                return -EINVAL;
+	memset(p,0,sizeof(*p));
+	p->filter_list = NULL;
+	p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
+	if (!p->indices)
+		return -EINVAL;
+	for (tmp = p->indices; tmp != 1; tmp >>= 1) {
+		if (tmp & 1)
+			return -EINVAL;
+	}
+	p->default_index = 0;
+	if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
+		if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
+			return -EINVAL;
+		p->default_index =
+		    *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
+		if (!p->default_index || p->default_index >= p->indices)
+			return -EINVAL;
+	}
+	p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
+	p->mask = kmalloc(p->indices*2,GFP_KERNEL);
+	if (!p->mask)
+		return -ENOMEM;
+	p->value = p->mask+p->indices;
+	memset(p->mask,0xff,p->indices);
+	memset(p->value,0,p->indices);
+	if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
+		p->q = &noop_qdisc;
+	DPRINTK("dsmark_init: qdisc %p\n",&p->q);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+
+static void dsmark_reset(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
+	qdisc_reset(p->q);
+	sch->q.qlen = 0;
+}
+
+
+static void dsmark_destroy(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	struct tcf_proto *tp;
+
+	DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n",sch,p);
+	while (p->filter_list) {
+		tp = p->filter_list;
+		p->filter_list = tp->next;
+		tp->ops->destroy(tp);
+	}
+	qdisc_destroy(p->q);
+	p->q = &noop_qdisc;
+	kfree(p->mask);
+	MOD_DEC_USE_COUNT;
+}
+
+
+#ifdef CONFIG_RTNETLINK
+
+static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
+    struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	unsigned char *b = skb->tail;
+	struct rtattr *rta;
+
+	DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl);
+	if (!cl || cl > p->indices)
+		return -EINVAL;
+	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle),cl-1);
+	rta = (struct rtattr *) b;
+	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
+	RTA_PUT(skb,TCA_DSMARK_MASK,1,&p->mask[cl-1]);
+	RTA_PUT(skb,TCA_DSMARK_VALUE,1,&p->value[cl-1]);
+	rta->rta_len = skb->tail-b;
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb,b-skb->data);
+	return -1;
+}
+
+static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct dsmark_qdisc_data *p = PRIV(sch);
+	unsigned char *b = skb->tail;
+	struct rtattr *rta;
+
+	rta = (struct rtattr *) b;
+	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
+	RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices);
+	if (p->default_index)
+		RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16),
+			&p->default_index);
+	if (p->set_tc_index)
+		RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL);
+	rta->rta_len = skb->tail-b;
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb,b-skb->data);
+	return -1;
+}
+
+#endif
+
+
+static struct Qdisc_class_ops dsmark_class_ops =
+{
+	dsmark_graft,			/* graft */
+	dsmark_leaf,			/* leaf */
+	dsmark_get,			/* get */
+	dsmark_put,			/* put */
+	dsmark_change,			/* change */
+	dsmark_delete,			/* delete */
+	dsmark_walk,			/* walk */
+
+	dsmark_find_tcf,		/* tcf_chain */
+	dsmark_bind_filter,		/* bind_tcf */
+	dsmark_put,			/* unbind_tcf */
+
+#ifdef CONFIG_RTNETLINK
+	dsmark_dump_class,		/* dump */
+#endif
+};
+
+struct Qdisc_ops dsmark_qdisc_ops =
+{
+	NULL,				/* next */
+	&dsmark_class_ops,		/* cl_ops */
+	"dsmark",
+	sizeof(struct dsmark_qdisc_data),
+
+	dsmark_enqueue,			/* enqueue */
+	dsmark_dequeue,			/* dequeue */
+	dsmark_requeue,			/* requeue */
+	dsmark_drop,			/* drop */
+
+	dsmark_init,			/* init */
+	dsmark_reset,			/* reset */
+	dsmark_destroy,			/* destroy */
+	NULL,				/* change */
+
+#ifdef CONFIG_RTNETLINK
+	dsmark_dump			/* dump */
+#endif
+};
+
+#ifdef MODULE
+int init_module(void)
+{
+	return register_qdisc(&dsmark_qdisc_ops);
+}
+
+
+void cleanup_module(void) 
+{
+	unregister_qdisc(&dsmark_qdisc_ops);
+}
+#endif
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
--- v2.3.37/linux/net/sched/sch_generic.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_generic.c	Fri Jan  7 16:57:13 2000
@@ -7,6 +7,8 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *              Jamal Hadi Salim, <hadi@nortelnetworks.com> 990601
+ *              - Ingress support
  */
 
 #include <asm/uaccess.h>
@@ -590,6 +592,12 @@
 	dev->qdisc = &noop_qdisc;
 	dev->qdisc_sleeping = &noop_qdisc;
 	qdisc_destroy(qdisc);
+#ifdef CONFIG_NET_SCH_INGRESS
+        if ((qdisc = dev->qdisc_ingress) != NULL) {
+		dev->qdisc_ingress = NULL;
+		qdisc_destroy(qdisc);
+        }
+#endif
 	BUG_TRAP(dev->qdisc_list == NULL);
 	dev->qdisc_list = NULL;
 	spin_unlock_bh(&dev->queue_lock);
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_gred.c linux/net/sched/sch_gred.c
--- v2.3.37/linux/net/sched/sch_gred.c	Wed Dec 31 16:00:00 1969
+++ linux/net/sched/sch_gred.c	Fri Jan  7 16:57:13 2000
@@ -0,0 +1,606 @@
+/*
+ * net/sched/sch_gred.c	Generic Random Early Detection queue.
+ *
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:    J Hadi Salim (hadi@nortelnetworks.com) 1998,1999
+ *
+ *             991129: -  Bug fix with grio mode
+ *		       - a better sing. AvgQ mode with Grio
+ *		       - A finer grained VQ dequeue based on sugestion
+ *		         from Ren Liu
+ *
+ *
+ *
+ *  For all the glorious comments look at Alexey's sch_red.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#if 1 /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+#if 0 /* data */
+#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define D2PRINTK(format,args...)
+#endif
+
+struct gred_sched_data;
+struct gred_sched;
+
+struct gred_sched_data
+{
+/* Parameters */
+	u32		limit;		/* HARD maximal queue length	*/
+	u32		qth_min;	/* Min average length threshold: A scaled */
+	u32		qth_max;	/* Max average length threshold: A scaled */
+        u32      	DP;		/* the drop pramaters */
+	char		Wlog;		/* log(W)		*/
+	char		Plog;		/* random number bits	*/
+	u32		Scell_max;
+	u32		Rmask;
+	u32		bytesin;	/* bytes seen on virtualQ so far*/
+	u32		packetsin;	/* packets seen on virtualQ so far*/
+	u32		backlog;	/* bytes on the virtualQ */
+	u32		forced;	/* packets dropped for exceeding limits */
+	u32		early;	/* packets dropped as a warning */
+	u32		other;	/* packets dropped by invoking drop() */
+	u32		pdrop;	/* packets dropped because we exceeded physical queue limits */
+	char		Scell_log;
+	u8		Stab[256];
+	u8              prio;        /* the prio of this vq */
+
+/* Variables */
+	unsigned long	qave;		/* Average queue length: A scaled */
+	int		qcount;		/* Packets since last random number generation */
+	u32		qR;		/* Cached random number */
+
+	psched_time_t	qidlestart;	/* Start of idle period	*/
+};
+
+struct gred_sched
+{
+	struct gred_sched_data *tab[MAX_DPs];
+	u32 		DPs;   
+	u32 		def; 
+	u8 		initd; 
+	u8 		grio; 
+	u8 		eqp; 
+};
+
+static int
+gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+{
+	psched_time_t now;
+	struct gred_sched_data *q=NULL;
+	struct gred_sched *t= (struct gred_sched *)sch->data;
+	unsigned long	qave=0;	
+	int i=0;
+
+	if (!t->initd) {
+		DPRINTK("NO GRED Queues setup yet! Enqueued anyway\n");
+		if (q->backlog <= q->limit) {
+			__skb_queue_tail(&sch->q, skb);
+			return NET_XMIT_DROP; /* @@@@ */
+		}
+	}
+
+
+	if ( ((skb->tc_index&0xf) > t->DPs) || !(q=t->tab[skb->tc_index&0xf])) {
+		printk("GRED: setting to default (%d)\n ",t->def);
+		if (!(q=t->tab[t->def])) {
+			DPRINTK("GRED: setting to default FAILED! dropping!! "
+			    "(%d)\n ", t->def);
+			goto drop;
+		}
+		/* fix tc_index? --could be controvesial but needed for
+		   requeueing */
+		skb->tc_index=(skb->tc_index&0xfffffff0) | t->def;
+	}
+
+	D2PRINTK("gred_enqueue virtualQ 0x%x classid %x backlog %d "
+	    "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog,
+	    sch->stats.backlog);
+	/* sum up all the qaves of prios <= to ours to get the new qave*/
+	if (t->grio) {
+		for (i=0;i<t->DPs;i++) {
+			if ((!t->tab[i]) || (i==q->DP))	
+				continue; 
+			if (t->tab[i]->prio == q->prio ){
+				qave=0;
+				t->eqp=1;
+				q->qave=t->tab[t->def]->qave;
+				q->qidlestart=t->tab[t->def]->qidlestart;
+				break;
+			}
+				
+			if ((t->tab[i]->prio < q->prio) && (PSCHED_IS_PASTPERFECT(t->tab[i]->qidlestart)))
+				qave +=t->tab[i]->qave;
+		}
+			
+	}
+
+        q->packetsin++;
+        q->bytesin+=skb->len;
+
+	if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
+		long us_idle;
+		PSCHED_GET_TIME(now);
+		us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
+		PSCHED_SET_PASTPERFECT(q->qidlestart);
+
+		q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
+	} else {
+		q->qave += q->backlog - (q->qave >> q->Wlog);
+	}
+	
+
+	if (t->eqp && t->grio) 
+		t->tab[t->def]->qave=q->qave;
+
+	if ((q->qave+qave) < q->qth_min) {
+		q->qcount = -1;
+enqueue:
+		if (q->backlog <= q->limit) {
+			__skb_queue_tail(&sch->q, skb);
+			sch->stats.backlog += skb->len;
+			sch->stats.bytes += skb->len;
+			sch->stats.packets++;
+			q->backlog += skb->len;
+			return 0;
+		} else {
+			q->pdrop++;
+		}
+
+drop:
+		kfree_skb(skb);
+		sch->stats.drops++;
+		return NET_XMIT_DROP;
+	}
+	if ((q->qave+qave) >= q->qth_max) {
+		q->qcount = -1;
+		sch->stats.overlimits++;
+		q->forced++;
+		goto drop;
+	}
+	if (++q->qcount) {
+		if ((((qave+q->qave) - q->qth_min)>>q->Wlog)*q->qcount < q->qR)
+			goto enqueue;
+		q->qcount = 0;
+		q->qR = net_random()&q->Rmask;
+		sch->stats.overlimits++;
+		q->early++;
+		goto drop;
+	}
+	q->qR = net_random()&q->Rmask;
+	goto enqueue;
+}
+
+static int
+gred_requeue(struct sk_buff *skb, struct Qdisc* sch)
+{
+	struct gred_sched_data *q;
+	struct gred_sched *t= (struct gred_sched *)sch->data;
+        q= t->tab[(skb->tc_index&0xf)];
+/* error checking here -- probably unnecessary */
+	PSCHED_SET_PASTPERFECT(q->qidlestart);
+
+	__skb_queue_head(&sch->q, skb);
+	sch->stats.backlog += skb->len;
+	q->backlog += skb->len;
+	return 0;
+}
+
+static struct sk_buff *
+gred_dequeue(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+	struct gred_sched_data *q;
+	struct gred_sched *t= (struct gred_sched *)sch->data;
+
+	skb = __skb_dequeue(&sch->q);
+	if (skb) {
+		q= t->tab[(skb->tc_index&0xf)];
+		sch->stats.backlog -= skb->len;
+		q->backlog -= skb->len;
+		if (!q->backlog && !t->eqp)
+			PSCHED_GET_TIME(q->qidlestart);
+		return skb;
+	}
+
+	if (t->eqp) {
+			q= t->tab[t->def];
+			if (!q)	
+				printk("no default VQ set: Results will be "
+				       "screwed up\n");
+			else
+				PSCHED_GET_TIME(q->qidlestart);
+	}
+
+	return NULL;
+}
+
+static int
+gred_drop(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+	int i;
+
+	struct gred_sched_data *q;
+	struct gred_sched *t= (struct gred_sched *)sch->data;
+
+	skb = __skb_dequeue_tail(&sch->q);
+	if (skb) {
+		q= t->tab[(skb->tc_index&0xf)];
+		sch->stats.backlog -= skb->len;
+		sch->stats.drops++;
+		q->backlog -= skb->len;
+		q->other++;
+		kfree_skb(skb);
+		return 1;
+	}
+
+/* could probably do it for a single VQ before freeing the skb */
+        for (i=0;i<t->DPs;i++) {
+	        q= t->tab[i];
+		if (!q)	
+			continue; 
+        	PSCHED_GET_TIME(q->qidlestart);
+        }
+
+	return 0;
+}
+
+static void gred_reset(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+	int i;
+
+	struct gred_sched_data *q;
+	struct gred_sched *t= (struct gred_sched *)sch->data;
+
+	while((skb=__skb_dequeue(&sch->q))!=NULL)
+		kfree_skb(skb);
+	sch->stats.backlog = 0;
+
+/* could probably do it for a single VQ before freeing the skb */
+        for (i=0;i<t->DPs;i++) {
+	        q= t->tab[i];
+		if (!q)	
+			continue; 
+		PSCHED_SET_PASTPERFECT(q->qidlestart);
+		q->qave = 0;
+		q->qcount = -1;
+		q->backlog = 0;
+		q->other=0;
+		q->forced=0;
+		q->pdrop=0;
+		q->early=0;
+	}
+}
+
+static int gred_change(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct gred_sched *table = (struct gred_sched *)sch->data;
+	struct gred_sched_data *q;
+        struct tc_gred_qopt *ctl;
+        struct tc_gred_sopt *sopt;
+        struct rtattr *tb[TCA_GRED_STAB];
+        struct rtattr *tb2[TCA_GRED_STAB];
+
+        if (opt == NULL ||
+            rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
+                return -EINVAL;
+
+	if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 &&
+	    tb[TCA_GRED_DPS-1] != 0) {
+		rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),
+		    RTA_PAYLOAD(opt));
+
+	    	sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]);
+	    	table->DPs=sopt->DPs;   
+	    	table->def=sopt->def_DP; 
+	    	table->grio=sopt->grio; 
+		table->initd=0;
+                /* probably need to clear all the table DP entries as well */
+		MOD_INC_USE_COUNT;
+		return 0;
+	    }
+
+
+            if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 ||
+		RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
+		RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
+                return -EINVAL;
+
+        ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
+        if (ctl->DP > MAX_DPs-1 || ctl->DP <0) {
+		/* misbehaving is punished! Put in the default drop probability */
+		DPRINTK("\nGRED: DP %u not in  the proper range fixed. New DP "
+			"set to default at %d\n",ctl->DP,table->def);
+		ctl->DP=table->def;
+	}
+	
+	if (table->tab[ctl->DP] == NULL) {
+		table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data),
+					    GFP_KERNEL);
+	        memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
+        }
+	q= table->tab[ctl->DP]; 
+
+	if (table->grio) {
+		if (ctl->prio <=0) {
+			if (table->def && table->tab[table->def]) {
+				DPRINTK("\nGRED: DP %u does not have a prio setting "
+					"default to %d\n",ctl->DP,
+					table->tab[table->def]->prio);
+				q->prio=table->tab[table->def]->prio;
+			} else { 
+				DPRINTK("\nGRED: DP %u does not have a prio setting "
+					"default to 8\n",ctl->DP);
+				q->prio=8;
+			}
+		} else {
+			q->prio=ctl->prio;
+		}
+	} else {
+		q->prio=8;
+        }
+
+
+	q->DP=ctl->DP;
+	q->Wlog = ctl->Wlog;
+	q->Plog = ctl->Plog;
+	q->limit = ctl->limit;
+	q->Scell_log = ctl->Scell_log;
+	q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
+	q->Scell_max = (255<<q->Scell_log);
+	q->qth_min = ctl->qth_min<<ctl->Wlog;
+	q->qth_max = ctl->qth_max<<ctl->Wlog;
+	q->qave=0;
+	q->backlog=0;
+	q->qcount = -1;
+	q->other=0;
+	q->forced=0;
+	q->pdrop=0;
+	q->early=0;
+
+	PSCHED_SET_PASTPERFECT(q->qidlestart);
+	memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
+
+	if (!table->initd) {
+		table->initd=1;
+		/* 
+        	the first entry also goes into the default until
+        	over-written 
+		*/
+
+		if (table->tab[table->def] == NULL) {
+			table->tab[table->def]=
+			    kmalloc(sizeof(struct gred_sched_data), GFP_KERNEL);
+			memset(table->tab[table->def], 0,
+			       (sizeof(struct gred_sched_data)));
+                }
+		q= table->tab[table->def]; 
+		q->DP=table->def;
+		q->Wlog = ctl->Wlog;
+		q->Plog = ctl->Plog;
+		q->limit = ctl->limit;
+		q->Scell_log = ctl->Scell_log;
+		q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
+		q->Scell_max = (255<<q->Scell_log);
+		q->qth_min = ctl->qth_min<<ctl->Wlog;
+		q->qth_max = ctl->qth_max<<ctl->Wlog;
+
+                if (table->grio)
+			q->prio=table->tab[ctl->DP]->prio;
+                else
+			q->prio=8;
+
+		q->qcount = -1;
+		PSCHED_SET_PASTPERFECT(q->qidlestart);
+		memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
+	}
+        return 0;
+
+}
+
+static int gred_init(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct gred_sched *table = (struct gred_sched *)sch->data;
+        struct tc_gred_sopt *sopt;
+        struct rtattr *tb[TCA_GRED_STAB];
+        struct rtattr *tb2[TCA_GRED_STAB];
+
+        if (opt == NULL ||
+            rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
+                return -EINVAL;
+
+	if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 &&
+	    tb[TCA_GRED_DPS-1] != 0) {
+		rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),
+		    RTA_PAYLOAD(opt));
+
+	    	sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]);
+	    	table->DPs=sopt->DPs;   
+	    	table->def=sopt->def_DP; 
+	    	table->grio=sopt->grio; 
+		table->initd=0;
+		MOD_INC_USE_COUNT;
+		return 0;
+	}
+
+        DPRINTK("\n GRED_INIT error!\n");
+	return -EINVAL;
+}
+
+#ifdef CONFIG_RTNETLINK
+static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	unsigned long qave;
+	struct rtattr *rta;
+	struct tc_gred_qopt *opt;
+	struct tc_gred_qopt *dst;
+	struct gred_sched *table = (struct gred_sched *)sch->data;
+	struct gred_sched_data *q;
+	int i;
+	unsigned char	 *b = skb->tail;
+
+	rta = (struct rtattr*)b;
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+	opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
+
+	if (opt  == NULL) {
+		DPRINTK("gred_dump:failed to malloc for %d\n",
+		    sizeof(struct tc_gred_qopt)*MAX_DPs);
+		goto rtattr_failure;
+	}
+
+	memset(opt, 0, (sizeof(struct tc_gred_qopt))*table->DPs);
+
+	if (!table->initd) {
+		DPRINTK("NO GRED Queues setup!\n");
+		return -1;
+	}
+
+	for (i=0;i<MAX_DPs;i++) {
+		dst= &opt[i]; 
+		q= table->tab[i]; 
+
+		if (!q) {
+			/* hack -- fix at some point with proper message
+			   This is how we indicate to tc that there is no VQ
+			   at this DP */
+
+			dst->DP=MAX_DPs+i;
+			continue;
+		}
+
+		dst->limit=q->limit;
+		dst->qth_min=q->qth_min>>q->Wlog;
+		dst->qth_max=q->qth_max>>q->Wlog;
+		dst->DP=q->DP;
+		dst->backlog=q->backlog;
+		if (q->qave) {
+			if (table->eqp && table->grio) {
+				q->qidlestart=table->tab[table->def]->qidlestart;
+				q->qave=table->tab[table->def]->qave;
+			}
+			if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
+				long idle;
+				psched_time_t now;
+				PSCHED_GET_TIME(now);
+				idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
+				qave  = q->qave >> q->Stab[(idle>>q->Scell_log)&0xFF];
+				dst->qave = qave >> q->Wlog;
+
+			} else {
+				dst->qave = q->qave >> q->Wlog;
+			}
+		} else {
+			dst->qave = 0;
+		}
+		
+
+		dst->Wlog = q->Wlog;
+		dst->Plog = q->Plog;
+		dst->Scell_log = q->Scell_log;
+		dst->other = q->other;
+		dst->forced = q->forced;
+		dst->early = q->early;
+		dst->pdrop = q->pdrop;
+		dst->prio = q->prio;
+		dst->packets=q->packetsin;
+		dst->bytesin=q->bytesin;
+	}
+
+	RTA_PUT(skb, TCA_GRED_PARMS, sizeof(struct tc_gred_qopt)*MAX_DPs, opt);
+	rta->rta_len = skb->tail - b;
+
+	return skb->len;
+
+rtattr_failure:
+	DPRINTK("gred_dump: FAILURE!!!!\n");
+
+/* also free the opt struct here */
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+#endif
+
+static void gred_destroy(struct Qdisc *sch)
+{
+	struct gred_sched *table = (struct gred_sched *)sch->data;
+	int i;
+
+	for (i = 0;i < table->DPs; i++) {
+		if (table->tab[i])
+			kfree(table->tab[i]);
+	}
+	MOD_DEC_USE_COUNT;
+}
+
+struct Qdisc_ops gred_qdisc_ops =
+{
+	NULL,
+	NULL,
+	"gred",
+	sizeof(struct gred_sched),
+	gred_enqueue,
+	gred_dequeue,
+	gred_requeue,
+	gred_drop,
+	gred_init,
+	gred_reset,
+	gred_destroy,
+	gred_change, /* change */
+#ifdef CONFIG_RTNETLINK
+	gred_dump,
+#endif
+};
+
+
+#ifdef MODULE
+int init_module(void)
+{
+	return register_qdisc(&gred_qdisc_ops);
+}
+
+void cleanup_module(void) 
+{
+	unregister_qdisc(&gred_qdisc_ops);
+}
+#endif
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_ingress.c linux/net/sched/sch_ingress.c
--- v2.3.37/linux/net/sched/sch_ingress.c	Wed Dec 31 16:00:00 1969
+++ linux/net/sched/sch_ingress.c	Fri Jan  7 16:57:13 2000
@@ -0,0 +1,392 @@
+/* net/sched/sch_ingress.c - Ingress qdisc 
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Jamal Hadi Salim 1999
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
+#include <net/pkt_sched.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <linux/kmod.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+
+
+
+
+#if 0  /* control */
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+#if 0  /* data */
+#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define D2PRINTK(format,args...)
+#endif
+
+
+#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
+
+
+
+struct ingress_qdisc_data {
+	struct Qdisc		*q;
+	struct tcf_proto	*filter_list;
+};
+
+
+/* ------------------------- Class/flow operations ------------------------- */
+
+
+static int ingress_graft(struct Qdisc *sch,unsigned long arg,
+    struct Qdisc *new,struct Qdisc **old)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
+		sch, p, new, old);
+	DPRINTK("\n ingress_graft: You cannot add qdiscs to classes");
+        return 1;
+}
+
+
+static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	return NULL;
+}
+
+
+static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
+	return TC_H_MIN(classid) + 1;
+}
+
+
+static unsigned long ingress_bind_filter(struct Qdisc *sch,
+    unsigned long parent, u32 classid)
+{
+	return ingress_get(sch, classid);
+}
+
+
+static void ingress_put(struct Qdisc *sch, unsigned long cl)
+{
+}
+
+
+static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
+    struct rtattr **tca, unsigned long *arg)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
+		"arg 0x%lx\n", sch, p, classid, parent, *arg);
+	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
+	return 0;
+}
+
+
+
+static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
+}
+
+
+static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	return &p->filter_list;
+}
+
+
+/* --------------------------- Qdisc operations ---------------------------- */
+
+
+static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+	struct tcf_result res;
+	int result;
+
+	D2PRINTK("ingress_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+	result = tc_classify(skb, p->filter_list, &res);
+	D2PRINTK("result %d class 0x%04x\n", result, res.classid);
+	/*
+	 * Unlike normal "enqueue" functions, ingress_enqueue returns a
+	 * firewall FW_* code.
+	 */
+	switch (result) {
+#ifdef CONFIG_NET_CLS_POLICE
+		case TC_POLICE_SHOT:
+			result = NF_DROP;
+			break;
+		case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
+		case TC_POLICE_OK:
+		case TC_POLICE_UNSPEC:
+		default:
+			result = NF_ACCEPT;
+			break;
+#endif
+	};
+
+#ifdef CONFIG_NET_CLS_TCINDEX
+         skb->tc_index = TC_H_MIN(res.classid);
+#endif
+	return result;
+}
+
+
+static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
+{
+/*
+	struct ingress_qdisc_data *p = PRIV(sch);
+	D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])\n",sch,PRIV(p));
+*/
+	return NULL;
+}
+
+
+static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
+{
+/*
+	struct ingress_qdisc_data *p = PRIV(sch);
+	D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,PRIV(p));
+*/
+	return 0;
+}
+
+static int ingress_drop(struct Qdisc *sch)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
+	return 0;
+}
+
+static unsigned int
+ing_hook(unsigned int hook, struct sk_buff **pskb,
+                             const struct net_device *indev,
+                             const struct net_device *outdev,
+	                     int (*okfn)(struct sk_buff *))
+{
+	
+	struct Qdisc *q;
+	struct sk_buff *skb = *pskb;
+        struct net_device *dev = skb->dev;
+	int fwres=NF_ACCEPT;
+
+	DPRINTK("ing_hook: skb %s dev=%s len=%u\n",
+		skb->sk ? "(owned)" : "(unowned)",
+		skb->dev ? (*pskb)->dev->name : "(no dev)",
+		skb->len);
+
+/* 
+revisit later: Use a private since lock dev->queue_lock is also
+used on the egress (might slow things for an iota)
+*/
+
+	if (dev->qdisc_ingress) {
+		spin_lock(&dev->queue_lock);
+		if ((q = dev->qdisc_ingress) != NULL)
+			fwres = q->enqueue(skb, q);
+		spin_unlock(&dev->queue_lock);
+        }
+			
+	return fwres;
+}
+
+
+/* after iptables */
+static struct nf_hook_ops ing_ops =
+{
+	{ NULL, NULL},
+	ing_hook,
+	NULL,
+	PF_INET,
+	NF_IP_PRE_ROUTING,
+	1
+};
+
+int ingress_init(struct Qdisc *sch,struct rtattr *opt)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
+	memset(p, 0, sizeof(*p));
+	p->filter_list = NULL;
+	p->q = &noop_qdisc;
+#ifndef MODULE
+	if (nf_register_hook(&ing_ops) < 0) {
+		printk("Unable to register ingress \n");
+		goto error;
+	}
+#endif
+	DPRINTK("ingress_init: qdisc %p\n", sch);
+	MOD_INC_USE_COUNT;
+	return 0;
+#ifndef MODULE
+error:
+#endif
+	return -EINVAL;
+}
+
+
+static void ingress_reset(struct Qdisc *sch)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+
+	DPRINTK("ingress_reset(sch %p,[qdisc %p])\n", sch, p);
+
+/*
+#if 0
+*/
+/* for future use */
+	qdisc_reset(p->q);
+/*
+#endif
+*/
+}
+
+/* ------------------------------------------------------------- */
+
+
+/* ------------------------------------------------------------- */
+
+static void ingress_destroy(struct Qdisc *sch)
+{
+	struct ingress_qdisc_data *p = PRIV(sch);
+	struct tcf_proto *tp;
+
+	DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p);
+	while (p->filter_list) {
+		tp = p->filter_list;
+		p->filter_list = tp->next;
+		tp->ops->destroy(tp);
+	}
+	memset(p, 0, sizeof(*p));
+	p->filter_list = NULL;
+
+#if 0
+/* for future use */
+	qdisc_destroy(p->q);
+#endif
+
+#ifndef MODULE
+	nf_unregister_hook(&ing_ops);
+#endif
+
+	MOD_DEC_USE_COUNT;
+}
+
+
+#ifdef CONFIG_RTNETLINK
+
+
+static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	unsigned char *b = skb->tail;
+	struct rtattr *rta;
+
+	rta = (struct rtattr *) b;
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	rta->rta_len = skb->tail - b;
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+#endif
+
+
+static struct Qdisc_class_ops ingress_class_ops =
+{
+	ingress_graft,			/* graft */
+	ingress_leaf,			/* leaf */
+	ingress_get,			/* get */
+	ingress_put,			/* put */
+	ingress_change,			/* change */
+	NULL,				/* delete */
+	ingress_walk,				/* walk */
+
+	ingress_find_tcf,		/* tcf_chain */
+	ingress_bind_filter,		/* bind_tcf */
+	ingress_put,			/* unbind_tcf */
+
+#ifdef CONFIG_RTNETLINK
+	NULL,		/* dump */
+#endif
+};
+
+struct Qdisc_ops ingress_qdisc_ops =
+{
+	NULL,				/* next */
+	&ingress_class_ops,		/* cl_ops */
+	"ingress",
+	sizeof(struct ingress_qdisc_data),
+
+	ingress_enqueue,		/* enqueue */
+	ingress_dequeue,		/* dequeue */
+	ingress_requeue,		/* requeue */
+	ingress_drop,			/* drop */
+
+	ingress_init,			/* init */
+	ingress_reset,			/* reset */
+	ingress_destroy,		/* destroy */
+	NULL,				/* change */
+
+#ifdef CONFIG_RTNETLINK
+	ingress_dump,			/* dump */
+#endif
+};
+
+#ifdef MODULE
+int init_module(void)
+{
+	int ret = 0;
+
+	if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
+		printk("Unable to register Ingress qdisc\n");
+		return ret;
+	}
+
+        if (nf_register_hook(&ing_ops) < 0) {
+		printk("Unable to register ingress on hook \n");
+		unregister_qdisc(&ingress_qdisc_ops);
+		return 0;
+	}
+
+	return ret;
+}
+
+
+void cleanup_module(void) 
+{
+	nf_unregister_hook(&ing_ops);
+	unregister_qdisc(&ingress_qdisc_ops);
+}
+#endif
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_prio.c linux/net/sched/sch_prio.c
--- v2.3.37/linux/net/sched/sch_prio.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_prio.c	Fri Jan  7 16:57:13 2000
@@ -7,6 +7,8 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Fixes:       19990609: J Hadi Salim <hadi@nortelnetworks.com>: 
+ *              Init --  EINVAL when opt undefined
  */
 
 #include <linux/config.h>
@@ -211,8 +213,6 @@
 
 static int prio_init(struct Qdisc *sch, struct rtattr *opt)
 {
-	static const u8 prio2band[TC_PRIO_MAX+1] =
-	{ 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
 	struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
 	int i;
 
@@ -220,14 +220,7 @@
 		q->queues[i] = &noop_qdisc;
 
 	if (opt == NULL) {
-		q->bands = 3;
-		memcpy(q->prio2band, prio2band, sizeof(prio2band));
-		for (i=0; i<3; i++) {
-			struct Qdisc *child;
-			child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
-			if (child)
-				q->queues[i] = child;
-		}
+		return -EINVAL;
 	} else {
 		int err;
 
diff -u --recursive --new-file v2.3.37/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
--- v2.3.37/linux/net/sched/sch_teql.c	Tue Aug 31 17:29:15 1999
+++ linux/net/sched/sch_teql.c	Fri Jan  7 16:57:13 2000
@@ -437,7 +437,7 @@
 	dev->stop		= teql_master_close;
 	dev->get_stats		= teql_master_stats;
 	dev->change_mtu		= teql_master_mtu;
-	dev->type		= 0;
+	dev->type		= ARPHRD_VOID;
 	dev->mtu		= 1500;
 	dev->tx_queue_len	= 100;
 	dev->flags		= IFF_NOARP;
